我们经常会在项目中使用recyclerview,今天就从源码的角度来真正认识和分析一下recyclerview
1、recyclerview继承ViewGroup,并且实现了ScroolingView和NestedScrollingchild接口
2、为recyclerview设置LayoutManager,Google为我们提供了三种类型的layoutmanager,
LinearLayoutManager(Horizontal和Vertical两个方向)、
GridLayoutManager(继承自linearlayoutmanager)
/** * A {@link RecyclerView.LayoutManager} implementations that lays out items in a grid. * <p> * By default, each item occupies 1 span. You can change it by providing a custom * {@link SpanSizeLookup} instance via {@link #setSpanSizeLookup(SpanSizeLookup)}. */ public class GridLayoutManager extends LinearLayoutManager {
/** * Constructor used when layout manager is set in XML by RecyclerView attribute * "layoutManager". If spanCount is not specified in the XML, it defaults to a * single column. * * @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_spanCount */ public GridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); Properties properties = getProperties(context, attrs, defStyleAttr, defStyleRes); setSpanCount(properties.spanCount); } /** * 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); } /** * @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, int orientation, boolean reverseLayout) { super(context, orientation, reverseLayout); setSpanCount(spanCount); }和
StaggeredGridLayoutManager
瀑布流式布局
3、recyclerview与listview不同的一点就是,需要设置布局管理器layoutmanager来设置条目的排列样式。并且,recyclerview必须在setadapter()方法之前设置layoutmanager才能显示item的内容
4、google 为我们提供了设置分割线的方法,但是没有默认的分割线,我们需要自定义分割线。我们可以使用recyclerview.addItemDecoration()方法来加入分割线。我们自定义的itemdecoration需要继承自recyclerview.itemdecoration。核心的方法就是ondraw方法,它会根据传进来的orientation来判断是绘制横向的item的分割线还是纵向item的分割线,drawHorizontal绘制横向item的分割线,drawVertical绘制纵向item的分割线。getItemOffsets方法用于设置item的padding属性。
虽然google没有为我们提供默认的分割线,但是好处也就是我们可以更灵活的自定义分割线。
我们需要在setAdapter之前就加入分割线,这样才能使分割线有效。方法为:recyclerview.addItemDecoration(new DividerItemDecoration)
5、item的点击事件需要我们来自定义,这是一个不尽如人意的地方。但是自定义点击事件也并不困难,在adapter中定义接口并提供回调即可实现自定义item的点击事件
6、实现瀑布流
我们可以不用在代码中写addItemdecoration,而是在item的布局文件中定义分割距离android:layout_margin=“2dp”,实现瀑布流也很简单,在adapter中写一个随机的高度来控制每个item的高度就可以了。通常这个高度是有服务器返回的数据的高度来控制的
LayoutParams lp = holder.tv.getLayoutParams();
lp.htight = holder.tv.getMeasuredHeight();
holder.tv.setLayoutParams(lp);