web-dev-qa-db-fra.com

Comment créer un ListView avec des angles arrondis sous Android?

Comment créer un ListView avec des angles arrondis sous Android?

175
Legend

Voici une façon de le faire (Merci à Android Documentation cependant!):

Ajoutez ce qui suit dans un fichier (par exemple, customshape.xml), puis placez-le dans (res/drawable/customshape.xml)

<?xml version="1.0" encoding="UTF-8"?> 
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android" 
     Android:shape="rectangle"> 
     <gradient 
         Android:startColor="#SomeGradientBeginColor"
         Android:endColor="#SomeGradientEndColor" 
         Android:angle="270"/> 

    <corners 
         Android:bottomRightRadius="7dp" 
         Android:bottomLeftRadius="7dp" 
         Android:topLeftRadius="7dp" 
         Android:topRightRadius="7dp"/> 
</shape> 

Une fois que vous avez terminé avec la création de ce fichier, définissez simplement l'arrière-plan de l'une des manières suivantes:

via le code:listView.setBackgroundResource(R.drawable.customshape);

Through XML, ajoutez simplement l'attribut suivant au conteneur (ex: LinearLayout ou à n'importe quel champ):

Android:background="@drawable/customshape"

J'espère que quelqu'un le trouvera utile ...

367
Legend

Bien que cela ait fonctionné, il a également supprimé toute la couleur de fond. Je cherchais un moyen de ne faire que la frontière et de simplement remplacer ce code de mise en page XML par celui-ci et j'étais prêt à partir!

<shape xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <stroke Android:width="4dp" Android:color="#FF00FF00" />
    <padding Android:left="7dp" Android:top="7dp"
            Android:right="7dp" Android:bottom="7dp" />
    <corners Android:radius="4dp" />
</shape> 
56
Kevin Parker

@ kris-van-bael

Pour ceux qui rencontrent des problèmes avec la sélection, mettez en surbrillance la ligne supérieure et inférieure où le rectangle d'arrière-plan apparaît lors de la sélection, vous devez définir le sélecteur pour la vue liste de manière à ce qu'il soit de couleur transparente.

listView.setSelector(R.color.transparent);

Dans color.xml, ajoutez ce qui suit -

<color name="transparent">#00000000</color>
12
alvins

Mettre à jour

La solution de nos jours est d’utiliser un CardView avec un support pour les coins arrondis.


Réponse originale *

Une autre façon que j’ai trouvée était de masquer votre mise en page en traçant une image par-dessus celle-ci. Cela pourrait vous aider. Départ Android XML arrondi coins coupés

3

Les autres réponses sont très utiles, merci aux auteurs!

Mais je ne voyais pas comment personnaliser le rectangle lors de la sélection d'un élément lors de la sélection, plutôt que de désactiver la mise en surbrillance @alvins @bharat dojeha.

Ce qui suit me permet de créer un conteneur d’éléments de la liste arrondi sans contour et un gris plus clair lorsqu’il est sélectionné avec la même forme:

Votre fichier xml doit contenir un sélecteur tel que par exemple (dans res/drawable/customshape.xml):

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android" >
<item Android:state_pressed="true" >
    <shape xmlns:Android="http://schemas.Android.com/apk/res/Android" >
        <stroke Android:width="8dp" Android:color="@Android:color/transparent" />
        <padding Android:left="14dp" Android:top="14dp"
                Android:right="14dp" Android:bottom="14dp" />
        <corners Android:radius="10dp" />
        <gradient 
             Android:startColor="@Android:color/background_light"
             Android:endColor="@Android:color/transparent" 
             Android:angle="225"/> 
    </shape>
</item>
<item Android:state_pressed="false">
    <shape xmlns:Android="http://schemas.Android.com/apk/res/Android" >
        <stroke Android:width="8dp" Android:color="@Android:color/transparent" />
        <padding Android:left="14dp" Android:top="14dp"
                Android:right="14dp" Android:bottom="14dp" />
        <corners Android:radius="10dp" />
        <gradient 
             Android:startColor="@Android:color/darker_gray"
             Android:endColor="@Android:color/transparent" 
             Android:angle="225"/> 
    </shape>        
</item>

Ensuite, vous devez implémenter un adaptateur de liste et remplacer la méthode getView pour définir le sélecteur personnalisé en arrière-plan.

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        //snip
        convertView.setBackgroundResource(R.drawable.customshape);
        //snip
    }

et devez également "masquer" le rectangle de sélecteur par défaut, par exemple dans onCreate (je cache également ma fine ligne de séparation grise entre les éléments):

listView.setSelector(Android.R.color.transparent);
listview.setDivider(null);

Cette approche permet de résoudre une solution générale pour les éléments dessinables, pas seulement ListViewItem avec divers états de sélection.

3
dr_g

Une autre solution de sélection met en évidence les problèmes avec le premier et le dernier élément de la liste:

Ajoutez un remplissage en haut et en bas de l'arrière-plan de votre liste égal ou supérieur au rayon. Cela garantit que la mise en surbrillance de la sélection ne chevauche pas vos courbes de coin.

C'est la solution la plus simple lorsque vous avez besoin d'une mise en surbrillance de sélection non transparente.

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android" >
    <solid Android:color="@color/listbg" />
    <stroke
        Android:width="2dip"
        Android:color="#D5D5D5" />
    <corners Android:radius="10dip" />

    <!-- Make sure bottom and top padding match corner radius -->
    <padding
        Android:bottom="10dip"
        Android:left="2dip"
        Android:right="2dip"
        Android:top="10dip" />
</shape>
2
William Morrison

pour faire des bordures, il faut créer un autre fichier xml avec la propriété solide et coins dans le dossier pouvant être dessiné et l'appeler en arrière-plan

1
pawan kumar

C'était incroyablement pratique pour moi. Je voudrais suggérer une autre solution de contournement pour souligner parfaitement les coins arrondis si vous utilisez votre propre CustomAdapter.

Définir des fichiers XML

Tout d’abord, allez dans votre dossier pouvant être dessiné et créez 4 formes différentes:

  • shape_top

    <gradient
        Android:startColor="#ffffff"
        Android:endColor="#ffffff"
        Android:angle="270"/>
    <corners
        Android:topLeftRadius="10dp"
        Android:topRightRadius="10dp"/>
    
  • forme normale

    <gradient
        Android:startColor="#ffffff"
        Android:endColor="#ffffff"
        Android:angle="270"/>
    <corners
        Android:topLeftRadius="10dp"
        Android:topRightRadius="10dp"/>
    
  • forme_bottom

    <gradient
        Android:startColor="#ffffff"
        Android:endColor="#ffffff"
        Android:angle="270"/>
    <corners
        Android:bottomRightRadius="10dp"
        Android:bottomRightRadius="10dp"/>
    
  • forme_roundée

    <gradient
        Android:startColor="#ffffff"
        Android:endColor="#ffffff"
        Android:angle="270"/>
    <corners
        Android:topLeftRadius="10dp"
        Android:topRightRadius="10dp"
        Android:bottomRightRadius="10dp"
        Android:bottomRightRadius="10dp"/>
    

Maintenant, créez une mise en page différente pour chaque forme, c'est-à-dire pour shape_top:

  • Vous pouvez également le faire par programme en modifiant l'arrière-plan.

    <TextView
        Android:id="@+id/textView1"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_gravity="center"
        Android:layout_marginLeft="20dp"
        Android:layout_marginRight="10dp"
        Android:fontFamily="sans-serif-light"
        Android:text="TextView"
        Android:textSize="22dp" />
    
    <TextView
        Android:id="@+id/txtValue1"
        Android:layout_width="match_parent"
        Android:layout_height="48dp"
        Android:textSize="22dp"
        Android:layout_gravity="right|center"
        Android:gravity="center|right"
        Android:layout_marginLeft="20dp"
        Android:layout_marginRight="35dp"
        Android:text="Fix"
        Android:scaleType="fitEnd" />
    

Et définissez un sélecteur pour chaque liste de formes, c'est-à-dire pour shape_top:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <!-- Selected Item -->

    <item Android:state_selected="true"
        Android:drawable="@drawable/shape_top" />
    <item Android:state_activated="true"
        Android:drawable="@drawable/shape_top" />

    <!-- Default Item -->
    <item Android:state_selected="false"
        Android:drawable="@Android:color/transparent" />
</selector>

Changer votre CustomAdapter

Enfin, définissez les options de disposition dans votre CustomAdapter:

if(position==0)
{
 convertView = mInflater.inflate(R.layout.list_layout_top, null);
}
else
{
 convertView = mInflater.inflate(R.layout.list_layout_normal, null);
}

if(position==getCount()-1)
{
convertView = mInflater.inflate(R.layout.list_layout_bottom, null);
}

if(getCount()==1)
{
convertView = mInflater.inflate(R.layout.list_layout_unique, null);
}

Et c'est fait!

1
Machado

en fait, je pense que la meilleure solution est décrite sur ce lien:

http://blog.synyx.de/2011/11/Android-listview-with-rounded-corners/

en bref, il utilise un arrière-plan différent pour les éléments du haut, du milieu et du bas, de sorte que ceux du haut et du bas soient arrondis.

1
android developer

J'utilise une vue personnalisée que je mets par-dessus les autres et qui dessine simplement les 4 petits coins de la même couleur que l'arrière-plan. Cela fonctionne quel que soit le contenu de la vue et n'alloue pas beaucoup de mémoire.

public class RoundedCornersView extends View {
    private float mRadius;
    private int mColor = Color.WHITE;
    private Paint mPaint;
    private Path mPath;

    public RoundedCornersView(Context context) {
        super(context);
        init();
    }

    public RoundedCornersView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();

        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.RoundedCornersView,
                0, 0);

        try {
            setRadius(a.getDimension(R.styleable.RoundedCornersView_radius, 0));
            setColor(a.getColor(R.styleable.RoundedCornersView_cornersColor, Color.WHITE));
        } finally {
            a.recycle();
        }
    }

    private void init() {
        setColor(mColor);
        setRadius(mRadius);
    }

    private void setColor(int color) {
        mColor = color;
        mPaint = new Paint();
        mPaint.setColor(mColor);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setAntiAlias(true);

        invalidate();
    }

    private void setRadius(float radius) {
        mRadius = radius;
        RectF r = new RectF(0, 0, 2 * mRadius, 2 * mRadius);
        mPath = new Path();
        mPath.moveTo(0,0);
        mPath.lineTo(0, mRadius);
        mPath.arcTo(r, 180, 90);
        mPath.lineTo(0,0);
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {

        /*Paint paint = new Paint();
        Paint.setColor(Color.RED);
        canvas.drawRect(0, 0, mRadius, mRadius, Paint);*/

        int w = getWidth();
        int h = getHeight();
        canvas.drawPath(mPath, mPaint);
        canvas.save();
        canvas.translate(w, 0);
        canvas.rotate(90);
        canvas.drawPath(mPath, mPaint);
        canvas.restore();
        canvas.save();
        canvas.translate(w, h);
        canvas.rotate(180);
        canvas.drawPath(mPath, mPaint);
        canvas.restore();
        canvas.translate(0, h);
        canvas.rotate(270);
        canvas.drawPath(mPath, mPaint);
    }
}
0
mbonnin