如何在 Android 电视的 RecyclerView 中实现滚动?
How to implement scrolling in RecyclerView on Android TV?
我有一个应用程序需要适应 Android 电视。此应用程序包含水平 RecyclerView,当我按下遥控器上的方向键按钮时它不会滚动。
我找到 ,但它崩溃了。
这是代码:
<ru.myapp.package.HorizontalPersistentFocusWrapper
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="@null"
android:scrollbars="none"/>
</ru.myapp.package.HorizontalPersistentFocusWrapper>
HorizontalPersistentFocusWrapper 与 PersistentFocusWrapper 相同,但 mPersistFocusVertical = false;
崩溃发生在这个地方:
@Override
public void requestChildFocus(View child, View focused) {
super.requestChildFocus(child, focused);
View view = focused;
while (view != null && view.getParent() != child) {
view = (View) view.getParent(); <<<------ Crash here
}
mSelectedPosition = view == null ? -1 : ((ViewGroup) child).indexOfChild(view);
if (DEBUG) Log.v(TAG, "requestChildFocus focused " + focused + " mSelectedPosition " + mSelectedPosition);
}
崩溃堆栈跟踪:
java.lang.ClassCastException: android.view.ViewRootImpl cannot be cast to android.view.View
at ru.myapp.package.HorizontalPersistentFocusWrapper.requestChildFocus(HorizontalPersistentFocusWrapper.java:108)
at android.view.View.handleFocusGainInternal(View.java:5465)
at android.view.ViewGroup.handleFocusGainInternal(ViewGroup.java:714)
at android.view.View.requestFocusNoSearch(View.java:8470)
at android.view.View.requestFocus(View.java:8449)
at android.view.ViewGroup.requestFocus(ViewGroup.java:2747)
at android.view.View.requestFocus(View.java:8416)
at android.support.v4.widget.NestedScrollView.arrowScroll(NestedScrollView.java:1222)
at android.support.v4.widget.NestedScrollView.executeKeyEvent(NestedScrollView.java:551)
at android.support.v4.widget.NestedScrollView.dispatchKeyEvent(NestedScrollView.java:512)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
试试这个。适合我。
@Override
public void requestChildFocus(View child, View focused) {
super.requestChildFocus(child, focused);
View view = focused;
while (view != null && view.getParent() != child) {
try {
view = (View) view.getParent();
} catch (ClassCastException e) {
view = null;
}
}
mSelectedPosition = view == null ? -1 : ((ViewGroup) child).indexOfChild(view);
if (DEBUG)
Log.v(TAG, "requestChildFocus focused " + focused + " mSelectedPosition " + mSelectedPosition);
}
使用最新版本的 RecyclerView。
或者至少使用
com.android.support:recyclerview-v7:23.2.0
有关详细信息,请参阅此 link:
https://code.google.com/p/android/issues/detail?id=190526&thanks=190526&ts=1445108573
现在是重要的部分:
新版本的 RecyclerView 开始遵守其子项的规则(例如高度和宽度)。
您必须将子项 XML 中的根视图设置为:
android:focusable="true"
现在,滚动将按预期进行。
在 recyclerview 项目的根视图中将 focusable 设置为 true。 android:focusable="true"
并将 选择器背景 应用于根视图项。一切都可以在 xml 文件中完成。通过以下设置,方向键或遥控器将可以上下滚动列表,列表中当前选中的项目将突出显示。
RecyclerView中列表项根视图的布局文件:list_item.xml,这里重要的部分是android:background="@drawable/item_selector"
和android:focusable="true"
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/item_selector"
android:focusable="true">
<TextView
android:id="@+id/topic"
android:layout_width="match_parent"
android:layout_height="60dp"
android:textColor="#ffffff"
android:gravity="center"
tools:text="Education"/>
</LinearLayout>
drawable文件夹中的drawable选择器文件:item_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#000000" android:state_pressed="true"/>
<item android:drawable="#000000" android:state_selected="true"/>
<item android:drawable="#000000" android:state_focused="true"/>
<item android:drawable="#03A9F4"></item>
</selector>
包含 RecyclerView 的布局文件:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</android.support.constraint.ConstraintLayout>
我有一个应用程序需要适应 Android 电视。此应用程序包含水平 RecyclerView,当我按下遥控器上的方向键按钮时它不会滚动。
我找到
<ru.myapp.package.HorizontalPersistentFocusWrapper
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="@null"
android:scrollbars="none"/>
</ru.myapp.package.HorizontalPersistentFocusWrapper>
HorizontalPersistentFocusWrapper 与 PersistentFocusWrapper 相同,但 mPersistFocusVertical = false;
崩溃发生在这个地方:
@Override
public void requestChildFocus(View child, View focused) {
super.requestChildFocus(child, focused);
View view = focused;
while (view != null && view.getParent() != child) {
view = (View) view.getParent(); <<<------ Crash here
}
mSelectedPosition = view == null ? -1 : ((ViewGroup) child).indexOfChild(view);
if (DEBUG) Log.v(TAG, "requestChildFocus focused " + focused + " mSelectedPosition " + mSelectedPosition);
}
崩溃堆栈跟踪:
java.lang.ClassCastException: android.view.ViewRootImpl cannot be cast to android.view.View
at ru.myapp.package.HorizontalPersistentFocusWrapper.requestChildFocus(HorizontalPersistentFocusWrapper.java:108)
at android.view.View.handleFocusGainInternal(View.java:5465)
at android.view.ViewGroup.handleFocusGainInternal(ViewGroup.java:714)
at android.view.View.requestFocusNoSearch(View.java:8470)
at android.view.View.requestFocus(View.java:8449)
at android.view.ViewGroup.requestFocus(ViewGroup.java:2747)
at android.view.View.requestFocus(View.java:8416)
at android.support.v4.widget.NestedScrollView.arrowScroll(NestedScrollView.java:1222)
at android.support.v4.widget.NestedScrollView.executeKeyEvent(NestedScrollView.java:551)
at android.support.v4.widget.NestedScrollView.dispatchKeyEvent(NestedScrollView.java:512)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
试试这个。适合我。
@Override
public void requestChildFocus(View child, View focused) {
super.requestChildFocus(child, focused);
View view = focused;
while (view != null && view.getParent() != child) {
try {
view = (View) view.getParent();
} catch (ClassCastException e) {
view = null;
}
}
mSelectedPosition = view == null ? -1 : ((ViewGroup) child).indexOfChild(view);
if (DEBUG)
Log.v(TAG, "requestChildFocus focused " + focused + " mSelectedPosition " + mSelectedPosition);
}
使用最新版本的 RecyclerView。
或者至少使用
com.android.support:recyclerview-v7:23.2.0
有关详细信息,请参阅此 link:
https://code.google.com/p/android/issues/detail?id=190526&thanks=190526&ts=1445108573
现在是重要的部分:
新版本的 RecyclerView 开始遵守其子项的规则(例如高度和宽度)。
您必须将子项 XML 中的根视图设置为:
android:focusable="true"
现在,滚动将按预期进行。
在 recyclerview 项目的根视图中将 focusable 设置为 true。 android:focusable="true"
并将 选择器背景 应用于根视图项。一切都可以在 xml 文件中完成。通过以下设置,方向键或遥控器将可以上下滚动列表,列表中当前选中的项目将突出显示。
RecyclerView中列表项根视图的布局文件:list_item.xml,这里重要的部分是android:background="@drawable/item_selector"
和android:focusable="true"
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/item_selector"
android:focusable="true">
<TextView
android:id="@+id/topic"
android:layout_width="match_parent"
android:layout_height="60dp"
android:textColor="#ffffff"
android:gravity="center"
tools:text="Education"/>
</LinearLayout>
drawable文件夹中的drawable选择器文件:item_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#000000" android:state_pressed="true"/>
<item android:drawable="#000000" android:state_selected="true"/>
<item android:drawable="#000000" android:state_focused="true"/>
<item android:drawable="#03A9F4"></item>
</selector>
包含 RecyclerView 的布局文件:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</android.support.constraint.ConstraintLayout>