简体   繁体   中英

How to round corners of list item at the top and bottom of the list view? (not only for top and bottom items)

I have a listview with rounded corner at the top and the bottom. Look like this image: 在此输入图像描述

But when I click on the top and the bottom of ListView, the List Item's background is rectangle not rounded as background of ListView at top and bottom. Like this image :

列表项的角不圆

How to resolve this issue?

this is my code :

1/ list_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#cacaca">

<ListView
    android:id="@+id/listView3"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:background="@drawable/list_border"
    android:listSelector="@drawable/list_selector"/>
</LinearLayout>

2/ list_border.xml

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#fff"/>
<corners android:bottomRightRadius="10dp"
    android:bottomLeftRadius="10dp"
    android:topLeftRadius="10dp"
    android:topRightRadius="10dp"/>
</shape>

3/ list_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"
        android:drawable="@color/colorPrimary" />
</selector>

4/ ListActivity.java

ListView listView = (ListView)findViewById(R.id.listView3);

ArrayList<String> listItems = new ArrayList<>();

for(int i=0;i<20;i++){
    listItems.add(""+i);
}

ArrayAdapter<String> adapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_selectable_list_item, listItems);
listView.setAdapter(adapter);

This solution is not pretty but it does what you want. The idea is to invert the corner and draw them as foreground :

the ListView is wrapped in a FrameLayout :

<FrameLayout
      android:layout_width="match_parent"
      android:layout_height="0dp"
      android:layout_margin="10dp"
      android:foreground="@drawable/inverted_corners"
      android:layout_weight="1">
      <ListView
          android:id="@+id/listView3"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:background="#fff"
          android:listSelector="@drawable/list_selector" />
  </FrameLayout>

which foreground ( drawable/inverted_corners.xml ) is set to a rounded hole , drawn with the background color. The trick is to draw a line outside the shape, instead of a filled shape :

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:bottom="-11dp"
        android:left="-11dp"
        android:right="-11dp"
        android:top="-11dp">
        <shape android:shape="rectangle">
            <stroke
                android:width="10dp"
                android:color="#cacaca" />
            <corners android:radius="22dp" />
        </shape>
    </item>
</layer-list>

This garanties that the rounded corners are on top of the selector, and the overscroll effect.

I suggest you should set the layout with corners to your ListView 's first and last element, but not to the whole ListView .

You can create two extra .xml files in addition to your list_selector.xml : one for first element with the round corners at the top (lets call it list_selector_top.xml ) and another one for the last element with the round corners at the bottom ( list_selector_bottom.xml ).

Then you can create your own MyAdapter extends ArrayAdapter and somewhere in getView() method set the appropriate background to your element's View (if position==0 set list_selector_top.xml , if position==getCount()-1 set list_selector_bottom.xml , by default set list_selector.xml ).

It might be not the simpliest approach, but it works.

Set your corner radius to list view selector also using this:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/list"
        android:state_pressed="true"
        >
        <shape>
        <solid android:color="@color/colorPrimary"/>
        <corners
            android:radius="10dp"/>
        </shape>
        </item>

</selector>

so your selection will not be cross boundry of list view .

在此输入图像描述

cons - you will not able to define which radius you have to set as per top and bottom part that is why have to set radius to all sides.

hope this should help or at least give you some direction to resolve your issue.

If you can use FrameLayout as parent to the ListView , then set the cornered shape as foreground to the parent FrameLayout .

<?xml version="1.0" encoding="utf-8"?>
    <FrameLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:foreground="@drawable/list_border">

    <ListView
        android:id="@+id/listView3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:listSelector="@drawable/list_selector"/>
    </FrameLayout>

If you want to use LinearLayout as parent of ListView, then surround your ListView with ForegroundLinearLayout and set the cornered shape as foreground to the ForegroundLinearLayout .

What is ForegroundLinearLayout ? It is LinearLayout with Foreground property like FrameLayout . Get the code from Chris Banes. https://gist.github.com/chrisbanes/9091754

Your code should be:

<?xml version="1.0" encoding="utf-8"?>
<ForegroundLinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:foreground="@drawable/list_border">

<ListView
    android:id="@+id/listView3"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:listSelector="@drawable/list_selector"/>
</ForegroundLinearLayout>

please add padding in your style.i updated style here.
2 list_border.xml

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#fff"/>
<corners android:bottomRightRadius="10dp"
android:bottomLeftRadius="10dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp"/>
<padding android:left="10dp"
      android:right="10dp"
      android:top="10dp"
      android:bottom="10dp"
      />
</shape>

This can be done easily by using Android's support library's CardView . Just wrap your ListView in a CardView layout and set a cardCornerRadius to the CardView , like this:

        <?xml version="1.0" encoding="utf-8"?>
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:orientation="vertical" android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#cacaca">

            <android.support.v7.widget.CardView
                xmlns:card_view="http://schemas.android.com/apk/res-auto"
                android:layout_height="wrap_content"
                android:layout_width="match_parent"
                card_view:cardCornerRadius="10dp"
                >

                <ListView
                    android:id="@+id/listView3"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_margin="10dp"
                    android:listSelector="@drawable/list_selector"/>
            </android.support.v7.widget.CardView>
        </LinearLayout>

Dont forgot to import the CardView 's support library:

compile 'com.android.support:cardview-v7:23.1.1'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM