使用形状可绘制对象作为背景,在底部添加一条线。

75

我正在将一个Drawable作为TextView的背景,只是为了在文本下面有一个分隔线。我使用了以下这个可绘制的XML文件:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <shape 
        android:shape="rectangle">
            <solid android:color="#FFDDDDDD" />
            <gradient 
                android:angle="0"
                android:startColor="#FFAAAAAA"
                android:endColor="#FFEEEEEE"
                />
        </shape>
    </item>

    <item android:bottom="2dp">
        <shape 
        android:shape="rectangle">
            <solid android:color="#FF000000" />
        </shape>
    </item>

</layer-list>

但是这种方法会在黑色矩形上方绘制一个彩色矩形。我只想要形状底部的线条,没有黑色矩形,因为黑色不透明。我该如何实现?


1
似乎有点过头了。为什么不只使用一个带颜色的视图呢? - dmon
同样适用 - 我如何在该视图底部添加一条细线? - ZoolWay
3
我的意思是,视图就是那条线。 <View android:backgroundColor="#FF000000" android:layout_height="2dp" android:layout_width="fill_parent"/> - dmon
啊,好的,那不是一个背景,而是一个非常细的视图,它将成为线本身!稍后会尝试一下。不过,了解如何在可绘制的 XML 中底部对齐某些内容也是很好的。 - ZoolWay
1
一般来说,除非绝对必要,我尽量不去干扰背景,因为这样会覆盖掉具有聚焦、按下等状态的默认背景颜色。 - dmon
由于缺乏答案,我猜想没有解决方案可以使用可绘制的XML实现我想要的功能。所以@dmon总结了您反对它的建议,因为默认背景加上视图,我将接受它作为答案 ;) - ZoolWay
8个回答

221

这是我为自己的底部获得线条的方法。绘制一条线,然后将项目向上和向侧面移动,以使顶部和侧面不显示线条:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:top="-8dp" android:left="-8dp" android:right="-8dp">
        <shape> 
            <solid android:color="#2b7996"/>
            <stroke android:color="#33b5e5" android:width="6dp"/>
        </shape>
    </item>
</layer-list>

我听起来好像OP想避免在实心区域使用颜色。如果是这种情况,实心部分可以用透明的#00000000替代#2b7996。8位十六进制值用前两位数字指定alpha。 - Joey Harwood
我喜欢这个解决方案,它在RecyclerView中作为项目分隔符非常有用,可以减少布局的层数。 - Spark.Bao
3
去掉 <solid android:color="#2b7996"/> 后,我的期望结果得以实现,至少在Galaxy S4 (Kit Kat)设备上只有下划线,其他设备不确定。 - sotrh
<solid android:color="#2b7996"/> 如果我想要透明的颜色怎么办? - DJphy
它工作得很好,但如何实现圆角半径呢 :( - Darshan Khatri
显示剩余2条评论

56

我认为这是更好的解决方案:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:gravity="bottom">
        <shape>
            <size android:height="1dp" />
            <solid android:color="#000000" />
        </shape>
    </item>
</layer-list>

3
除了三星Lollipop设备外,这个解决方案适用于几乎所有设备。整个视图都是使用“solid”标签中提供的颜色绘制的。由于三星在市场上的占比,这一点不应忽略。 - R. Zagórski
这个解决方案在Nexus 4 / API 22和模拟器/ API 19上不起作用。可能只支持API 23及以上版本。 - gmk57

32

一般来说,除非绝对必要,我会尽可能少地干预背景,因为这样会覆盖默认的背景颜色,并具有聚焦、按下等状态。我建议只使用一个额外的视图(在垂直LinearLayout中),它的厚度与您需要的厚度相同。例如:

 <View 
       android:background="#FF000000" 
       android:layout_height="2dp" 
       android:layout_width="fill_parent"/>

8
我对你的解决方案并不太满意,因为它需要一个额外的布局和一个额外的视图,这两个对象只是为了一个横线而显得过于冗余。如果你们不喜欢使用背景,为什么不重写onDraw()方法,直接画一条线呢? - rupps
啊哈哈哈哈,非常简单,非常出色。我尝试过但没有成功地做一个简单的底部背景。为什么我没想到呢?谢谢。 - pablobaldez
是的,不应该使用太多视图,仅为了添加一个视图背景而添加一个视图非常低效,只应在屏幕上几乎没有任何内容的琐碎情况下使用。 - Teovald
覆盖背景可能是一个不错的解决方案,只要您还使用选择器来绘制最重要的状态,例如按下或选定。 - Benjamin Piette

7
通常对于类似的任务 - 我会创建一个像这样的层列表绘制对象:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
    <shape android:shape="rectangle">
        <solid android:color="@color/underlineColor"/>
    </shape>
</item>
<item android:bottom="3dp">
    <shape android:shape="rectangle">
        <solid android:color="@color/buttonColor"/>
    </shape>
</item>

这个想法是先用underlineColor画矩形,然后在其上面用实际的buttonColor再画一个矩形,但应用bottomPadding。这样总是有效的。

但当我需要使用透明的buttonColor时,我不能使用上述可绘制对象。我找到了另一种解决方案。

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
    <shape android:shape="rectangle">
        <solid android:color="@android:color/transparent"/>
    </shape>
</item>

<item android:drawable="@drawable/white_box" android:gravity="bottom" android:height="2dp"/>
</layer-list>

如您所见,mainButtonColor 是透明的,white_box 只是一个简单的矩形 drawable,其中填充颜色为白色。

需要最低 API 23 才能使 android:gravity="bottom" 正常工作。 - Dominikus K.

3

使用此解决方案,您可以在需要不同行时进行设置。我的要求只是下划线。您甚至可以为布局提供不同的颜色。您可以在下面的图片中看到白色线条 enter image description here

    <?xml version="1.0" encoding="UTF-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:top="-5dp" android:left="-5dp" android:right="-5dp">
        <shape>
            <solid android:color="@android:color/transparent"/>
            <stroke android:color="@color/white" android:width="5dp"/>
        </shape>
    </item>

    <item android:top="-5dp" android:bottom="-5dp" android:right="-5dp">
        <shape>
            <solid android:color="@android:color/transparent"/>
            <stroke android:color="@color/colorPrimaryDark" android:width="5dp"/>
        </shape>
    </item>

    <item android:bottom="-5dp" android:left="-5dp" android:right="-5dp">
        <shape>
            <solid android:color="@android:color/transparent"/>
            <stroke android:color="@color/colorPrimaryDark" android:width="5dp"/>
        </shape>
    </item>

    <item android:top="-5dp" android:left="-5dp" android:bottom="-5dp">
        <shape>
            <solid android:color="@android:color/transparent"/>
            <stroke android:color="@color/colorPrimaryDark" android:width="5dp"/>
        </shape>
    </item>

    <item android:bottom="2dp" android:left="5dp" android:right="5dp" android:top="5dp">
        <shape>
            <solid android:color="@color/colorPrimary"/>

            <corners android:bottomRightRadius="0dp"
                android:bottomLeftRadius="0dp"
                android:topLeftRadius="0dp"
                android:topRightRadius="0dp" />
        </shape>
    </item>
</layer-list>

2
这是上述内容的稍微轻量级的变体。
/drawable/rect_highlight.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <stroke android:width="1px" android:color="@color/colorHighlight"/>
</shape>

/drawable/underline.xml

<inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetLeft="-1px" android:insetRight="-1px" android:insetTop="-1px" android:drawable="@drawable/rect_highlight"/>

使用方法:

<TextView ... android:background="@drawable/underline"/>

这不是我的创意,比我聪明的人想出了它。如果我更聪明,我会问是谁想出来的。 :)


1
这个解决方案适用于我需要类似功能的大多数情况。
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@android:color/transparent" /> <!--background color of box-->
        </shape>
    </item>

    <item
        android:height="2dp"
        android:gravity="bottom">
        <shape>
            <solid android:color="#000000" />
        </shape>
    </item>
</layer-list>

-1
一个简单的解决方案是扩展TextView,然后重写onDraw方法。
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Paint paint = new Paint();
    paint.setColor(ContextCompat.getColor(getContext(),R.color.colorTextUnderLine));
    paint.setStrokeWidth(10);
    canvas.drawLine(0.0f,canvas.getHeight(),canvas.getWidth(),canvas.getHeight(),
            paint);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接