LinearLayout
在布局文件设置分割线不仅方便,而且高效,对于布局来说十分重要。然而我在为LinearLayout
设置分割线的时候却碰到一个问题,十分不解。先来看看是什么现象吧:
布局文件如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:divider="@drawable/divider"
android:showDividers="end"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"
android:textSize="50sp"
android:visibility="visible"
android:id="@+id/textView" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/editText"
android:text="EditText"
android:textSize="50sp"
android:background="@null"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="@+id/button"
android:visibility="visible"
/>
</LinearLayout>
布局很简单,分割线在最后显示。
然而当我们设置Button
属性android:visibility="gone"
后,再来看看:
分割线竟然跑最上面了!
然后还是最开始的布局,我们设置LinearLayout
属性android:showDividers="beginning"
,显示效果为:
然后设置TextView
属性android:visibility="gone"
后,再来看看:
分割线消失了!
到网上搜了搜没有找到相关的问题,没办法,看源码吧。
下面是LinearLayout
画水平分割线的函数:
void drawDividersVertical(Canvas canvas) {
final int count = getVirtualChildCount();
for (int i = 0; i < count; i++) {
final View child = getVirtualChildAt(i);
if (child != null && child.getVisibility() != GONE) {
if (hasDividerBeforeChildAt(i)) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
final int top = child.getTop() - lp.topMargin - mDividerHeight;
drawHorizontalDivider(canvas, top);
}
}
}
if (hasDividerBeforeChildAt(count)) {
final View child = getVirtualChildAt(count - 1);
int bottom = 0;
if (child == null) {
bottom = getHeight() - getPaddingBottom() - mDividerHeight;
} else {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
bottom = child.getBottom() + lp.bottomMargin;
}
drawHorizontalDivider(canvas, bottom);
}
}
for
循环中,i=0是第一个view,也就是上面布局中的TextView
,设置不可见时,drawHorizontalDivider(canvas, top)
不被执行,也就是开头的分割线没有画出来的原因。下面代码:
if (hasDividerBeforeChildAt(count)) { final View child = getVirtualChildAt(count - 1); int bottom = 0; if (child == null) { bottom = getHeight() - getPaddingBottom() - mDividerHeight; } else { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); bottom = child.getBottom() + lp.bottomMargin; } drawHorizontalDivider(canvas, bottom); }
这段代码是用来画结尾的分割线的,当我们设置
Button
属性android:visibility="gone"
时,child.getBottom()
为0,所以分割线就画到离顶端lp.bottomMargin
的位置了。
原因虽然找到了,但还是没有什么好的解决方案,只能靠我们自己设置表示分割线的View了。