Android TV move focus between RecyclerViews

大憨熊 提交于 2019-12-21 12:59:59

问题


I am building an Android TV app with the following layout:

Both lists on the left and on the right are RecyclerViews with vertical LinearLayoutManagers, Header view is static. Navigation with D-PAD works fine within one list, but when switching from one list to another there are issues. Focus moves from, say list1's item 5 to list2' item 5. When list 2 is short has less than 5 items, it just loses focus.

I want the last focused item index saved and when the user navigates list1-list2-list1 the item with that index to gain focus again and also prevent the views from losing focus. Is there any good solution to this?

Required behaviour: user navigates to the top of the list and presses "UP" - focus stays where it was, nothing happens. user navigates to the bottom of the list and presses "DOWN" - focus stays where it was, nothing happens. user navigates from list1 to list2 - the item, that previously had focus in list2, gains focus or item0 gains focus if none was focused previously.

main layout:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    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"
    >

    <ImageView
        android:id="@+id/iv_background"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:focusable="false"
        />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="27dp"
        android:layout_marginLeft="48dp"
        android:layout_marginRight="48dp"
        android:layout_marginTop="27dp"
        android:orientation="horizontal"
        >

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:orientation="vertical"
            >

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:focusable="false"
                android:orientation="horizontal"
                >

                <ImageView
                    android:id="@+id/iv_poster"
                    android:layout_width="@dimen/episodes_list_item_height"
                    android:layout_height="@dimen/episodes_list_image_width"
                    />

                <LinearLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:orientation="vertical"
                    >

                    <TextView
                        android:id="@+id/tv_title"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        />

                    <FrameLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        >

                        <TextView
                            android:id="@+id/tv_release_date"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_gravity="left"
                            />

                        <TextView
                            android:id="@+id/tv_rating"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_gravity="right"
                            android:drawableLeft="@drawable/ic_star_white_24dp"
                            android:drawablePadding="@dimen/view_padding_small"
                            />

                    </FrameLayout>

                    <TextView
                        android:id="@+id/tv_description"
                        android:layout_width="match_parent"
                        android:layout_height="0dp"
                        android:layout_weight="1"
                        />
                </LinearLayout>

            </LinearLayout>

            <android.support.v7.widget.RecyclerView
                android:id="@+id/rv_seasons_list"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:focusable="false"
                />

        </LinearLayout>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv_episodes_list"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="3"
            android:focusable="false"
            />

    </LinearLayout>

</FrameLayout>

item layout, used for both lists:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/seasons_list_item_height"
    android:orientation="horizontal"
    android:focusable="true"
    >

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:layout_weight="1"
        />

    <TextView
        android:id="@+id/tv_episodes_count"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:ems="10"
        />

</LinearLayout>

回答1:


Digging through Google's Leanback library sources answered my payers. If you face the same trouble, just wrap your RecyclerViews with this and don't forget to set

private boolean mPersistFocusVertical = false;

if you want the focus to be persisted when searching horizontally, like in my layout.




回答2:


Modify your main layout as below.

For directional navigation we can add properties like nextFocusDown, nextFocusLeft, nextFocusRight, nextFocusUp to focus relevant items as per our requirements.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
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"
>

<ImageView
    android:id="@+id/iv_background"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusable="false"
    />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginBottom="27dp"
    android:layout_marginLeft="48dp"
    android:layout_marginRight="48dp"
    android:layout_marginTop="27dp"
    android:orientation="horizontal"
    >

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="2"
        android:orientation="vertical"
        >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:focusable="false"
            android:orientation="horizontal"
            >

            <ImageView
                android:id="@+id/iv_poster"
                android:layout_width="@dimen/episodes_list_item_height"
                android:layout_height="@dimen/episodes_list_image_width"
                />

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:orientation="vertical"
                >

                <TextView
                    android:id="@+id/tv_title"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    />

                <FrameLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    >

                    <TextView
                        android:id="@+id/tv_release_date"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="left"
                        />

                    <TextView
                        android:id="@+id/tv_rating"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="right"
                        android:drawableLeft="@drawable/ic_star_white_24dp"
                        android:drawablePadding="@dimen/view_padding_small"
                        />

                </FrameLayout>

                <TextView
                    android:id="@+id/tv_description"
                    android:layout_width="match_parent"
                    android:layout_height="0dp"
                    android:layout_weight="1"
                    />
            </LinearLayout>

        </LinearLayout>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv_seasons_list"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:focusable="false"
            android:nextFocusDown="@+id/rv_episodes_list"
            />

    </LinearLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_episodes_list"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3"
        android:focusable="false"
        android:nextFocusUp="@+id/rv_seasons_list"
        />

</LinearLayout>

Hope this will solve your problem !!



来源:https://stackoverflow.com/questions/35203829/android-tv-move-focus-between-recyclerviews

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!