先看下效果:
做车机项目时,需要动态更新WIFI信息,WIFI列表增加焦点控制
开发中遇到两个问题
- RecyclerView抢占了item的焦点,导致不显示红色框框
- RecyclerView刷新数据时焦点丢失
(刷新前焦点位置比刷新后大于刷新后的数据大小,这样系统就会去找layout中可以获取的焦点的控件,可能不会是recyclerview,这时焦点就会消失掉;反之,则会在recyclerview的第一个位置)
先解决第一个问题:
第一步
<?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="match_parent"
tools:context="com.yftech.myapplication.MainActivity"
android:background="#000"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/recy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
##表示当子控件不需要focus的时候,recyclerview才会去获取focus
android:descendantFocusability="afterDescendants"
/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:focusableInTouchMode="false"
android:text="刷新数据"/>
</LinearLayout>
第二步
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item"
##必须设置
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/list_selector">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="@dimen/text_item_height"
android:textColor="@android:color/white"
android:gravity="left|center_vertical"
android:textSize="@dimen/item_text_size"
android:height="65dp"
android:paddingLeft="30dp"
##指的是当前控件是否跟随父控件的(点击、焦点等)状态
android:duplicateParentState="true"
/>
</LinearLayout>
搞定第一个问题!!!
重点解决第二个问题
1.adapter的setHasStableIds设置成true
adapter.setHasStableIds(true);
解释:设置item是否可以有一个id(具体意思可以百度)
2.重写adapter的getItemId方法
@Override
public long getItemId(int position) {
return position;
}
解释:给item生成一个id,用于定位焦点的
3.这两步已经可以保存recyclerview的焦点了,但是使用notify系列方法仍然会出现focus丢失的问题,现在官方已经承认这是一个bug,可以暂时使用禁用notifyDataSetChanged动画的方法来规避:
mRecyclerView.setItemAnimator(null);
搞定