如何在 Android 中创建带圆角的 ListView?

如何在 Android 中创建带圆角的 ListView?

122419 次浏览

这里有一种方法(不过还是要感谢 Android 文档!) :

将以下内容添加到文件中(比如 customshape.xml) ,然后将其放入(res/draable/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>

创建完这个文件后,只需用以下方法之一设置背景:

代码: listView.setBackgroundResource(R.drawable.customshape);

通过 XML ,只需将以下属性添加到容器(例如: LinearLayout 或任何字段) :

android:background="@drawable/customshape"

希望有人觉得有用。

虽然这样做的工作,它采取了整个背景颜色以及。我正在寻找一种方法,只是做边界,只是替换 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


原始答案 *

我发现的另一种方法是通过在布局顶部绘制图像来掩盖布局。也许能帮到你。看看 Android XML 圆角剪裁

@ kris-van-bael

对于那些有问题的选择高亮顶部和底部行背景矩形显示在选择,你需要设置选择器为您的列表视图透明的颜色。

listView.setSelector(R.color.transparent);

在 color.xml 中,只需添加以下内容-

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

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

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

简而言之,它为顶部、中部和底部项目使用不同的背景,这样顶部和底部项目将被圆滑。

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

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

当您需要非透明选择突出显示时,这是最简单的解决方案。

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

然后,您需要实现一个列表适配器并重写 getView 方法以将自定义选择器设置为背景

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

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

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

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

这对我来说非常方便。我想建议另一个解决方案,以完美突出的圆角,如果你使用自己的 CustomAdapter

定义 XML 文件

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

  • Shape _ top

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

现在,为每个形状创建一个不同的行布局,即 shape_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" />
    

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

更改自定义适配器

最后,定义 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);
}

就这么定了!

为了制作边框,你必须在可绘制文件夹中制作另一个具有实心和角的属性的 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。 这里有一些步骤。

  1. 创建一个布局资源文件; 我们将其命名为“ listitem.xml”
  2. 复制并粘贴下封闭的 Xml布局主体到其中。
  3. 为每个列表数据创建 RowItem 类; 稍后您将实例化该类以为每个列表项分配值。检查下面的 Code,RowItem.class。
  4. 创建一个自定义 ListAdapter; 我们将其命名为 ListAdapter.class,并为每个列表项膨胀这个(# 1)列表项布局(检查第二个代码片段)
  5. 按照在 listview 所属的活动中设置默认适配器的方式设置此适配器(# 3)。也许唯一的区别是您首先必须用值实例化 RowItem 类,并将 RowItem 对象添加到适配器,然后通知适配器数据已更改。
**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 同学们

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


}

示例 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;


};
}