Открытый Android штрих?

95

Можно ли создать объект формы 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?

Рид Морс
источник

Ответы:

127

Я нашел хорошее решение с этим:

<?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>

Это хорошо работает, если вам нужен прозрачный фон, но цвет обводки открыт (в моем случае мне нужна была только нижняя строка). Если вам нужен цвет фона, вы можете добавить цвет сплошной формы, как в ответе Марага.

ИЗМЕНИТЬ 1

Иногда для устройств с высокой плотностью использование низких значений падения может заканчиваться очень тонкими или невидимыми штрихами или расстояниями. Это может случиться с вами также при установке разделителей ListView.

Самый простой обходной путь - использовать расстояние 1 пиксель вместо 1 dp. Это сделает линию всегда видимой при любой плотности. Лучшим решением было бы создать ресурсы размеров для каждой плотности, чтобы получить наилучший размер для каждого устройства.

Редактировать 2

Забавно, но я попытался использовать это 6 лет спустя, и я не могу получить хороший результат на устройствах Lollipop.

Вероятно, текущее решение - использовать 9-патч. За все это время Android должен был найти простое решение этой проблемы.

Хтафоя
источник
Это тоже сработало для меня, но я точно не знаю, почему мне пришлось использовать -2dp вместо -1dp. Если бы я использовал последнее, я все равно мог бы видеть тонкую линию.
Edu Zamora
1
@EduZamora да, похоже, для устройств с высокой плотностью -1dp работает не так, как ожидалось
htafoya 01
Я также получаю границу для всех сторон, но не только нижнюю границу.
Cheok Yan Cheng
@YanChengCHEOK попробуйте использовать 1px вместо 1dp.
htafoya
@htafoya, это отличное решение. Благодарность!
abriggs 07
53

Я знаю, что этот вопрос был опубликован давно, поэтому ответ не будет использоваться тем, кто разместил этот вопрос, но он все равно может помочь другим.

 <?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"

Нирмал Дхара
источник
Да, и не делайте того, что я сделал, и не пытайтесь вставить атрибут вставки в тег обводки, не читая остальную часть ответа! (спасибо за ответ, BTW OP. Идеальное решение)
Kiran
элегантно! Мне нравится это решение
Хао Ци
41

Я решил это, используя слой-список, объединив две фигуры, одна из которых с высотой 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. Это помогло мне, надеюсь, это поможет кому-то другому.

Ответ отредактирован для размещения слоев в правильном порядке. Спасибо, Алекс!

Maragues
источник
Может быть удобно не публиковать ответ, если вы действительно хотите получить ответ самостоятельно. Когда другие разработчики видят, что ответ уже есть (хотя в данном случае это на самом деле нет), они не так склонны отвечать.
MrSnowflake
31

Другой подход к другим ответам с использованием заполнения. Этот небольшой фрагмент образует границу сверху и снизу.

<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>
ug_
источник
4
Это, безусловно, лучший ответ, если вам нужны закругленные углы.
MacKinley Smith
Этот тоже мне очень помог. Пожалуйста, попробуйте и проголосуйте за
Boy
@ug_ Думаю, это лучший подход. Работает отлично, спасибо
Лалит Шарма
Работает. Выглядит совершенно неправильно в панели предварительного просмотра Android Studio (v1.1), но на устройстве все в порядке.
Мурат Огат,
26

Ответ @Maragues - в обратном порядке, поскольку чертежи списка слоев рисуются сверху вниз (что означает, что последний элемент в списке отображается сверху):

<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

Брайан Коронел
источник