在Android tv中的开发中,经常要跟焦点打交道,一个常见的需求是要有焦点记忆功能,焦点移动到列表中的某一项中,焦点移出去,在回来时焦点还要定位到原来的项目上,对于这种需求,常见的实现方式是列表用用listview或者recyclerview实现,维护一个变量去存储上次的焦点位置,并在焦点变动或者按键事件中去维护这个变量和使用这个变量来定位.
具体实现
比如说用recyclerview实现列表时,在每个itemview的按键事件中,根据按键的方向和当前view的位置,判断是否是向外移走焦点的,如果是,那么就去设置父view也就是recyclerview的焦点模式,并且要保存当前view的位置信息
recyclerview.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
在用户操作移回焦点时,由于前一步设置了焦点模式为block,因此会父view会首先获取焦点,增加焦点变动的事件处理:
recyclerview.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus){
Recyclerview recyclerview = (Recyclerview)v;
recyclerView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
if(mCurrentFocusPosition>0){
LayoutManager layoutManager = recyclerView.getLayoutManager();
View viewByPosition = layoutManager.findViewByPosition(mCurrentFocusPosition);
if(viewByPosition!=null){
viewByPosition.requestFocus();
}
}
}
}
});
如代码所示,在焦点变动处理中,设置view的焦点模式,可以让子view获取焦点;拿到上一步保存的位置信息来手动设置焦点.
后面介绍另一种更简便的方法,有更好的封装性,不需要外层逻辑做维护处理.
文章已经发布,请查看:RecyclerView的焦点记忆封装