LayoutManager
是一个抽象类,有3个子类:
- LinearLayoutManager 线性布局管理器
- GridLayoutManager 表格布局管理器
- StaggeredGridLayoutManager 瀑布流布局管理器
3个布局管理器,之前都是很简单地使用,了解的并都算不多。学习下每个布局管理器中常用的方法,同时了解一下涉及思路,也为以后学习自定义LayoutManager
先打点基础
1.LinearLayoutManager 线性布局管理器 <p>
线性布局使用频率很高,几乎每个应用都会有列表,基本都会用到。
1.1 构造方法 <p>
有3个构造方法:
LinearLayoutManager(Context context)
LinearLayoutManager(Context context,int orientation,boolean reverseLayout)
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:
但此时的设置的分割线如果考虑的不够全面,就会受到影响。具体的使用场景不清楚。如果只是为了让数据倒序展示,而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
会自动滑倒尾部,直到最后一条数据完整展示
这个方法和manager.setReverseLayout(true)
共同点就是都自动滑动尾部,RecyclerView
默认会展示末尾的item
。差别在于,manager.setStackFromEnd(true)
不会影响内部的数据顺序,怎么添加进Adapter
的,就怎么展示
1.3scrollToPosition(int position)滑动到指定item<p>
使用也特简单,manager.scrollToPosition(15)
方法中需要的position
是adapter 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 positoin
为15
的item
,但整个RecycelrView
中的内容,向下偏移了30 px
1.4 获取当前RecyclerView首尾可见item的adapter positon方法 <p>
方法 | 作用 |
---|---|
findFirstVisibleItemPosition() |
返回当前RecycelrView 中第一个可见的item 的adapter postion
|
findLastVisibleItemPosition() |
返回当前RecycelrView 中最后一个可见的item 的adapter postion
|
findFirstCompletelyVisibleItemPosition() |
返回当前RecycelrView 中第一个完整可见的item 的adapter postion
|
findLastCompletelyVisibleItemPosition() |
返回当前RecycelrView 中最后一个完整可见的item 的adapter postion
|
方法1:findFirstVisibleItemPosition()
和方法2:findFirstCompletelyVisibleItemPosition()
的差别在于:在RecyclerView
中,第一个item_A
只是露出一点点,并没有完全展示,item_B
是A
下方的一个item
,完全展示在屏幕上,方法1
返回的是item_A
的adapter position
,方法2
返回item_B
的adapter position
例如:
- findFirstVisibleItemPosition():14
- findFirstCompletelyVisibleItemPosition():15
- findLastVisibleItemPosition():33
- findLastCompletelyVisibleItemPosition():32
这4个方法,只有当RecyclerView
在屏幕展示出来后,才能得到正常的返回值,否则都是-1
LinearLayoutManager
暂时就先学习这几个常用的方法
2. GridLayoutManager 表格布局管理器 <p>
继承之LinearLayoutManager,在需要使用instanceof
对LinearLayoutManager
做判断时,需要注意
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 Bang
和One Step
倒是更感兴趣,尤其Big Bang
,感觉会是一个非常不错的学习资料。等代码开源出来后,要是能够学得动代码,也记录一下
本人很菜,有错误请指出
共勉 :)
网友评论