Android使用CardView作为RecyclerView的Item并实现拖拽和左滑删除

引言

CardView是Android 5.0系统之后引入的众多控件之一,实现之后的效果也是比较酷的,它经常被用在RecyclerView和ListView中的Item中。今天我们就来了解一下CardView的属性,然后使用CardView和RecyclerView结合实现一个可以拖拽Item的布局。

CardView的属性

CardView继承自FrameLayout,所以子控件的布局规则和FrameLayout的一样,是按照层次堆叠的

下面是CardView的一些常用属性:

CardView的基本使用

先看一下效果:

这是一个CardView,多个罗列起来看起啦会更酷,好了,我们先看一下代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:orientation="vertical" android:paddingTop="10dp"
  android:layout_width="match_parent" android:layout_height="wrap_content">

  <android.support.v7.widget.CardView
    android:layout_width="match_parent" android:layout_height="60dp"
    android:layout_marginLeft="10dp" android:layout_marginRight="10dp"
    app:contentPaddingLeft="20dp" app:cardBackgroundColor="@color/colorPrimary"
    app:cardCornerRadius="5dp" app:cardElevation="5dp"
    android:layout_marginBottom="10dp"
    app:cardPreventCornerOverlap="true">
    <LinearLayout
      android:layout_width="match_parent" android:layout_height="match_parent"
      android:orientation="horizontal" android:gravity="center_vertical">
      <!--左侧图片-->
      <ImageView
        android:layout_width="50dp" android:layout_height="50dp"
        android:src="@mipmap/ic_launcher"/>
      <LinearLayout
        android:layout_width="match_parent" android:layout_height="match_parent"
        android:orientation="vertical" android:layout_marginLeft="10dp"
        android:gravity="center_vertical">
        <!--姓名-->
        <TextView
          android:id="@+id/txt_name" android:layout_width="wrap_content"
          android:layout_height="wrap_content" android:textSize="16sp"
          android:textColor="@android:color/white" android:text="王二"/>
        <!--描述-->
        <TextView
          android:id="@+id/txt_describe" android:layout_width="wrap_content"
          android:layout_height="wrap_content" android:layout_marginTop="5dp"
          android:textSize="12sp" android:textColor="@android:color/darker_gray"
          android:text="一个很厉害的人"/>
      </LinearLayout>
    </LinearLayout>
  </android.support.v7.widget.CardView>
</LinearLayout>

看完了布局文件,是不是觉得这个布局不仅炫酷而且使用简单,下面我们把它应用到RecyclerView中,看起来会更炫酷。

CardView应用在RecyclerView中

CardView通常会应用在RecyclerView和ListView中,今天我们就讲一讲如何应用在RecyclerView中。我们现在在大多数应用或者手机系统界面中会见到这样的效果:

是不是觉得很棒,下面我们就用CardView和RecyclerView来实现一下这个效果。

布局文件

我们实现这个效果的第一步是先添加依赖库:

implementation 'com.android.support:recyclerview-v7:26.+'
implementation 'com.android.support:cardview-v7:26.+'

然后写一下布局文件,Item的布局文件我就直接采用上面的代码了,然后再写一个主界面的布局文件,比较简单,如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical" android:paddingTop="10dp"
  tools:context="com.jyx.demo.myapplication.MainActivity">

  <android.support.v7.widget.RecyclerView
    android:id="@+id/my_recyclerView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

</LinearLayout>

Activity内代码

public class MainActivity extends AppCompatActivity {
  private RecyclerView mRecyclerView;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mRecyclerView = (RecyclerView) findViewById(R.id.my_recyclerView);
    //设置LayoutManager
    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
    linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    mRecyclerView.setLayoutManager(linearLayoutManager);

    //绑定adapter
    MyAdapter myAdapter = new MyAdapter(this);
    mRecyclerView.setAdapter(myAdapter);  

  }
  //adapter
  class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

    LayoutInflater mInflater;
    List<MData> mList = addData();

    public MyAdapter(Context context) {
      mInflater = LayoutInflater.from(context);
    }

    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
      View view = mInflater.inflate(R.layout.item_my_recyclerview,parent,false);
      ViewHolder viewHolder = new ViewHolder(view);
      return viewHolder;
    }

    @Override
    public void onBindViewHolder(MyAdapter.ViewHolder holder, int position) {
      holder.mName.setText(mList.get(position).getUserName());
      holder.mDescribe.setText(mList.get(position).getDescription());
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {
      private TextView mName;
      private TextView mDescribe;
      public ViewHolder(View itemView) {
        super(itemView);
        mName = itemView.findViewById(R.id.txt_name);
        mDescribe = itemView.findViewById(R.id.txt_describe);
      }
    }
  }
  //制造一个数据源
  private class MData{
    String userName;
    String description;

    public String getUserName() {
      return userName;
    }

    public void setUserName(String userName) {
      this.userName = userName;
    }

    public String getDescription() {
      return description;
    }

    public void setDescription(String description) {
      this.description = description;
    }
  }
  private List<MData> addData(){
    List<MData> list = new ArrayList();

    MData mData = new MData();
    mData.setUserName("王二");
    mData.setDescription("一个很厉害的人");
    list.add(mData);

    mData = new MData();
    mData.setUserName("张三");
    mData.setDescription("呵呵");
    list.add(mData);

    mData = new MData();
    mData.setUserName("李四");
    mData.setDescription("嘻嘻");
    list.add(mData);

    mData = new MData();
    mData.setUserName("赵一");
    mData.setDescription("呵呵");
    list.add(mData);

    mData = new MData();
    mData.setUserName("钱多");
    mData.setDescription("地主家的傻儿子");
    list.add(mData);
    return list;
  }
}

好了,这就是一个没有任何效果的列表界面,我一看一下效果:

ItemTouchHelper

想实现拖拽和滑动删除的效果,很可惜RecyclerView并没有提供现成的API供我们使用,但是SDK为我们提供了ItemTouchHelper这样一个工具类帮助我们来轻松实现这些功能,我们先来了解一下ItemTouchHelper。官方文档是这样介绍的:

This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.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.Depending on which functionality you support, you should override onMove(RecyclerView, ViewHolder, ViewHolder) and / or onSwiped(ViewHolder, int).

大致意思就是,这是个工具类,可以实拖拽移动和策划删除,使用这个工具需要RecyclerView和Callback。同时需要重写onMove()和onSwiped()方法。接下来就讲讲如何使用ItemTouchHlper。

1.新建一个接口,并且让Adapter实现

我们选择使用一个接口来实现Adapter和ItemTouchHelper之间涉及数据的操作,因为ItemTouchHelper完成触摸的各种动画以后,就要对Adapter的数据进行操作,比如我们在侧滑删除以后,最后需要调用Adapter的notifyItemRemove()方法来移除该数据。所以我们可以把数据操作的部分抽象成一个接口方法,让Callbac调用它即可。具体如下:

新建一个接口:

ItemTouchHelperAdapter

public interface ItemTouchHelperAdapter {
  //移动item
  public void onItemMove(int fromPosition,int toPosition);
  //删除item
  public void onItemDelete(int position);
}

之后让Adapter实现这个接口

class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements ItemTouchHelperAdapter{

    LayoutInflater mInflater;
    List<MData> mList = addData();

    public MyAdapter(Context context) {
      mInflater = LayoutInflater.from(context);
    }

    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
      View view = mInflater.inflate(R.layout.item_my_recyclerview,parent,false);
      ViewHolder viewHolder = new ViewHolder(view);
      return viewHolder;
    }

    @Override
    public void onBindViewHolder(MyAdapter.ViewHolder holder, int position) {
      holder.mName.setText(mList.get(position).getUserName());
      holder.mDescribe.setText(mList.get(position).getDescription());
    }

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

    @Override
    public void onItemMove(int fromPosition, int toPosition) {
      //交换位置
      Collections.swap(mList,fromPosition,toPosition);
      notifyItemMoved(fromPosition,toPosition);
    }

    @Override
    public void onItemDelete(int position) {
      //移除数据
      mList.remove(position);
      notifyItemRemoved(position);
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
      private TextView mName;
      private TextView mDescribe;
      public ViewHolder(View itemView) {
        super(itemView);
        mName = itemView.findViewById(R.id.txt_name);
        mDescribe = itemView.findViewById(R.id.txt_describe);
      }
    }
  }

接下来我们直接在Callback中直接调用接口里的方法就可以了。

2.新建Callback方法,继承ItemTouchHelper.Callback

官方文档已经告诉我们,使用ItemTouchHelper需要一个Callback,这个Callback是ItemTouchHelper.Callback的子类,我们需要新建一个类来继承ItemTouchHelper.Callback,然后重写一些方法来实现我们的需求。代码如下:

public class myItemTouchHelperCallBack extends ItemTouchHelper.Callback{
  private ItemTouchHelperAdapter itemTouchHelperAdapter;

  public myItemTouchHelperCallBack(ItemTouchHelperAdapter itemTouchHelperAdapter) {
    this.itemTouchHelperAdapter = itemTouchHelperAdapter;
  }

  @Override
  public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    //允许上下拖动
    int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
    //允许从右向左滑动
    int swipeFlags = ItemTouchHelper.LEFT;
    return makeMovementFlags(dragFlags,swipeFlags);
  }

  @Override
  public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    //onItemMove接口里的方法
    itemTouchHelperAdapter.onItemMove(viewHolder.getAdapterPosition(),target.getAdapterPosition());
    return true;
  }

  @Override
  public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
    //onItemDelete接口里的方法
    itemTouchHelperAdapter.onItemDelete(viewHolder.getAdapterPosition());
  }

  @Override
  public boolean isLongPressDragEnabled() {
    //该方法返回值为true时,表示支持长按ItemView拖动
    return true;
  }

  @Override
  public boolean isItemViewSwipeEnabled() {
    //该方法返回true时,表示如果用户触摸并且左滑了view,那么可以执行滑动删除操作,就是可以调用onSwiped()方法
    return true;
  }
}

ItemTouchHelper.Callback还有其他几个常用方法:

  1. public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState):从静止状态变为拖拽或者滑动的时候会调用该方法,参数actionState表示当前状态。
  2. public void clearView(RecyclerView recyclerView, ViewHolder viewHolder):当用户操作完某个item并且动画也结束后会调用该方法,一般我们在该方法内恢复ItemView的初始状态,防止由于复用而产生的错乱问题。
  3. public void onChildDraw(…):我们可以在这个方法内实现我们自定义的交互规则或者自定义动画。

这样下来我们就只剩下一步了。

3.为RecyclerView添加ItemTouchHelper

代码如下:

  ItemTouchHelper.Callback callback = new myItemTouchHelperCallBack(myAdapter);
  ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
  touchHelper.attachToRecyclerView(mRecyclerView);

这样,我们就实现了我们的需求,我们一起来看看效果:

好了,我们的需求完成了,效果是不是很炫酷,当然大家可以根据自己的需求做出更炫酷的效果,到时候别忘了与大家一起分享。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android自定义ListView实现仿QQ可拖拽列表功能

    我们大致的思路,其实是这样子的,也是我的设想,我们可以先去实现一个简单的ListView的数据,但是他的Adapter,我们可以用系统封装好的,然后传递进去一个实体类,最后自定义一个listview去操作,所以我们先把准备的工作做好,比如? list_item.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.a

  • Android仿QQ左滑删除置顶ListView操作

    最近闲来无事,于是研究了一下qq的左滑删除效果,尝试着实现了一下,先上效果图: 大致思路原理: - 通过设置margin实现菜单的显示与隐藏 - 监听onTouchEvent,处理滑动事件 上代码 import android.content.Context; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.MotionEvent; import android.v

  • Android DragVideo实现播放视频时任意拖拽的方法

    Android DragVideo实现播放视频时任意拖拽 DragVideo A Method to Drag the Video When Playing Video 一种在播放视频时,能够拖拽的方案 为什么有这个工程 经常在爱奇艺网站上看电影,看到如果滑动掩盖了播放窗口后,就后在最下面有一个小播放界面.并且这个播放界面,是可以任意拖拽的.感觉很酷 既然web端能实现,就想了想在移动端设备上,是否也能实现这个效果,于是就有了- 效果图: ------> 实现思路:1.播放视频的view选择Te

  • Android ListView实现仿iPhone实现左滑删除按钮的简单实例

    需要自定义ListView.这里就交FloatDelListView吧. 复写onTouchEvent方法.如下: @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN:<BR> // 获取按下的条目视图(child view) int childCount = getChildCount(); int[] listViewCo

  • Android实现让图片在屏幕上任意移动的方法(拖拽功能)

    本文实例讲述了Android实现让图片在屏幕上任意移动的方法.分享给大家供大家参考,具体如下: public class DragExampleActivity extends Activity { Bitmap mBitmap; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInst

  • Android使用PullToRefresh完成ListView下拉刷新和左滑删除功能

    ListView下刷新刷功能相信从事Android开发的猿友们并不陌生,包括现在Google亲儿子SwipeRefreshLayout实现效果在一些APP上也能看见(不过个人不喜欢官方的刷新效果).本文就带领一些刚入门android的朋友或者一起爱分享的朋友来简单的实现ListView的下拉刷新和左滑删除效果. 一.本文主要内容: 使用PullToRefresh完成ListView下拉.上拉刷新: 扩展PullToRefresh完美的实现ListView左滑删除效果: 注意:本文中的PullTo

  • android 大图片拖拽并缩放实现原理

    由于最近项目忙,博客一直没有时间更新,今天有点时间就连续更新两篇吧,过过瘾. 这篇图片拖拽缩放也是我在项目中用到的,今天整理一下,将源码奉献给大家,希望对大家以后碰到相似的问题有帮助. 这篇就不做过多介绍了,直接上源码: 复制代码 代码如下: public class SpacePageActivity extends Activity { private LinearLayout linnerLayout_spacepage; private RelativeLayout relativeLa

  • Android仿QQ列表左滑删除操作

    最近学习了如何做一个像QQ的左滑RecyclerView的item显示选项的,主要是用到Scroller 我们首先新建一个自己的RecyclerView 定义好一些要用的的变量 重写构造方法,把前两个构造方法改为如下,使无论如何构造都要执行第三个构造方法 在第三个构造方法里初始化Scroller public class LeftSwipeMenuRecyclerView extends RecyclerView { //置顶按钮 private TextView tvTop; //删除按钮 p

  • android ListView和GridView拖拽移位实现代码

    关于ListView拖拽移动位置,想必大家并不陌生,比较不错的软件都用到如此功能了.如:搜狐,网易,百度等,但是相比来说还是百度的用户体验较好,不偏心了,下面看几个示例:             首先说一下:拖拽ListView的item就不应该可以任意移动,只应该在ListView所在的范围内,而网易的你看看我都可以移动到状态栏了,虽然你做了处理,但是用户体验我个人感觉不好,在看看百度的,不仅控制了移动范围,更不错的百度的移动起来会时时的换位,看起来相当的形象,所以我认为这样相当的棒.说明一点

  • Android自定义组合控件之自定义下拉刷新和左滑删除实例代码

    绪论 最近项目里面用到了下拉刷新和左滑删除,网上找了找并没有可以用的,有比较好的左滑删除,但是并没有和下拉刷新上拉加载结合到一起,要不就是一些比较水的结合,并不能在项目里面使用,小编一着急自己组合了一个,做完了和QQ的对比了一下,并没有太大区别,今天分享给大家,其实并不难,但是不知道为什么网上没有比较好的Demo,当你的项目真的很急的时候,又没有比较好的Demo,那么"那条友谊的小船儿真是说翻就翻啊",好了,下面先来具体看一下实现后的效果吧: 代码已经上传到Github上了,小伙伴们记

  • Android自定义可拖拽的悬浮按钮DragFloatingActionButton

    悬浮按钮FloatingActionButton是Android 5.0系统添加的新控件,FloatingActionButton是继承至ImageView,所以FloatingActionButton拥有ImageView的所有属性.本文讲解的是一个实现了可拖拽的悬浮按钮,并为此添加了类似于qq的吸附边框的功能.在此之前,先了解下其简单的使用方式吧: 首先你得添加其依赖 compile 'com.android.support:design:25.3.1' 然后在布局文件中使用. <andro

随机推荐