Android——RecyclerView入门学习之LayoutManager

来源:互联网 发布:查看qq密码软件 编辑:程序博客网 时间:2024/06/16 00:52
LayoutManager是一个抽象类,有3个子类:
  • LinearLayoutManager 线性布局管理器
  • GridLayoutManager 表格布局管理器
  • StaggeredGridLayoutManager 瀑布流布局管理器

3个布局管理器,之前都是很简单地使用,了解的并都算不多。学习下每个布局管理器中常用的方法,同时了解一下涉及思路,也为以后学习自定义LayoutManager先打点基础


1.LinearLayoutManager 线性布局管理器

线性布局使用频率很高,几乎每个应用都会有列表,基本都会用到。


1.1 构造方法

有3个构造方法:

  1. LinearLayoutManager(Context context)
  2. LinearLayoutManager(Context context,int orientation,boolean reverseLayout)
  3. LinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr,int defStyleRes)

第一个构造方法内部调用了第二个构造方法,第二个构造方法参数的含义:

  • Context context :上下文,初始化时,构造方法内部加载资源用
  • int orientation :方向,垂直和水平,默认为垂直
  • boolean reverseLayout:是否倒序,设置为True,从最后一个item开始,倒序加载。此时,RecyclerView第一个item是添加进Adapter中的最后一个,最后一个item是第一个加进Adapter的数据,RecyclerView会自动滑到末尾

将reverseLayout设置为true:


倒序展示,RecycelrView自动滑动到最后

但此时的设置的分割线如果考虑的不够全面,就会受到影响。具体的使用场景不清楚。如果只是为了让数据倒序展示,而RecyclerView还是从头开始而不自动滑动末尾,可以在数据添加进Adapter前,将集合内的数据进行倒序处理

orientation,也可以通过manger.setOritation()设置
reverseLayout,也可以通过manager.setReverseLayout()设置


第3个构造方法,可以使用自定义属性,根据属性优先级选择在不同的时机,根据需求来使用不同的样式,目前使用不多,详细的内容可以查看Android自定义View构造函数详解


1.2 setStackFromEnd(boolean stackFromEnd)

源码中的注释:

When stack from bottom is set to true, the list fills its content starting from the bottom of the view.

当从堆底部开始展示设置为true时,列表便会从底部开始展示内容

设置为true时,RecycelrView会自动滑倒尾部,直到最后一条数据完整展示


setStackFromEnd(true)时

这个方法和manager.setReverseLayout(true)共同点就是都自动滑动尾部,RecyclerView默认会展示末尾的item。差别在于,manager.setStackFromEnd(true)不会影响内部的数据顺序,怎么添加进Adapter的,就怎么展示


1.3scrollToPosition(int position)滑动到指定item

使用也特简单,manager.scrollToPosition(15)


scrollToPosition(15)

方法中需要的positionadapter position,就是在Adapter中,item实际的positon

这个方法在刚刚初始化LayoutManger时,就可以使用,此时还没有向Adapter中添加数据

方法源码:

/** *Scroll the RecyclerView to make the position visible.  * *Note that scroll position change will not be reflected until the next layout call.</p> * * @param position Scroll to this adapter position * @see #scrollToPositionWithOffset(int, int) */@Overridepublic void scrollToPosition(int position) {    mPendingScrollPosition = position;    mPendingScrollPositionOffset = INVALID_OFFSET;    if (mPendingSavedState != null) {        mPendingSavedState.invalidateAnchor();    }    requestLayout();}

方法将传递进来的positon赋值给了mPendingScrollPosition,并调用了requestLayout()方法。感觉是在布局chidlView时,进行了回调处理

暂时只是简单看了一眼源码,里面具体的过程比较复杂,没有深挖

mPendingScrollPositionOffset = INVALID_OFFSET这行代码是设置偏移量的,INVALID_OFFSET默认为Integer.MIN_VALUE


这个方法还有一个类似的方法scrollToPositionWithOffset(int position, int offset)

源码中两个方法的差别在于mPendingScrollPositionOffset = offset

将之前的manager.scrollToPosition(15)换成manager.scrollToPositionWithOffset(15,30),同样会调到adapter positoin15item,但整个RecycelrView中的内容,向下偏移了30 px


设置偏移量为30

1.4 获取当前RecyclerView首尾可见item的adapter positon方法

方法作用findFirstVisibleItemPosition()返回当前RecycelrView中第一个可见的itemadapter postionfindLastVisibleItemPosition()返回当前RecycelrView中最后一个可见的itemadapter postionfindFirstCompletelyVisibleItemPosition()返回当前RecycelrView中第一个完整可见的itemadapter postionfindLastCompletelyVisibleItemPosition()返回当前RecycelrView中最后一个完整可见的itemadapter postion

方法1:findFirstVisibleItemPosition()方法2:findFirstCompletelyVisibleItemPosition()的差别在于:在RecyclerView中,第一个item_A只是露出一点点,并没有完全展示,item_BA下方的一个item,完全展示在屏幕上,方法1返回的是item_Aadapter position方法2返回item_Badapter position

例如:


设置偏移量为30
  • findFirstVisibleItemPosition():14
  • findFirstCompletelyVisibleItemPosition():15
  • findLastVisibleItemPosition():33
  • findLastCompletelyVisibleItemPosition():32

这4个方法,只有当RecyclerView在屏幕展示出来后,才能得到正常的返回值,否则都是-1

LinearLayoutManager暂时就先学习这几个常用的方法


2. GridLayoutManager 表格布局管理器

继承之LinearLayoutManager,在需要使用instanceofLinearLayoutManager做判断时,需要注意

GridLayoutManager同样也有3个构造方法,由于是继承LiearLayoutMnager,使用起来差别不大,构造方法内使用了super()方法来直接调用了父类的构造方法:

代码:

 /**  * Creates a vertical GridLayoutManager  *  * @param context Current context, will be used to access resources.  * @param spanCount The number of columns in the grid  */public GridLayoutManager(Context context, int spanCount) {    super(context);    setSpanCount(spanCount);}
  • spanCount : 列数

根据方法的注释,可以知道,默认情况下,GridLayoutManager是垂直的

在方法内,列数是调用setSpanCount(spanCount)进行设置;相应的,getSpanCount()可以得到列数


注意:
setStackFromEnd()不支持GridLayoutManager(),但支持setReverseLayout(boolean)方法

常用的方法在LinearLayoutManager()提过了,其他的方法暂时先放一下


3.StaggeredGridLayoutManager 瀑布流管理器

简单使用:

public class LMActivity extends AppCompatActivity {    private RecyclerView rv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_lm);        init();    }    /**     * 初始化     */    private void init() {        rv = (RecyclerView) findViewById(R.id.rv_lm_activity);        //瀑布流布局管理器        StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);        rv.setLayoutManager(manager);        //添加边距        rv.addItemDecoration(new RVItemDecoration(16));        //适配器        RecyclerViewAdapter adapter  = new RecyclerViewAdapter(rv,R.layout.id_rv_item_layout,R.id.tv__id_item_layout);        rv.setAdapter(adapter);        //添加数据        List<String> dataList = new ArrayList<>();        final String res = "英勇青铜5";        for (int i = 0 ; i < 50; i ++){            int num = (int)(Math.random() * 20 +1);            StringBuilder stringBuilder = new StringBuilder();            for (int j = 0 ; j < num; j ++){                stringBuilder.append(res,0,res.length());            }            dataList.add(stringBuilder.toString());            stringBuilder.delete(0,stringBuilder.length());        }        adapter.setData(dataList);    }     @Override    protected void onDestroy() {        super.onDestroy();        rv.setAdapter(null);    }}

Item布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="vertical">    <TextView        android:id="@+id/tv__id_item_layout"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:background="@color/colorAccent"        android:textAllCaps="false"        android:textColor="@android:color/white"        android:textSize="20sp" /></LinearLayout>

效果:


瀑布流

使用这3个布局管理器,差不多90%的需求都能满足吧,自定义LayoutManager打算放在学习过RecycelrView的工作流程后再学习

0 0