每个App都会用到分割线,一个两边顶到头的分割线只需要使用<View>配合background属性就能够轻松实现。
常见的分割线形式还有如下这种两端或者一端留出一定空白距离的分割线。

实现这种效果有很多解决方案,我能想到的有三种:
第一种,也是最简单的一种实现方式是:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/divider_height"
android:background="@android:color/white"
android:paddingLeft="@dimen/divider_padding"
android:paddingRight="@dimen/divider_padding">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"/>
</LinearLayout>
这种实现方式会引起不必要的overdraw,因为容器的背景绘制了一次,然后分割线再绘制了一次。
第二种,可以用三个不同background的<View>来避免overdraw
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/divider_height"
android:orientation="horizontal">
<View
android:layout_width="@dimen/divider_padding"
android:layout_height="match_parent"
android:background="@android:color/white"/>
<View
android:layout_width="@dimen/divider_padding"
android:layout_height="match_parent"
android:layout_weight="1.0"
android:background="@color/divider_color"/>
<View
android:layout_width="@dimen/divider_padding"
android:layout_height="match_parent"
android:background="@android:color/white"/>
</LinearLayout>
这个方案解决了overdraw问题,但也并非完美,因为为了实现分割线增加了一层嵌套。那么接下来就引出了本篇想要记录的重点
第三种,自定义View绘制分割线
这样最终分割线的布局代码非常简练:
<Divider
android:layout_width="match_parent"
android:layout_height="@dimen/divider_height"
custom:dividerLineColor="@color/divider_color"
custom:dividerPaddingLeft="@dimen/divider_padding"
custom:dividerPaddingRight="@dimen/divider_padding" />
具体自定义View的细节不做详细记录,这里只记录一下在canvas上画线的重点代码
@Override
protected void onDraw(Canvas canvas){
Paint paint = new Paint();
// canvas的宽度和高度
int lineWidth = getWidth();
int lineHeight = getHeight();
// 设置线的粗细为canvas的高度
paint.setStrokeWidth(lineHeight);
// 画左端的白线,假设两端留白长度是30
paint.setColor(Color.WHITE);
canvas.drawLine(0, lineHeight/2, 30, lineHeight/2, paint);
// 画中间的分割线
paint.setColor(Color.BLACK);
canvas.drawLine(30, lineHeight/2, lineWidth-30, lineHeight/2, paint);
// 画右端的白线,假设两端留白长度是30
paint.setColor(Color.WHITE);
canvas.drawLine(lineWidth-30, lineHeight/2, lineWidth, lineHeight/2, paint);
}
上面代码的关键是
1、画线方法:drawLine方法的前四个参数组成了两组坐标,参数和坐标的关系如下图:

2、上面的代码中的startY和stopY都是lineHeight/2,这代表了两层含义
(1)画的是一条水平的线
(2)分割线的宽度,是从中间往上下两侧扩散的
所以设置startY、stopY为lineHeight/2之后,这条线就处于canvas的垂直中间位置,如果再设置线宽度为canvas的高度,那么这个时候line的高度就正好占满了canvas的高度

网友评论