博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
仿CSDN客户端首页(二)----拖拽排序Tabs的实现
阅读量:7166 次
发布时间:2019-06-29

本文共 6500 字,大约阅读时间需要 21 分钟。

上一篇博客用TabLayout实现了类似CSDN客户端首页选项卡的滑动效果:

然后发现了CSDN首页拖拽排序效果,先上自己完成的效果图:
这里写图片描述
这里是在之前的基础上进行修改的:点击右侧的箭头,出现Tabs的列表,按住Item右侧图标,可以进行上下拖动,进行排序,排序以后再次点击箭头,首页Tabs顺序也会改变;点击列表的某一个Item,会跳转到对应的界面。整体上效果还是和CSDN客户端很像的。

OK,一起看看怎么实现的吧。

1.界面布局:

主界面还是延续之前的TabLayout+ViewPager来实现的,右侧用的一个checkbox来控制视图的显示与隐藏。

2.主界面代码实现:

recyclerview = (RecyclerView) view.findViewById(R.id.sorts_recyclerview);        if (type == TABS) {            sortTxt.setVisibility(View.VISIBLE);            sortView.setVisibility(View.VISIBLE);            txt.setVisibility(View.GONE);            recyclerview.setVisibility(View.VISIBLE);            initSortViews();        } else {            sortTxt.setVisibility(View.GONE);            sortView.setVisibility(View.GONE);            txt.setVisibility(View.VISIBLE);            recyclerview.setVisibility(View.GONE);        }    }    //加载排序布局    private void initSortViews() {        adapter = new TabsAdapter(getActivity(), this);        adapter.setListener(new TabsAdapter.onItemClickListener() {            @Override            public void onItemClick(int position) {                Event item = new Event(position);                EventBus.getDefault().post(item);            }        });        LinearLayoutManager manger = new LinearLayoutManager(getActivity());        recyclerview.setLayoutManager(manger);        recyclerview.setAdapter(adapter);        }

这里复用的是同一个Fragment,根据传递过来的参数,显示不同的界面。

可参考:

当点击checkbox跳转过来的时候,传递一个不一样的参数,显示recyclerview。然后就是适配器的代码。

3.recyclerview的点击事件:

这里的处理我之前有一篇博客说的很详细:

这种接口回调的方式本质就是为了拿到被点击item的position,在Fragment获取到position以后,我们需要在Activity里面根据position进行切换界面的操作。activity与fragment的通信,我用的是Eventbus来进行处理的:

@Subscribe    public void onEventMainThread(Event item) {        viewpager.setCurrentItem(item.getPosition());    }

目的就是在Activity中让viewpager切换到指定的位置

4.recyclerview的拖拽排序事件

这里使用了RecyclerView的ItemTouchHelper类来实现了Item的拖动和删除功能,ItemTouchHelper是v7包下的一个类,专门用来配合RecyclerView实现滑动删除和拖拽功能的类。我们看看怎么使用。

public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
private onMoveAndSwipedListener mAdapter; public SimpleItemTouchHelperCallback(onMoveAndSwipedListener listener) { mAdapter = listener; } /** * 这个方法是用来设置我们拖动的方向以及侧滑的方向的 */ @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { //如果是ListView样式的RecyclerView //设置拖拽方向为上下 final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; //将方向参数设置进去 return makeMovementFlags(dragFlags, 0); } /** * 当我们拖动item时会回调此方法 */ @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { //如果两个item不是一个类型的,我们让他不可以拖拽 if (viewHolder.getItemViewType() != target.getItemViewType()) { return false; } //回调adapter中的onItemMove方法 mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return true; } /** * 当我们侧滑item时会回调此方法 */ @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { }

(1)自定义一个类继承实现ItemTouchHelper.Callback接口,实现里面的三个方法,分别是设置拖动与侧滑的方向,拖动时回调的方法,侧滑时回调的方法。

我这里没有进行侧滑的处理,所以将 makeMovementFlags(dragFlags, swipeFlags)中第二个参数设置为0,表示不进行侧滑操作。
(2)如果我们设置了非0的dragFlags ,那么当item被拖拽的时候会不断的回调onMove方法,所以我们需要同时Adapter做出相应的改变,对mItems数据做出交换的操作,因此我们需要一个回调接口来继续回调Adapter中的方法。

public interface onMoveAndSwipedListener {    boolean onItemMove(int fromPosition , int toPosition);}

我们让TabsAdapter实现此接口,并且重写里面的方法

public class TabsAdapter extends RecyclerView.Adapter
implements onMoveAndSwipedListener {
}

重写拖动的方法,其实就是交换集合中指定元素的位置:

@Override    public boolean onItemMove(int fromPosition, int toPosition) {        //交换mItems数据的位置        Collections.swap(TabLayoutActivity.tabTitle, fromPosition, toPosition);        //交换RecyclerView列表中item的位置        notifyItemMoved(fromPosition, toPosition);        return true;    }

再回到我们的SimpleItemTouchHelperCallback,在构造方法中将实现了onMoveAndSwipedListener接口的TabsAdapter 传进来。然后我们就在onMove()方法里获取当前拖拽的item和已经被拖拽到所处位置的item的ViewHolder,有了这2个ViewHolder,我们就可以拿到对应的position,然后调用传递过来的adapter中的onItemMove方法,这样adapter就会进行改变。

(3)这样recyclerview的拖拽就实现了,我们希望拖拽的Item在拖拽的过程中背景颜色加深,这样就需要继续重写下面两个方法:

/**当状态改变时回调此方法*/  @Override    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {            viewHolder.itemView.setBackgroundColor(Color.LTGRAY);        }        super.onSelectedChanged(viewHolder, actionState);    } /**当用户拖拽完或者侧滑完一个item时回调此方法,用来清除施加在item上的一些状态*/    @Override    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {        super.clearView(recyclerView, viewHolder);        viewHolder.itemView.setBackgroundColor(0);    }

(4)我们要是希望拖动右侧图标也可以进行拖拽,那么我们需要实现ItemTouchHelper的StartDrag(ViewHolder viewHolder)方法。

现在问题就是取得按住图标时对应的viewholder就行,其实这个实现方法和获取点击item的position一样,接口回调即可实现。

tabViewHolder.imgs.setOnTouchListener(new View.OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                //如果按下                if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {                    //回调RecyclerListFragment中的startDrag方法                    //让mItemTouchHelper执行拖拽操作                    dragListener.startDrag(holder);                }                return false;            }        });

拿到holder以后,让fragment实现这个接口里的方法,进行操作即可。

5.fragment的相关代码:

public class TabLayoutFragment extends Fragment implements TabsAdapter.onStartDragListener {
}

实现拖动图标时候拖拽事件的接口

//关联ItemTouchHelper和RecyclerView        ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter);        mItemTouchHelper = new ItemTouchHelper(callback);        mItemTouchHelper.attachToRecyclerView(recyclerview);

然后就是关联我们的ItemTouchHelper和RecyclerView,并且记得在实现方法里面加上操作:

@Override    public void startDrag(RecyclerView.ViewHolder viewHolder) {        mItemTouchHelper.startDrag(viewHolder);    }

6.activity的相应代码:

为了演示效果,我这里使用的是一个静态集合,所以在fragment排序以后,数据顺序已经改变,我要做的就是在点击checkbox的时候,通知activity的tablayout的标题进行改变。

adapter.setTabTitle(tabTitle);     tab.setupWithViewPager(viewpager);

其实就是重新设置了一下标题,并进行关联。可以看到,还是达到了预期效果。

过几天试着模仿类似网易和微博那种tabs的添加,删除,排序等效果,今天就到这里,收工~~~

你可能感兴趣的文章
2019-06-11 Java学习日记之Bootstrap
查看>>
解决apache 443端口被占用
查看>>
PHP中PDO错误/异常(PDOException)处理
查看>>
中国科学院大学生创新实践训练计划-
查看>>
洛谷——P1294 高手去散步
查看>>
python正则表达式
查看>>
Blob写入文件
查看>>
Again Stone Game
查看>>
MySQL 5.7.9修改root密码以及新特性
查看>>
HTML5 —— 属性
查看>>
Oracle Alter Table Modify列语句
查看>>
CentOS7+CDH5.14.0安装全流程记录,图文详解全程实测-3禁止交换和禁用大页面
查看>>
php测试题整理(0519)
查看>>
winform下重画ListBox
查看>>
洛谷 P1439【模板】最长公共子序列
查看>>
String 总结
查看>>
构造函数
查看>>
openstack 网络
查看>>
安装配置
查看>>
RabbitMQ用户管理
查看>>