乐趣区

关于android:Android-RecyclerView的使用

Android RecyclerView 的应用

一:RecyclerView 是什么
从 Android5.0 开始,谷歌推出一个用于大量数据展现的新控件 RecyclerView, 能够代替传统的 ListView, 更加弱小和灵便。
在 AndroidX 我的项目中增加依赖:implementation ‘androidx.recyclerview:recyclerview:1.1.0’
在非 AndroidX 我的项目中增加依赖:implementation ‘com.android.support:recyclerview-v7:26.1.0’// 对应的是 compileSdkVersion 的版本

//Android 布局应用
<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
    
    //AndroidX 布局应用
    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

RecyclerView 的长处
1. 反对部分刷新
2. 能够自定义 Item 增删时的动画
3. 可能实现 Item 拖拽和侧滑删除等性能
二:RecyclerView 应用

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/tv_recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

1. 创立布局管理器
LinearLayoutManager: 线性布局,以垂直或程度滚动形式显示列表
GridLayoutManager: 网格布局,在网格中显示我的项目
StaggeredGridLayoutManager:瀑布流布局,在扩散对齐网格中显示我的项目

LinearLayoutManager layoutManager=new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);// 线性布局管理器

  GridLayoutManager gridLayoutManager=new GridLayoutManager(this,3);// 网格布局管理器
  
  StaggeredGridLayoutManager staggeredGridLayoutManager=new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);// 瀑布流布局
  

2. 适配器应用

public class MyRecycleViewAdapter extends RecyclerView.Adapter<MyRecycleViewAdapter.MyHolder> {
    private List<String> mDatas;// 数据源
    private Context context;
    
      private OnItemClickListener onItemClickListener;
    /** 向内部提供调用设置监听 */
    public void setOnItemClickListener(OnItemClickListener onItemClickListener){this.onItemClickListener=onItemClickListener;}

    public MyRecycleViewAdapter(Context context,List<String> mDatas) {
        this.context=context;
        this.mDatas = mDatas;
    }

    /**
     * 创立 ViewHolder 并返回,后续 item 布局里控件都是从 ViewHolder 中取出
     */

    @NonNull
    @Override
    public MyHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // 将咱们自定义的 item 布局转成 View
        View view = LayoutInflater.from(context).inflate(R.layout.item_one, parent, false);
        // 将 View 传递给咱们自定义 ViewHolder
        return new MyHolder(view);
    }
    /** 通过办法提供的 ViewHolder, 将数据绑定到的 ViewHolder 中 */

    @Override
    public void onBindViewHolder(@NonNull MyHolder holder, int position) {holder.tv_content.setText(mDatas.get(position));
        
         holder.tv_content.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {if (onItemClickListener!=null){onItemClickListener.onItemClick(v,holder.getAdapterPosition()+1);
                }
            }
        });


    }

    /**
     * 获取数据源总的条目
     */
    @Override
    public int getItemCount() {return mDatas.size();
    }

   static class MyHolder extends RecyclerView.ViewHolder {
        TextView tv_content;

        public MyHolder(@NonNull View itemView) {super(itemView);
            tv_content=itemView.findViewById(R.id.tv_content);
        }
    }
    
     /** 自定义的接口 */
    public interface OnItemClickListener{void onItemClick(View view,int position);
    }
}

RecyclerView 封装了 viewholder 的回收复用,标准化了 ViewHolder,编写 Adapter 面向的是 ViewHolder 而不是 View, 复用的逻辑封装了
创立适配器步骤:
1. 创立 Adapter:创立一个继承 RecyclerView.Adapter<VH> 的 Adapter 类(VH 是 ViewHolder 的类名)
2. 创立 ViewHolder:在 Adapter 中创立一个继承 RecyclerView.ViewHolder 的动态外部类,记为 VH。ViewHolder 的实现和 ListView 的 ViewHolder 实现简直一样。
三个办法:
onCreateViewHolder:创立 ViewHolder 并返回,后续 item 布局里控件都是从 ViewHolder 中取出。
onBindViewHolder:通过办法提供的 ViewHolder,将数据绑定到 ViewHolder 中。
getItemCount:获取数据源总的条数。
下面 2 个适配器和布局管理器是必须设置的

3.Item Decoration(可选)设置分割线

 // 增加分割线
        tv_recycler.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL));// 默认的分割线
        

能够自定义距离款式须要继承 RecyclerView.ItemDecoration 类,该类是抽象类

public class MyItemDecoration extends RecyclerView.ItemDecoration {
    private final Drawable mLine;
    private final int orientation;
    public MyItemDecoration(Context context, int orientation) {
        this.orientation = orientation;
        int[] attrs = new int[]{android.R.attr.listDivider};// 零碎的分割线色彩
        TypedArray a = context.obtainStyledAttributes(attrs);
        mLine = a.getDrawable(0);
        a.recycle();}

    /** 在 Item 绘制之前被调用,用于绘制距离款式 */
    @Override
    public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {super.onDraw(c, parent, state);
        if (orientation==RecyclerView.HORIZONTAL){drawVertical(c, parent, state);
        }else if (orientation==RecyclerView.VERTICAL){drawHorizontal(c, parent, state);
        }
    }
    /**onDraw 和 onDrawOver2 个其中一个就行 */

    @Override
    public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {super.onDrawOver(c, parent, state);
    }
    /** 设置 item 的偏移量,偏移的局部用于填充距离款式,即设置分割线的宽、高;在 RecyclerView 的 onMesure()中会调用该办法。*/

    @Override
    public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {super.getItemOffsets(outRect, view, parent, state);
        if (orientation == RecyclerView.HORIZONTAL) {
            // 画垂直线
            outRect.set(0, 0, mLine.getIntrinsicWidth(), 0);
        } else if (orientation == RecyclerView.VERTICAL) {
            // 画水平线
            outRect.set(0, 0, 0, mLine.getIntrinsicHeight());
        }
    }

    /**
     * 画垂直分割线
     */
    private void drawVertical(Canvas c, RecyclerView parent, RecyclerView.State state) {int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {View child = parent.getChildAt(i);
            int left = child.getRight();
            int top = child.getTop();
            int right = left + mLine.getIntrinsicWidth();
            int bottom = child.getBottom();
            mLine.setBounds(left, top, right, bottom);
            mLine.draw(c);
        }
    }


    /**
     * 画程度分割线
     */
    private void drawHorizontal(Canvas c, RecyclerView parent, RecyclerView.State state) {int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {View child = parent.getChildAt(i);
            int left = child.getLeft();
            int top = child.getBottom();
            int right = child.getRight();
            int bottom = top + mLine.getIntrinsicHeight();
            mLine.setBounds(left, top, right, bottom);
            mLine.draw(c);
        }
    }

}

咱们能够批改零碎自定义分割线色彩
在 res 下 values 下 theme 主题中
<!– 自定义零碎分割线色彩 –>
<item name=”android:listDivider”>@drawable/customizelistdivider </item>
在 res/drawable 中设置 customizelistdivider

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient
        android:endColor="#ff0000ff"
        android:startColor="#ffff0000"
        android:type="linear" />
    <size android:height="4dp"
        android:width="4dp"/>
</shape>


应用设置自定义分割线
tv_recycler.addItemDecoration(new MyItemDecoration(this,RecyclerView.VERTICAL));

4.ItemAnimator 动画(可选)
tv_recycler.setItemAnimator(new DefaultItemAnimator());// 设置默认动画
默认动画继承 DefaultItemAnimator 来实现自定义动画

相干实现

public class SecondActivity extends AppCompatActivity {
    private RecyclerView tv_recycler;
    private MyRecycleViewAdapter myRecycleViewAdapter;
    private List<String> mDatas=new ArrayList<>();
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        initData();// 初始化数据
        tv_recycler=findViewById(R.id.tv_recycler);
        // 创立布局管理器
        LinearLayoutManager layoutManager=new LinearLayoutManager(this);// 默认垂直排列
        //GridLayoutManager gridLayoutManager=new GridLayoutManager(this,3);
        //StaggeredGridLayoutManager staggeredGridLayoutManager=new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
        layoutManager.setOrientation(RecyclerView.HORIZONTAL);// 设置程度排列
        //LinearLayoutManager layoutManager1=new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
        // 设置布局管理器
        tv_recycler.setLayoutManager(layoutManager);
        // 增加分割线
        tv_recycler.addItemDecoration(new MyItemDecoration(this,RecyclerView.VERTICAL));// 自定义分割线
        tv_recycler.setItemAnimator(new DefaultItemAnimator());
        //tv_recycler.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL));// 默认的分割线
        // 创立数据适配器
        myRecycleViewAdapter=new MyRecycleViewAdapter(this,mDatas);
        // 设置数据适配器
        tv_recycler.setAdapter(myRecycleViewAdapter);
        // 内部适配器数据监听条目点击
        myRecycleViewAdapter.setOnItemClickListener(new MyRecycleViewAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {Toast.makeText(SecondActivity.this, "第"+position+"条数据", Toast.LENGTH_SHORT).show();}
        });
    }

    private void initData() {for (int i=0;i<40;i++){mDatas.add("我是 item"+i);
        }
    }
}

5.Item 条目监听,点击事件监听

  /** 向内部提供调用设置监听 */
    public void setOnItemClickListener(OnItemClickListener onItemClickListener){this.onItemClickListener=onItemClickListener;}

    public MyRecycleViewAdapter(Context context,List<String> mDatas) {
        this.context=context;
        this.mDatas = mDatas;
    }

   /** 自定义的接口 */
    public interface OnItemClickListener{void onItemClick(View view,int position);
    }
    
        @Override
    public void onBindViewHolder(@NonNull MyHolder holder, int position) {holder.tv_content.setText(mDatas.get(position));
        
         holder.tv_content.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {if (onItemClickListener!=null){onItemClickListener.onItemClick(v,holder.getAdapterPosition()+1);// 在绑定数据的时候给内部传递得 postion 从 1 开始
                }
            }
        });


    }
    
    // 内部调用开始
    myRecycleViewAdapter.setOnItemClickListener(new MyRecycleViewAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {Toast.makeText(SecondActivity.this, "第"+position+"条数据", Toast.LENGTH_SHORT).show();}
        });

END: 只愿年过半百,归来仍是少年

退出移动版