仿网易栏目添加功能

在qq群里面发现一个小伙伴有需要做类似于网易新闻客户端栏目拖拽添加的这种效果,特意做了类似效果,效果图如下(文章结尾有源码链接):

实现了点击、长按删除、添加等功能。其实就是利用RecycleViewItemTouchHelper这两个类来实现上面的效果

好了,内容正式开始……

1、添加依赖包

(app)build.gradle

implementation 'com.android.support:recyclerview-v7:26.1.0'

2、实现布局

首先,在drawable文件夹下新建tv_bg.xml文件作为样式文件。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <stroke android:width="1dp" android:color="#aaa"/>

    <solid android:color="#eee"/>

    <corners android:radius="5dp"/>

</shape>

矩形的shape,stoke为边框,solid为背景色,corners为圆角矩形的半径。

其次在layout文件夹下新建item.xml(Recycleview的Item布局)和tv.xml文件(文字效果),具体代码参详源码

3、加载数据

在MainActivity中的onCreate方法中初始化数据initData()方法加载默认数据

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mRecycleSelected = (RecyclerView) findViewById(R.id.recycle_selected);
    mRecycleUnSelected = (RecyclerView) findViewById(R.id.recycle_unselected);
    mFinishedText = (TextView) findViewById(R.id.tv_finish);

    initData();
    initView();
    initEvent();
}

initView()主要为RecycleView设置LayoutManager以及分割线的功能

4、RecycleViewAdapter的实现

使用过RecycleView的小伙伴都知道,RecyleView自身没有回调接口,需要我们为其添加,供外部调用,由于SelectedRecycleAdapter和UnSelectedRecycleAdapter代码类似,就只分析SelectedRecycleAdapter这个类了

public class SelectedRecycleAdapter extends RecyclerView.Adapter<SelectedRecycleAdapter.MyViewHolder>
        implements ItemTouchHelperCallback.OnItemPositionChangeListener {

    private List<String> mDatas;
    private MainActivity mContext;

    public interface OnItemClickListener {
        void onItemClickListener(MyViewHolder viewHolder, int pos);

        void onItemLongClickListener(MyViewHolder viewHolder, int pos);
    }

    public interface OnDeleteIconClickListener {
        void onDeleteIconClick(int pos);
    }

    private OnItemClickListener mListener;
    private OnDeleteIconClickListener mDeleteListener;

    public void setOnItemClickListener(OnItemClickListener listener) {
        this.mListener = listener;
    }

    public void setOnDeleteIconClickListener(OnDeleteIconClickListener listener) {
        mDeleteListener = listener;
    }

    public SelectedRecycleAdapter(Context context, List<String> datas) {
        mDatas = datas;
        mContext = (MainActivity) context;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(mContext).inflate(R.layout.item, parent, false);
        MyViewHolder viewHolder = new MyViewHolder(itemView);

        return viewHolder;
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {
        holder.tv.setText(mDatas.get(position));

        if (mContext.isDeleteIconsShow()) {
            holder.ivDelete.setVisibility(View.VISIBLE);
        } else {
            holder.ivDelete.setVisibility(View.INVISIBLE);
        }

        holder.ivDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mDeleteListener != null) {
                    mDeleteListener.onDeleteIconClick(holder.getLayoutPosition());
                }
            }
        });

        if (mListener != null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mListener.onItemClickListener(holder, position);
                }
            });

            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    mListener.onItemLongClickListener(holder, position);
                    return false;
                }
            });
        }

    }

    @Override
    public int getItemCount() {
        return mDatas.size();
    }

    //根据用户的手势,交换Adapter数据集中item的位置
    @Override
    public boolean onItemMove(int fromPos, int toPos) {
        Collections.swap(mDatas, fromPos, toPos);
        notifyItemMoved(fromPos, toPos);
        return true;
    }

    public void addData(String data, int pos) {
        mDatas.add(pos, data);
        notifyItemInserted(pos);
    }

    public void removeData(int pos) {
        mDatas.remove(pos);

        notifyDataSetChanged();
        notifyItemRemoved(pos);
    }

    class MyViewHolder extends RecyclerView.ViewHolder {
        TextView tv;
        ImageView ivDelete;

        public MyViewHolder(View itemView) {
            super(itemView);

            tv = (TextView) itemView.findViewById(R.id.tv);
            ivDelete = (ImageView) itemView.findViewById(R.id.delelte);
        }
    }
}

在这个类中我定义了一个接口,OnItemClickListener来实现点击和长按的监听效果。

然后在MainActivity中的initEvent()方法实现该接口

mSelectedAdatper.setOnItemClickListener(new SelectedRecycleAdapter.OnItemClickListener() {
    @Override
    public void onItemClickListener(SelectedRecycleAdapter.MyViewHolder viewHolder, int pos) {
        if (!isDeleteIconsShow) {
            Toast.makeText(MainActivity.this, mSelectedDatas.get(pos), Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onItemLongClickListener(SelectedRecycleAdapter.MyViewHolder viewHolder, int pos) {
        if (!isDeleteIconsShow) {
            showAllDeleteIcons();

            mFinishedText.setVisibility(View.VISIBLE);
        }
    }
});

代码比较简单那么到此为止就结束了,诶,别走啊你拖拽功能还没有说怎么实现呢?

5、ItemTouchHelper

还记得上面我所说的一个类吗?ItemTouchHelper对,没错就是这个,根据官方说明如下:

/**
 * This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.
 * <p>
 * It works with a RecyclerView and a Callback class, which configures what type of interactions
 * are enabled and also receives events when user performs these actions.
 * <p>
 * Depending on which functionality you support, you should override
 * {@link Callback#onMove(RecyclerView, ViewHolder, ViewHolder)} and / or
 * {@link Callback#onSwiped(ViewHolder, int)}.
 * <p>
 * This class is designed to work with any LayoutManager but for certain situations, it can be
 * optimized for your custom LayoutManager by extending methods in the
 * {@link ItemTouchHelper.Callback} class or implementing {@link ItemTouchHelper.ViewDropHandler}
 * interface in your LayoutManager.
 * <p>
 * By default, ItemTouchHelper moves the items' translateX/Y properties to reposition them. You can
 * customize these behaviors by overriding {@link Callback#onChildDraw(Canvas, RecyclerView,
 * ViewHolder, float, float, int, boolean)}
 * or {@link Callback#onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int,
 * boolean)}.
 * <p/>
 * Most of the time you only need to override <code>onChildDraw</code>.
 */

大体说的就是:ItemTouchHelper是一个工具类,为RecyclerView提供拖拽、滑动的支持。并且有一个Callback回调类用于处理用户的action操作

在ItemTouchHelperCallback中的结构图中我们可以看到以下的一些方法

在此类中我们自定义一个Listener让SelectedRecycleAdapter实现该监听方法,这样我们就根据用户的拖动的手势改变数据位置了。

//根据用户的手势,交换Adapter数据集中item的位置
@Override
public boolean onItemMove(int fromPos, int toPos) {
    Collections.swap(mDatas, fromPos, toPos);
    notifyItemMoved(fromPos, toPos);
    return true;
}

6、源码下载地址:

https://github.com/GHpeter/DragRecycleView,觉得不错的小伙伴给个star或关注一下吧。

原文发布于微信公众号 - 猿份到(sparkcliff)

原文发表时间:2018-02-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏向治洪

Android侧滑删除另一种实现,SwipeListView补充

前不久在在做聊天删除功能的时候使用SwipeListView进行侧滑删除有一点小问题,因为SwipeListView嵌套在Fragment内的时候,会报一个转换...

1809
来自专栏分享达人秀

StackView实现卡片堆叠如此简单

上一期学习了AdapterViewFilpper的使用,你已经掌握了吗?本期开始学习同系列的StackView控件的使用方法。 一、认识StackView ...

18510
来自专栏分享达人秀

自定义BaseAdapter

在ListView的使用中,有时候还需要在里面加入按钮等控件,实现单独的操作。也就是说,这个ListView不再只是展示数据,也不仅仅是这一行要来处理用...

1968
来自专栏分享达人秀

RecyclerView点击事件处理

前面两期学习了RecyclerView的简单使用,并为其item添加了分割线。在实际运用中,无论是List还是Grid效果,基本都会伴随着一些点击操作,...

1929
来自专栏向治洪

achartengine之折线图

问题在文章的最后,大致说来就是折线图,如果点的个数大于3个的时候,不是所有的点都显示对应的值的,这是为什么呢,本来以为是小问题,但两天了还没找到原因) 将前...

18310
来自专栏pangguoming

Android利用V4包中的SwipeRefreshLayout实现上拉加载

基本原理 上拉加载或者说滚动到底部时自动加载,都是通过判断是否滚动到了ListView或者其他View的底部,然后触发相应的操作,这里我们以 ListView来...

3059
来自专栏编程之路

羊皮书APP(Android版)开发系列(七)Android沉浸通知栏

543
来自专栏向治洪

RecyclerView 实现gallery画廊效果

1、RecyclerView的基本用法 首先主Activity的布局文件: <RelativeLayout xmlns:android="http://sc...

2645
来自专栏Jack的Android之旅

高仿网易严选底部弹出菜单

在网易严选的看东西的时候在商品详情页里看到他的底部弹出菜单,本能反应是想用DottomSheetDialog或者PopupWindow来实现,可是发现实现不了他...

752
来自专栏开发之途

Android 为图片添加水印

1264

扫描关注云+社区