项目实践-RecyclerView(一)

前言

因为是项目实践,所以不是面面俱到的学习RecyclerView。本文的书写逻辑就是:先说说最简单的使用一个RecyclerView,然后就来实现我要的功能。

一.上手一个最简单的RecyclerView

项目实践-RecyclerView(一)
RecyclerView的实现方式:

  1. 在想要RecyclerView的地方声明一个RecyclerView
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        
        图+字
        <ImageView/>
        <TextView/>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/card_item_folder_RecyclerView"
            android:layout_marginTop="15dp"
            android:layout_marginBottom="10dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/card_item_folder_img"/>

		下方的按钮
        <LinearLayout> 
        </LinearLayout>

    </RelativeLayout>
</android.support.v7.widget.CardView>
  1. 设置RecyclerView的子项布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/card_item_text"
        android:text="hello"
        android:textSize="18dp"
        android:layout_marginLeft="30dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>
  1. 创建RecyclerView的item Class
public class Card_Recycler_item {
    String title;

    public Card_Recycler_item(String title) {
        this.title = title;
    }

    public String getTitle() {return title;}

    public void setTitle(String title) { this.title = title;}
}

  1. 创建RecyclerView的适配器
/**
 * 卡片里的列表
 * 这个列表的item项只有一个标题
 */
public class Card_Recycler_adapter extends RecyclerView.Adapter<Card_Recycler_adapter.ViewHolder> {
    ArrayList<Card_Recycler_item> items = new ArrayList<>();


    public Card_Recycler_adapter(ArrayList<Card_Recycler_item> items) {
        this.items = items;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_item, viewGroup, false);
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {
        Card_Recycler_item item = items.get(i);
        viewHolder.textView.setText(item.getTitle());

    }

    @Override
    public int getItemCount() {
        return items.size() >= 5 ? 5 : items.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView textView;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.card_item_text);
        }
    }
}

  1. 在要用RecyclerView的Fragment/Acytiviy中使用RecyclerView
        RecyclerView recyclerView = view.findViewById(R.id.card_item_folder_RecyclerView);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity(), 
        			LinearLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(linearLayoutManager);
        initItems();
        adapter = new Card_Recycler_adapter(items);
        recyclerView.setAdapter(adapter);

二.长按拖拽功能

2.1 样式设计

项目实践-RecyclerView(一)
添加分割线

        recyclerView.setAdapter(adapter);
        recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL));

2.2 响应拖拽和侧滑事件

参考文章

2.2.1 简单的ItemTouchHelper使用

上面那篇参考文章,以及一系列其他的文章都说了要使用ItemTouchHelper。我却完全不懂它是什么。
官方API文档
☆基本的ItemTouchHelper示例-泡网翻译

  • 它是什么?
    它就是Google为了帮助你完成RecyclerView的滑动和拖拽而制作的工具类。它就是干这个的!之前还以为他是处理Touch响应的类,只是功能强大,顺便来这里帮下手。其实完全不是,就是名字起得大,啧啧。

This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.

  • 怎么用?
    Callback类配置哪些交互是允许的,这需要一个类getMovementFlags,相应的,滑动和拖拽分别需要两个类onMoveonSwiped

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.
.它需要配合一个RecyclerViewCallback类工作。Callback用来配置哪些交互被允许的,并接受这些交互事件
Depending on which functionality you support, you should override onMove(RecyclerView, ViewHolder, ViewHolder) and / or onSwiped(ViewHolder, int).
.
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 ItemTouchHelper.Callback class or implementing ItemTouchHelper.ViewDropHandler interface in your LayoutManager.
项目实践-RecyclerView(一)

public class Card_Recycler_Callback extends ItemTouchHelper.Callback {
	//解耦设计:因为滑动和移除涉及到数据交换,抽象出方法,然后让RecyclerAdapter实现这个抽象。
	//其实我不是特别理解怎么想到的,这个又是什么思想,但是的确非常好用。这方面的思想应该在哪里能系统的学习到呢?
    private final ItemTouchHelperAdapter mAdapter;  

    public Card_Recycler_Callback(ItemTouchHelperAdapter mAdapter) {
        this.mAdapter = mAdapter;
    }
    @Override
    public int getMovementFlags(){...}

    @Override
    public boolean onMove(){
	    mAdapter.onItemMove(viewHolder.getAdapterPosition(),
	         viewHolder1.getAdapterPosition());
    }

    @Override
    public void onSwiped(){...}

    @Override
    public boolean isLongPressDragEnabled() {
        return true;
    }

    @Override
    public boolean isItemViewSwipeEnabled() {
        return true;
    }
}
public class Card_Recycler_adapter extends RecyclerView.Adapter<Card_Recycler_adapter.ViewHolder> 
		implements ItemTouchHelperAdapter {
public interface ItemTouchHelperAdapter {

    void onItemMove(int fromPosition, int toPosition);
    
    //这个是对应滑动方法,你想要滑动打开就写滑动打开的方法,想要滑动删除就写删除的方法。
    void onItemDismiss(int position);
}

最后,在Activity/Fragment中使用

		//这个adapter就是RecyclerAdapter
        ItemTouchHelper.Callback callback = new Card_Recycler_Callback(adapter);
        ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
        touchHelper.attachToRecyclerView(recyclerView);

2.2.2 实践反馈 - 长按效果

这个长按如果能出现升高行为,以提示用户可以进行拖拽会比较好。
拖拽的时候能覆盖其他地方,不产生重叠比较好。
参考-看他的效果图
项目实践-RecyclerView(一)

在callback中

   //设置滑动item的背景
    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
        //判断选中状态
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
            viewHolder.itemView.setBackgroundColor
            	(viewHolder.itemView.getContext().getResources().getColor(R.color.grey_300));
    }
        super.onSelectedChanged(viewHolder, actionState);

    }

    //清除滑动item的背景
    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        // 恢复
        viewHolder.itemView.setBackgroundColor(Color.WHITE);
        super.clearView(recyclerView, viewHolder);
    }