电视TV端使用RecyclerView开发遇到的问题

最近在做一个TV端使用的相册。

偷偷展示一下,相册大概长这个样子:

相册也支持多选删除:

非删除模式下点击单一图片会进入单一图片展示界面。单一图片可以左右翻页。

从展示界面返回相册界面,光标定位到展示图片所在的相册位置。

主要控件使用了CardView 和RecyclerView。
TV开发和手机开发有个不同的就是焦点问题
在手机端,手指只要一划就可以到后面了,而在TV端,需要用遥控器左右键控制焦点移动。

RecyclerView(简称RV)在TV端的应用可以借鉴的案例不多,相比于ListView,RV的很多功能都需要自己实现。诸如,wrap_content自适应问题,选中的背景问题,setSelection()方法等。

将遇到的问题及大致解决方法mark一下,方便以后查询。

1.wrap_content自适应问题

参见RecyclerView自适应高度的LayoutManager

2.RV占据焦点,RV的子View没有获取焦点(ps:工程使用的是androidannotations框架,以下代码使用了androidannotations注解)

需要在RV获取焦点后手动设置下焦点:

@FocusChange(R.id.id_recyclerview_horizontal)
void focusRecyclerView(boolean hasFocus) {
        if (hasFocus) {
            focusChild(false);
        }
    }

 @UiThread
 void focusChild(boolean isInit) {
        if (mRecyclerView.getChildCount() > 0) {
            mRecyclerView.getChildAt(0).requestFocus();
        }
        if (isInit) {
            mAct.setSelectPos(0);
        }
    }

3.多选问题
多选问题一开始是使用的List保存需要删除的图片位置,在onBindViewHolder方法中根据list中的数据来做判断,决定显示垃圾筐(选择状态)还是正常图片(非选择状态)。这样做也能达到效果,但由于Item的View是一个包含多个控件的FrameLayout,这样写需要getChildAt或者findViewById来决定取舍,觉得这样有点low。
最后选择了com.bignerdranch.android.multiselector工具
嗯,好用。

4.选中的背景问题
在SwappingHolder的子类中复写如下方法:

 @Override
public void setSelectionModeBackgroundDrawable(Drawable selectionModeBackgroundDrawable) {  super.setSelectionModeBackgroundDrawable(mAct.getResources().getDrawable(R.drawable.selector_list_item_shadow));
}

5.setSelection()方法,跳转到最后几个Item的问题
RV没有setSelection方法,官方API是这么说的

RecyclerView will scroll the minimum amount that is necessary to make the target position visible. If you are looking for a similar behavior to setSelection(int) or setSelectionFromTop(int, int), use scrollToPositionWithOffset(int, int).
有个问题就是,如果总共有15张图片,最后一页展示4个图片,那么跳转到pos大于11的图片时候,焦点却在pos==11的图片位置上。所以这个时候需要手动设置下。

@UiThread
void fouceSelected() {
if (mAct.getSelectPos() 
<= linearLayoutManager.findLastVisibleItemPosition() &&
mAct.getSelectPos() >=linearLayoutManager.findFirstVisibleItemPosition()) {
            linearLayoutManager.findViewByPosition(mAct.getSelectPos()).requestFocus();

int focusPos = mRecyclerView.getChildCount() + mAct.getSelectPos() - linearLayoutManager.findLastVisibleItemPosition() - 1;
mRecyclerView.getChildAt(focusPos).requestFocus();
        }
    }

获取RV当前显示的第一个控件的位置和最后一个控件显示的位置来计算出当前应该获取焦点的View的位置,把焦点交给它。

你可能感兴趣的:(android,电视,tv,焦点问题,RecycleVie)