Android TV develops RecycleView to regain the focus and return to the original item position to let the item get the focus

new method:

Use HorizontalGridView and VerticalGridView instead of RecyclerView, the method of use is basically the same as RecyclerView, but there is no need to set LayoutManager.

In addition, if you want the focus to jump out of the boundary, you need xml settings (manual):

app:focusOutFront="true"

(abandoned~)

old--

After reading a lot of information, some of them need to customize recycleview to realize it, which is too troublesome, so I implemented a relatively simple method by myself.

A View is needed to save the last focused item: 

private View lastView = null; 

If the page does not stay all the time, it may exit or be destroyed. It is recommended—— 

@Override
    public void onDestroyView() {
        super.onDestroyView();
        lastView = null;
    }

 RecycleView adds monitoring:

wifiBinding.recycleView.setOnFocusChangeListener((v, hasFocus) -> {
    Log.d(TAG, "onFocusChange: " + lastView);
    if (hasFocus) {
        //重新获得焦点后回到保存的位置
        if (lastView != null) {
            lastView.setSelected(true);
            lastView.requestFocus();
        }
    }
});

XML add the following two lines:

android:focusable="true"

android:descendantFocusability="beforeDescendants"

<androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycleView"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_marginStart="50dp"
            android:layout_marginTop="10dp"
            android:layout_marginEnd="250dp"
            android:layout_marginBottom="20dp"
            android:nextFocusLeft="@id/refresh"
            android:nextFocusUp="@id/backpress"
            android:padding="10dp"
            android:focusable="true"
            android:descendantFocusability="beforeDescendants"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/connected" />

Finally, update the lastView event in RecycleView.ViewHolder—— 

private class ViewHolder extends RecyclerView.ViewHolder {
    public ViewHolder(@NonNull View itemView) {
        super(itemView);
        itemView.setOnFocusChangeListener((v, hasFocus) -> {
            if (hasFocus) {
        //时刻更新最近获得焦点的item,并保存
                if (lastView != null) {
                    lastView = v;
                }
            }
        });
    }
    @SuppressLint("SetTextI18n")
    public void bind(Wifi item, int position) {        
        //此处作用只是在初始化时获得第一个position的View
        if (lastView == null) {
            if (position == 0) {
                lastView = itemView;
            }
        }
    }
}

Some other minor issues:

After refreshing the recycleview data, the focus will be lost, the processing method is as follows:

(This method cannot return to the original item, the wifi settings I made, recycleview gets the wifi list, the previously selected item may disappear after refreshing the data, so the refreshed focus returns to the top of the list (initial position) .

adapter.setHasStableIds(true);

Override the method in the adapter:

@Override
public long getItemId(int position) {
    return position;
}

Before refreshing the data use:

lastView = null;
layoutManager.scrollToPosition(0);

Guess you like

Origin blog.csdn.net/weixin_44917215/article/details/126389974
Recommended