额,关于RecyclerView就不过多的解释了,大家应该都比较了解它了,鸿洋博客有比较详细的解释:Android RecyclerView 使用完全解析 体验艺术般的控件。写本篇博客的目的就是,自己在学习的过程中想要实现该功能,想做个笔记哈,所以就有了本篇博客喽~
我们知道无论是RecyclerView还是ListView都需要item的,额……这个布局实在没什么可说的,毕竟每个人的item都不相同嘛,如下的布局代码是模仿微信的,代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#ffffff"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@mipmap/ic_launcher" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="4dp">
<TextView
android:id="@+id/tv_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_weight="1"
android:text="李林雄"
android:textColor="#000000"
android:textSize="16dp" />
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="22:10"
android:textColor="#888888"
android:textSize="14dp" />
LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="4dp">
<TextView
android:id="@+id/tv_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:text="干嘛呢"
android:textColor="#888888"
android:textSize="14dp" />
LinearLayout>
LinearLayout>
LinearLayout>
LinearLayout>
有了item布局,我们就该有相对应的Bean啦,这个是必须的,Bean代码如下:
package com.example.lilinxiong.recycleviewdragdrop;
/**
* 项目名: RecycleViewDragDrop
* 包名: com.example.lilinxiong.recycleviewdragdrop
* 文件名: Bean
* 创建者: LLX
* 创建时间: 2017/3/28 17:22
* 描述: Bean
*/
public class Bean {
//名字
private String username;
//时间
private String time;
//消息内容
private String message;
//头像id
private int img_id;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getImg_id() {
return img_id;
}
public void setImg_id(int img_id) {
this.img_id = img_id;
}
}
package com.example.lilinxiong.recycleviewdragdrop;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
/**
* 项目名: RecycleViewDragDrop
* 包名: com.example.lilinxiong.recycleviewdragdrop
* 文件名: RecycleViewAdapter
* 创建者: LLX
* 创建时间: 2017/3/28 17:29
* 描述: RecyclerView适配器
*/
public class RecycleViewAdapter extends RecyclerView.Adapter.ViewHolder> {
//List数据
private List beanList;
public RecycleViewAdapter(List beanList) {
this.beanList = beanList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycleview_item, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Bean bean = beanList.get(position);
holder.iv_icon.setImageResource(bean.getImg_id());
holder.tv_username.setText(bean.getUsername());
holder.tv_time.setText(bean.getTime());
holder.tv_message.setText(bean.getMessage());
}
@Override
public int getItemCount() {
return beanList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
ImageView iv_icon;
TextView tv_username;
TextView tv_time;
TextView tv_message;
public ViewHolder(View view) {
super(view);
iv_icon = (ImageView) view.findViewById(R.id.iv_icon);
tv_username = (TextView) view.findViewById(R.id.tv_username);
tv_time = (TextView) view.findViewById(R.id.tv_time);
tv_message = (TextView) view.findViewById(R.id.tv_message);
}
}
}
万事具备,现在就来实现我们的拖拽排序,侧滑删除效果吧。我们先来捋一下逻辑哈!
使用一个RecyclerView这些条件是必不可少的,绑定id,数据和adapter初始化这些是必须的,layoutManager则是控制数据在RecyclerView如何显示的,然后接下来就是为RecyclerView设置layoutManager和设置adapter了。
最后一个就是实现拖拽排序、侧滑删除的关键了。嘿嘿,还是在代码中讲解吧,这样讲的话太空洞了,OK,代码如下:
package com.example.lilinxiong.recycleviewdragdrop;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private RecycleViewAdapter adapter;
private List beanList;
private LinearLayoutManager layoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化控件
initView();
//初始化数据
initData();
//初始化数据
private void initData() {
for (int i = 0; i < 20; i++) {
Bean bean = new Bean();
bean.setImg_id(R.mipmap.ic_launcher);
bean.setTime("2017-03-28");
bean.setMessage("今天我学习到了RecyclerView拖拽排序、RecyclerView侧滑删除");
bean.setUsername("李林雄");
beanList.add(bean);
}
adapter.notifyDataSetChanged();
}
//初始化控件
private void initView() {
//绑定id
mRecyclerView = (RecyclerView) findViewById(R.id.mRecyclerView);
//beanList初始化
beanList = new ArrayList<>();
//adapter初始化
adapter = new RecycleViewAdapter(beanList);
//layoutManager初始化
layoutManager = new LinearLayoutManager(this);
//RecyclerView设置layoutManager
mRecyclerView.setLayoutManager(layoutManager);
//RecyclerView绑定适配器
mRecyclerView.setAdapter(adapter);
}
}
如上代码就是使用RecyclerView所做的事儿了,若是想实现RecyclerView的拖拽排序、侧滑删除,则需要如下代码了,如下:
ItemTouchHelper helper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
//首先回调的方法 返回int表示是否监听该方向
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;//线性排列时监听到的为上下动作则为:拖拽排序
int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;//线性排列时监听到的为左右动作时则为:侧滑删除
return makeMovementFlags(dragFlags, swipeFlags);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
//滑动事件
//交换位置
Collections.swap(beanList, viewHolder.getAdapterPosition(), target.getAdapterPosition());
//刷新adapter
adapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return false;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
//侧滑事件
beanList.remove(viewHolder.getAdapterPosition());
//刷新adapter
adapter.notifyItemRemoved(viewHolder.getAdapterPosition());
}
@Override
public boolean isLongPressDragEnabled() {
//是否可拖拽
return true;
}
});
helper.attachToRecyclerView(mRecyclerView);
这段代码的逻辑就是,首先我监听现在的动作是什么,即!手指为上下移动还是左右移动,上下则去交换item的位置,左右移动则将该item的数据从list中remove,然后再刷新adapter就好了,上下为拖拽,那么我们就应该在isLongPressDragEnabled中返回true,即,允许拖拽!最后,设置下生效的RecyclerView就好了,即!helper.attachToRecyclerView()这句代码!大致逻辑就这样子了,其他的看下代码中的注释吧,我感觉挺清楚的了,嘿嘿!看下效果吧:
若是我们想要实现如下的效果呢:
嘿嘿,也就是表格的哈,有点儿丑,不要介意哈,毕竟实现效果就好了嘛,若想实现以上效果,改动的地方并不大,首先我们要将mRecyclerView.setLayoutManager();中的格式改为GridLayoutManager的,然后由于现在我们用不到右滑或者左滑删除了,那么我们ItemTouchHelper中的监听方向的方法也改一改啦,其他的不用更改,代码如下:
...
GridLayoutManager gridLayoutManager = new GridLayoutManager(MainActivity.this, 2);
//RecyclerView设置layoutManager
mRecyclerView.setLayoutManager(gridLayoutManager);
...
new GridLayoutManager(MainActivity.this, 2),该方法中需要传两个参数,第一个是,Context,第二个就是,每行显示几个item。
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
//首先回调的方法 返回int表示是否监听该方向
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
int swipeFlags = 0;
return makeMovementFlags(dragFlags, swipeFlags);
}
由于我们用不到swipeFlags则给它值为0就好了,OK,这样修改完后,上图的效果就实现啦!是不是很简单呢?
关于RecyclerView有很多博客的,比如鸿洋大神的为RecyclerView打造通用Adapter 让RecyclerView更加好用,当然还有开篇提到的那篇哈,关于RecyclerView几乎都包括了呢。
额,有一点,那个主布局的代码没有写,当然还有闭包哈,闭包就一句话“compile ‘com.android.support:recyclerview-v7:25.2.0’”,主布局就一个RecyclerView,没啥的,所以就不贴代码了哈,嘻嘻~
大家若是有什么不懂的,可以在下面评论区中留言哈,我看到后会回的,另外对android有兴趣的同学可以加我们程序员刘某人的群:555974449,群里面有很多大神的,而且很热情,很热心的,大家不懂的可以问的。
Demo下载