zoukankan      html  css  js  c++  java
  • RecyclerView实现拖动排序和滑动删除功能

    RecyclerView 的拖动排序需要借助一下 ItemTouchHelper 这个类,ItemTouchHelper 类是 Google 提供的一个支持 RecyclerView 滑动和拖动的一个使用类,下面使用该类实现 RecyclerView 的滑动删除和拖动排序功能。首先大概介绍一下 ItemTouchHelper 的一个内部抽象类 Callback 类。

    ItemTouchHelper.Callback

    该类是ItemTouchHelper类中的一个静态抽象类,作用主要是将ItemTouchHelper于自己的应用联系在一起,让开发者通过ViewHolder控制每一个View的具体行为,接收用户的事件回调。该类里面有三个抽象方法:getMovementFlags、onMove、onSwiped。也是开发中经常要是用的。

    getMovementFlags

    该方法返回一个Flags表示Item的三种状态状态:idle(空闲)、 swiping(滑动)、dragging(拖动),根据RecyclerView不同的布局管理器,设置不同的滑动、拖动方向,一般使用makeMovementFlags(int dragFlags, int swipeFlags)方法返回,dragFlags表示拖动的方向,swipeFlags表示滑动的方向。

    public abstract int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder);

    onMove

    当ItemTouchHelper拖动一个Item时该方法将会被回调,Item将从旧的位置移动到新的位置,如果不拖动这个方法将从来不会调用,返回true表示Item已经被移动到新的位置。

    public abstract boolean onMove(RecyclerView recyclerView, ViewHolder viewHolder, ViewHolder target);

    onSwiped

    当Item滑动的时候调用,如果不滑动该方法不会被调用,可通过direction做相应的判断执行某些操作。

    public abstract void onSwiped(ViewHolder viewHolder, int direction);

    此外经常使用的方法有 onSelectedChanged、clearView等方法。

    onSelectedChanged

    当item由静止状态变为滑动或拖动状态时调用此方法,可通过actionState判断Item在哪种状态下执行某些操作,重写该方法时必须调用其父类的该方法。

    public void onSelectedChanged(ViewHolder viewHolder, int actionState) {
            if (viewHolder != null) {
                sUICallback.onSelected(viewHolder.itemView);
            }
    }

    clearView

    当与用户交互结束或相关动画完成之后被 调用该方法被调用。

    public void clearView(RecyclerView recyclerView, ViewHolder viewHolder) {
            sUICallback.clearView(viewHolder.itemView);
    }

    RecyclerView实现拖动排序

    RecyclerView的拖动排序需要借助一个 android.support.v7.widget.helper.ItemTouchHelper 这个类来实现,拖动排序重点是在接口里面的 onMove(int fromPosition, int toPosition) 方法,其在GridAdapter中的具体实现参考如下:

    @Override
    public void onMove(int fromPosition, int toPosition) {
        if (fromPosition < toPosition) {
            for (int i = fromPosition; i < toPosition; i++) {
                Collections.swap(list, i, i + 1);
            }
        } else {
            for (int i = fromPosition; i > toPosition; i--) {
                Collections.swap(list, i, i - 1);
            }
        }
        notifyItemMoved(fromPosition, toPosition);
    }

    RecyclerView实现侧滑删除

    RecyclerView的拖动排序需要借助一个 android.support.v7.widget.helper.ItemTouchHelper 这个类来实现,侧滑删除重点是在接口中的 onSwiped(int position),其在GridAdapter中的具体实现参考如下:

    
        @Override
        public void onSwiped(int position) {
            Log.i("drag","onSwiped");
            list.remove(position);
            notifyItemRemoved(position);
        }

    参考代码

    ItemTouchHelper.Callback 的实现类

    /**
     * Created by jzman on 2017/5/17 0015.
     */
    public class ItemTouchCallBack extends ItemTouchHelper.Callback {
        private static final String TAG = "drag";
        private OnItemTouchListener onItemTouchListener;
    
        public void setOnItemTouchListener(OnItemTouchListener onItemTouchListener) {
            this.onItemTouchListener = onItemTouchListener;
        }
    
        /**
         * 根据 RecyclerView 不同的布局管理器,设置不同的滑动、拖动方向
         * 该方法使用 makeMovementFlags(int dragFlags, int swipeFlags) 方法返回
         * 参数: dragFlags:拖动的方向
         *      swipeFlags:滑动的方向
         * @param recyclerView
         * @param viewHolder
         * @return
         */
        @Override
        public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
            Log.i(TAG,"getMovementFlags");
            if (recyclerView.getLayoutManager() instanceof GridLayoutManager ||
                    recyclerView.getLayoutManager() instanceof StaggeredGridLayoutManager){
                //此处不需要进行滑动操作,可设置为除4和8之外的整数,这里设为0
                //不支持滑动
                return makeMovementFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN |
                                       ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT, 0 );
            }else {
                //如果是LinearLayoutManager则只能向上向下滑动,
                //此处第二个参数设置支持向右滑动
                return makeMovementFlags(ItemTouchHelper.UP   | ItemTouchHelper.DOWN , ItemTouchHelper.RIGHT );
            }
        }
    
        /**
         * 当 ItemTouchHelper 拖动一个Item时该方法将会被回调,Item将从旧的位置移动到新的位置
         * 如果不拖动这个方法将从来不会调用,返回true表示已经被移动到新的位置
         * @param recyclerView
         * @param viewHolder
         * @param target
         * @return
         */
        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
            Log.i(TAG,"onMove");
            int fromPosition = viewHolder.getAdapterPosition();
            int toPosition   = target.getAdapterPosition();
            onItemTouchListener.onMove(fromPosition,toPosition);
            return true;
        }
    
        /**
         * 当Item被滑动的时候被调用
         * 如果你不滑动这个方法将不会被调用
         * @param viewHolder
         * @param direction
         */
        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
            Log.i(TAG,"onSwiped");
            //此处是侧滑删除的主要代码
            int position = viewHolder.getAdapterPosition();
            onItemTouchListener.onSwiped(position);
        }
    
        /**
         * 当Item被滑动、拖动的时候被调用
         * @param viewHolder
         * @param actionState
         */
        @Override
        public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
            Log.i(TAG,"onSelectedChanged");
            //...
            super.onSelectedChanged(viewHolder, actionState);
        }
    
        /**
         * 当与用户交互结束或相关动画完成之后被调用
         * @param recyclerView
         * @param viewHolder
         */
        @Override
        public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
            Log.i(TAG,"clearView");
            //...
            super.clearView(recyclerView, viewHolder);
        }
    
        /**
         * 移动交换数据的更新监听
         */
        public interface OnItemTouchListener {
            //拖动Item时调用
            void onMove(int fromPosition, int toPosition);
            //滑动Item时调用
            void onSwiped(int position);
        }
    }
    

    Adapter的实现

    /**
     * Created by jzman on 2017/05/17 0009.
     * RecycleView的Adapter
     */
    public class GridAdapter extends RecyclerView.Adapter<GridAdapter.DataViewHolder> implements View.OnClickListener,ItemTouchCallBack.OnItemTouchListener {
        private Context context;
        private List<SimpleTitleGrid> list;
    
        public GridAdapter(Context context, List<SimpleTitleGrid> list) {
            this.context = context;
            this.list = list;
        }
    
        /**
         * 创建ViewHolder
         * @param parent
         * @param viewType
         * @return
         */
        @Override
        public DataViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            //加载item布局文件(每一个)
            View view = LayoutInflater.from(context).inflate(R.layout.item,null);
    
            //为View设置单击事件
            view.setOnClickListener(this);
            DataViewHolder viewHolder = new DataViewHolder(view);
    
            //使用代码设置宽高(xml布局设置无效时)
            view.setLayoutParams(new RecyclerView.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT));
            return viewHolder;
        }
    
        /**
         * 绑定数据
         * @param holder
         * @param position
         */
        @Override
        public void onBindViewHolder(DataViewHolder holder, int position) {
            //设置每一个Item的高度
            holder.textView.setText(list.get(position).getTitle());
        }
    
        /**
         * 选项总数
         * @return
         */
        @Override
        public int getItemCount() {
            return list.size();
        }
    
        /**
         * 单击事件
         * @param v
         */
        @Override
        public void onClick(View v) {
            if(onItemClickListener!=null){
                int position = recyclerView.getChildAdapterPosition(v);
                //程序执行到此,会执行该方法的具体实现
                onItemClickListener.onItemClick(recyclerView,v,position,list.get(position));
            }
        }
    
        @Override
        public void onMove(int fromPosition, int toPosition) {
            if (fromPosition < toPosition) {
                for (int i = fromPosition; i < toPosition; i++) {
                    Collections.swap(list, i, i + 1);
                }
            } else {
                for (int i = fromPosition; i > toPosition; i--) {
                    Collections.swap(list, i, i - 1);
                }
            }
            notifyItemMoved(fromPosition, toPosition);
        }
    
        @Override
        public void onSwiped(int position) {
            Log.i("drag","onSwiped");
            list.remove(position);
            notifyItemRemoved(position);
        }
    
        /**
         *  RecycleView中针对ViewHolder来实现
         */
        public static class DataViewHolder extends RecyclerView.ViewHolder {
            TextView textView;
            public DataViewHolder(View itemView) {
                super(itemView);
                textView = (TextView) itemView.findViewById(R.id.tv_grid);
            }
        }
        private RecyclerView recyclerView;
        private  OnItemClickListener onItemClickListener;
        public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
            this.onItemClickListener = onItemClickListener;
        }
        /**
         * 设计recycleView选项单击事件的回调接口(给外面使用)
         * 参考ListView选项单击事件方法
         */
        public interface OnItemClickListener{
            //参数(父组件,点击的View,位置,这里可能是某个对象的id或对象/这里不需要)
            void onItemClick(RecyclerView recyclerView, View view, int position, SimpleTitleGrid obj);
        }
        /**
         *   将RecycleView附加到Adapter上
         */
        @Override
        public void onAttachedToRecyclerView(RecyclerView recyclerView) {
            super.onAttachedToRecyclerView(recyclerView);
            this.recyclerView= recyclerView;
        }
        /**
         *   将RecycleView从Adapter解除
         */
        @Override
        public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
            super.onDetachedFromRecyclerView(recyclerView);
            this.recyclerView = null;
        }
    }

    MainActivity

    /**
     * Created by jzman on 2017/05/17 0029.
     * RecycleView的Adapter
     */
    public class MainActivity extends AppCompatActivity implements GridAdapter.OnItemClickListener{
        private RecyclerView rv_user;
        private GridAdapter adapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
        }
    
        private void initView() {
            rv_user = (RecyclerView) findViewById(R.id.rv_user);
            adapter = new GridAdapter(this, DataUtils.getUserGrids());
    
            ItemTouchCallBack touchCallBack = new ItemTouchCallBack();
            touchCallBack.setOnItemTouchListener(adapter);
            ItemTouchHelper itemTouchHelper = new ItemTouchHelper(touchCallBack);
    
            rv_user.setLayoutManager(new GridLayoutManager(this,3));
    //        rv_user.setLayoutManager(new LinearLayoutManager(this));
            rv_user.setAdapter(adapter);
            itemTouchHelper.attachToRecyclerView(rv_user);
    
            adapter.setOnItemClickListener(this);
        }
    
        @Override
        public void onItemClick(RecyclerView recyclerView, View view, int position, SimpleTitleGrid obj) {
            Toast.makeText(MainActivity.this, obj.getTitle(), Toast.LENGTH_SHORT).show();
        }
    }

    显示效果

    GridLayoutManager LinearLayoutManager
    image image

    可关注微信公众号:jzman-blog 获取最新文章更新,一起交流学习!

    这里写图片描述

  • 相关阅读:
    vbs习题
    spotlight监控工具使用
    vue 不同路由同一个组件 缓存问题
    iphone手机上3D动画transform:rotateY闪现一下或者不显示
    vue 单独引用sass文件
    cnpm安装 npm安装node-sass报错
    webpack 打包css时提示Unexpected character '@'
    window下npm启动报错This is probably not a problem with npm. There is likely additional logging output above.
    HBuilder 配置android模拟器
    windows 切换git远程仓库地址后 git push 提示Authentication failed
  • 原文地址:https://www.cnblogs.com/jzmanu/p/10284784.html
Copyright © 2011-2022 走看看