可拖动、可滑动的组件===》RecyclerView

本文介绍如何使用RecyclerView实现可拖动和滑动删除的组件功能。通过分析严振杰的demo,简化代码,理解其工作原理。文中会展示主要代码,并提供关键类的实现,如ItemTouchHelper和自定义Adapter。最后,将分享完整的项目代码供读者参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近因为项目需要所以碰到了一个需要重新排序的ListView布局,然后就去网上找了一个严振杰(noHttp的作者)写的一个demo,运行成功之后就去看代码,看了半天感觉代码的可读性很差,本来很简单的事被他封装了好几层实现,所以我就开始研究了代码了。

实际上这个可交换item位置也可以滑动删除的控件是用RecyclerView实现的。下面就给大家从代码开始分析一下实现原理。

这个RecyclerView用Studio开发的童鞋们呢就直接依赖下就好了  具体怎么使用我就不跟大家细说了  我就开始捞干货说了啊。首先看主程序的布局,很简单,我为了让大家能够看到RecyclerView我上下放了两个TextView。代码就不贴了  太占篇幅了。最后我会把我的代码分享给大家,希望大家可以看完文章。

先看效果↓

看主Activity代码,我直接贴上代码,注释我已经写的很清楚了

/**
 * @author 宋鑫
 * Created by admin on 2017/1/3.
 * 主界面
 * 布局很简单
 */
public class MainActivity extends AppCompatActivity  implements StartDragListener{
    private RecyclerView myrecycler;
    private ItemTouchHelper touchHelper;//这个就是RecyclerView实现拖动和滑动的帮助类
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /**
         * 制造点假数据
         */
        List<User> list = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            User u = new User();
            u.setName("用户"+i);
            u.setPhone("1324044535"+i);
            u.setAddress("丰台科技园"+i+"号楼");
            list.add(u);
        }
        myrecycler = (RecyclerView) findViewById(R.id.myRecycler);//实例化组件
        myrecycler.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));//设置布局管理器,我设置的是纵向的LinearLyaout
        MyrecyclerAdapter adapter = new MyrecyclerAdapter(list,this);//实例化适配器
        myrecycler.setAdapter(adapter);
        touchHelper = new ItemTouchHelper(new RecyclerViewCallback(adapter));//这里大家可能不知道传入的参数是什么,再这个类里面我会注释
        touchHelper.attachToRecyclerView(myrecycler);//将事件绑定导RecyclerView上
    }
    @Override
    public void onStartDrag(RecyclerView.ViewHolder view) {//这个方法主要是为了将拖动事件绑定给某一个控件上
        touchHelper.startDrag(view);
    }
}

看完之后是不是有两个类不认识?ItemTouchHelperand MyrecyclerAdapter

那么其它的先不要管,先去看看这个!首先是ItemTouchHelper这个类是google粑粑给的,所以已经封装好了很多东西。大家用空可以去看看源码....(太多了我就不分析了),看着ItemTochHelper类跟Recycler绑定之前需要一个callback,就是一个回掉,就是说你拖动了,滑动了,告诉谁啊?所以我就去new了一个类来实现这个itemTochHelper.callback。贴上我的代码↓

/**
 * @author 宋鑫
 * Created by admin on 2017/1/3.
 * RecyclerView监听回调类
 */
public class RecyclerViewCallback extends ItemTouchHelper.Callback {
    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        //判断时候需要监听哪些动作
        /**
         * 000001 ItemTouchHelper.UP
         * 000010 ItemTouchHelper.DOWN
         * 000100 ItemTouchHelper.LEFT
         * 001000 ItemTouchHelper.RIGHT
         * 001111 上面四个的合成版
         */
        int dragfalgs = ItemTouchHelper.UP | ItemTouchHelper.DOWN;//上下拖动  如果是这两个的话结果就为000011
        int swiped = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;//左右滑动 如果是这两个的话结果就为001100
        return makeMovementFlags(dragfalgs, swiped);//调用方法来判断当前的操作是什么
    }
    /**
     * 拖动完的回调方法
     */
    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        
        return true;
    }
    /**
     * 滑动完的回调方法
     *
     * @param viewHolder
     * @param direction
     */
    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
         
    }
    /**
     * 是否允许拖动
     * @return 为true是允许RecyclerView可以拖动
     */
    @Override
    public boolean isLongPressDragEnabled() {
         //返回true允许拖动  false不允许拖动
        return true;
    }
}
通过以上代码大家应该能看明白,我们只需要在 isLongPressDragEnabled方法处返回true就可以上下拖动位置,但是大家可以试试拖动的效果,相信看完之后就会想到下一步了,因为你拖动完之后没有停到所在的位置。那么我们需要在 onMove方法中干啥呢?对,我们需要刷新数据和刷新界面。好的,我们回到主Activity中,大家看到我在实例化ItemTochhelper的时候还把适配器传进去了,其实我需要的并不是适配器,而是一个回调接口。因为需要刷新适配器的数据,所以RecyclerView的适配器就实现了这个接口,看看这个接口里有什么。看代码↓

/**
 * Created by admin on 2017/1/3.
 * 宋鑫
 */
public interface itemTochHerlper {
    boolean onItemMove(int startIndex,int endIndex);//拖动完成之后刷新的方法
    void onItemSwiped(int position);//左右滑动之后刷新的方法
}

那么我们再去Adapter中看看,RecyclerView的适配器我相信应该不用给大家说了吧?过多的代码我就不贴了,主要看实现接口的方法吧

/**
 * 上下拖动之后刷新
 * @param startIndex 被拖动的item的位置
 * @param endIndex  最终目标位置
 * @return
 */
@Override
public boolean onItemMove(int startIndex, int endIndex) {
    Collections.swap(list,startIndex,endIndex);//交换集合中的位置
    notifyItemMoved(startIndex,endIndex);//只刷新这两个位置的视图
    return false;
}
/**
 * 左右滑动之后刷新
 * @param position 被滑动item的位置
 */
@Override
public void onItemSwiped(int position) {
    list.remove(position);
    notifyItemRemoved(position);
}
刚才还说了一下,有一个功能是对item里面的某一个组件,添加可拖动事件,需要在adapter的 onBindViewHolder 里面实现,请看↓

@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
    holder.tv_name.setText(list.get(position).getName());
    holder.tv_phone.setText(list.get(position).getPhone());
    holder.tv_address.setText(list.get(position).getAddress());
    /**
     * 给holder的tv1绑定拖动事件
     * 按住tv_name就可以拖动整个item进行移动
     */
    holder.tv_name.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            startCallback.onStartDrag(holder);
            return true;
        }
    });
}

	这个startCallback也是一个回调接口,主要是为了能够调到主Activity里面的ItemTochHelper实例。看接口↓
/**
 * @author 宋鑫
 * 这个接口主要是为了监听某一个组件的Touch事件的
 */
public interface StartDragListener {
  void onStartDrag(RecyclerView.ViewHolder view);
}
然后在Adapter的构造器中实例一个接口
private  List<User> list;
private StartDragListener startCallback;

public MyrecyclerAdapter( List<User> list,StartDragListener startCallback){
    this.list = list;
    this.startCallback = startCallback;
}
好了,讲到这里基本原理就全讲完了,代码在这里===》
	本人的文采不是很好啊,写的不好的地方还需要大家来指正,谢谢支持。微笑






评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值