Existe uma maneira fácil de adicionar uma borda na parte superior e inferior de um Android View?

407

Eu tenho um TextView e gostaria de adicionar uma borda preta ao longo das bordas superior e inferior. Tentei adicionar android:drawableTope android:drawableBottomao TextView, mas isso só fez com que toda a exibição ficasse preta.

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

Existe uma maneira de adicionar facilmente uma borda superior e inferior a uma View (em particular, uma TextView) no Android?

empapar
fonte
2
É surpreendente que ninguém tenha mencionado dividerVertical ! Essa é a coisa criada pelo Android para obter, bem, divisores verticais. Não pode ser mais fácil e você faz tudo no painel WYSIWYG "Design" no Android Studio.
Fattie
note dividerVertical foi implementado na API 11.
JPM 26/02
1
Talvez você possa mostrar como usar o dividerVertical?
androidguy

Respostas:

430

No Android 2.2, você pode fazer o seguinte.

Crie um drawable xml como /res/drawable/textlines.xml e atribua-o como uma propriedade de segundo plano do 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>

O lado negativo disso é que você deve especificar uma cor de fundo opaca, pois as transparências não funcionarão. (Pelo menos eu pensei que eles fizeram, mas eu estava enganado). No exemplo acima, você pode ver que a cor sólida da primeira forma #FFdddddd é copiada na cor do traçado da 2ª forma.

Emile
fonte
11
Consulte também esta solução, que também funciona para TextViews, se você quiser uma borda por toda parte: stackoverflow.com/questions/3263611/…
emmby
26
Tente usar android:color="@null"para evitar problemas de fundo opaco.
27611 Matt Mattiançon
@emmby: quando testar este código no tablet, é preciso tempo para render em tela, após 1 fronteiras SEC Buscar exibida quando eu rolar
Chetan
5
O truque android: color = "@ null" não fez o mesmo por manter a transparência e exibir apenas uma borda em um lado da vista. A resposta do usuário1051892 abaixo fez o trabalho!
Rick Pastoor
8
Essa solução também fazia uma borda à esquerda e à direita - embora mais fina.
AlikElzin-Kilaka
279

Eu usei um truque para que a borda seja exibida fora do contêiner. Com esse truque, apenas uma linha é desenhada para que o plano de fundo seja mostrado na vista subjacente.

<?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>
user1051892
fonte
3
Isso funcionou muito bem para mim, com alguns ajustes para tornar a linha um pouco mais fina.
19413 Jeff
1
Um truque muito bom, embora possa ser melhor se não for necessário enganar o computador para fazer as coisas.
Yukio Fukuzawa
bem feito! o que você deve prestar atenção é esquerda do item, superior, direita e inferior deve - (largura de acidente vascular cerebral) dp
asakura89
Não mostrou nenhuma borda - apenas fez com que meu conteúdo de visualização parecesse menor :(
AlikElzin-kilaka 30/07/2013
1
Bem feito, trabalhou com fundo transparente. Testado em 2.2 e 4.4.2. Deve cobrir todos entre :)
humanos
97

Opção 1: Forma Drawable

Essa é a opção mais simples se você quiser uma borda em torno de um layout ou exibição na qual possa definir o plano de fundo. Crie um arquivo XML na drawablepasta que se parece com isso:

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

Você pode remover o solidse não desejar um preenchimento. O conjunto background="@drawable/your_shape_drawable"no seu layout / exibição.

Opção 2: Vista em segundo plano

Aqui está um pequeno truque que eu usei no RelativeLayout. Basicamente, você tem um quadrado preto embaixo da vista que deseja dar uma borda e, em seguida, dê a ela um pouco de preenchimento (não margem!) Para que o quadrado preto apareça nas bordas.

Obviamente, isso só funciona corretamente se a visualização não tiver áreas transparentes. Se isso acontecer, recomendo que você escreva um costume BorderViewque desenhe apenas a borda - deve haver apenas algumas dezenas de linhas 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/..." />

Se você está se perguntando, ele faz o trabalho com adjustViewBounds=true. No entanto, não funciona se você deseja ter um plano de fundo em um todo RelativeLayout, porque há um erro que impede que você preencha um RelativeLayoutcom a View. Nesse caso, eu recomendaria o Shapedrawable.

Opção 3: 9 patches

Uma opção final é usar um drawable de 9 patches como este:

Você pode usá-lo em qualquer vista em que possa definir android:background="@drawable/...". E sim, precisa ser 6x6 - tentei 5x5 e não funcionou.

A desvantagem desse método é que você não pode alterar as cores com muita facilidade, mas se você deseja bordas sofisticadas (por exemplo, apenas uma borda na parte superior e inferior, como nesta pergunta), talvez não consiga fazê-las com o Shapedrawable , o que não é muito poderoso.

Opção 4: visualizações extras

Esqueci de mencionar essa opção realmente simples se você quiser apenas bordas acima e abaixo da sua visualização. Você pode colocar sua visualização em uma vertical LinearLayout(se ainda não estiver) e adicionar Views vazios acima e abaixo desta forma:

<View android:background="#000" android:layout_width="match_parent" android:layout_height="1px"/>
Timmmm
fonte
4
O patch 9 e o shape drawable estão ok, mas eu recomendaria não adicionar visualizações ou visualizações de imagens para resolver esse problema. O motivo é que você deve remover tantos <elementos> de seus layouts para melhorar o redesenho e a animação do layout. Eu iria retirar estes para fora imediatamente e implementar algum semelhante a opção 1 ou 2.
Emile
2
@Emile Isso é verdade, mas se você estiver usando um ListView personalizado que não suporta divisores, um modo de exibição simples é bom. O impacto no desempenho é quase nulo, especialmente se você tiver certeza de manter o layout em profundidade. Ele também evita bugs com os divisores do ListView entre dispositivos (vi alguns dispositivos que ignoram essa propriedade).
Tom
Você também pode usar o padrão eficiente de visualizador com visualizações de lista para garantir a redução do número de chamadas para findViewByID, que geralmente é a causa do desempenho ruim da lista.
Emile
No iOS, você tem apenas uma maneira de fazer isso. No android, você deve testar pelo menos quatro, no meu caso, a opção 4 foi o caminho a percorrer. Às vezes, os desenháveis ​​como pano de fundo penduram para renderizar, esteja ciente disso.
Ratata Tata
1
Por que o Android não tem a solução mais fácil para essas coisas? como em outra linguagem, como HTML, CSS ou algo como JavaFX, WPF ......
Asif Mushtaq
95

Para adicionar uma 1dpborda branca apenas na parte inferior e ter um fundo transparente, use o seguinte, que é mais simples do que a maioria das respostas aqui.

Para a TextViewou outra visualização, adicione:

android:background="@drawable/borderbottom"

E no drawablediretório, adicione o seguinte XML, chamadoborderbottom.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>

Se você deseja uma borda na parte superior, altere android:top="-2dp"paraandroid:bottom="-2dp"

A cor não precisa ser branca e o fundo também não precisa ser transparente.

O solidelemento pode não ser necessário. Isso vai depender do seu design (obrigado V. Kalyuzhnyu).

Basicamente, esse XML criará uma borda usando a forma de retângulo, mas empurrará os lados superior, direito e esquerdo para além da área de renderização da forma. Isso deixa apenas a borda inferior visível.

Tigre
fonte
8
Esta é a melhor solução, pois ela não cria excedentes como os outros
Greg Ennis
Existe uma razão para as posições negativas serem duas vezes maiores que o AVC com ( -2dpvs 1dp)? Parece funcionar quando são iguais em quantidade ( -1e 1).
Denis Kniazhev
@DenisKniazhev: Ao usar -2dpo resultado estava sempre limpo. Eu acho que houve um caso de teste em que o resultado não foi limpo. Não me lembro se era uma tela de baixa ou alta densidade ou mesmo uma versão mais antiga do Android (talvez 2.x).
Tigger
Interessante. Você sabe se este é um caso geral, por exemplo, se eu uso 4dpna largura do traço, devo usar -8dpno posicionamento?
Denis Kniazhev
1
@ DenisKniazhev: (da memória) parecia um cálculo de ponto flutuante que era um pouco grande ou pequeno. Isso significa que um valor de -5dpseria tudo o que é necessário com um valor de largura de 4pd. Ele simplesmente precisava ser um pouco maior para superar a imprecisão do valor flutuante.
quer
36

A resposta atualmente aceita não funciona. Ele cria bordas verticais finas nos lados esquerdo e direito da exibição, como resultado da suavização de serrilhado.

Esta versão funciona perfeitamente. Ele também permite que você defina as larguras das bordas independentemente, e também pode adicionar bordas nos lados esquerdo / direito, se desejar. A única desvantagem é que ele NÃO suporta transparência.

Crie um drawable xml nomeado /res/drawable/top_bottom_borders.xmlcom o código abaixo e atribua-o como uma propriedade em segundo plano do 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>

Testado no Android KitKat através do Marshmallow

gregschlom
fonte
Como tornar o interior transparente?
Hitesh Sahu
1
@HiteshSahu Eu acho que a desvantagem desta situação é que você teria que corresponder ao fundo do layout com o fundo do widget aqui
chntgomez
35

Então, eu queria fazer algo um pouco diferente: SOMENTE uma borda na parte inferior, para simular um divisor do ListView. Modifiquei a resposta de Piet Delport e obtive o seguinte:

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

Observe o uso de px em vez de dp para obter exatamente um divisor de 1 pixel (alguns DPIs de telefone farão desaparecer uma linha de 1dp).

phreakhead
fonte
2
querida! qual é o valor de "@color/background_trans_light"?
Shajeel Afzal 8/08/13
Cheers @phreakhead, isso realmente funciona para mim! Sem borda superior, esquerda ou direita. Exatamente o que eu precisava, obrigado!
precisa saber é o seguinte
2
Por favor, você pode explicar por que quando você coloca -2dp, ele desaparece e quando você coloca -1dp, ele ainda é visível? Obrigado!
Francisco Romero
9

Assim como o @Nic Hubbard disse, existe uma maneira muito fácil de adicionar uma linha de fronteira.

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

Você pode alterar a altura e a cor do plano de fundo para o que quiser.

MattZ
fonte
8

Minhas respostas são baseadas na versão @Emile, mas eu uso cores transparentes em vez de sólidas.
Este exemplo irá desenhar uma borda 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 é a cor do plano de fundo na qual você desenha sua vista com borda.

Se você deseja alterar a posição da borda, altere o deslocamento com um dos seguintes:

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

ou combine-os para ter 2 ou mais bordas:

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

Você também pode quebrar a vista em um FrameLayout e definir a cor de fundo e o preenchimento do quadro para o que desejar; no entanto, a visualização de texto, por padrão, possui um plano de fundo 'transparente'; portanto, você também precisa alterar a cor do plano de fundo da visualização de texto.

okaram
fonte
Bem simples. Você controla o tamanho e a direção dos contornos pelas margens da vista interna. Obrigado.
Scott Biggs
5

Por que não criar apenas uma vista alta de 1dp com uma cor de fundo? Em seguida, ele pode ser facilmente colocado onde você quiser.

Nic Hubbard
fonte
4

Apenas para adicionar minha solução à lista.

Eu queria uma borda inferior semitransparente que ultrapassasse a forma original (portanto, a borda semitransparente estava fora do retângulo pai).

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

O que me dá;

insira a descrição da imagem aqui

Cadab
fonte
4

Para mudar isso:

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

Eu prefiro essa abordagem em "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>

Isso cria apenas as bordas, não um retângulo que aparecerá se o fundo tiver uma cor.

Dinidiniz
fonte
3

Primeiro, crie um arquivo xml com o conteúdo mostrado abaixo e chame-o de border.xml e coloque-o na pasta de layout, no diretório 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>

Depois disso, dentro do código, use

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

Isso criará uma linha preta na parte superior e inferior do TextView.

Nikhil Dinesh
fonte
Sim, vai funcionar, eu verifiquei. Botão button = (Botão) findViewById (R.id.button); button.setBackgroundResource (R.layout.border);
Nikhil Dinesh
Usei a cor preta no arquivo xml acima. Sua cor de fundo pode ser preta. Tente usar outra cor. Definitivamente funcionará <? Xml version = "1.0" encoding = "UTF-8"?> <Shape xmlns: android = " schemas.android.com/apk/res/android "> <android sólido: color = "# 474848 "/> <curso android: width =" 1dp "android: color =" # ffff00 "/> <preenchimento android: left =" 1dp "android: top =" 1dp "android: right =" 1dp "android: bottom =" 1dp "/> </shape>
Nikhil Dinesh
1
Não funcionou para mim. A linha da borda foi pintada no meio da exibição de texto - horizontalmente.
AlikElzin-Kilaka
3

Anote o código abaixo

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

Aqui está uma maneira de alcançá-lo.

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

Primeiro item para curso e segundo para plano de fundo sólido. Ocultando as bordas esquerda e direita.

Kavya Shravan
fonte
2

A maneira mais simples de adicionar bordas para inserir as bordas usando InsetDrawable, a seguir mostrará apenas a borda 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
fonte
2

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

Adicionar link neste arquivo à propriedade em segundo plano

Oleg
fonte
1

Tente agrupar a imagem com um layout linear e defina o plano de fundo com a cor da borda desejada ao redor do texto. Em seguida, defina o preenchimento na visualização de texto para a espessura desejada para sua borda.

Matt
fonte
1

Você também pode usar um caminho de 9 para fazer seu trabalho. Crie-o para que o pixel colorido não se multiplique em altura, mas apenas o pixel transparente.

Kowlown
fonte
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
fonte
1

Basta adicionar vistas na parte superior e inferior da 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
fonte
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
fonte
-1
<TextView
    android:id="@+id/textView3"
    android:layout_width="match_parent"
    android:layout_height="2dp"
    android:background="#72cdf4"
    android:text=" aa" />

Basta adicionar este TextView abaixo do texto em que você deseja adicionar a borda

Aquib Maniyar
fonte
-1

Só para fazer valer de @phreakhead e das user1051892 respostas, <item android:bottom|android:left|android:right|android:top>se for negativo, deve ser maior do que <stroke android:width>. Caso contrário, a pintura do item será misturada à pintura do traçado e você poderá pensar que esses valores não estão funcionando.

Garry Dias
fonte