Wie erstelle ich in Android eine ListView mit abgerundeten Ecken?


Antworten:


371

Hier ist eine Möglichkeit (Dank der Android-Dokumentation!):

Fügen Sie Folgendes in eine Datei ein (z. B. customshape.xml) und platzieren Sie es in (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> 

Wenn Sie mit dem Erstellen dieser Datei fertig sind, stellen Sie den Hintergrund auf eine der folgenden Arten ein:

Durch Code: listView.setBackgroundResource(R.drawable.customshape);

Fügen Sie über XML einfach das folgende Attribut zum Container hinzu (z. B. LinearLayout oder beliebige Felder):

android:background="@drawable/customshape"

Hoffe, jemand findet es nützlich ...


2
Danke für den tollen Tipp. Nur zu Ihrer Information, das Einfügen von Kopien gab mir eine Laufzeitausnahme mit der Aufschrift "XmlPullParserException: Für das binäre XML-Dateizeil # 4 <gradient> -Tag muss das Attribut 'angle' ein Vielfaches von 45" sein. Einfach zu beheben, indem der Winkel auf 270 geändert wird.
Allclaws

Vielen Dank für die Korrektur ... Aber ich weiß nicht, warum das passieren könnte. Haben Sie einen bestimmten Grund gefunden?
Legende

@teedyay: Jederzeit Kumpel :)
Legende

1
Wie bei allclaws sollte der Winkel ein Vielfaches von 45 sein: "XmlPullParserException: Für das <gradient> -Tag der binären XML-Dateizeile Nr. 4 muss das Attribut 'angle' ein Vielfaches von 45 sein"
Youssef

29
Es funktioniert jedoch nicht gut mit Auswahlhervorhebung: Wenn das obere oder untere Element ausgewählt ist, ist der farbige Hintergrund rechteckig und wird über den Hintergrund mit runden Ecken gezeichnet.
Kris Van Bael

56

Obwohl das funktioniert hat, wurde auch die gesamte Hintergrundfarbe entfernt. Ich suchte nach einer Möglichkeit, nur den Rand zu erstellen und den XML-Layoutcode durch diesen zu ersetzen, und es konnte losgehen!

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


12

@ kris-van-bael

Wenn Sie Probleme mit der Auswahlmarkierung für die obere und untere Reihe haben, in der das Hintergrundrechteck bei der Auswahl angezeigt wird, müssen Sie den Selektor für Ihre Listenansicht auf transparente Farbe einstellen.

listView.setSelector(R.color.transparent);

Fügen Sie in color.xml einfach Folgendes hinzu:

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

5
es hat bei mir nicht funktioniert. Ich fügte jedoch die folgende Zeile hinzu, und sie wurde android:cacheColorHint="@android:color/transparent"
beseitigt

1
Dies hat definitiv das Auswahlproblem für mich behoben - danke! Sie können auch android.R.color.transparent für die Auswahlfarbe verwenden, anstatt Ihre eigene zu erstellen.
Greg7gkb

3
Anstatt dies programmgesteuert zu tun, fügen Sie dies Ihrer ListView im XML-Layout hinzu, um die Auswahlfarbe auszublenden: android: listSelector = "# 00000000"
Elad Nava

@alvins Gibt es eine Möglichkeit, das Layout für die Hervorhebung eines Listenansichtselements auswählbar zu machen?
Bharat Dodeja

Was soll ich tun, wenn ich für listSelector eine undurchsichtige Farbe verwenden möchte?
Suitianshi

3

Die anderen Antworten sind dank der Autoren sehr nützlich!

Ich konnte jedoch nicht sehen, wie das Rechteck angepasst werden kann, wenn ein Element bei der Auswahl hervorgehoben wird, anstatt das Hervorheben von @alvins @bharat dojeha zu deaktivieren.

Das Folgende funktioniert für mich, um einen gerundeten Listenansicht-Elementcontainer ohne Umriss und mit einem helleren Grau zu erstellen, wenn dieselbe Form ausgewählt wird:

Ihre XML muss einen Selektor enthalten, wie z. B. (in 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>

Anschließend müssen Sie einen Listenadapter implementieren und die getView-Methode überschreiben, um den benutzerdefinierten Selektor als Hintergrund festzulegen

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

und müssen auch das Standard-Auswahlrechteck 'ausblenden', z. B. in onCreate (ich verstecke auch meine dünne graue Trennlinie zwischen den Elementen):

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

Dieser Ansatz löst eine allgemeine Lösung für Drawables, nicht nur für ListViewItem mit verschiedenen Auswahlzuständen.


3

Aktualisieren

Die Lösung besteht heutzutage darin, eine CardViewmit Unterstützung für eingebaute abgerundete Ecken zu verwenden.


Ursprüngliche Antwort *

Eine andere Möglichkeit, die ich gefunden habe, bestand darin, Ihr Layout auszublenden, indem Sie ein Bild über das Layout zeichnen. Es könnte dir helfen. Schauen Sie sich abgerundete Ecken von Android XML an


2

Eine weitere Lösung für die Auswahl zeigt Probleme mit dem ersten und dem letzten Element in der Liste auf:

Fügen Sie am oberen und unteren Rand Ihres Listenhintergrunds einen Abstand hinzu, der dem Radius entspricht oder größer ist. Dadurch wird sichergestellt, dass sich die Auswahlhervorhebung nicht mit Ihren Eckkurven überschneidet.

Dies ist die einfachste Lösung, wenn Sie eine nicht transparente Auswahlhervorhebung benötigen.

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


1

Das war unglaublich praktisch für mich. Ich möchte eine andere Problemumgehung vorschlagen, um die abgerundeten Ecken perfekt hervorzuheben, wenn Sie Ihre eigenen verwenden CustomAdapter.

XML-Dateien definieren

Gehen Sie zunächst in Ihren Zeichenordner und erstellen Sie 4 verschiedene Formen:

  • shape_top

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

  • shape_normal

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

  • shape_bottom

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

  • shape_rounded

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

Erstellen Sie nun für jede Form ein anderes Zeilenlayout, dh für shape_top:

  • Sie können dies auch tun, indem Sie den Hintergrund programmgesteuert ändern.

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

Und definieren Sie einen Selektor für jede geformte Liste, dh für 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>

Ändern Sie Ihren CustomAdapter

Definieren Sie abschließend die Layoutoptionen in Ihrem 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);
}

Und das ist erledigt!


1

Um einen Rahmen zu erstellen, müssen Sie eine weitere XML-Datei mit der Eigenschaft Solid und Ecken im Zeichenordner erstellen und im Hintergrund aufrufen


0

Ich verwende eine benutzerdefinierte Ansicht, die ich über den anderen anordne und die nur die 4 kleinen Ecken in derselben Farbe wie der Hintergrund zeichnet. Dies funktioniert unabhängig vom Inhalt der Ansicht und weist nicht viel Speicher zu.

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);
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.