开放式的安卓划痕?

103

有没有可能创建一个只在特定边框上有描边的Android形状对象?

例如,我有:

<stroke 
 android:width="3dip" 
 android:color="#000000"
    android:dashWidth="10dip" 
    android:dashGap="6dip" />

这与以下 CSS 类似:

border: 3px dashed black;

我如何只在一个边框上设置描边?这是我在CSS中的做法:

border-left: 3px dashed black;

在Android XML中如何做到这一点?

8个回答

135

我用这个方法得到了一个好的解决方案:

<?xml version="1.0" encoding="utf-8"?>

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- This is the line -->
    <item android:top="-1dp" android:right="-1dp" android:left="-1dp">
      <shape>
            <solid android:color="@android:color/transparent" />
            <stroke android:width="1dp" android:color="#ffffff" />
      </shape>
    </item>

</layer-list>

如果您需要一个透明背景但仍需要有边框颜色(在我的情况下,我只需要底部的线),那么这个方法很有效。如果您需要一个背景颜色,可以像Maragues的回答那样添加实心形状颜色。

编辑1

对于高密度设备,使用低dp值可能会导致非常细或不可见的描边或距离。当设置ListView分隔线时,您也可能遇到这种情况。

最简单的解决方法是改用1px的距离而不是1dp。这将使该线在所有密度下始终可见。最好的解决方案是为每个密度创建尺寸资源,以获得每个设备的最佳尺寸。

编辑2

有趣的是,我6年后尝试使用这个方法,在Lollipop设备上却无法得到很好的结果。

可能当前的解决方案是使用9-patch。在这么长时间之后,Android应该已经为这个问题提供了一个简单的解决方案。


1
@EduZamora 是的,似乎对于高密度设备,-1dp 的效果不如预期。 - htafoya
@htafoya 这是一个非常棒的解决方案。谢谢! - abriggs
我改成了dip。 - Jordy
@Jordy dip 和 dp 是相同的。 - htafoya
@htafoya 我正在使用它来控制我的按钮,但是它显示在顶部而不是底部,你能帮我解决一下吗? - user4050065
显示剩余4条评论

62

我知道这个问题很久以前就发布了,所以答案可能不会被提问者使用,但它可能仍然有助于其他人。

 <?xml version="1.0" encoding="UTF-8"?>
    <!-- inset is used to remove border from top, it can remove border from any other side-->
    <inset xmlns:android="http://schemas.android.com/apk/res/android"
        android:insetTop="-2dp"
        >
    <shape xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rectangle">
        <stroke android:width="1dp" android:color="#b7b7b7" />
        <corners android:bottomRightRadius="5dp"  android:bottomLeftRadius="5dp"/>

        <solid android:color="#454444"/>
    </shape>
    </inset>

使用 inset 标签,并给出你想要移除的边框的负值。

可能的值包括:

android:insetTop="-1dp" android:insetBottom="-1dp" android:insetLeft="-1dp" android:insetRight="-1dp"


是的,不要像我一样,在没有阅读完整个答案的情况下尝试将插入属性放在描边标签中!(顺便感谢回答者。完美的解决方案) - Kiran
1
优雅!我喜欢这个解决方案。 - Hao Qi

42
我通过使用一个列表层来解决了这个问题,将两个形状组合在一起,其中一个形状的高度为1dp,放置在底部。
optionscreen_bottomrectangle.xml:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- This is the line -->
<item>
      <shape>
            <solid android:color="#535353" />
      </shape>
</item>
<!-- This is the main color -->
<item android:bottom="1dp">
     <shape>
           <solid android:color="#252525" />
     </shape>
</item>
</layer-list>

接下来,在layout/main.xml文件中

<TextView
    android:id="@+id/bottom_rectangle"
    android:background="@drawable/optionscreen_bottomrectangle"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_below="@id/table_options"
    android:layout_above="@id/exit_bar"/>

在 table_options 和 exit_bar 之间填充一个背景,并在 exit_bar 前打印一个1dp的线。这对我很有用,希望能帮到其他人。

答案已编辑以将图层放置在正确的顺序中。谢谢 Alex!


如果你真的想得到一个答案,最好不要发布回答。当其他开发人员看到已经有了一个答案(尽管在这种情况下实际上没有),他们就不太愿意回答了。 - MrSnowflake

33

使用填充方式来实现其他回答所述效果的另一种方法。这个小片段在上下各加了一个边框。

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- This is the line -->
    <item>
          <shape>
                <padding android:left="0dp" android:top="1dp" android:right="0dp" android:bottom="1dp"/>
                <solid android:color="#898989" />
          </shape>
    </item>
    <!-- This is the main color -->
    <item>
         <shape>
             <solid android:color="#ffffff" />
         </shape>
    </item>
</layer-list>

5
如果您需要圆角,这绝对是最好的答案。 - MacKinley Smith
这个也非常帮助我。请试一试并点赞。 - Boy
@ug_ 我认为这是最好的方法。完美地运作,谢谢。 - Lalit Sharma
可以工作。在Android Studio(v1.1)预览窗格中看起来完全错误,但在设备上却没问题。 - Murat Ögat

27

@Maragues的回答是反过来的,因为layer-list可绘制对象是从上往下绘制的(也就是说列表中最后一个项目会被绘制在顶部):

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- This is the line -->
<item>
      <shape>
            <solid android:color="#535353" />
      </shape>
</item>
<!-- This is the main color -->
<item android:bottom="1dp">
     <shape>
           <solid android:color="#252525" />
     </shape>
</item>

</layer-list>

这将有效地用线条颜色填充形状,然后在其上绘制背景颜色,留下最后1dp的空间以展示线条颜色。


2
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >


<item>
    <shape android:shape="rectangle" >
        <stroke  android:width="2dp"
                 android:color="#BBBBBB" />
        <solid android:color="@android:color/transparent" />
    </shape>
</item>
<item  android:bottom="2dp" >
    <shape android:shape="rectangle" >
        <stroke  android:width="2dp"
                 android:color="@color/main_background_color" />
        <solid android:color="@android:color/transparent" />
    </shape>
</item>


2
我使用了以下代码。
<?xml version="1.0" encoding="UTF-8"?>
<!-- inset is used to remove border from top, it can remove border from any other side-->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:insetTop="-2dp" android:insetLeft="-2dp" android:insetRight="-2dp"
    >
    <shape xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rectangle">
        <stroke android:width="1dp" android:color="@color/colorPrimary" />
        <solid android:color="#0000"/>
        <padding android:left="2dp" android:top="2dp" android:bottom="2dp" android:right="2dp"/>
    </shape>
</inset>

0

简单高效

如果想让整个布局看起来透明,外层视图又有一层颜色覆盖,你可以构建一个视图来封装中心视图,而不会干扰到中心视图的外部视图

这样你就避免了在布局之外使用可绘制的方法,并且无需在运行时进行计算就能更好地控制视图之间的距离。

<androidx.constraintlayout.widget.ConstraintLayout .. >

    <View
        android:id="@+id/center"
        android:layout_width="100dp"
        android:layout_height="100dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:background="@color/transparent"/>

   <View
        android:id="@+id/left_overlay"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/center"
        app:layout_constraintTop_toBottomOf="@id/top_overlay"
        app:layout_constraintBottom_toTopOf="@id/bottom_overlay"
        android:background="@color/black"
        android:alpha="0.5"
        />

    <View
        android:id="@+id/right_overlay"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toRightOf="@id/center"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/top_overlay"
        app:layout_constraintBottom_toTopOf="@id/bottom_overlay"
        android:background="@color/black"
        android:alpha="0.5"
        />

    <View
        android:id="@+id/top_overlay"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@id/center"
        android:background="@color/black"
        android:alpha="0.5"
        />

    <View
        android:id="@+id/bottom_overlay"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/center"
        android:background="@color/black"
        android:alpha="0.5"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

GL


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