Есть ли простой способ добавить границы сверху и снизу представления Android?


407

У меня есть TextView, и я хотел бы добавить черную рамку вдоль ее верхней и нижней границ. Я попытался добавить android:drawableTopи android:drawableBottomк TextView, но это только заставило весь вид стать черным.

<TextView
    android:background="@android:color/green"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:drawableTop="@android:color/black"
    android:drawableBottom="@android:color/black"
    android:text="la la la" />

Есть ли способ легко добавить верхнюю и нижнюю границу к представлению (в частности, к TextView) в Android?


2
Удивительно, что никто не упомянул dividerVertical ! Это то, что создано Android для достижения вертикальных разделителей. Не проще, и вы все делаете на панели «Дизайн» WYSIWYG в Android Studio.
Толстяк

note dividerVertical был реализован в API 11.
JPM

1
Может быть, вы можете показать, как использовать dividerVertical?
AndroidGuy

Ответы:


430

В Android 2.2 вы можете сделать следующее.

Создайте отрисовываемый файл XML, например /res/drawable/textlines.xml, и назначьте его в качестве свойства фона TextView.

<TextView
android:text="My text with lines above and below"
android:background="@drawable/textlines"
/>

/res/drawable/textlines.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
      <shape 
        android:shape="rectangle">
            <stroke android:width="1dp" android:color="#FF000000" />
            <solid android:color="#FFDDDDDD" />

        </shape>
   </item>

   <item android:top="1dp" android:bottom="1dp"> 
      <shape 
        android:shape="rectangle">
            <stroke android:width="1dp" android:color="#FFDDDDDD" />
            <solid android:color="#00000000" />
        </shape>
   </item>

</layer-list>

Недостатком является то, что вы должны указать непрозрачный цвет фона, так как прозрачные пленки не будут работать. (По крайней мере, я думал, что они сделали, но я ошибся). В приведенном выше примере вы можете видеть, что сплошной цвет первой фигуры #FFdddddd копируется в цвет обводки 2-й фигуры.


11
Также посмотрите это решение, которое также работает для TextViews, если вы хотите, чтобы вокруг была вся граница: stackoverflow.com/questions/3263611/…
emmby

26
Попробуйте использовать, android:color="@null"чтобы избежать непрозрачной фоновой проблемы.
Мэтт Бриансон

@emmby: при тестировании этого кода на планшете требуется время для рендеринга на экране, через 1 секунду при прокрутке отображаются границы
Chetan

5
Трюк android: color = "@ null" не помог мне сохранить прозрачность и просто отобразить границу с одной стороны вида. Ответ от user1051892 ниже сделал свою работу!
Рик Пастур

8
Это решение сделало границу слева и справа, хотя и более тонким.
Алик Эльзин-килака

279

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

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:bottom="1dp"
        android:left="-2dp"
        android:right="-2dp"
        android:top="-2dp">
        <shape android:shape="rectangle" >
            <stroke
                android:width="1dp"
                android:color="#FF000000" />

            <solid android:color="#00FFFFFF" />

            <padding android:left="10dp"
                android:right="10dp"
                android:top="10dp"
                android:bottom="10dp" />
        </shape>
    </item>

</layer-list>

3
Это отлично сработало для меня, сделав несколько настроек, чтобы сделать линию немного тоньше.
Джефф

1
Очень хороший трюк, хотя он может быть лучше, если нам не нужно обманывать компьютер, чтобы добиться цели.
Юкио Фукузава

красиво сделано! то, что вы должны смотреть, это элемент слева, сверху, справа, снизу следует - (ширина обводки) dp
asakura89

Границу не показывали - просто сделал мой вид контента меньше :(
AlikElzin-kilaka

1
Красиво сделано, работает с прозрачным фоном. Проверено в 2.2 и 4.4.2. Должен охватить все промежуточное :)
HumaN

98

Вариант 1: Форма Drawable

Это самый простой вариант, если вам нужна рамка вокруг макета или вида, в которой вы можете установить фон. Создайте файл XML в drawableпапке, которая выглядит примерно так:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <solid android:color="#8fff93" />

    <stroke
        android:width="1px"
        android:color="#000" />

</shape>

Вы можете удалить, solidесли вы не хотите заполнять. Набор background="@drawable/your_shape_drawable"на ваш макет / вид.

Вариант 2: фоновый вид

Вот маленький трюк, который я использовал в RelativeLayout. По сути, у вас есть черный квадрат под видом, который вы хотите задать рамку, а затем дать этому виду некоторый отступ (не отступ!), Чтобы черный квадрат просвечивал по краям.

Очевидно, что это работает правильно, только если у вида нет прозрачных областей. Если это произойдет, я бы порекомендовал вам написать кастом, BorderViewкоторый рисует только границу - это должно быть всего несколько десятков строк кода.

<View
    android:id="@+id/border"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignBottom="@+id/image"
    android:layout_alignLeft="@+id/image"
    android:layout_alignRight="@+id/image"
    android:layout_alignTop="@+id/main_image"
    android:background="#000" />

<ImageView
    android:id="@+id/image"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_...
    android:padding="1px"
    android:src="@drawable/..." />

Если вам интересно, что делает работу с adjustViewBounds=true. Тем не менее, это не работает, если вы хотите иметь фон целиком RelativeLayout, потому что есть ошибка, которая мешает вам заполнить RelativeLayoutс View. В этом случае я бы порекомендовал ShapeDrawable.

Вариант 3: 9-патч

Последний вариант - использовать 9-патч, как этот:

Вы можете использовать его в любом представлении, где вы можете установить android:background="@drawable/...". И да, это должно быть 6х6 - я пробовал 5х5, и это не сработало.

Недостаток этого метода в том, что вы не можете изменить цвета очень легко, но если вам нужны причудливые границы (например, только границы сверху и снизу, как в этом вопросе), то вы не сможете сделать их с помощью Shapeрисования. , который не очень мощный.

Вариант 4: дополнительные виды

Я забыл упомянуть этот действительно простой вариант, если вы хотите, чтобы границы только выше и ниже вашего обзора. Вы можете поместить свой вид по вертикали LinearLayout(если это еще не так), а затем добавить пустые Views над и под ним, например:

<View android:background="#000" android:layout_width="match_parent" android:layout_height="1px"/>

4
9 патч и нарисованная форма в порядке, но я бы рекомендовал не добавлять виды или изображения для решения такой проблемы. Причина в том, что вы должны удалить как можно больше таких <элементов> из ваших макетов, чтобы улучшить их перерисовку и анимацию. Я бы сразу же убрал их и реализовал нечто подобное варианту 1 или 2.
Эмиль

2
@Emile Это правда, но если вы используете пользовательский ListView, который не поддерживает разделители, простой View подойдет. Влияние на производительность практически равно нулю, особенно если вы уверены, что сохраните глубину макета. Это также позволяет обойти ошибки, связанные с разделителями ListView между устройствами (я видел некоторые устройства, которые игнорируют это свойство).
Том

Вы также можете использовать эффективный шаблон представления с списками, чтобы уменьшить количество вызовов для findViewByID, что часто является причиной низкой производительности списка.
Эмиль

В iOS у вас есть только один способ сделать это. На Android вы должны протестировать как минимум четыре, в моем случае вариант 4 был путь. Иногда рисовать как фон висят, чтобы знать, об этом.
Ратата Тата

1
Почему у андроида не было самого простого решения для таких вещей? как и в других языках, таких как HTML, CSS или что-то JavaFX, WPF ......
Асиф Муштак

95

Чтобы добавить 1dpбелую рамку только внизу и иметь прозрачный фон, вы можете использовать следующее, что проще, чем большинство ответов здесь.

Для просмотра TextViewили добавления добавьте:

android:background="@drawable/borderbottom"

И в drawableкаталоге добавьте следующий XML, называемыйborderbottom.xml

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

Если вы хотите границы в верхней части, изменить android:top="-2dp"кandroid:bottom="-2dp"

Цвет не обязательно должен быть белым, а фон не обязательно должен быть прозрачным.

solidМожет не быть необходимым элементом. Это будет зависеть от вашего дизайна (спасибо В. Калюжню).

По сути, этот XML создаст границу, используя форму прямоугольника, но затем вытолкнет верхнюю, правую и левую стороны за область рендеринга для фигуры. Это оставляет только нижнюю границу видимой.


8
Это лучшее решение, так как оно не создает перерасход, как другие
Грег Эннис

Есть ли причина, по которой отрицательные позиции в два раза больше, чем ход ( -2dpпротив 1dp)? Кажется, работает, когда они равны по количеству ( -1и 1).
Денис Княжев

@DenisKniazhev: При использовании -2dpрезультат всегда был чистым. Я думаю, что был тестовый случай, где результат не был чистым. Я не могу вспомнить, был ли это экран с низкой или высокой плотностью или даже более старая версия Android (возможно, 2.x).
Тигр

Интересно. Знаете ли вы, если это общий случай, например, если я использую 4dpдля ширины хода, я должен использовать -8dpдля позиционирования?
Денис Княжев

1
@DenisKniazhev: (из памяти) это выглядело как вычисление с плавающей запятой, которое было немного большим или маленьким. Это означает, что значением -5dpбудет все, что нужно со значением ширины 4pd. Просто нужно быть немного больше, чтобы преодолеть неточность значения с плавающей точкой.
Тигр

36

В настоящее время принятый ответ не работает. Это создает тонкие вертикальные границы на левой и правой сторонах вида в результате сглаживания.

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

Создайте отрисовываемый файл XML /res/drawable/top_bottom_borders.xmlс указанным ниже кодом и назначьте его в качестве фонового свойства TextView.

<?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="#DDDD00" /> <!-- border color -->
        </shape>
    </item>

    <item
        android:bottom="1dp" 
        android:top="1dp">   <!-- adjust borders width here -->
        <shape android:shape="rectangle">
            <solid android:color="#FFFFFF" />  <!-- background color -->
        </shape>
    </item>
</layer-list>

Проверено на Android KitKat через Зефир


Как сделать внутри прозрачным?
Хитеш Саху

1
@HiteshSahu Я думаю, что недостатком этого является то, что вам придется сопоставить фон макета с фоном виджета здесь
chntgomez

35

Поэтому я хотел сделать что-то немного другое: ТОЛЬКО границу снизу, чтобы имитировать разделитель ListView. Я изменил ответ Пита Дельпорта и получил это:

<?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="@color/background_trans_light" />    

        </shape>
   </item>

    <!-- this mess is what we have to do to get a bottom border only. -->
   <item android:top="-2dp"
         android:left="-2dp"
         android:right="-2dp"
         android:bottom="1px"> 
      <shape 
        android:shape="rectangle">    
            <stroke android:width="1dp" android:color="@color/background_trans_mid" />
            <solid android:color="@null" />
        </shape>
   </item>

</layer-list>

Обратите внимание на использование px вместо dp, чтобы получить ровно 1 пиксельный делитель (некоторые телефонные DPI приводят к исчезновению линии 1dp).


2
дорогой! какова стоимость "@color/background_trans_light"?
Shajeel Afzal

Ура @phreakhead, это на самом деле работает для меня! Нет верхней, левой или правой границы. Именно то, что мне было нужно, спасибо!
shanehoban

2
Не могли бы вы объяснить, почему, когда вы ставите -2dp, он исчезает, а когда вы ставите -1dp, он все еще виден? Спасибо!
Франциско Ромеро

9

Как сказал @Nic Hubbard, существует очень простой способ добавить границу.

<View
    android:layout_width="match_parent"
    android:layout_height="2dp"
    android:background="#000000" >
</View>

Вы можете изменить высоту и цвет фона на любой другой.


8

Мои ответы основаны на версии @Emile, но я использую прозрачный цвет вместо сплошного.
Этот пример нарисует нижнюю границу 2dp.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <shape android:shape="rectangle" >
            <stroke  android:width="2dp"
                     android:color="#50C0E9" />
            <solid android:color="@android:color/transparent" />
        </shape>
    </item>
    <item  android:bottom="2dp" >
        <shape android:shape="rectangle" >
            <stroke  android:width="2dp"
                     android:color="@color/bgcolor" />
            <solid android:color="@android:color/transparent" />
        </shape>
    </item>
</layer-list>

@ color / bgcolor - это цвет фона, на котором вы рисуете свой вид с рамкой.

Если вы хотите изменить положение границы, измените смещение одним из:

android:bottom="2dp"
android:top="2dp"
android:right="2dp"
android:left="2dp"

или объедините их, чтобы иметь 2 или более границ:

android:bottom="2dp" android:top="2dp"

7

Вы также можете обернуть вид в FrameLayout, а затем установить цвет фона рамки и отступа на то, что вы хотите; однако у textview по умолчанию имеется «прозрачный» фон, поэтому вам также придется изменить цвет фона textview.


Довольно просто Вы управляете размером и направлением контуров по краям внутреннего вида. Спасибо.
Скотт Биггс

5

Почему бы просто не создать 1dp высокий вид с цветом фона? Тогда его можно легко разместить там, где вы хотите.


4

Просто чтобы добавить мое решение в список ..

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

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
  <item>
    <shape android:shape="rectangle" >      
      <solid android:color="#33000000" /> <!-- Border colour -->
    </shape>
  </item>
  <item  android:bottom="2dp" >
    <shape android:shape="rectangle" >     
      <solid android:color="#164586" />
    </shape>
  </item>
</layer-list>

Что дает мне;

введите описание изображения здесь


4

Чтобы изменить это:

<TextView
    android:text="My text"
    android:background="@drawable/top_bottom_border"/>

Я предпочитаю такой подход в "drawable / top_bottom_border.xml":

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <gradient
                android:angle="270"
                android:startColor="#000"
                android:centerColor="@android:color/transparent"
                android:centerX="0.01" />
        </shape>
    </item>
    <item>
        <shape>
            <gradient
                android:angle="90"
                android:startColor="#000"
                android:centerColor="@android:color/transparent"
                android:centerX="0.01" />
        </shape>
    </item>
</layer-list>

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


3

Сначала создайте XML-файл с содержимым, показанным ниже, назовите его border.xml и поместите его в папку макета внутри директории res

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <stroke android:width="1dp" android:color="#0000" />
    <padding android:left="0dp" android:top="1dp" android:right="0dp"
        android:bottom="1dp" />
</shape>

После этого внутри кода используйте

TextView tv = (TextView)findElementById(R.id.yourTextView);
tv.setBackgroundResource(R.layout.border);

Это сделает черную линию сверху и снизу TextView.


Да, это будет работать, я проверил. Кнопка button = (Button) findViewById (R.id.button); button.setBackgroundResource (R.layout.border);
Нихил Динеш

Я использовал черный цвет в приведенном выше XML-файле, ваш фоновый цвет может быть черным, попробуйте использовать другой цвет. Это определенно будет работать <? Xml version = "1.0" encoding = "UTF-8"?> < Shape xmlns: android = " schemas.android.com/apk/res/android "> <solid android: color = "# 474848 "/> <штрих android: width =" 1dp "android: color =" # ffff00 "/> <отступ android: left =" 1dp "android: top =" 1dp "android: right =" 1dp "android: bottom =" 1dp "/> </ shape>
Нихил Динеш

1
Не работал для меня Граница была нарисована в середине текстового представления - горизонтально.
АликЭльзин-килака

3

Запишите ниже код

<View
    android:layout_width="wrap_content"
    android:layout_height="2dip"
    android:layout_below="@+id/topics_text"
    android:layout_marginTop="7dp"
    android:layout_margin="10dp"
    android:background="#ffffff" />

2

Вот способ достичь этого.

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item>
            <shape android:shape="rectangle">
                <stroke
                    android:width="1dp"
                    android:color="@color/grey_coaching_text" />
            </shape>
        </item>

        <item
            android:bottom="1dp"
            android:top="1dp">
            <shape android:shape="rectangle">
                <solid android:color="@color/white" />
            </shape>
        </item>
    </layer-list>

Первый элемент для обводки и второй для сплошного фона. Скрытие левой и правой границ.


2

Простейший способ добавить границы для вставки границ, используя InsetDrawableследующее, покажет только верхнюю границу:

<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:insetBottom="-2dp"
    android:insetLeft="-2dp"
    android:insetRight="-2dp">
    <shape android:shape="rectangle">

        <solid android:color="@color/light_gray" />
        <stroke
            android:width=".5dp"
            android:color="@color/dark_gray" />
    </shape>
</inset>

2

Добавить файл в res / drawable

<?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:left="-2dp" android:right="-2dp">
            <shape android:shape="rectangle">
                <stroke
                    android:width="1dp"
                    android:color="#000000" />
            </shape>
        </item>
    </layer-list>

Добавить ссылку на этот файл в фоновое свойство


1

Попробуйте обернуть изображение линейным макетом и установите его цвет фона в соответствии с желаемым цветом текста. Затем установите отступ для текстового представления так, чтобы он соответствовал толщине вашей границы.


1

Вы также можете использовать 9-путь, чтобы сделать свою работу. Создайте его так, чтобы цветной пиксель не умножался по высоте, а только был прозрачным пикселем.


1
<shape xmlns:android="http://schemas.android.com/apk/res/android">

<solid android:color="@color/light_grey1" />
<stroke
    android:width="1dip"
    android:color="@color/light_grey1" />

<corners
    android:bottomLeftRadius="0dp"
    android:bottomRightRadius="0dp"
    android:topLeftRadius="5dp"
    android:topRightRadius="5dp" />

    </shape>

1

Просто добавьте виды сверху и снизу View

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/your_color"
        app:layout_constraintBottom_toTopOf="@+id/textView"
        app:layout_constraintEnd_toEndOf="@+id/textView"
        app:layout_constraintStart_toStartOf="@+id/textView" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:gravity="center"
        android:text="Testing"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/your_color"
        app:layout_constraintEnd_toEndOf="@+id/textView"
        app:layout_constraintStart_toStartOf="@+id/textView"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

</android.support.constraint.ConstraintLayout>

0
// Just simply add border around the image view or view

<ImageView
                android:id="@+id/imageView2"
                android:layout_width="90dp"
                android:layout_height="70dp"
                android:layout_centerVertical="true"
                android:layout_marginRight="10dp"
                android:layout_toLeftOf="@+id/imageView1"
                android:background="@android:color/white"
                android:padding="5dip" />

// After that dynamically put color into your view or image view object

objView.setBackgroundColor(Color.GREEN);

//VinodJ/Abhishek

-1
<TextView
    android:id="@+id/textView3"
    android:layout_width="match_parent"
    android:layout_height="2dp"
    android:background="#72cdf4"
    android:text=" aa" />

Просто добавьте этот TextView ниже текста, где вы хотите добавить границу


-1

Просто для обеспечения выполнения ответов @phreakhead и user1051892 , <item android:bottom|android:left|android:right|android:top>если они отрицательные, должно быть больше, чем <stroke android:width>. Если нет, то рисование элемента будет смешано с рисованием мазка, и вы можете подумать, что эти значения не работают.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.