最近開始做TV端的安卓項目了,TV上的安卓項目主要問題就是要處理焦點問題。下面就對我在TV端使用RecyclerView是遇到的問題做一個總結。
RecyclerView在長按遙控器的情況下會導致Item的焦點丟失或者說是飛到別的控件上。主要是因爲RecyclerView設置適配器,將數據全部填充進去之後,並不會將所有的item的view創建出來,只會創建出顯示和需要的item的View,沒有顯示的Item的View很可能沒有被創建。所以在快速移動的時候,RecyclerView並沒有創建那個應該獲取焦點的View,所以導致焦點飛到其他可承載焦點的View上去了。
解決這個焦點丟失的問題我目前知道有兩種方法。
一、控制遙控器按鍵的速度,也就是降低按鍵的觸發速度。當下一個item創建出來之後,再讓他切換焦點。代碼如下:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
long current = System.currentTimeMillis();
boolean dispatch;
if (current - mLastKeyDownTime < 150) {
dispatch= true;
} else {
dispatch= super.onKeyDown(keyCode, event);
mLastKeyDownTime = current;
}
return dispatch;
}
二、 在RecyclerView的LayoutManager中,有這樣一個方法onInterceptFocusSearch(View focused, int direction),這個方法就是用於尋找焦點的。當遇到長按或者連續按鍵焦點飛掉的情況時,需要重載RecyclerView的LayoutManager,重寫此方法。
public class FocusFixedLinearLayoutManagerextends android.support.v7.widget.LinearLayoutManager {
public FocusFixedLinearLayoutManager(Context context) {
super (context);
}
public FocusFixedLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context,orientation,reverseLayout);
}
public FocusFixedLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context,attrs,defStyleAttr,defStyleRes);
}
@Override
public View onInterceptFocusSearch(View focused, int direction) {
int currentPosition= getPosition(getFocusedChild());//這裏要用這個方法
int count = getItemCount();
int lastVisiblePosition=findLastVisibleItemPosition();
switch(direction){
case View.FOCUS_RIGHT:
currentPosition++;
break;
case View.FOCUS_LEFT:
currentPosition--;
break;
}
if(currentPosition<0||currentPosition>count){
return focused;
}else{
if(currentPosition>lastVisiblePosition){
scrollToPosition(currentPosition);
}
}
return super .onInterceptFocusSearch(focused, direction);
}
}