如何在Android中创建圆角列表视图?

如何在Android中创建圆角列表视图?,android,android-layout,android-listview,Android,Android Layout,Android Listview,如何在Android中创建圆角列表视图?以下是一种方法(感谢Android文档!): 将以下内容添加到文件(比如customshape.xml)中,然后将其放入(res/drawable/customshape.xml) 希望有人会觉得它有用…虽然它确实有用,但它也去掉了整个背景色。我正在寻找一种方法来处理边界,并用这个代码替换XML布局代码,我很乐意去做 <shape xmlns:android="http://schemas.android.com/apk/res/android"&g

如何在Android中创建圆角列表视图?

以下是一种方法(感谢Android文档!):

将以下内容添加到文件(比如customshape.xml)中,然后将其放入(res/drawable/customshape.xml)


希望有人会觉得它有用…

虽然它确实有用,但它也去掉了整个背景色。我正在寻找一种方法来处理边界,并用这个代码替换XML布局代码,我很乐意去做

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

更新

现在的解决方案是使用内置圆角支持的
CardView


原始答案*

我发现的另一种方法是通过在布局顶部绘制图像来掩盖布局。这可能对你有帮助。查看

@kris van bael

对于那些在选择时显示背景矩形的顶行和底行的选择高亮显示有问题的用户,您需要将listview的选择器设置为透明颜色

listView.setSelector(R.color.transparent);
在color.xml中,只需添加以下内容-

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

实际上,我认为最好的解决方案是在这个链接上描述的:


简言之,它对顶部、中间和底部项目使用不同的背景,因此顶部和底部项目将被舍入

选择的另一个解决方案突出了列表中第一项和最后一项的问题:

在列表背景的顶部和底部添加等于或大于半径的填充。这样可以确保选择高亮显示不会与角点曲线重叠

当您需要不透明的选择高亮显示时,这是最简单的解决方案

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

感谢作者,其他答案非常有用

但我看不出如何在选择时突出显示项目时自定义矩形,而不是禁用突出显示@alvins@bharat dojeha

以下内容可用于创建圆形列表视图项容器,当选择相同形状时,该容器没有轮廓且为浅灰色:

您的xml需要包含选择器,例如(在res/drawable/customshape.xml中):

并且还需要“隐藏”默认选择器矩形,例如在onCreate中(我还隐藏项目之间的灰色细分隔线):


这种方法解决了可绘图项的通用解决方案,而不仅仅是具有各种选择状态的ListViewItem

这对我来说非常方便。如果您正在使用自己的
CustomAdapter
,我想建议另一种解决方法来完美突出圆角

定义XML文件 首先,进入可绘制文件夹,创建4种不同的形状:

  • 形状与顶部

并为每个形状列表定义一个选择器,即为
shape\u 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>

完成了

要创建边框,您必须在可绘制文件夹中创建另一个具有solid和corners属性的xml文件,并在后台调用它

我使用的是一个自定义视图,我将其布局在其他视图的顶部,它仅以与背景相同的颜色绘制4个小角。无论视图内容是什么,它都可以工作,并且不会分配太多内存

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

有不同的方法来实现它。最新的方法是对每个ListItem组件使用CardView。 以下是一些步骤

  • 创建布局资源文件;让我们把它命名为“listitem.xml”
  • 将封闭的Listitem.xml布局正文复制并粘贴到其中
  • 为每个listitem数据创建RowItem类;稍后您将实例化该类以为每个列表项分配值。请检查下面的代码RowItem.class
  • 创建一个自定义ListAdapter;让我们将其命名为ListAdapter.class,并为每个列表项扩展此(#1)列表项布局(检查第二个代码段)
  • 按照在listview所属的活动中设置默认适配器的方式设置此适配器(#3)。可能唯一的区别是,首先必须使用值实例化RowItem类,并将RowItem对象添加到适配器,然后通知适配器数据已更改
  • 示例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;
    
        };
    }
    
    公共类ListAdapter扩展了BaseAdapter{
    私有数组列表单行;
    私人停车场,充气机;
    公共ListAdapter(上下文上下文,ArrayList aRow){
    this.singleRow=aRow;
    thisInflater=(LayoutInflater.from(context));
    }
    @凌驾
    public int getCount(){
    返回singleRow.size();}
    @凌驾
    公共对象getItem(int位置){
    返回singleRow.get(位置);}
    @凌驾
    公共长getItemId(int位置){
    返回位置;
    }
    公共视图getView(内部位置、视图视图、视图组父视图){
    如果(视图==null){
    视图=此充气器。充气(R.layout.mylist2,父项,false);
    //在此处设置listview对象
    //范例
    TextView titleText=(TextView)view.findViewById(R.id.titleoflistview);
    RowItem currentRow=(RowItem)getItem(位置);
    titleText.setText(currentRow.getHeading());
    }
    返回视图;
    //LayoutInflater充气器=.getLayoutInflater();
    //视图行视图=充气机。充气(R.layout.mylist,null,true);
    //
    //titleText.setText(主标题[职位]);
    //subtitleText.setText(副标题[位置]);
    //返回null;
    };
    }
    
    谢谢你的精彩提示。仅供参考,复制粘贴给了我一个运行时异常,它说:“XmlPullParserException:Binary XML file line#4标记要求'angle'属性是45的倍数".. 将角度更改为270即可轻松修复。感谢您的修复。。。但我不知道为什么会这样。。你找到什么具体原因了吗?谢谢你的提示!只是
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            //snip
            convertView.setBackgroundResource(R.drawable.customshape);
            //snip
        }
    
    listView.setSelector(android.R.color.transparent);
    listview.setDivider(null);
    
    <gradient
        android:startColor="#ffffff"
        android:endColor="#ffffff"
        android:angle="270"/>
    <corners
        android:topLeftRadius="10dp"
        android:topRightRadius="10dp"/>
    
    <gradient
        android:startColor="#ffffff"
        android:endColor="#ffffff"
        android:angle="270"/>
    <corners
        android:topLeftRadius="10dp"
        android:topRightRadius="10dp"/>
    
    <gradient
        android:startColor="#ffffff"
        android:endColor="#ffffff"
        android:angle="270"/>
    <corners
        android:bottomRightRadius="10dp"
        android:bottomRightRadius="10dp"/>
    
    <gradient
        android:startColor="#ffffff"
        android:endColor="#ffffff"
        android:angle="270"/>
    <corners
        android:topLeftRadius="10dp"
        android:topRightRadius="10dp"
        android:bottomRightRadius="10dp"
        android:bottomRightRadius="10dp"/>
    
    <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" />
    
    <?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>
    
    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);
    }
    
    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);
        }
    }
    
    **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>
    
    
    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;
        }
    
    }
    
    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;
    
        };
    }