首先,什么是ItemDecoration?来看看官网是如何解释的。html
ItemDecoration容许从adapter的数据集合中为特定的item视图添加特性的绘制以及布局间隔。它能够用来实现item之间的分割线,高亮,分组边界等。
咱们不能简单的把ItemDecoration当作一个名字响亮的分割线。它比divider要多不少内容。一个divider只能绘制在item之间,可是ItemDecoration能够绘制在item的四边。ItemDecoration为decoration的测量和绘制提供了全方位的控制。一个decoration能够是一条分割线,也能够仅仅是一个间隔(inset)。java
但不幸的是,绝大多数android开发者都没有使用item decoration。在这个分为三部分的系列文章中,咱们将了解ItemDecoration的强大之处。android
第一部分: 不要添加view来作分割线— 使用 ItemDecorationcanvas
第二部分: 不要使用padding来作间隔 —使用 ItemDecorationide
第三部分: 在GridLayoutManager中高效的绘制decorations布局
本文是第一部分。post
我曾看到一些开发者在为RecyclerView添加divider的时候采用了一些捷径。缘由很简单,ListView原生支持divider,能够直接在xml中设置divider。性能
<ListView android:id="@+id/activity_home_list_view" android:layout_width="match_parent" android:layout_height="match_parent" android:divider="@android:color/black" android:dividerHeight="8dp"/>
可是到了RecyclerView,就不再能直接添加divider了。须要添加一个绘制divider的ItemDecoration。可是开发者发现它很麻烦,因而直接把divider添加到(item的)view上,而不是使用ItemDecoration。动画
<LinearLayout android:orientation="vertical"> <LinearLayout android:orientation="horizontal"> <ImageView /> <TextView /> </LinearLayout> <View android:width="match_parent" android:height="1dp" android:background="#333" /> </LinearLayout>
每当咱们走捷径的时候,都有可能会产生反作用。而这里的反作用是可能影响性能。3d
当在布局中添加了一个divider的时候,咱们增长了view的个数。咱们都知道view的数目越少会获得越好的性能。有时候增长一个view来实现divider还会增长布局的层级。好比上面的例子中,咱们不单单增长了一个view,还增长了一个包含它们的 linear layout。为了一个divider而建立了额外的布局。
由于divider是view的一部分,因此在item 动画期间,divider也会一块儿跟着动画。以下图:
显然divider不该该随着item一块儿作动画。而是和item分开,像这样才是对的:
若是divider是(item的)view的一部分,那么你就没法控制它。你惟一能控制的就是根据item的position改变divider的可见状态。 而item decoration就灵活多了。
In the above image for the last item in the group divider fills the entire width. Other dividers have a margin of 56dp to their left side. Here is the ItemDecorator’s onDraw code.
在上图中,group最后一个item的divider充满了整个宽度。其它的divider都有一个56dp的左边距。这是这个ItemDecorator的onDraw代码:
@Override public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) { canvas.save(); final int leftWithMargin = convertDpToPixel(56); final int right = parent.getWidth(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); int adapterPosition = parent.getChildAdapterPosition(child); left = (adapterPosition == lastPosition) ? 0 : leftWithMargin; parent.getDecoratedBoundsWithMargins(child, mBounds); final int bottom = mBounds.bottom + Math.round(ViewCompat.getTranslationY(child)); final int top = bottom - mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(canvas); } canvas.restore(); }
写一个本身的ItemDecoration其实很是简单。你只须要建立一个继承了ItemDecoration的类就能够了。重写 getItemOffsets() 和 onDraw() 方法。具体实现能够参考 这个 示例。
而 25.0.0版本的支持库中,咱们有一个新的类 “DividerItemDecoration”。这个类直接实现了divider。
DividerItemDecoration decoration = new DividerItemDecoration(getApplicationContext(), VERTICAL); recyclerView.addItemDecoration(decoration);
一个RecyclerView能够添加多个ItemDecoration。发挥头脑风暴的时候到了。
全部decoration都在item绘制以前绘制。若是你想让decoration在view以后绘制,重写onDrawOver() 而不是onDraw() 。
因此下次想为RecyclerView添加分割线的时候,别使用在item布局添加view这种方式了,使用ItemDecoration。