¿Hay una manera fácil de agregar un borde en la parte superior e inferior de una vista de Android?

407

Tengo un TextView y me gustaría agregar un borde negro a lo largo de sus bordes superior e inferior. Intenté agregar android:drawableTopy android:drawableBottomal TextView, pero eso solo causó que toda la vista se volviera negra.

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

¿Hay alguna manera de agregar fácilmente un borde superior e inferior a una vista (en particular, una vista de texto) en Android?

emmby
fuente
2
Es sorprendente que nadie haya mencionado dividerVertical ! Esto es lo creado por Android, para lograr, bueno, divisores verticales. COold no será más fácil y haces todo en el panel "Diseño" WYSIWYG en Android Studio.
Fattie
note dividerVertical se implementó en la API 11.
JPM
1
¿Tal vez pueda mostrar cómo usar dividerVertical?
androidguy

Respuestas:

430

En Android 2.2 puedes hacer lo siguiente.

Cree un dibujo xml como /res/drawable/textlines.xml y asígnelo como una propiedad de fondo de 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>

La desventaja de esto es que debe especificar un color de fondo opaco, ya que las transparencias no funcionarán. (Al menos pensé que sí, pero me equivoqué). En el ejemplo anterior, puede ver que el color sólido de la primera forma #FFdddddd se copia en el color del trazo de la segunda forma.

Emile
fuente
11
También vea esta solución, que también funciona para TextViews, si desea un borde alrededor: stackoverflow.com/questions/3263611/…
emmby
26
Intente usar android:color="@null"para evitar problemas de fondo opaco.
Matt Briançon
@emmby: al probar este código en la tableta, toma tiempo renderizar en la pantalla, después de que se muestran los bordes de 1 segundo cuando me desplazo
Chetan
55
El truco android: color = "@ null" no me sirvió para mantener la transparencia y solo mostrar un borde a un lado de la vista. La respuesta del usuario 1051892 a continuación hizo el trabajo.
Rick Pastoor
8
Esta solución también hizo un borde a la izquierda y a la derecha, aunque más delgado.
AlikElzin-kilaka
279

He usado un truco para que el borde se muestre fuera del contenedor. Con este truco, solo se dibuja una línea, por lo que se mostrará el fondo de la vista subyacente.

<?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>
usuario1051892
fuente
3
Esto funcionó muy bien para mí, con algunos ajustes para hacer que la línea sea un poco más delgada.
Jeff
1
Muy buen truco, aunque podría ser mejor si no tenemos que engañar a la computadora para hacer las cosas.
Yukio Fukuzawa
¡bien hecho! lo que debe ver es el elemento izquierdo, superior, derecho, inferior debe - (ancho del trazo) dp
asakura89
No mostró ningún borde, solo hice que mi contenido de vista se viera más pequeño :(
AlikElzin-kilaka
1
Bien hecho, trabajado con fondo transparente. Probado en 2.2 y 4.4.2. Debe cubrir todos en el medio :)
humanos
97

Opción 1: forma dibujable

Esta es la opción más simple si desea un borde alrededor de un diseño o vista en el que puede establecer el fondo. Cree un archivo XML en la drawablecarpeta que se vea así:

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

Puede eliminar el solidsi no desea un relleno. El conjunto background="@drawable/your_shape_drawable"en su diseño / vista.

Opción 2: Vista de fondo

Aquí hay un pequeño truco que he usado en un RelativeLayout. Básicamente, tiene un cuadrado negro debajo de la vista que desea dar a un borde, y luego dale a esa vista algo de relleno (¡no margen!) Para que el cuadrado negro se vea en los bordes.

Obviamente, esto solo funciona correctamente si la vista no tiene áreas transparentes. Si es así, te recomendaría que escribas una costumbre BorderViewque solo dibuje el borde, solo debería ser una docena de líneas de código.

<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/..." />

Si usted se pregunta, que hace el trabajo con adjustViewBounds=true. Sin embargo, no funciona si quieres tener un fondo completo RelativeLayout, porque hay un error que te impide llenar un RelativeLayouta View. En ese caso, recomendaría el Shapedibujable.

Opción 3: 9 parches

Una última opción es usar un dibujo de 9 parches como este:

Puede usarlo en cualquier vista donde pueda configurarlo android:background="@drawable/...". Y sí, tiene que ser 6x6: probé 5x5 y no funcionó.

La desventaja de este método es que no puede cambiar los colores muy fácilmente, pero si desea bordes elegantes (por ejemplo, solo un borde en la parte superior e inferior, como en esta pregunta), es posible que no pueda hacerlo con el Shapedibujo , que no es muy poderoso.

Opción 4: vistas adicionales

Olvidé mencionar esta opción realmente simple si solo quieres bordes arriba y abajo de tu vista. Puede poner su vista en vertical LinearLayout(si aún no lo está) y luego agregar Views vacías arriba y debajo de esta manera:

<View android:background="#000" android:layout_width="match_parent" android:layout_height="1px"/>
Timmmm
fuente
44
9 parche y la forma dibujable están bien, pero recomendaría no agregar vistas o vistas de imágenes para resolver este problema. La razón es que debe eliminar tantos <elementos> de sus diseños para mejorar el rediseño y la animación del diseño. Quitaría estos de inmediato e implementaría algunos similares a la opción 1 o 2.
Emile
2
@Emile Eso es cierto, pero si está utilizando un ListView personalizado que no admite divisores, una Vista simple está bien. El impacto en el rendimiento es casi nulo, especialmente si está seguro de mantener baja la profundidad de su diseño. También evita los errores con los divisores ListView entre dispositivos (he visto algunos dispositivos que ignoran esta propiedad).
Tom
También puede usar el patrón de vista eficiente con vistas de lista para asegurarse de reducir la cantidad de llamadas a findViewByID, que a menudo es la causa del bajo rendimiento de la lista.
Emile
En iOS solo tienes una forma de hacerlo. En Android deberías probar al menos cuatro, en mi caso la opción 4 era el camino a seguir. A veces, los elementos dibujables como fondo se cuelgan para renderizarse, tenga en cuenta.
Ratata Tata
1
¿Por qué Android no tenía la solución más fácil para tales cosas? como en otro idioma, como HTML, CSS o algo JavaFX, WPF ......
Asif Mushtaq
95

Para agregar un 1dpborde blanco solo en la parte inferior y tener un fondo transparente, puede usar lo siguiente, que es más simple que la mayoría de las respuestas aquí.

Para la TextViewu otra vista, agregue:

android:background="@drawable/borderbottom"

Y en el drawabledirectorio agregue el siguiente XML, llamadoborderbottom.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>

Si desea un borde en la parte superior, cambie el android:top="-2dp"aandroid:bottom="-2dp"

El color no necesita ser blanco y el fondo tampoco tiene que ser transparente.

El solidelemento puede no ser requerido. Esto dependerá de su diseño (gracias V. Kalyuzhnyu).

Básicamente, este XML creará un borde con la forma del rectángulo, pero luego empujará los lados superior, derecho e izquierdo más allá del área de representación de la forma. Esto deja solo el borde inferior visible.

Tigger
fuente
8
Esta es la mejor solución, ya que no crea sobregiro como los demás
Greg Ennis
¿Hay alguna razón por la que las posiciones negativas sean dos veces más grandes que el golpe con ( -2dpvs 1dp)? Parece funcionar cuando son iguales en cantidad ( -1y 1).
Denis Kniazhev
@DenisKniazhev: Al usar -2dpel resultado siempre estaba limpio. Creo que hubo un caso de prueba donde el resultado no fue limpio. No recuerdo si era una pantalla de baja o alta densidad o incluso una versión anterior de Android (2.x tal vez).
Tigger
Interesante. ¿Sabe si este es un caso general, por ejemplo, si lo uso 4dppara el ancho del trazo, debería usarlo -8dppara el posicionamiento?
Denis Kniazhev
1
@DenisKniazhev: (de memoria) parecía un cálculo de coma flotante que era un poco grande o pequeño. Esto significa que un valor de -5dpsería todo lo que se necesita con un valor de ancho de 4pd. Simplemente necesitaba ser un poco más grande para superar la imprecisión del valor flotante.
Tigger
36

La respuesta actualmente aceptada no funciona. Crea bordes verticales delgados en los lados izquierdo y derecho de la vista como resultado del suavizado.

Esta versión funciona perfectamente. También le permite establecer los anchos de los bordes de forma independiente, y también puede agregar bordes en los lados izquierdo / derecho si lo desea. El único inconveniente es que NO admite transparencia.

Cree un xml dibujable /res/drawable/top_bottom_borders.xmlcon el siguiente código y asígnelo como una propiedad de fondo de 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>

Probado en Android KitKat a través de Marshmallow

gregschlom
fuente
¿Cómo hacer el interior transparente?
Hitesh Sahu
1
@HiteshSahu Creo que la desventaja de esto es que tendrías que hacer coincidir el fondo del diseño con el fondo del widget aquí
chntgomez
35

Entonces quería hacer algo ligeramente diferente: un borde en la parte inferior SOLAMENTE, para simular un divisor ListView. Modifiqué la respuesta de Piet Delport y obtuve esto:

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

Tenga en cuenta el uso de px en lugar de dp para obtener exactamente 1 divisor de píxeles (algunos DPI del teléfono harán desaparecer una línea de 1dp).

phreakhead
fuente
2
¡querido! ¿Cuál es el valor de "@color/background_trans_light"?
Shajeel Afzal
Saludos @phreakhead, ¡esto realmente funciona para mí! Sin borde superior, izquierdo o derecho. Exactamente lo que necesitaba, gracias!
shanehoban
2
¿Puedes explicar por qué cuando pones -2dp desaparece y cuando pones -1dp todavía está visible? ¡Gracias!
Francisco Romero
9

Tal como dijo @Nic Hubbard, hay una manera muy fácil de agregar una línea de borde.

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

Puede cambiar la altura y el color de fondo a lo que desee.

MattZ
fuente
8

Mis respuestas se basan en la versión @Emile, pero uso color transparente en lugar de sólido.
Este ejemplo dibujará un borde inferior de 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 es el color del fondo en el que dibuja su vista con borde.

Si desea cambiar la posición del borde, cambie el desplazamiento con uno de:

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

o combinarlos para tener 2 o más bordes:

android:bottom="2dp" android:top="2dp"
vovahost
fuente
7

También puede ajustar la vista en FrameLayout, luego establecer el color de fondo y el relleno del marco a lo que desee; sin embargo, la vista de texto, de manera predeterminada, tiene un fondo "transparente", por lo que también deberá cambiar el color de fondo de la vista de texto.

okaram
fuente
Bastante simple. Usted controla el tamaño y la dirección de los contornos por los márgenes de la Vista interna. Gracias.
Scott Biggs
5

¿Por qué no simplemente crear una vista alta de 1dp con un color de fondo? Luego se puede colocar fácilmente donde desee.

Nic Hubbard
fuente
4

Solo para agregar mi solución a la lista ...

Quería un borde inferior semitransparente que se extienda más allá de la forma original (por lo que el borde semitransparente estaba fuera del rectángulo principal).

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

Lo que me da;

ingrese la descripción de la imagen aquí

Cadab
fuente
4

Para cambiar esto:

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

Prefiero este enfoque en "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>

Esto solo hace los bordes, no un rectángulo que aparecerá si su fondo tiene un color.

Dinidiniz
fuente
3

Primero cree un archivo xml con el contenido que se muestra a continuación, asígnele el nombre border.xml y colóquelo dentro de la carpeta de diseño dentro del directorio 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>

Después de eso dentro del uso del código

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

Esto hará una línea negra en la parte superior e inferior de TextView.

Nikhil Dinesh
fuente
Sí, funcionará, lo he comprobado. Botón botón = (Botón) findViewById (botón R.id.); button.setBackgroundResource (R.layout.border);
Nikhil Dinesh
He usado color negro en el archivo xml anterior, su color de fondo puede ser negro, intente usar otro color. Definitivamente funcionará <? Xml version = "1.0" encoding = "UTF-8"?> < Shape xmlns: android = " schemas.android.com/apk/res/android "> <android sólido: color = "# 474848 "/> <stroke android: width =" 1dp "android: color =" # ffff00 "/> <padding android: left =" 1dp "android: top =" 1dp "android: right =" 1dp "android: bottom =" 1dp "/> </shape>
Nikhil Dinesh
1
No funciono para mi. La línea del borde se pintó en el medio de la vista de texto, horizontalmente.
AlikElzin-kilaka
3

Escriba debajo del código

<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" />
Abhi
fuente
2

Aquí hay una manera de lograrlo.

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

Primer elemento para trazo y segundo para fondo sólido. Ocultando las fronteras izquierda y derecha.

Kavya Shravan
fuente
2

La manera más simple de agregar bordes para insertar los bordes usando InsetDrawable, a continuación, mostrará solo el borde superior:

<?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>
Zaid Mirza
fuente
2

Agregar archivo a 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>

Agregar enlace en este archivo a la propiedad de fondo

Oleg
fuente
1

Intente ajustar la imagen con una distribución lineal y configure su fondo con el color del borde que desee alrededor del texto. Luego, configure el relleno en la vista de texto para que sea el grosor que desea para su borde.

Mate
fuente
1

También puede usar una ruta de 9 para hacer su trabajo. Créelo para que el píxel de color no se multiplique en altura, sino solo el píxel transparente.

Kowlown
fuente
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>
Vinoj Vetha
fuente
1

Simplemente agregue Vistas en la parte superior e inferior de la 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>
Levon Petrosyan
fuente
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
Vinod Joshi
fuente
-1
<TextView
    android:id="@+id/textView3"
    android:layout_width="match_parent"
    android:layout_height="2dp"
    android:background="#72cdf4"
    android:text=" aa" />

Simplemente agregue este TextView debajo del texto donde desea agregar el borde

Aquib Maniyar
fuente
-1

Solo para hacer cumplir las respuestas de @phreakhead y user1051892 , <item android:bottom|android:left|android:right|android:top>si es negativo, debe ser mayor que <stroke android:width>. Si no, la pintura del elemento se mezclará con la pintura de trazo y puede pensar que estos valores no funcionan.

Garry Dias
fuente