Android RecycleView的item用法示例详解
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>RecyclerView 的主要特点</li><li>子项的点击事件和长按点击事件</li><li>ItemTouchHelper</li><li>子项的删除事件</li><ul class="second_class_ul"><li>子项删除事件的动画效果</li></ul><li>子项的拖动事件</li><ul class="second_class_ul"></ul></ul></div><blockquote><p><strong>RecyclerView</strong> 是 Android 提供的一个强大的列表控件,用来显示大量数据。</p></blockquote><p class="maodian"></p><h2>RecyclerView 的主要特点</h2>
<p><strong>1. 高性能的视图复用机制</strong></p>
<p>Recycle就是循环的意思,那么recycleview的特点也很鲜明了,它只会创建出在屏幕内和一定缓存的itemview,当view滑出屏幕时,不会销毁重建,而是复用旧的view,可以极高的提高性能;</p>
<p><strong>2. 高度可定制</strong></p>
<p>可以添加分割线、动画、拖拽、滑动删除;</p>
<p><strong>3. 支持多种布局</strong></p>
<p>支持线性、网格、瀑布流等布局实现;</p>
<p class="maodian"></p><h2>子项的点击事件和长按点击事件</h2>
<p>总体思路:因为我们在适配器的<code>viewholder</code>中可以拿到每个子项的<code>view</code>的,此时可以设置监听调用<code>Onclick</code>方法或者<code>OnLongClick</code>方法,然后通过接口回调的方式在<code>RecycleView</code>中设置回调的逻辑处理;</p>
<p>那么为什么要通过接口回调的方式呢?是因为适配器的任务就是绑定数据后显示<code>UI</code>,它不应该决定点击事件后的逻辑处理,所以在适配器中实现子项的监听,但是真正的实现我们放到<code>Activity</code>或者<code>Fragment</code>中,这样有利于解耦;</p>
<p>接下来看看具体的实现:</p>
<p>在适配器中:</p>
<div class="jb51code"><pre class="brush:java;">private OnItemClickListener onItemClickListener;
public interface OnItemClickListener{
void onItemClick(cityadapt cityadapt,int position);
void onItemLongClick(cityadapt cityadapt,int position);
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener){
this.onItemClickListener = onItemClickListener;
}
//实现接口,使得调用适配器中的Onclick的方法,然后再进行接口回调
public class cityviewholder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
public cityviewholder(@NonNull View itemView) {
super(itemView);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View view) {
if(onItemClickListener!= null){
onItemClickListener.onItemClick(cityadapt.this,getAdapterPosition());
}
}
@Override
public boolean onLongClick(View view) {
return true;
}
}</pre></div>
<p>在实现类中</p>
<div class="jb51code"><pre class="brush:java;">cityadapt1.setOnItemClickListener(new cityadapt.OnItemClickListener() {
@Override
public void onItemClick(cityadapt cityadapt, int position) {
viewPager2.setCurrentItem(position,true);
}
@Override
public void onItemLongClick(cityadapt cityadapt, int position) {
}
});</pre></div>
<p>在进行子项的删除和拖动的学习之前,得先了解一个类:<code>ItemTouchHelper</code></p>
<p class="maodian"></p><h2>ItemTouchHelper</h2>
<ul><li><code>ItemTouchHelper</code> 是 Android 官方提供的一个 <strong>RecyclerView 辅助类</strong>。</li><li>它通过 <strong>监听手势事件</strong>,帮助我们轻松实现:</li><li>Item 拖动(上下或左右移动)</li><li>Item 滑动(左滑/右滑删除,或执行其他操作)</li><li>不需要自己去写复杂的手势检测逻辑。</li></ul>
<p>我理解的本质也是接口回调,我们只定义接口的实现,然后作为构造方法的参数传入<code>ItemTouchHelper</code>的实例中,最后与RecycleView绑定;</p>
<p>在这里我们定义回调后的实现,比如允许滑动的方向等等;</p>
<div class="jb51code"><pre class="brush:java;">ItemTouchHelper.Callback callback = new ItemTouchHelper.Callback() {
}</pre></div>
<p>然后通过<code>ItemTouchHelper</code>的实例传入,使得后续做出自定义的逻辑判断和反应等;</p>
<div class="jb51code"><pre class="brush:java;">ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);</pre></div>
<p>最后通过<code>attachToRecyclerView</code>与recycleview绑定,<code>binding.recyCity</code>是recycleview的实例;</p>
<div class="jb51code"><pre class="brush:java;">itemTouchHelper.attachToRecyclerView(binding.recyCity);</pre></div>
<p>在<code>ItemTouchHelper.Callback</code>中有必须实现的三个抽象方法:</p>
<ul><li><code>getMovementFlags()</code>:用来指定支持的拖拽和滑动方向</li><li><code>onMove()</code>:拖拽时回调(交换两个 item 的位置)</li><li><code>onSwiped()</code>:侧滑时回调(比如删除 item)</li></ul>
<p>在本模块中介绍一下`getMovementFlags()</p>
<div class="jb51code"><pre class="brush:java;">//规定可以滑动的方向
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
int position = viewHolder.getAdapterPosition();
if(position == 0){
return 0;
}
int ver = 0;
int hor = ItemTouchHelper.LEFT;
return makeMovementFlags(ver,hor);
}</pre></div>
<ul><li>最后返回一个方法<code>makeMovementFlags(ver,hor)</code>,参数有两个,第一个是关于允许上下滑动或拖拽的,第二个是关于上下的;</li></ul>
<div class="jb51code"><pre class="brush:java;">int position = viewHolder.getAdapterPosition();
if(position == 0){
return 0;
}</pre></div>
<p>这里这么写得到当前滑动或者拖动的位置,如果这个是recycleview中第一个的话,就返回0,意味着不允许滑动或者拖拽;</p>
<ul><li><code>ItemTouchHelper.LEFT</code>: <code>ItemTouchHelper.LEFT</code> 是 <code>ItemTouchHelper</code> 里定义的一个<strong>常量</strong>,代表滑动(swipe)时允许的方向之一;</li></ul>
<p>剩余的其他:</p>
<p>ItemTouchHelper.UP // 向上拖动</p>
<p>ItemTouchHelper.DOWN // 向下拖动</p>
<p>ItemTouchHelper.LEFT // 向左滑动</p>
<p>ItemTouchHelper.RIGHT // 向右滑动</p>
<p class="maodian"></p><h2>子项的删除事件</h2>
<p>在<code>ItemTouchHelper</code>的基础上,我们还需重写一个方法:</p>
<div class="jb51code"><pre class="brush:java;">//是否允许滑动移除
@Override
public boolean isItemViewSwipeEnabled() {
return true;
}</pre></div>
<p>然后在<code>ItemTouchHelper</code>中的<code>onSwiped</code>方法内规定逻辑;</p>
<div class="jb51code"><pre class="brush:java;"> //规定左滑后的逻辑
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
int i = viewHolder.getAdapterPosition();
if(i != 0){
cityadapt1.getData().remove(i);
cityadapt1.notifyItemRemoved(i);
// MainActivity.deleteFragment(i);
addtomainweather.deleteFragment(i);
}
}</pre></div>
<p>里面有三个方法:</p>
<ul><li><code>cityadapt1.getData().remove(i)</code> : 把适配器中持有的数据源里对应的 item 移除;</li><li><code>cityadapt1.notifyItemRemoved(i)</code>:触发删除的动画;</li><li><code>addtomainweather.deleteFragment(i)</code>:通过接口回调的方式,自定义实现删除的逻辑;</li></ul>
<p>当然我们也可以定义删除的动画</p>
<p class="maodian"></p><h3>子项删除事件的动画效果</h3>
<p>代码如下:</p>
<div class="jb51code"><pre class="brush:java;">public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE){
View view = viewHolder.itemView;
Paint paint = new Paint();
paint.setColor(Color.WHITE);
if(dX < 0){
c.drawRect((float) view.getRight()+dX,(float) view.getTop(),(float) view.getRight(),(float) view.getBottom(),paint);
Bitmap icon = BitmapFactory.decodeResource(recyclerView.getContext().getResources(),R.drawable.deletecity);
int iconmargin =( view.getHeight() - icon.getHeight())/2;
int top = view.getTop()+iconmargin;
int bottom = top + icon.getHeight();
int left = view.getRight() - iconmargin - icon.getWidth();
int right =view.getRight() - iconmargin;
c.drawBitmap(icon,null,new Rect(left,top,right,bottom),null);
}
}
}</pre></div>
<p>这个方法是 <code>ItemTouchHelper.Callback</code> 提供的 <strong>onChildDraw</strong>,用来在 <strong>拖动/滑动时绘制额外的 UI 效果</strong>(比如背景、按钮、图标;</p>
<p>先看看这个方法对应的参数:</p>
<p><code>@NonNull Canvas c</code>, // 画布</p>
<p><code>@NonNull RecyclerView recyclerView</code>, // 当前的 RecyclerView</p>
<p><code>@NonNull RecyclerView.ViewHolder viewHolder</code>, // 当前正在交互的 item</p>
<p><code>float dX,</code> // X 方向的位移</p>
<p><code>float dY, </code> // Y 方向的位移</p>
<p><code>int actionState,</code> // 当前手势状态(滑动/拖动)</p>
<p><code>boolean isCurrentlyActive </code> // 手指是否还在按住 item</p>
<p>代码中的部分说明:</p>
<p><code>actionState == ItemTouchHelper.ACTION_STATE_SWIPE</code>是如果手势是滑动的话;</p>
<p>其他的滑动:</p>
<ul><li><code>ItemTouchHelper.ACTION_STATE_IDLE</code> → 没有操作</li><li><code>ItemTouchHelper.ACTION_STATE_DRAG</code> → 拖动中</li></ul>
<p><code>View view = viewHolder.itemView</code>;获得当前的item;</p>
<p><code>c.drawRect((float) view.getRight()+dX,(float) view.getTop(),(float) view.getRight(),(float) view.getBottom(),paint);</code> :里面有五个参数,分别是规定滑动后矩形的左边界,矩形的上边界,矩形的右边界,矩形的下边界,以及绘制的颜色/样式;</p>
<p><code>Bitmap icon = BitmapFactory.decodeResource(recyclerView.getContext().getResources(),R.drawable.deletecity);``recyclerView.getContext().getResources()</code>,得到文件资源管理器,得到对应的图片等;<br /><code>BitmapFactory.decodeResource(Resources res, int id)</code>,<code>BitmapFactory</code>是一个解码工具类,这个方法会读取资源文件,并转成内存中的 <strong>Bitmap 对象</strong>;</p>
<p><code>c.drawBitmap(icon,null,new Rect(left,top,right,bottom),null);</code>四个参数分别代表:设置到画布上的bitmap对象,源区域(null代表设置整张图片),以及你要放置的位置,设置透明度等;</p>
<p class="maodian"></p><h2>子项的拖动事件</h2>
<p>重写此方法:</p>
<div class="jb51code"><pre class="brush:java;">//是否允许长按拖拽
@Override
public boolean isLongPressDragEnabled() {
return true;
}</pre></div>
<p>此处跟删除的逻辑差不多,解释放在注释中,可自行观看;</p>
<div class="jb51code"><pre class="brush:java;"> @Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
//返回当前正在拖动的适配器中的数据索引
int i = viewHolder.getAdapterPosition();
//返回目标适配器中的数据索引
int j = target.getAdapterPosition();
//把适配器中持有的数据源里对应的 item 交换;
Collections.swap(cityadapt1.getData(),i,j);
//刷新item移动动画
cityadapt1.notifyItemMoved(i,j);
addtomainweather.swapFragment(i,j);
return true;
}</pre></div>
<p>这样我们就可以实现子项的点击事件,删除,拖动啦;</p>
<p>到此这篇关于Android RecycleView的item用法的文章就介绍到这了,更多相关Android RecycleView item用法内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
<div class="art_xg">
<b>您可能感兴趣的文章:</b><ul><li>Android RecycleView实现Item拖拽效果</li><li>Android使用RecycleView实现拖拽交换item位置</li><li>Android 中RecycleView实现item的点击事件</li><li>Android实现Recycleview悬浮粘性头部外加右侧字母导航</li><li>Android中RecycleView与ViewPager冲突的解决方法及原理</li><li>Android使用NestedScrollView 内嵌RecycleView滑动冲突问题解决</li></ul>
</div>
</div>
<!--endmain-->
頁:
[1]