RecycleView的使用及坑

腾讯写的:https://www.cnblogs.com/bugly/p/6264751.html

RecycleView的使用及坑

原文: http://dalufan.com/2016/12/02/android-recycleview-useage-issues/  作者: 大路


控制Item的宽度

在布局中存在某个item占用一行,而有的一行会有多个item,及类似于listview和gridview的混合,这时可以通过下面的方法来设置:

       
       
1
2
3
4
5
6
7
8
9
10
       
       
GridLayoutManager layoutManager = new GridLayoutManager( this, 3);
layoutManager.setSpanSizeLookup( new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
//如果isSection(position),那么这个条目将占用SpanCount()这么多的列数,也就是3
         //而如果不是,就占用1列即可
return isSection(position) ? layoutManager.getSpanCount() : 1;
}
});
recycleview.setLayoutManager(layoutManager);

滑动停止刷新数据

判断是否正在滑动的方法是getScrollState(),如果它等于RecyclerView.SCROLL_STATE_IDLE说明不在滑动,判断有没有在计算layout的方法是isComputingLayout(),取否就可以得到不在计算的时候,通过这两个条件来决定是否刷新数据

       
       
1
2
3
       
       
if (!recyclerView.isComputingLayout() && RecyclerView.SCROLL_STATE_IDLE == recyclerView.getScrollState()) {
mAdapter.notifyDataSetChanged();
}

getPosition getLayoutPosition getAdapterPosition

  • getPosition(); 查阅资料后发现[已弃用]
  • getLayoutPosition(); [条目在最新布局计算中的位置]
  • getAdapterPosition(); [条目在是适配器中的位置]

getLayoutPositiongetAdapterPosition这两种类型的位置是等同的,除非在分发adapter.notify*事件和更新布局时。

adapter和layout的位置会有时间差(<16ms), 如果你改变了Adapter的数据然后刷新视图, layout需要过一段时间才会更新视图, 在这段时间里面, 这两个方法返回的position会不一样.

在notifyDataSetChanged之后并不能马上获取Adapter中的position, 要等布局结束之后才能获取到.

而对于Layout的position, 在notifyItemInserted之后, Layout不能马上获取到新的position, 因为布局还没更新(需要<16ms的时间刷新视图), 所以只能获取到旧的, 但是Adapter中的position就可以马上获取到最新的position.

返回布局位置的方法使用最近一次布局运算后的位置,如getLayoutPosition()和findViewHolderForLayoutPosition(int)。这些位置包含了最近一次布局运算后的变化。你可以根据这些位置来与用户正在屏幕上看到的保持一致。比如,你有一个条目列表,当用户请求第5个条目时,你可以使用这些方法来匹配用户看到的。

另外一系列方法与AdapterPosition关联,比如getAdapterPosition()和findViewHolderForAdapterPosition(int)。当你想获得条目在更新后的适配器中的位置使用这些方法,即使这些位置变化还没反映到布局中。比如,你想访问适配器中条目的位置时,就应该使用getAdapterPosition()。注意,如果notifyDataSetChanged()已经被调用而且还没计算新布局,这些方法或许不能够计算适配器位置。所以,你要小心处理这些方法返回NO_POSITION和null的情况。

总之,当使用RecycleView.LayoutManager时使用getLayoutPosition布局位置。使用RecycleView.Adapter时,使用getAdapterPosition适配器位置。

pointToPosition

在AbsListView(listview、gridview)中,有个根据屏幕位置获取pos的方法:pointToPosition,但在recycleview中没有这个方法,可以通过下面方法来达到相同的效果

       
       
1
2
       
       
View targetView = recyclerView.findChildViewUnder(x, y);
recyclerView.getChildAdapterPosition(targetView);

OnContextMenuListener

http://stackoverflow.com/questions/26466877/how-to-create-context-menu-for-recyclerview

ContextMenuRecyclerView.java

       
       
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
       
       
public class ContextMenuRecyclerView extends RecyclerView {
public ContextMenuRecyclerView(Context context) {
super(context);
}
public ContextMenuRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ContextMenuRecyclerView(Context arg0, AttributeSet arg1, int arg2) {
super(arg0, arg1, arg2);
}
private RecyclerViewContextMenuInfo mContextMenuInfo;
@Override
protected ContextMenu. ContextMenuInfo getContextMenuInfo() {
return mContextMenuInfo;
}
@Override
public boolean showContextMenuForChild(View originalView) {
final int longPressPosition = getChildAdapterPosition(originalView);
if (longPressPosition >= 0) {
final long longPressId = getAdapter().getItemId(longPressPosition);
mContextMenuInfo = new RecyclerViewContextMenuInfo(longPressPosition, longPressId);
return super.showContextMenuForChild(originalView);
}
return false;
}
public static class RecyclerViewContextMenuInfo implements ContextMenu.ContextMenuInfo {
public RecyclerViewContextMenuInfo(int position, long id) {
this.position = position;
this.id = id;
}
final public int position;
final public long id;
}
}

In your Fragment (or Activity):

       
       
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
       
       
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mRecyclerView = view.findViewById(R.id.recyclerview);
registerForContextMenu(mRecyclerView);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
// inflate menu
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.my_context_menu, menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
return super.onContextItemSelected(item);
RecyclerViewContextMenuInfo info = (RecyclerViewContextMenuInfo) item.getMenuInfo();
// handle menu item here
}

ViewHolder

       
       
1
2
3
4
5
6
       
       
class MyViewHolder extends RecyclerView.View.ViewHolder {
...
private void onLongClick() {
itemView.showContextMenu();
}
}

getChildAt is null

使用下面两个方法代替

       
       
1
2
3
4
5
       
       
//1
findViewHolderForAdapterPosition
//2
View viewItem = recycleView.getLayoutManager().findViewByPosition(position);
View icon = viewItem.findViewById(R.id.view);

notifyitemchanged方法会回到顶部

当点击某个item的时候,RecyclerView回到顶部.
解决办法。使用setHasFixedSize(true)方法。

下面是RecyclerView单选点击实现:

       
       
1
2
3
4
5
       
       
categories.get(lastPosition).setSelected( false);
categoryAdapter.notifyItemChanged(lastPosition);
categories.get(position).setSelected( true);
categoryAdapter.notifyItemChanged(position);
lastPosition=position;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值