How do I create a ListView with rounded corners in Android?

AndroidAndroid LayoutAndroid Listview

Android Problem Overview


How do I create a ListView with rounded corners in Android?

Android Solutions


Solution 1 - Android

Here is one way of doing it (Thanks to Android Documentation though!):

Add the following into a file (say customshape.xml) and then place it 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> 

Once you are done with creating this file, just set the background in one of the following ways:

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

Through XML, just add the following attribute to the container (ex: LinearLayout or to any fields):

android:background="@drawable/customshape"

Hope someone finds it useful...

Solution 2 - Android

Although that did work, it took out the entire background colour as well. I was looking for a way to do just the border and just replace that XML layout code with this one and I was good to go!

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

Solution 3 - Android

@kris-van-bael

For those having issues with selection highlight for the top and bottom row where the background rectangle shows up on selection you need to set the selector for your listview to transparent color.

listView.setSelector(R.color.transparent);

In color.xml just add the following -

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

Solution 4 - Android

Update

The solution these days is to use a CardView with support for rounded corners built in.


Original answer*

Another way I found was to mask out your layout by drawing an image over the top of the layout. It might help you. Check out https://stackoverflow.com/questions/4328166/android-xml-rounded-clipped-corners

Solution 5 - Android

The other answers are very useful, thanks to the authors!

But I could not see how to customise the rectangle when highlighting an item upon selection rather than disabling the highlighting @alvins @bharat dojeha.

The following works for me to create a rounded list view item container with no outline and a lighter grey when selected of the same shape:

Your xml needs to contain a selector such as e.g. ( 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>

Then you need to implement a list adapter and override the getView method to set the custom selector as background

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

and need to also 'hide' the default selector rectangle e.g in onCreate (I also hide my thin grey divider line between the items):

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

This approach solves a general solution for drawables, not just ListViewItem with various selection states.

Solution 6 - Android

Yet another solution to selection highlight problems with first, and last items in the list:

Add padding to the top and bottom of your list background equal to or greater than the radius. This ensures the selection highlighting doesn't overlap with your corner curves.

This is the easiest solution when you need non-transparent selection highlighting.

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

Solution 7 - Android

actually, i think the best solution is described on this link:

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

in short, it uses a different background for the top, middle and bottom items, so that the top and bottom ones would be rounded.

Solution 8 - Android

This was incredibly handy to me. I would like to suggest another workaround to perfectly highlight the rounded corners if you are using your own CustomAdapter.

Defining XML Files

First of all, go inside your drawable folder and create 4 different shapes:

  • shape_top

    http://schemas.android.com/apk/res/android" android:shape="rectangle">

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

  • shape_normal

    http://schemas.android.com/apk/res/android" android:shape="rectangle">

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

  • shape_bottom http://schemas.android.com/apk/res/android" android:shape="rectangle">

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

  • shape_rounded http://schemas.android.com/apk/res/android" android:shape="rectangle">

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

Now, create a different row layout for each shape, i.e. for shape_top :

  • You can also do this programatically changing the background.

    http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:background="@drawable/list_selected_top" >

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

And define a selector for each shaped-list, i.e. for 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>

Change your CustomAdapter

Finally, define the layout options inside your 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);
}

And that's done!

Solution 9 - Android

to make border u have to make another xml file with property of solid and corners in the drawable folder and calls it in background

Solution 10 - Android

I'm using a custom view that I layout on top of the other ones and that just draws the 4 small corners in the same color as the background. This works whatever the view contents are and does not allocate much memory.

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);
    }
}

Solution 11 - Android

There are different ways to achieve it. The latest approach is using CardView for each ListItem component. Here are some steps.

  1. Create a layout resource file; let's name it "listitem.xml
  2. Copy and paste the under enclosed Listitem.xml layout body into it.
  3. Create RowItem class for each listitem data; later you will instantiate this to assign values for each list item. Check Code below, RowItem.class.
  4. Create a custom ListAdapter; let's name it ListAdapter.class, and inflate this (#1) list item layout for each list item (Check the second code snippet for this one)
  5. Set this adapter (#3) the way you set default adapters inside an activity the listview belongs to. maybe the only difference would be you first have to instantiate RowItem class with values and add RowItem object to your adapter then notify your adapter that the data is changed.
**listitem.xml**
<?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        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="wrap_content"
        android:orientation="vertical">
        <GridLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"

            android:alignmentMode="alignMargins"
            android:columnCount="1"
            android:columnOrderPreserved="false"
            android:rowCount="1">
            <androidx.cardview.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_rowWeight="1"
                android:layout_columnWeight="1"
                android:layout_margin="6dp"
                app:cardCornerRadius="8dp"
                app:cardElevation="6dp">
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="horizontal">
                    <ImageView
                        android:id="@+id/sampleiconimageID"
                        android:layout_width="60dp"
                        android:layout_height="60dp"
                        android:padding="5dp"/>
                    <LinearLayout android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:orientation="vertical">
                        <TextView
                            android:id="@+id/titleoflistview"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:text="Main Heading"
                            android:textStyle="bold" />
                        <TextView
                            android:id="@+id/samplesubtitle"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:text="Sub Heading"
                           />
                        </LinearLayout>
                </LinearLayout>
            </androidx.cardview.widget.CardView>
        </GridLayout>
    </LinearLayout>

RowItem.Class

public class RowItem {
    private String heading;
    private String subHeading;
    private int smallImageName;
    private String datetime;
    private int count;

    public void setHeading( String theHeading ) {
        this.heading = theHeading;
    }

    public String getHeading() {
        return this.heading;
    }
    public void setSubHeading( String theSubHeading ) {

        this.subHeading = theSubHeading;

    }

    public String getSubHeading( ) {

        return this.subHeading;

    }

    public void setSmallImageName(int smallName) {

        this.smallImageName = smallName;

    }

    public int getSmallImageName() {

        return this.smallImageName;

    }

    public void setDate(String datetime) {
        this.datetime = datetime;
    }

    public String getDate() {
        return this.datetime;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public int getCount() {
        return this.count;
    }

}

Sample ListAdapter

public class ListAdapter extends BaseAdapter {
    private ArrayList<RowItem> singleRow;
    private LayoutInflater thisInflater;

    public ListAdapter(Context context, ArrayList<RowItem> aRow){

        this.singleRow = aRow;
        thisInflater = ( LayoutInflater.from(context) );
    }
    @Override
    public int getCount() {
        return singleRow.size();    }

    @Override
    public Object getItem(int position) {
        return singleRow.get( position );    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View view, ViewGroup parent) {

        if (view == null) {
            view = thisInflater.inflate( R.layout.mylist2, parent, false );
            //set listview objects here
            //example

            TextView titleText = (TextView) view.findViewById(R.id.titleoflistview);
           
            RowItem currentRow = (RowItem) getItem(position);
            
            titleText.setText( currentRow.getHeading() );
          
        }

        return view;

//        LayoutInflater inflater=.getLayoutInflater();
//        View rowView=inflater.inflate(R.layout.mylist, null,true);
//

//        titleText.setText(maintitle[position]);
//        subtitleText.setText(subtitle[position]);

//        return null;

    };
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLegendView Question on Stackoverflow
Solution 1 - AndroidLegendView Answer on Stackoverflow
Solution 2 - AndroidKevin ParkerView Answer on Stackoverflow
Solution 3 - AndroidalvinsView Answer on Stackoverflow
Solution 4 - AndroidRichard Le MesurierView Answer on Stackoverflow
Solution 5 - Androiddr_gView Answer on Stackoverflow
Solution 6 - AndroidWilliam MorrisonView Answer on Stackoverflow
Solution 7 - Androidandroid developerView Answer on Stackoverflow
Solution 8 - AndroidMachadoView Answer on Stackoverflow
Solution 9 - Androidpawan kumarView Answer on Stackoverflow
Solution 10 - AndroidmbonninView Answer on Stackoverflow
Solution 11 - AndroidNatiCogView Answer on Stackoverflow