RecyclerView的item布局方式依赖于其配置的布局管理器。不同的布局管理器可以实现不同的界面效果。
LayoutManager介绍
RecyclerView可以通过setLayoutManager设置布局管理器,该方法的源码如下:
/*** Set the {@link LayoutManager} that this RecyclerView will use.** <p>In contrast to other adapter-backed views such as {@link android.widget.ListView}* or {@link android.widget.GridView}, RecyclerView allows client code to provide custom* layout arrangements for child views. These arrangements are controlled by the* {@link LayoutManager}. A LayoutManager must be provided for RecyclerView to function.</p>** <p>Several default strategies are provided for common uses such as lists and grids.</p>** @param layout LayoutManager to use*/public void setLayoutManager(@Nullable LayoutManager layout)
上述方法的入参为LayoutManager,该类为RecyclerView的抽象静态类。该类型的具体实现存在以下几种:
- MaterialCalendar中的匿名实现类:日历管理器中实现的布局管理器,由于是内部匿名类,因此开发过程中无法进行使用。
- LinearLayoutManager:线性布局管理器,线性排列RecyclerView的item,可以分为水平和垂直两个方向。
- GridLayoutManager:网格布局管理器,继承了LinearLayoutManager,可以将item以网格的形式进行展示,构造方法中存在spanCount参数,可以表明每行存在数据的个数。
- LinearLayoutManagerImpl:线性布局的进一步加工实现,主要为了viewPage的布局切换实现。
- SmoothCalendarLayoutManager:com.google.android.material.datepicker包下package作用范围的 LinearLayoutManager子类。主要为日期选择器提供布局支持,开发过程中无法进行使用。
- StaggeredGridLayoutManager:交错网格布局管理器,可以再两个方向(垂直、水平)交错的进行item布局,计算机输入键盘可以使用该布局进行实现(也可以用网格布局管理器)
LinearLayoutManager详解
/*** A {@link RecyclerView.LayoutManager} implementation which provides* similar functionality to {@link android.widget.ListView}.*/
public class LinearLayoutManager extends RecyclerView.LayoutManager implementsItemTouchHelper.ViewDropHandler, RecyclerView.SmoothScroller.ScrollVectorProvider
ViewDropHandler:滑动消除、拖动支持的辅助接口
ScrollVectorProvider:平滑滚动的接口
最简单的构造方法,本质上是调用LinearLayoutManager(Context context, @RecyclerView.Orientation int orientation, boolean reverseLayout) 进行初始化实例。
/*** Creates a vertical LinearLayoutManager** @param context Current context, will be used to access resources.*/public LinearLayoutManager(Context context) {this(context, RecyclerView.DEFAULT_ORIENTATION, false);}
参数较为齐全的构造方法,包含了布局方式【水平、竖直】以及是否反转item展示。
例如展示list=[1,2,3,4,5],如果reverseLayout=true则从左到右或从上到下(受orientation参数影响)的展示1,2,3,4,5,否则展示内容为:5,4,3,2,1
/*** @param context Current context, will be used to access resources.* @param orientation Layout orientation. Should be {@link #HORIZONTAL} or {@link* #VERTICAL}.* @param reverseLayout When set to true, layouts from end to start.*/public LinearLayoutManager(Context context, @RecyclerView.Orientation int orientation,boolean reverseLayout) {setOrientation(orientation);setReverseLayout(reverseLayout);}
如注释说明,该构造方法使用通过XML配置线性构造管理器,相比较上面构造方法外该方法增加了setStackFromEnd(properties.stackFromEnd);调用。setStackFromEnd表明从底部进行数据加载和展示。
/*** Constructor used when layout manager is set in XML by RecyclerView attribute* "layoutManager". Defaults to vertical orientation.** {@link android.R.attr#orientation}* {@link androidx.recyclerview.R.attr#reverseLayout}* {@link androidx.recyclerview.R.attr#stackFromEnd}*/public LinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr,int defStyleRes) {Properties properties = getProperties(context, attrs, defStyleAttr, defStyleRes);setOrientation(properties.orientation);setReverseLayout(properties.reverseLayout);setStackFromEnd(properties.stackFromEnd);}
通过上述构造方法可以初始化创建一个线性布局管理器,并针对该管理器进行了基础配置。每个item都交友该管理器进行布局管理,此外线性管理器还提供配置布局参数(宽度、高度、权重)的方法,以及定位到指定位置的方法。
GridLayoutManager详解
网格管理器的构造方法类似于线性布局管理器,在其基础上还增加了spanCount参数的配置。该参数配置了在一行或者一列中展示item的最大数量
/*** @param context Current context, will be used to access resources.* @param spanCount The number of columns or rows in the grid* @param orientation Layout orientation. Should be {@link #HORIZONTAL} or {@link* #VERTICAL}.* @param reverseLayout When set to true, layouts from end to start.*/public GridLayoutManager(Context context, int spanCount,@RecyclerView.Orientation int orientation, boolean reverseLayout) {super(context, orientation, reverseLayout);setSpanCount(spanCount);}
StaggeredGridLayoutManager详解
交错网格布局类似于网格布局的构造方法
使用示例
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);binding = ActivityMainBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());recyclerView = binding.recyclerView;//设置垂直的线性布局管理器,Orientation --> VERTICAL:垂直 HORIZONTAL:水平LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext(),LinearLayoutManager.VERTICAL,false);layoutManager.setStackFromEnd(false);
// layoutManager.setOrientation(LinearLayoutManager.VERTICAL);//GridLayoutManager gridLayoutManager = new GridLayoutManager(getApplicationContext(),2);StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(2,LinearLayoutManager.HORIZONTAL);recyclerView.setLayoutManager(staggeredGridLayoutManager);BaseAdapter<String> baseAdapter = new BaseAdapter<String>(R.layout.item_line) {@Overridepublic void bindView(ViewHolder holder, String obj, int position) {holder.setText(R.id.item,obj);}};baseAdapter.add("一个");baseAdapter.add("二个");baseAdapter.add("三个");baseAdapter.add("四个");baseAdapter.add("五个");baseAdapter.add("六个");baseAdapter.add("七个");recyclerView.setAdapter(baseAdapter);}
交错布局