美文网首页Android开发学习Android资源收录Android杂识
Android——RecyclerView入门学习之Layout

Android——RecyclerView入门学习之Layout

作者: 英勇青铜5 | 来源:发表于2016-10-19 10:39 被阅读13136次

    LayoutManager是一个抽象类,有3个子类:

    • LinearLayoutManager 线性布局管理器
    • GridLayoutManager 表格布局管理器
    • StaggeredGridLayoutManager 瀑布流布局管理器

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


    1.LinearLayoutManager 线性布局管理器 <p>

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


    1.1 构造方法 <p>

    有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) <p>

    源码中的注释:

    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<p>

    使用也特简单,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)
     */
    @Override
    public 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方法 <p>

    方法 作用
    findFirstVisibleItemPosition() 返回当前RecycelrView中第一个可见的itemadapter postion
    findLastVisibleItemPosition() 返回当前RecycelrView中最后一个可见的itemadapter postion
    findFirstCompletelyVisibleItemPosition() 返回当前RecycelrView中第一个完整可见的itemadapter postion
    findLastCompletelyVisibleItemPosition() 返回当前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 表格布局管理器 <p>

    继承之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 瀑布流管理器<p>

    简单使用:

    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的工作流程后再学习


    4. 最后 <p>

    都是非常基础的使用,几个方法的简单说明,非常基础,并没有啥知识点。还真是照应标题,首尾呼应,符合入门学习 :(

    昨天晚上,看了老罗锤子M1的发布会。作为一个Android开发者,对于Big BangOne Step倒是更感兴趣,尤其Big Bang,感觉会是一个非常不错的学习资料。等代码开源出来后,要是能够学得动代码,也记录一下

    本人很菜,有错误请指出

    共勉 :)

    相关文章

      网友评论

      • 明风桦:我用的倒序排列。 layout.setReverseLayout(true); layout.setStackFromEnd(true)但是怎么还是没有按照正确的顺序,只有刚开始是,但是你重新回来又是1,3,2这样排下去的
        英勇青铜5:@几景然 可以试试把数据的list倒序
        明风桦:@英勇青铜5 额,倒序就三行代码,怎么排查:smile:
        英勇青铜5:@几景然 额。。你自己再看看源码的注释,排查下吧
      • Deps:为什么简书安卓版代码看不全,左右滑动不了😂
        英勇青铜5:@Deps :scream:不知道啊,我日常用的5s

      本文标题:Android——RecyclerView入门学习之Layout

      本文链接:https://www.haomeiwen.com/subject/pqcxuttx.html