Como desenhar borda em apenas um lado de um layout linear?

186

Sou capaz de desenhar uma borda em um layout linear, mas está sendo desenhada por todos os lados. Quero restringi-lo apenas ao lado direito, como você faz em CSS (borda direita: 1px vermelho sólido;).

Eu tentei isso, mas ainda atrai por todos os lados:

<?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:height="2dp"
            android:width="2dp"
            android:color="#FF0000" />

        <solid android:color="#000000" />

        <padding
            android:bottom="0dp"
            android:left="0dp"
            android:right="1dp"
            android:top="0dp" />

        <corners
            android:bottomLeftRadius="0dp"
            android:bottomRightRadius="5dp"
            android:radius="1dp"
            android:topLeftRadius="5dp"
            android:topRightRadius="0dp" />
    </shape>
</item>

Alguma sugestão de como fazer isso?

BTW, eu não quero usar o hack de colocar uma visão de 1dp de largura no lado necessário.

Nitin Bansal
fonte
você pode usar drawableLeft em seu layout
njzk2

Respostas:

359

Você pode usar isso para obter uma borda de um lado

<?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="#FF0000" />
    </shape>
</item>
<item android:left="5dp">
    <shape android:shape="rectangle">
        <solid android:color="#000000" />
    </shape>
</item>
</layer-list>

EDITADO

Como muitos de mim gostariam de ter uma borda de um lado com fundo transparente, eu implementei uma BorderDrawableque poderia me dar bordas com tamanho e cor diferentes da mesma maneira que usamos css. Mas isso não pôde ser usado via xml. Para dar suporte ao XML, adicionei um BorderFrameLayoutno qual seu layout pode ser agrupado.

Veja meu github para a fonte completa.

Vivek Khandelwal
fonte
5
e se você quiser uma cor sólida baseada em alfa com uma borda inferior? Eu estive pensando em uma solução para isso com a API XML Android Drawable, mas não consigo descobrir.
Mario Lenci 24/07/2012
Isso não funcionou para mim - estranhamente, o inverso do que eu queria era uma cor mais escura por dentro, com o gradiente de cinza que eu sobreponhava para as fronteiras. Estive pensando em tornar um retângulo desenhável em um determinado tamanho para colocar como um drawableLeft no item. Isso não parece tão simplificado.
Jbenowitz 14/05
@ jbenowitz: A ordem do item na lista de camadas é mais importante. Se você reverter, obterá esse resultado.
Vivek Khandelwal
Corrigi isso adicionando um traço na cor da borda e na forma que permanece na cor do botão. Isso fez o truque.
Jbenowitz 16/05
242

Fácil como torta, permitindo uma BG transparente:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:angle="0"
        android:startColor="#f00"
        android:centerColor="@android:color/transparent"
        android:centerX="0.01" />
</shape>

Altere o ângulo para alterar a localização da borda:

  • 0 = esquerda
  • 90 = inferior
  • 180 = direita
  • 270 = superior
Oded Breiner
fonte
19
Esta é de longe a melhor resposta aqui, muito ruim não é upvoted
mittelmania
11
Bom, no entanto, eu certamente não descreveria como "fácil como torta".
funkybro
7
Isso não funciona se você precisar de uma borda mais grossa ou se precisar de bordas em vários lados.
princípio holográfico
1
@ codeman - use isso como pano de fundo para a sua visualização, e herdará sua altura.
Oded Breiner
2
como ajustar a largura do traçado ou da borda?
Ruturaj Patil
101

também é possível implementar o que você deseja usando uma única camada

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

    <item
        android:bottom="-5dp"
        android:right="-5dp"
        android:top="-5dp">
        <shape android:shape="rectangle" >
            <solid android:color="@color/color_of_the_background" />

            <stroke
                android:width="5dp"
                android:color="@color/color_of_the_border" />
        </shape>
    </item>

</layer-list>

Desta forma única fronteira esquerda é visível, mas você pode conseguir qualquer combinação desejada, jogando com bottom, left, righte topatributos do itemelemento

Viktor Grekov
fonte
3
Definitivamente, isso é útil quando você tem outra cor de fundo e deseja sobrepor essa borda desenhável com borda. (y)
Aung Pyae
3
Exatamente o que eu preciso, mas é correto usar almofadas negativas?
IlyaEremin
1
essa é a melhor solução. Estou incomodando o que -5dp faz lá.
Amit Kumar 22/02
1
O preenchimento negativo é comum em HTML / CSS. Simplesmente cutuca as coisas na outra direção. Na minha experiência, parece perfeitamente válido no Android também.
spaaarky21
Implementações usando margens negativas não funcionam bem se o layout tiver clipChildren = false ou clipToPadding = false. Se este for o caso, você pode usar a solução com dois retângulos sobrepostos, como a proposta por Vivek Khandelwal
Jesús Barrera
80

Para obter uma borda em apenas um lado de um drawable, aplique um negativo insetnos outros 3 lados (fazendo com que essas bordas sejam desenhadas fora da tela).

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

    <shape android:shape="rectangle">
        <stroke android:width="2dp" android:color="#FF0000" />
        <solid android:color="#000000" />
    </shape>

</inset>

insira a descrição da imagem aqui

Essa abordagem é semelhante à resposta de naykah, mas sem o uso de a layer-list.

Soldado
fonte
4
Esta é a melhor resposta IMO
James
resposta muito boa, só preciso alterar a largura e inserir para 10dp :) E mais, preciso de borda à esquerda, então altero android: insetLeft para android: insetRight. Tão simples! Mantendo o botão de materiais clique: D
Phuong
Exatamente o que eu precisava, mude insertXno topo para decidir quais bordas mostrar e quais não.
CularBytes 10/09/2015
Posso até ter uma cor sólida de @null e, em seguida, esse método não causa overdraw. Gênio. Obrigado!
Unknownweirdo
2
Atenção: isso mudará o conteúdo da sua visualização e também o redimensionará. Use com cuidado.
vovahost
7

Como alternativa (se você não quiser usar o plano de fundo), poderá fazê-lo facilmente, exibindo da seguinte maneira:

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

Por ter apenas uma borda direita, coloque-o após o layout (onde você deseja colocar a borda):

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

Por ter apenas uma borda esquerda, coloque-a antes do layout (onde você deseja colocar a borda):

Trabalhou para mim ... Espero que seja de alguma ajuda ....

Nishant Jha
fonte
6

Consegui alcançar o efeito com o seguinte código

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

Você pode ajustar as suas necessidades de posição da borda alterando a direção do deslocamento

IvelinStanchev
fonte
5
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" >
        <shape>
            <solid
                android:color="#f28b24" />
            <stroke
                android:width="1dp"
                android:color="#f28b24" />
            <corners
                android:radius="0dp"/>
            <padding
                android:left="0dp"
                android:top="0dp"
                android:right="0dp"
                android:bottom="0dp" />
        </shape>
    </item>
    <item>
        <shape>
            <gradient
                android:startColor="#f28b24"
                android:endColor="#f28b24"
                android:angle="270" />
            <stroke
                android:width="0dp"
                android:color="#f28b24" />
            <corners
                android:bottomLeftRadius="8dp"
                android:bottomRightRadius="0dp"
                android:topLeftRadius="0dp"
                android:topRightRadius="0dp"/>
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" />
        </shape>
    </item>
</selector>
alejandrocordon
fonte
5

Outro ótimo exemplo exemplo

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<inset xmlns:android="http://schemas.android.com/apk/res/android"
     android:insetRight="-2dp">

     <shape android:shape="rectangle">
         <corners
             android:bottomLeftRadius="4dp"
             android:bottomRightRadius="0dp"
             android:topLeftRadius="4dp"
             android:topRightRadius="0dp" />
         <stroke
             android:width="1dp"
             android:color="@color/nasty_green" />
         <solid android:color="@android:color/transparent" />
     </shape>

</inset>
Muklas
fonte
2

Não há menção sobre arquivos com nove patches aqui. Sim, você precisa criar o arquivo, no entanto, é um trabalho bastante fácil e é realmente uma solução " compatível com várias versões e transparência ". Se o arquivo for colocado no drawable-nodpidiretório, ele funcionará com pxbase e drawable-mdpifuncionará aproximadamente como dp base (graças à nova amostra).

O arquivo de exemplo da pergunta original ( borda direita: 1px vermelho sólido; ) está aqui:

http://ge.tt/517ZIFC2/v/3?c

Basta colocá-lo no drawable-nodpidiretório

Quark
fonte
2

Fronteiras de cores diferentes. Eu usei 3 itens.

<?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/colorAccent" />
        </shape>
    </item>
    <item android:top="3dp">
        <shape android:shape="rectangle">
            <solid android:color="@color/light_grey" />
        </shape>
    </item>
    <item
        android:bottom="1dp"
        android:left="1dp"
        android:right="1dp"
        android:top="3dp">
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimary" />
        </shape>
    </item>
</layer-list>
Ritesh
fonte