【问题标题】:How to implement scrolling in RecyclerView on Android TV?如何在 Android TV 上的 RecyclerView 中实现滚动?
【发布时间】:2017-02-12 21:10:33
【问题描述】:

我有一个需要适应 Android TV 的应用程序。此应用程序包含水平 RecyclerView,当我按下遥控器上的 D-pad 按钮时它不会滚动。 我找到了this solution,但它崩溃了。 代码如下:

<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>

Horizo​​ntalPersistentFocusWrapper 与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)

【问题讨论】:

    标签: android-recyclerview android-tv


    【解决方案1】:

    使用最新版本的 RecyclerView。 或者至少使用
    com.android.support:recyclerview-v7:23.2.0
    有关详细信息,请参阅此链接:
    https://code.google.com/p/android/issues/detail?id=190526&thanks=190526&ts=1445108573

    现在是重要的部分:
    新版本的 RecyclerView 开始遵守其子项的规则(如高度和宽度)。 您必须将子项 XML 中的根视图设置为:
    android:focusable="true"

    现在,滚动将按预期进行。

    【讨论】:

      【解决方案2】:

      在recyclerview 项目的根视图中将focusable 设置为true。 android:focusable="true" 并将 选择器背景 应用于根视图项。一切都可以在 xml 文件中完成。通过以下设置,dpad或遥控器将能够上下滚动列表,列表中当前选择的项目将突出显示。

      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>
      

      【讨论】:

        【解决方案3】:

        试试这个。对我有用。

            @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 对 d-pad 没有反应。
        • 只是为了确定。 Horizo​​ntalPersistentFocusWrapper 用于包装 RecyclerView(s) 与垂直 LinearLayout 管理器和可能的其他视图。要使用水平 LineaLayoutManagers 包装 RecyclerViews,请使用 VerticalPersistentFocusWrapper。
        猜你喜欢
        • 1970-01-01
        • 2018-09-18
        • 2016-01-02
        • 2021-01-02
        • 2017-10-28
        • 2018-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多