Comment créer un ListView avec des angles arrondis sous Android?
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 ...
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>
@ 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>
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
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.
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>
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
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
.
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>
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!
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.
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);
}
}