Esiste un modo semplice per aggiungere un bordo nella parte superiore e inferiore di una vista Android?


407

Ho un TextView e vorrei aggiungere un bordo nero lungo i bordi superiore e inferiore. Ho provato ad aggiungere android:drawableTope android:drawableBottoma TextView, ma questo ha fatto diventare l'intera vista nera.

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

Esiste un modo per aggiungere facilmente un bordo superiore e inferiore a una vista (in particolare a TextView) in Android?


2
È sorprendente che nessuno abbia menzionato divisore verticale ! Questa è la cosa creata da Android, per ottenere, beh, divisori verticali. COold non è più semplice e fai tutto nel pannello "Design" WYSIWYG in Android Studio.
Fattie,

note dividerVertical è stato implementato nell'API 11.
JPM il

1
Forse puoi mostrare come usare divisore verticale?
androidguy,

Risposte:


430

In Android 2.2 potresti fare quanto segue.

Crea un drawable xml come /res/drawable/textlines.xml e assegnalo come proprietà di sfondo di 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>

Il lato negativo di questo è che devi specificare un colore di sfondo opaco, poiché i lucidi non funzioneranno. (Almeno pensavo lo facessero ma mi sbagliavo). Nell'esempio sopra puoi vedere che il colore solido della prima forma #FFdddddd viene copiato nel colore del tratto della 2a forma.


11
Anche questa soluzione, che funziona anche per TextViews, se si desidera un bordo tutto intorno: stackoverflow.com/questions/3263611/...
emmby

26
Prova a utilizzare android:color="@null"per evitare problemi di sfondo opaco.
Matt Briançon,

@emmby: durante il test di questo codice su tablet, ci vuole tempo per il rendering sullo schermo, dopo 1 secondo vengono visualizzati i bordi quando scorro
Chetan

5
Il trucco android: color = "@ null" non ha funzionato per me per mantenere la trasparenza e visualizzare solo un bordo su un lato della vista. Risposta dell'utente1051892 di seguito ha fatto il lavoro!
Rick Pastoor,

8
Questa soluzione ha creato un bordo anche a sinistra e a destra, anche se più sottile.
AlikElzin-Kilaka,

279

Ho usato un trucco in modo che il bordo venga visualizzato all'esterno del contenitore. Con questo trucco viene disegnata solo una linea in modo che lo sfondo venga mostrato nella vista sottostante.

<?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
Questo ha funzionato benissimo per me, con alcune modifiche per rendere la linea un po 'più sottile.
Jeff,

1
Trucco molto bello, anche se potrebbe essere più bello se non dovessimo ingannare il computer per fare le cose.
Yukio Fukuzawa,

ben fatto! quello che dovresti guardare è che l'elemento a sinistra, in alto, a destra, in basso dovrebbe - (larghezza del tratto) dp
asakura89

Non ho mostrato alcun bordo - ho appena ridotto il contenuto della mia vista :(
AlikElzin-kilaka

1
Ben fatto, lavorato con sfondo trasparente. Testato in 2.2 e 4.4.2. Dovrebbe coprire tutto in mezzo :)
HumaN,

97

Opzione 1: Shape Drawable

Questa è l'opzione più semplice se si desidera un bordo attorno a un layout o una vista in cui è possibile impostare lo sfondo. Crea un file XML nella drawablecartella che assomigli a questo:

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

È possibile rimuovere il solidse non si desidera un riempimento. Il set background="@drawable/your_shape_drawable"sul tuo layout / vista.

Opzione 2: vista di sfondo

Ecco un piccolo trucco che ho usato in a RelativeLayout. Fondamentalmente hai un quadrato nero sotto la vista che vuoi dare un bordo, e poi dai a quella vista un po 'di riempimento (non margine!) In modo che il quadrato nero sia visibile ai bordi.

Ovviamente questo funziona correttamente solo se la vista non ha aree trasparenti. In tal caso, ti consiglio di scrivere un'abitudine BorderViewche disegna solo il bordo: dovrebbe essere solo una dozzina di righe di codice.

<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 vi state chiedendo, si fa il lavoro con adjustViewBounds=true. Tuttavia, non funziona se vuoi avere uno sfondo nel suo insieme RelativeLayout, perché c'è un bug che ti impedisce di riempire a RelativeLayoutcon a View. In tal caso, consiglierei il Shapedisegno.

Opzione 3: 9 patch

Un'ultima opzione è quella di usare un disegnabile a 9 patch come questo:

È possibile utilizzarlo in qualsiasi vista in cui è possibile impostare android:background="@drawable/...". E sì, deve essere 6x6 - ho provato 5x5 e non ha funzionato.

Lo svantaggio di questo metodo è che non puoi cambiare i colori molto facilmente, ma se vuoi bordi fantasiosi (ad esempio solo un bordo in alto e in basso, come in questa domanda), potresti non essere in grado di farli con il Shapedisegno , che non è molto potente.

Opzione 4: visualizzazioni extra

Ho dimenticato di menzionare questa opzione davvero semplice se vuoi solo i bordi sopra e sotto la tua vista. Puoi mettere la vista in verticale LinearLayout(se non lo è già) e quindi aggiungere Views vuoti sopra e sotto di essa in questo modo:

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

4
9 patch e la forma disegnabile sono ok, ma sconsiglio di aggiungere visualizzazioni o immagini per risolvere un simile problema. Il motivo è che dovresti rimuovere altrettanti <elementi> dai tuoi layout per migliorare il ridisegno e l'animazione del layout. Vorrei eliminarli immediatamente e implementarne alcuni simili all'opzione 1 o 2.
Emile

2
@Emile È vero, ma se stai usando un ListView personalizzato che non supporta i divisori, una semplice Vista va bene. L'impatto sulle prestazioni è quasi nullo, soprattutto se sei sicuro di mantenere la profondità del layout. Inoltre elude i bug con i divisori ListView tra i dispositivi (ho visto alcuni dispositivi che ignorano questa proprietà).
Tom,

Puoi anche utilizzare l'efficiente modello di viewholder con le visualizzazioni elenco per assicurarti di ridurre il numero di chiamate per findViewByID, che spesso è causa di scarse prestazioni dell'elenco.
Emile,

In iOS hai solo un modo per farlo. Su Android dovresti testarne almeno quattro, nel mio caso l'opzione 4 era la strada da percorrere. A volte i disegnabili come sfondo si bloccano per il rendering, essere consapevoli di ciò.
Ratata Tata,

1
Perché Android non aveva la soluzione più semplice per queste cose? come in altre lingue, come HTML, CSS o qualcosa di simile a JavaFX, WPF ......
Asif Mushtaq

95

Per aggiungere un 1dpbordo bianco solo in fondo e per avere uno sfondo trasparente, puoi usare quanto segue, che è più semplice della maggior parte delle risposte qui.

Per l'una TextViewo l'altra vista aggiungere:

android:background="@drawable/borderbottom"

E nella drawabledirectory aggiungi il seguente XML, chiamatoborderbottom.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 vuoi un bordo in alto, cambia android:top="-2dp"inandroid:bottom="-2dp"

Non è necessario che il colore sia bianco e che lo sfondo non sia trasparente.

L' solidelemento potrebbe non essere richiesto. Questo dipenderà dal tuo design (grazie a V. Kalyuzhnyu).

Fondamentalmente, questo XML creerà un bordo usando la forma rettangolare, ma spinge i lati superiore, destro e sinistro oltre l'area di rendering per la forma. Questo lascia visibile solo il bordo inferiore.


8
Questa è la soluzione migliore, in quanto non crea sovraccarico come gli altri
Greg Ennis

C'è una ragione per cui le posizioni negative sono due volte più grandi della corsa con ( -2dpvs 1dp)? Sembra funzionare quando sono uguali in quantità ( -1e 1).
Denis Kniazhev,

@DenisKniazhev: quando si utilizzava -2dpil risultato era sempre pulito. Penso che ci sia stato un caso di test in cui il risultato non era pulito. Non riesco a ricordare se fosse uno schermo a bassa o alta densità o anche una versione precedente di Android (forse 2.x).
Tigro,

Interessante. Sai se questo è un caso generale, ad esempio se uso 4dpper la larghezza della corsa dovrei usare -8dpper il posizionamento?
Denis Kniazhev,

1
@DenisKniazhev: (dalla memoria) sembrava un calcolo in virgola mobile che era solo da piccolo a grande o piccolo. Ciò significa che un valore di -5dpsarebbe tutto ciò che è necessario con un valore di larghezza di 4pd. Doveva semplicemente essere un po 'più grande per superare l'imprecisione del valore float.
Tigro

36

La risposta attualmente accettata non funziona. Crea sottili bordi verticali sui lati sinistro e destro della vista a causa dell'antialiasing.

Questa versione funziona perfettamente. Consente inoltre di impostare le larghezze dei bordi in modo indipendente e, se lo si desidera, è anche possibile aggiungere bordi sui lati sinistro / destro. L'unico inconveniente è che NON supporta la trasparenza.

Crea un drawable xml denominato /res/drawable/top_bottom_borders.xmlcon il codice seguente e assegnalo come proprietà di sfondo di 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>

Testato su Android KitKat tramite Marshmallow


Come rendere l'interno trasparente?
Hitesh Sahu,

1
@HiteshSahu Penso che il lato negativo di questo sia che dovresti abbinare lo sfondo del layout con lo sfondo del widget qui
chntgomez,

35

Quindi volevo fare qualcosa di leggermente diverso: SOLO un bordo in basso, per simulare un divisore ListView. Ho modificato la risposta di Piet Delport e ho ottenuto questo:

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

Nota usando px invece di dp per ottenere esattamente 1 pixel divisore (alcuni DPI del telefono faranno scomparire una linea da 1dp).


2
caro! qual è il valore di "@color/background_trans_light"?
Shajeel Afzal,

Saluti @phreakhead, questo funziona davvero per me! Nessun bordo superiore, sinistro o destro. Esattamente quello di cui avevo bisogno, grazie!
shanehoban,

2
Per favore, puoi spiegare perché quando metti -2dp scompare e quando metti -1dp è ancora visibile? Grazie!
Francisco Romero,

9

Proprio come ha detto @Nic Hubbard, c'è un modo molto semplice per aggiungere una linea di confine.

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

È possibile modificare l'altezza e il colore di sfondo in base alle proprie esigenze.


8

Le mie risposte si basano sulla versione @Emile ma uso il colore trasparente anziché il solido.
Questo esempio disegna un bordo inferiore di 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 è il colore dello sfondo su cui si disegna la vista con il bordo.

Se vuoi cambiare la posizione del bordo cambia l'offset con uno di:

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

o combinali per avere 2 o più bordi:

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

7

Puoi anche avvolgere la vista in un FrameLayout, quindi impostare il colore di sfondo e il riempimento della cornice come desideri; tuttavia, la visualizzazione di testo, per impostazione predefinita, ha uno sfondo "trasparente", quindi è necessario modificare anche il colore di sfondo della visualizzazione di testo.


Abbastanza semplice. Puoi controllare le dimensioni e la direzione dei contorni dai margini della vista interna. Grazie.
Scott Biggs,

5

Perché non creare semplicemente una vista alta 1dp con un colore di sfondo? Quindi può essere facilmente posizionato dove vuoi.


4

Solo per aggiungere la mia soluzione all'elenco ..

Volevo un bordo inferiore semitrasparente che si estende oltre la forma originale (quindi il bordo semitrasparente era al di fuori del rettangolo principale).

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

Il che mi dà;

inserisci qui la descrizione dell'immagine


4

Per cambiare questo:

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

Preferisco questo approccio in "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>

Questo rende solo i bordi, non un rettangolo che apparirà se lo sfondo ha un colore.


3

Per prima cosa crea un file xml con i contenuti mostrati di seguito e chiamalo border.xml e posizionalo nella cartella layout all'interno della directory 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>

Dopo quello all'interno del codice usare

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

Ciò renderà una linea nera nella parte superiore e inferiore di TextView.


Sì, funzionerà, ho verificato. Button button = (Button) findViewById (pulsante R.id.); button.setBackgroundResource (R.layout.border);
Nikhil Dinesh,

Ho usato il colore nero nel file XML sopra, il tuo colore di sfondo potrebbe essere nero, prova usando un altro colore. Funzionerà sicuramente <? Xml version = "1.0" encoding = "UTF-8"?> <Shape xmlns: android = " schemas.android.com/apk/res/android "> <solido android: color = "# 474848 "/> <corsa android: larghezza =" 1dp "android: color =" # ffff00 "/> <padding android: left =" 1dp "android: top =" 1dp "android: right =" 1dp "android: bottom =" 1dp "/> </shape>
Nikhil Dinesh,

1
Non ha funzionato per me. La linea di confine è stata dipinta al centro della vista del testo - in orizzontale.
AlikElzin-Kilaka,

3

Scrivi sotto il codice

<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

Ecco un modo per raggiungerlo.

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

Primo elemento per tratto e secondo per sfondo solido. Nascondere i bordi sinistro e destro.


2

Il modo più semplice per aggiungere bordi per inserirli usando InsetDrawable, di seguito mostrerà solo il bordo superiore:

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

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

Aggiungi il collegamento su questo file alla proprietà in background


1

Prova a avvolgere l'immagine con uno schermo lineare e imposta lo sfondo sul colore del bordo desiderato attorno al testo. Quindi imposta l'imbottitura nella vista di testo in modo che sia lo spessore desiderato per il bordo.


1

Puoi anche usare un percorso a 9 per fare il tuo lavoro. Crealo in modo che il pixel colorato non si moltiplichi in altezza ma solo il pixel trasparente.


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

Aggiungi semplicemente Viste nella parte superiore e inferiore di 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" />

Basta aggiungere questo TextView sotto il testo in cui si desidera aggiungere il bordo


-1

Solo per imporre le risposte di @phreakhead e user1051892 , <item android:bottom|android:left|android:right|android:top>se negativo, deve essere maggiore di <stroke android:width>. In caso contrario, la pittura dell'oggetto verrà mescolata con la pittura del tratto e potresti pensare che questi valori non funzionino.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.