不知道早期的朋友还记不记得LIstView?GridView?是否忘记还是总是忘记复用(Viewholder)视图,而导致OOM ~
RecyclerVIew是跟着Android5.0而来的,谷歌将此控件放在了support-v7包下,它的产生更像是在封装ListView、GridView的基础之上进行了二次扩展 ~
相比早期的ListView、GridView,RecyclerView更加高级且灵活,提供了更为高效的回收复用机制,同时实现管理与视图的解耦 ~
关于RecyclerView有几个关键使用方法
LinearLayoutManager:核心方法,实现不同布局效果ItemDecoration:设置Item间的分割线(我还是习惯了以前的item内加View)ItemAnimator:设置Item的动画,Android提供默认动画(默认的一般够用了)我们常用的列表一般分为垂直效果、水平效果、网格效果和瀑布流效果 ~ 根据不同效果, 我们只需设置RecyclerView中不同的LayoutManager来实现不同的效果即可 !
线性布局:包含垂直列表、水平列表
LinearLayoutManager有俩种布局及垂直、水平 ~
//垂直列表 BasicAdapter verticalAdapter = new BasicAdapter(MainActivity.this, dataList); LinearLayoutManager verticalManager = new LinearLayoutManager(this); rvVertical.setLayoutManager(verticalManager); rvVertical.setAdapter(verticalAdapter); //水平列表 BasicAdapter horizontalAdapter = new BasicAdapter(MainActivity.this, dataList); LinearLayoutManager horizontalManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); rvHorizontal.setLayoutManager(horizontalManager); rvHorizontal.setAdapter(horizontalAdapter);网格布局:一般传入俩个参数,其一为上下文,其二则是每行展示的列数
/** * GridLayoutManager 不要帮网格布局设置展示方向!因为网格布局本身就是水平布局! * 如果你设置了类似layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);赶紧删掉...不然效果吓人 ~ * */ RecyclerView rvGrid = findViewById(R.id.rv_type2); BasicAdapter GridAdapter = new BasicAdapter(MainActivity.this, dataList); GridLayoutManager gridManager = new GridLayoutManager(this, 2); rvGrid.setLayoutManager(gridManager); rvGrid.setAdapter(GridAdapter);瀑布流布局:严格来讲其应该属于网络布局下的一种,但是又稍有不同,比较个性,对应的参数其实为每行的列数,其二为布局方向,一般有垂直和平行 ~
/** * StaggeredGridLayoutManager * */ RecyclerView rvStaggered = findViewById(R.id.rv_type3); BasicAdapter staggeredAdapter = new BasicAdapter(MainActivity.this, dataList); StaggeredGridLayoutManager staggeredManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); rvStaggered.setLayoutManager(staggeredManager); rvStaggered.setAdapter(staggeredAdapter);这里以GridLayoutManager为示例 ~
动态设置
GridLayoutManager gridManager = new GridLayoutManager(this, 2); rvGrid.setLayoutManager(gridManager);静态设置
主要使用RecyclerView自带的属性
<android.support.v7.widget.RecyclerView android:id="@+id/rv_type2" android:layout_width="match_parent" android:layout_height="wrap_content" app:layoutManager="android.support.v7.widget.GridLayoutManager" app:spanCount="2" />注意:部分代码是伪代码,如有需求直接查看下方的开发实战 ~
build(app) 引入依赖 implementation 'com.android.support:recyclerview-v7:27.1.1' xml引入 <android.support.v7.widget.RecyclerView android:id="@+id/rv_type1_vertical" android:layout_width="match_parent" android:layout_height="wrap_content" /> 创建Aadpter package nk.com.recyclerview; import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; /** * @author MrLiu * @date 2020/8/4 * desc */ public class BasiccAdapter extends RecyclerView.Adapter<BasiccAdapter.BasicViewHolder> { @NonNull @Override public BasiccAdapter.BasicViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { return null; } @Override public void onBindViewHolder(@NonNull BasiccAdapter.BasicViewHolder holder, int position) { } @Override public int getItemCount() { return 0; } class BasicViewHolder extends RecyclerView.ViewHolder { public BasicViewHolder(View view) { super(view); } } } 承载类调用 RecyclerView rvVertical = findViewById(R.id.rv_type1_vertical); //创建Adapter、dataList为传入Adapter内的数据源 BasicAdapter verticalAdapter = new BasicAdapter(MainActivity.this, dataList); //创建布局管理者,如参数内未传对应的LayoutManger则默认为垂直列表的LayoutManager LinearLayoutManager verticalManager = new LinearLayoutManager(this); //将布局管理者设置到对应的RecyclerView rvVertical.setLayoutManager(verticalManager); //将已创建的Adapter设置到对应的RecyclerView rvVertical.setAdapter(verticalAdapter);我直接写了个Demo,内部涵盖了已知的几种布局效果
build 引入依赖
implementation 'com.android.support:recyclerview-v7:27.1.1'MainActivity
package nk.com.recyclerview; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private List<TmpModel> dataList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initData(); initView(); } private void initData() { dataList = new ArrayList<>(); dataList.add(new TmpModel(R.mipmap.img1, "模拟 - 1")); dataList.add(new TmpModel(R.mipmap.img2, "模拟 - 2")); dataList.add(new TmpModel(R.mipmap.img3, "模拟 - 3")); } private void initView() { /** * LinearLayoutManager * */ RecyclerView rvVertical = findViewById(R.id.rv_type1_vertical); RecyclerView rvHorizontal = findViewById(R.id.rv_type1_horizontal); //垂直列表 BasicAdapter verticalAdapter = new BasicAdapter(MainActivity.this, dataList); LinearLayoutManager verticalManager = new LinearLayoutManager(this); rvVertical.setLayoutManager(verticalManager); rvVertical.setAdapter(verticalAdapter); //水平列表 BasicAdapter horizontalAdapter = new BasicAdapter(MainActivity.this, dataList); LinearLayoutManager horizontalManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); rvHorizontal.setLayoutManager(horizontalManager); rvHorizontal.setAdapter(horizontalAdapter); /** * GridLayoutManager * */ RecyclerView rvGrid = findViewById(R.id.rv_type2); BasicAdapter GridAdapter = new BasicAdapter(MainActivity.this, dataList); GridLayoutManager gridManager = new GridLayoutManager(this, 2); rvGrid.setLayoutManager(gridManager); rvGrid.setAdapter(GridAdapter); /** * StaggeredGridLayoutManager * */ RecyclerView rvStaggered = findViewById(R.id.rv_type3); BasicAdapter staggeredAdapter = new BasicAdapter(MainActivity.this, dataList); StaggeredGridLayoutManager staggeredManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); rvStaggered.setLayoutManager(staggeredManager); rvStaggered.setAdapter(staggeredAdapter); /** * 禁止RecyclerView内部事件 * */ rvVertical.setNestedScrollingEnabled(false); rvHorizontal.setNestedScrollingEnabled(false); rvGrid.setNestedScrollingEnabled(false); rvStaggered.setNestedScrollingEnabled(false); } }activity.xml
<?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" tools:context=".MainActivity"> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="none"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:padding="5dp" android:text="线性布局 - LinearLayoutManager" android:textStyle="bold" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="垂直效果" android:textColor="#f00" /> <android.support.v7.widget.RecyclerView android:id="@+id/rv_type1_vertical" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="水平效果" android:textColor="#f00" /> <android.support.v7.widget.RecyclerView android:id="@+id/rv_type1_horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="------------------------------------------------------" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:padding="5dp" android:text="网格布局 - GridLayoutManager" android:textStyle="bold" /> <android.support.v7.widget.RecyclerView android:id="@+id/rv_type2" android:layout_width="match_parent" android:layout_height="wrap_content" app:layoutManager="android.support.v7.widget.GridLayoutManager" app:spanCount="2" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="------------------------------------------------------" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:padding="5dp" android:text="瀑布流 - StaggeredGridLayoutManager" android:textStyle="bold" /> <android.support.v7.widget.RecyclerView android:id="@+id/rv_type3" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </android.support.v4.widget.NestedScrollView> </LinearLayout>TmpModel
package nk.com.recyclerview; /** * @author MrLiu * @date 2020/8/4 * desc */ public class TmpModel { private int img; private String des; public TmpModel(int img, String des) { this.img = img; this.des = des; } public int getImg() { return img; } public void setImg(int img) { this.img = img; } public String getDes() { return des; } public void setDes(String des) { this.des = des; } }BasicAdapter
package nk.com.recyclerview; import android.content.Context; 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; /** * @author MrLiu * @date 2020/8/4 * desc */ public class BasicAdapter extends RecyclerView.Adapter<BasicAdapter.BasicViewHolder> { private List<TmpModel> dataList; private Context mContext; public BasicAdapter(Context context, List<TmpModel> data) { this.mContext = context; this.dataList = data; } @Override public BasicViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View inflate = LayoutInflater.from(mContext).inflate(R.layout.item_layout, parent, false); return new BasicViewHolder(inflate); } @Override public void onBindViewHolder(BasicViewHolder holder, int position) { TmpModel tmpModel = dataList.get(position); holder.mImg.setImageResource(tmpModel.getImg()); holder.mDsc.setText(tmpModel.getDes()); } @Override public int getItemCount() { return dataList.size(); } class BasicViewHolder extends RecyclerView.ViewHolder { TextView mDsc; ImageView mImg; public BasicViewHolder(View view) { super(view); mDsc = view.findViewById(R.id.item_dsc); mImg = view.findViewById(R.id.item_img); } } }最外层布局的android:layout_width采用 match_parent,同时可尝试加入 android:layout_weight="1"
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="vertical"> <TextView android:id="@+id/item_dsc" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Item Content ~" /> </LinearLayout>目前我写的这种不太合适,我看了下效果主要是基本就是给每个item加了一个margin值~
创建 ItemOffsetDecoration继承RecyclerView.ItemDecoration package com.nk.machine.shop.view; import android.graphics.Rect; import android.support.v7.widget.RecyclerView; import android.view.View; /** * @author MrLiu * @date 2020/10/21 * desc */ public class ItemOffsetDecoration extends RecyclerView.ItemDecoration { private int mItemOffset; /** * * @param itemOffset item与item之间的间距 */ public ItemOffsetDecoration(int itemOffset) { mItemOffset = itemOffset; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); outRect.set(mItemOffset, mItemOffset, mItemOffset, mItemOffset); } } 使用方式 LinearLayoutManager layoutManager = new GridLayoutManager(this, 3); recyclerView.setLayoutManager(layoutManager); MyAdapter myAdapter = new MyAdapter(R.layout.item_layout, productList); recyclerView.setAdapter(myAdapter); //关键在这里~ spacing = 间距值 (自行设置即可) recyclerView.addItemDecoration(new ItemOffsetDecoration(spacing));场景:NestedScrollView内嵌套RecyclerView,打开页面时不显示在顶部
解决:NestedScrollView内加入以下属性
如不生效,则将以下属性放在上层布局或最外层布局
android:focusable="true" android:focusableInTouchMode="true"场景:NestedScrollView内嵌套RecyclerView,滑动冲突
解决:
recyclerView.setNestedScrollingEnabled(false);