Existe-t-il un moyen simple d'ajouter une bordure en haut et en bas d'une vue Android?


407

J'ai un TextView et je voudrais ajouter une bordure noire le long de ses bordures supérieure et inférieure. J'ai essayé d'ajouter android:drawableTopet android:drawableBottomà TextView, mais cela n'a fait que noircir la vue entière.

<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-t-il un moyen d'ajouter facilement une bordure supérieure et inférieure à une vue (en particulier, une TextView) dans Android?


2
Il est surprenant que personne n'ait mentionné dividerVertical ! C'est la chose créée par Android pour réaliser, enfin, des séparateurs verticaux. COold ne sera pas plus facile et vous faites tout dans le panneau "Design" WYSIWYG dans Android Studio.
Fattie

note dividerVertical a été implémenté dans l'API 11.
JPM

1
Peut-être pouvez-vous montrer comment utiliser dividerVertical?
androidguy

Réponses:


430

Dans Android 2.2, vous pouvez effectuer les opérations suivantes.

Créez un dessin xml tel que /res/drawable/textlines.xml et affectez-le en tant que propriété d'arrière-plan 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>

L'inconvénient est que vous devez spécifier une couleur d'arrière-plan opaque, car les transparents ne fonctionneront pas. (Au moins, je le pensais, mais je me trompais). Dans l'exemple ci-dessus, vous pouvez voir que la couleur unie de la première forme #FFdddddd est copiée dans la couleur de contour des 2e formes.


11
Voir également cette solution, qui fonctionne également pour TextViews, si vous voulez une bordure tout autour: stackoverflow.com/questions/3263611/…
emmby

26
Essayez d'utiliser android:color="@null"pour éviter un problème de fond opaque.
Matt Briançon

@emmby: lors du test de ce code sur tablette, le rendu à l'écran prend du temps, après 1 seconde, les bordures s'affichent lorsque je défile
Chetan

5
L'astuce android: color = "@ null" n'a pas fait l'affaire pour moi pour garder la transparence et simplement afficher une bordure d'un côté de la vue. La réponse de l'utilisateur1051892 ci-dessous a fait le travail!
Rick Pastoor

8
Cette solution a également créé une bordure à gauche et à droite, mais plus mince.
AlikElzin-kilaka

279

J'ai utilisé une astuce pour que la bordure s'affiche à l'extérieur du conteneur. Avec cette astuce, seule une ligne est tracée afin que l'arrière-plan soit affiché de la vue sous-jacente.

<?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
Cela a très bien fonctionné pour moi, avec quelques ajustements pour rendre la ligne un peu plus fine.
Jeff

1
Très bonne astuce, mais cela pourrait être plus agréable si nous n'avons pas à tromper l'ordinateur pour faire avancer les choses.
Yukio Fukuzawa

Bien fait! ce que vous devez regarder, c'est l'article gauche, en haut, à droite, en bas devrait - (largeur du trait) dp
asakura89

N'a montré aucune frontière - vient de rendre mon contenu de vue plus petit :(
AlikElzin-kilaka

1
Joliment fait, travaillé avec un fond transparent. Testé en 2.2 et 4.4.2. Devrait couvrir tout le
reste

98

Option 1: Forme dessinable

Il s'agit de l'option la plus simple si vous souhaitez une bordure autour d'une présentation ou d'une vue dans laquelle vous pouvez définir l'arrière-plan. Créez un fichier XML dans le drawabledossier qui ressemble à ceci:

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

Vous pouvez supprimer le solidsi vous ne voulez pas de remplissage. L'ensemble background="@drawable/your_shape_drawable"sur votre mise en page / vue.

Option 2: vue d'arrière-plan

Voici un petit truc que j'ai utilisé dans un RelativeLayout . Fondamentalement, vous avez un carré noir sous la vue que vous souhaitez donner une bordure, puis donnez à cette vue un rembourrage (pas de marge!) Afin que le carré noir soit visible sur les bords.

Évidemment, cela ne fonctionne correctement que si la vue n'a pas de zones transparentes. Si c'est le cas, je vous recommanderais d'écrire une coutume BorderViewqui ne dessine que la frontière - elle ne devrait contenir que quelques dizaines de lignes de code.

<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 vous vous demandez, il fait le travail avec adjustViewBounds=true. Cependant, cela ne fonctionne pas si vous voulez avoir un arrière-plan dans son ensemble RelativeLayout, car il y a un bogue qui vous empêche de remplir un RelativeLayoutavec un View. Dans ce cas, je recommanderais le Shapedrawable.

Option 3: 9 patchs

Une dernière option consiste à utiliser un patch à 9 patchs comme celui-ci:

Vous pouvez l'utiliser sur n'importe quelle vue où vous pouvez définir android:background="@drawable/...". Et oui, il doit être 6x6 - j'ai essayé 5x5 et cela n'a pas fonctionné.

L'inconvénient de cette méthode est que vous ne pouvez pas changer les couleurs très facilement, mais si vous voulez des bordures fantaisie (par exemple, seulement une bordure en haut et en bas, comme dans cette question), vous ne pourrez peut-être pas les faire avec le Shapedessinable , ce qui n'est pas très puissant.

Option 4: Vues supplémentaires

J'ai oublié de mentionner cette option vraiment simple si vous ne voulez que des bordures au-dessus et en dessous de votre vue. Vous pouvez placer votre vue dans une verticale LinearLayout(si ce n'est pas déjà fait) puis ajouter des Views vides au-dessus et en dessous comme ceci:

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

4
Le patch 9 et la forme dessinable sont corrects, mais je déconseille d'ajouter des vues ou des images pour résoudre un tel problème. La raison en est que vous devez supprimer autant de ces <éléments> de vos mises en page pour améliorer la redéfinition et l'animation des mises en page. Je les supprimerais tout de suite et j'implémenterais des options similaires à l'option 1 ou 2.
Emile

2
@Emile C'est vrai, mais si vous utilisez un ListView personnalisé qui ne prend pas en charge les séparateurs, une simple vue est très bien. L'impact sur les performances est presque nul, surtout si vous êtes sûr de garder la profondeur de votre disposition vers le bas. Il contourne également les bogues avec les séparateurs ListView sur les appareils (j'ai vu certains appareils qui ignorent cette propriété).
Tom

Vous pouvez également utiliser le modèle de visionneuse efficace avec les vues de liste pour vous assurer de réduire le nombre d'appels à findViewByID, qui est souvent la cause de mauvaises performances de liste.
Emile

Dans iOS, vous n'avez qu'une seule façon de le faire. Sur Android, vous devriez tester au moins quatre, dans mon cas, l'option 4 était la voie à suivre. Parfois, les tirables comme arrière-plan sont suspendus pour le rendu, sachez-le.
Ratata Tata

1
Pourquoi Android n'avait-il pas la solution la plus simple pour de telles choses? comme dans d'autres langages, comme HTML, CSS, ou quelque chose comme JavaFX, WPF ......
Asif Mushtaq

95

Pour ajouter une 1dpbordure blanche en bas uniquement et pour avoir un arrière-plan transparent, vous pouvez utiliser ce qui suit, qui est plus simple que la plupart des réponses ici.

Pour la TextViewou une autre vue, ajoutez:

android:background="@drawable/borderbottom"

Et dans le drawablerépertoire, ajoutez le XML suivant, appelé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>

Si vous voulez une bordure en haut, changez la android:top="-2dp"enandroid:bottom="-2dp"

La couleur n'a pas besoin d'être blanche et l'arrière-plan n'a pas besoin d'être transparent non plus.

L' solidélément peut ne pas être requis. Cela dépendra de votre conception (merci V. Kalyuzhnyu).

Fondamentalement, ce XML créera une bordure en utilisant la forme rectangle, mais repoussera ensuite les côtés supérieur, droit et gauche au-delà de la zone de rendu de la forme. Cela laisse juste la bordure inférieure visible.


8
C'est la meilleure solution, car elle ne crée pas de découvert comme les autres
Greg Ennis

Y a-t-il une raison pour laquelle les positions négatives sont deux fois plus grandes que le trait avec ( -2dpvs 1dp)? Semble fonctionner lorsque leur montant est égal ( -1et 1).
Denis Kniazhev

@DenisKniazhev: Lors de l'utilisation, -2dple résultat était toujours propre. Je pense qu'il y avait un cas de test où le résultat n'était pas propre. Je ne me souviens pas s'il s'agissait d'un écran basse ou haute densité ou même d'une ancienne version d'Android (2.x peut-être).
Tigger

Intéressant. Savez-vous s'il s'agit d'un cas général, par exemple si j'utilise 4dppour la largeur de trait dois-je utiliser -8dppour le positionnement?
Denis Kniazhev

1
@DenisKniazhev: (de mémoire), cela ressemblait à un calcul en virgule flottante qui était juste un peu trop grand ou petit. Cela signifie qu'une valeur de -5dpserait tout ce qui est nécessaire avec une valeur de largeur de 4pd. Elle devait simplement être un peu plus grande pour surmonter l'inexactitude de la valeur flottante.
Tigger

36

La réponse actuellement acceptée ne fonctionne pas. Il crée de fines bordures verticales sur les côtés gauche et droit de la vue en raison de l'anticrénelage.

Cette version fonctionne parfaitement. Il vous permet également de définir les largeurs de bordure indépendamment, et vous pouvez également ajouter des bordures sur les côtés gauche / droit si vous le souhaitez. Le seul inconvénient est qu'il ne prend pas en charge la transparence.

Créez un dessin xml nommé /res/drawable/top_bottom_borders.xmlavec le code ci-dessous et affectez-le en tant que propriété d'arrière-plan 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>

Testé sur Android KitKat via Marshmallow


Comment rendre l'intérieur transparent?
Hitesh Sahu

1
@HiteshSahu Je pense que l'inconvénient est que vous devez faire correspondre l'arrière-plan de la mise en page avec l'arrière-plan du widget ici
chntgomez

35

Je voulais donc faire quelque chose de légèrement différent: une bordure en bas UNIQUEMENT, pour simuler un diviseur ListView. J'ai modifié la réponse de Piet Delport et j'ai obtenu ceci:

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

Notez l'utilisation de px au lieu de dp pour obtenir exactement un diviseur de 1 pixel (certains DPI de téléphone feront disparaître une ligne de 1dp).


2
cher! quelle est la valeur de "@color/background_trans_light"?
Shajeel Afzal

Cheers @phreakhead, cela fonctionne vraiment pour moi! Pas de bordure supérieure, gauche ou droite. Exactement ce dont j'avais besoin, merci!
shanehoban

2
Pouvez-vous expliquer pourquoi lorsque vous mettez -2dp, il disparaît et quand vous mettez -1dp, il est toujours visible? Merci!
Francisco Romero

9

Comme l'a dit @Nic Hubbard, il existe un moyen très simple d'ajouter une ligne de bordure.

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

Vous pouvez modifier la hauteur et la couleur d'arrière-plan comme vous le souhaitez.


8

Mes réponses sont basées sur la version @Emile mais j'utilise une couleur transparente au lieu d'un solide.
Cet exemple dessine une bordure inférieure 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 est la couleur de l'arrière-plan sur lequel vous dessinez votre vue avec bordure.

Si vous souhaitez modifier la position de la bordure, modifiez le décalage avec l'un des éléments suivants:

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

ou combinez-les pour avoir 2 bordures ou plus:

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

7

Vous pouvez également envelopper la vue dans un FrameLayout, puis définir la couleur d'arrière-plan et le remplissage du cadre à votre guise; cependant, la vue de texte, par défaut, a un arrière-plan «transparent», vous devez donc également changer la couleur d'arrière-plan de la vue de texte.


Assez simple. Vous contrôlez la taille et la direction des contours par les marges de la vue intérieure. Merci.
Scott Biggs

5

Pourquoi ne pas simplement créer une vue haute de 1dp avec une couleur d'arrière-plan? Ensuite, il peut être facilement placé où vous le souhaitez.


4

Juste pour ajouter ma solution à la liste ..

Je voulais une bordure inférieure semi transparente qui dépasse la forme d'origine (donc la bordure semi-transparente était en dehors du rectangle parent).

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

Ce qui me donne;

entrez la description de l'image ici


4

Pour changer cela:

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

Je préfère cette approche dans "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>

Cela ne fait que les bordures, pas un rectangle qui apparaîtra si votre arrière-plan a une couleur.


3

Créez d'abord un fichier xml avec le contenu indiqué ci-dessous et nommez-le border.xml et placez-le dans le dossier de mise en page dans le répertoire 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>

Après cela, à l'intérieur du code, utilisez

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

Cela fera une ligne noire en haut et en bas du TextView.


Oui, cela fonctionnera, j'ai vérifié. Button button = (Button) findViewById (R.id.button); button.setBackgroundResource (R.layout.border);
Nikhil Dinesh

J'ai utilisé la couleur noire dans le fichier xml ci-dessus, votre couleur d'arrière-plan peut être noire, essayez d'utiliser une autre couleur. Cela fonctionnera certainement <? Xml version = "1.0" encoding = "UTF-8"?> < Shape xmlns: android = " schemas.android.com/apk/res/android "> <solid android: 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
Ça n'a pas marché pour moi. La ligne de bordure a été peinte au milieu de la vue texte - horizontalement.
AlikElzin-kilaka

3

Notez le code ci-dessous

<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

Voici un moyen d'y parvenir.

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

Premier élément pour le trait et deuxième pour le fond uni. Masquage des bordures gauche et droite.


2

Le moyen le plus simple d'ajouter des bordures pour insérer les bordures à l'aide de ce InsetDrawablequi suit ne montrera que la bordure supérieure:

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

Ajouter un fichier à 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>

Ajouter un lien sur ce fichier à la propriété d' arrière-plan


1

Essayez d'habiller l'image avec une disposition linéaire et définissez son arrière-plan sur la couleur de bordure souhaitée autour du texte. Ensuite, définissez le rembourrage sur la vue de texte pour qu'il soit l'épaisseur souhaitée pour votre bordure.


1

Vous pouvez également utiliser un chemin à 9 voies pour faire votre travail. Créez-le de sorte que le pixel coloré ne se multiplie pas en hauteur mais uniquement le pixel transparent.


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

Ajoutez simplement des vues en haut et en bas 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>

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

Ajoutez simplement ce TextView sous le texte où vous souhaitez ajouter la bordure


-1

Juste pour appliquer les réponses de @phreakhead et de user1051892 , <item android:bottom|android:left|android:right|android:top>si elles sont négatives, elles doivent être supérieures à <stroke android:width>. Sinon, la peinture de l'article sera mélangée avec la peinture du trait et vous pouvez penser que ces valeurs ne fonctionnent pas.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.