最近开始学习RecyclerView,总结了一些我自己觉得需要关注有那么点实用的点,跟大家分享一下。以备不时之需。也许你早就了解了。那就当复习复习吧。知识在于积累,学习,总结,分享,讨论。不管大小深浅,总结才能纳为己用。请笑纳咯。
RecyclerView.Adapter
Adapter的作用有两个:1. 填充数据 2. 给每一个Item创建正确的布局。
RecyclerView.Adapter
- public VH onCreateViewHolder(ViewGroup parent, int viewType) //return 一个ViewHolder对象
- public void onBindViewHolder(VH holder, int position) 通过ViewHolder给布局填充数据
- public int getItemCount() 获取数据总数
给RecyclerView
设置分割线的方法
- 如果不需要特殊的效果,则直接给item设置margin。- 如果要比较复杂的分割线效果,则给RecyclerView设置itemDecoration
RecyclerView的点击事件
RecyclerView本身没有点击事件,需要在适配器中给子view添加click监听,然后调用我们自己的回调来实现。有关点击事件的实现可以参考我的另一篇文章RecyclerView --onItemClick设置汇总
getItemOffsets()
getItemOffsets
相当于padding,相当于设置了相对于内容的上下左右的padding,padding出来的地方就是给onDraw方法来填充的。
getDraw
绘制在内容的下一层相当于内容的背景。
getDrawOver
绘制在内容的上一层,覆盖在内容上面,可以用于标签的绘制。
findChildViewUnder(int x, int y)
获取对应X,Y的view。可用于onInterceptTouchEvent
里面用于判断当前触摸的view。
删除,添加数据
注意: RecyclerView
的adapter刷新是不能用notifyDataChanged
而是根据删除和插入数据调用不同的方法。
删除数据之后,通知adapter
刷新数据的方法是notifyItemRemoved(int position)
.
添加数据之后,用notifyItemInserted(position)
ItemAnimator
ItemAnimator
用于RecyclerView的item的切换动画。
SimpleItemAnimator
方法解读:
-
animateRemove(ViewHolder holder)
当一个item要从RecyclerView中移除时,调用,而且在移除之后必须调用dispatchRemoveFinished(ViewHolder)。
getPositionByView
根据View获取当前View所在的position。
private int getPositionByView(View view) {
if (view == null) {
return NO_POSITION;
}
LayoutParams params = (LayoutParams) view.getLayoutParams();
if (params == null || params.isItemRemoved()) {
// when item is removed, the position value can be any value.
return NO_POSITION;
}
return params.getViewPosition();
}
requestChildFocus
requestChildFocus
是当一个子布局要获取焦点的时候调用。源码注释如下:
/**
* Called when a child of this parent wants focus
*
* @param child The child of this ViewParent that wants focus. This view
* will contain the focused view. It is not necessarily the view that
* actually has focus.
* @param focused The view that is a descendant of child that actually has
* focus
*/
public void requestChildFocus(View child, View focused);
从上面的英文注释我们可以知道当这个父布局的某个子布局要获取焦点的时候这个方法就会调用。注意,也有可能是该子布局中的子布局要获取焦点。第一个参数是父布局对应的子布局, 第二个参数才是真正获取焦点的view。从这个方法我们也可以获取到当前获取焦点的view的位置相关的信息。
Log.i("xxx", "getPositionByView(child)" + getPositionByView(child) + focused );
LinearLayoutManager
有时候我们需要获取当前布局完整看到的第一个item,以及完整看到的最后一个item。因为有时候虽然RecyclerView我们看到的只有五个,但是其实获取第一个可见的item的position和我们预期的position不是同一个,这是因为有一些item虽然没有被我们看到,但是它对于布局来说是可见的,只不过也许他只是没有显示内容只显示了边缘,我们就认定不可见。这个时候我们就需要通过坐标来获取到完全可见的item。幸运地是,刚好LinearLayoutManager里面提供了相应的方法。
获取最后一个完整可见的item的position,注意是完整可见的item的position哦。
/**
* Returns the adapter position of the last fully visible view. This position does not include
* adapter changes that were dispatched after the last layout pass.
*
* Note that bounds check is only performed in the current orientation. That means, if
* LayoutManager is horizontal, it will only check the view's left and right edges.
*
* @return The adapter position of the last fully visible view or
* {@link RecyclerView#NO_POSITION} if there aren't any visible items.
* @see #findLastVisibleItemPosition()
* @see #findFirstCompletelyVisibleItemPosition()
*/
public int findLastCompletelyVisibleItemPosition() {
final View child = findOneVisibleChild(getChildCount() - 1, -1, true, false);
return child == null ? NO_POSITION : getPosition(child);
}
获取第一个完整可见的item的position,注意是完整可见的item的position哦。
/**
* Returns the adapter position of the first fully visible view. This position does not include
* adapter changes that were dispatched after the last layout pass.
*
* Note that bounds check is only performed in the current orientation. That means, if
* LayoutManager is horizontal, it will only check the view's left and right edges.
*
* @return The adapter position of the first fully visible item or
* {@link RecyclerView#NO_POSITION} if there aren't any visible items.
* @see #findFirstVisibleItemPosition()
* @see #findLastCompletelyVisibleItemPosition()
*/
public int findFirstCompletelyVisibleItemPosition() {
final View child = findOneVisibleChild(0, getChildCount(), true, false);
return child == null ? NO_POSITION : getPosition(child);
}
RecyclerView在TV上的使用
RecyclerView在TV上面使用时,要保证子布局可以获取焦点否则上下键按键时布局无法移动!