问题描述:
在ipTv的开发中 因为不能触屏 所以当recycleView设置为GridLayoutManager之后 焦点移动到当前屏幕所能显示的最后一行时 recycleView并不会滑动 (LinearLayout可以) 然后按遥控器的向下按钮时 下一行的item还没有加载出来 这个时候 焦点就会丢失
解决方案:
首先 重写了RecyclerView 解决滑到下一屏时候 item没加载出来的问题
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (mInterceptLister != null && mInterceptLister.onIntercept(event)) {
return true;
}
boolean result = super.dispatchKeyEvent(event);
View focusView = this.getFocusedChild();
if (focusView == null) {
return result;
} else {
int dy = 0;
int dx = 0;
if (getChildCount() > 0) {
View firstView = this.getChildAt(0);
dy = firstView.getHeight();
dx = firstView.getWidth();
}
if (event.getAction() == KeyEvent.ACTION_UP) {
return true;
} else {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_DPAD_RIGHT:
View rightView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_RIGHT);
Log.i(TAG, "rightView is null:" + (rightView == null));
if (rightView != null) {
rightView.requestFocus();
return true;
} else {
this.smoothScrollBy(dx, 0);
return true;
}
case KeyEvent.KEYCODE_DPAD_LEFT:
View leftView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_LEFT);
Log.i(TAG, "leftView is null:" + (leftView == null));
if (leftView != null) {
leftView.requestFocus();
return true;
} else {
this.smoothScrollBy(-dx, 0);
return true;
}
case KeyEvent.KEYCODE_DPAD_DOWN:
View downView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_DOWN);
Log.i(TAG, " downView is null:" + (downView == null));
if (downView != null) {
downView.requestFocus();
return true;
} else {
this.smoothScrollBy(0, dy);
return true;
}
/*case KeyEvent.KEYCODE_DPAD_UP:
View upView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_UP);
Log.i(TAG, "upView is null:" + (upView == null));
if (event.getAction() == KeyEvent.ACTION_UP) {
return true;
} else {
if (upView != null) {
upView.requestFocus();
return true;
} else {
this.smoothScrollBy(0, -dy);
return true;
}
}*/
}
}
}
return result;
}
然后写分页加载的方法
recycleView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (isLoad){
int lastPosition = -1;
//当前状态为停止滑动状态SCROLL_STATE_IDLE时
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
//通过LayoutManager找到当前显示的最后的item的position
lastPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
} else if (layoutManager instanceof LinearLayoutManager) {
lastPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
//因为StaggeredGridLayoutManager的特殊性可能导致最后显示的item存在多个,所以这里取到的是一个数组
//得到这个数组后再取到数组中position值最大的那个就是最后显示的position值了
int[] lastPositions = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()];
((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(lastPositions);
lastPosition = findMax(lastPositions);
}
//时判断界面显示的最后item的position是否等于itemCount总数-1也就是最后一个item的position
//如果相等则说明已经滑动到最后了
if (lastPosition == recyclerView.getLayoutManager().getItemCount() - 1) {
// Toast.makeText(getContext(), "滑动到底了", Toast.LENGTH_SHORT).show();
}
}
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});
}
private int findMax(int[] lastPositions) {
int max = lastPositions[0];
for (int value : lastPositions) {
if (value > max) {
max = value;
}
}
return max;
}
在设置Adapter时 调用adapter.setHasStableIds(true); 在调用notifyDataSetChanged方法时 已经加载的item将不会重新刷新 但
是这样写数据会重复所以需要在适配器中重写getItemId方法 用来记录位置
@Override
public long getItemId(int position) {
return position;
}
ps:自定义recycleView的下载链接 https://download.csdn.net/download/ayrascal/11182875
end