Làm cách nào để tạo ListView với các góc tròn trong Android?


Câu trả lời:


371

Đây là một cách để làm điều đó (Nhờ Tài liệu Android!):

Thêm phần sau vào một tệp (giả sử customshape.xml) và sau đó đặt tệp đó vào (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> 

Khi bạn đã hoàn tất việc tạo tệp này, chỉ cần đặt nền theo một trong các cách sau:

Thông qua mã: listView.setBackgroundResource(R.drawable.customshape);

Thông qua XML , chỉ cần thêm thuộc tính sau vào vùng chứa (ví dụ: linearLayout hoặc vào bất kỳ trường nào):

android:background="@drawable/customshape"

Hy vọng ai đó thấy nó hữu ích ...


2
Cám ơn về tiền bo nhiều. Chỉ cần FYI, dán sao chép đã cho tôi một ngoại lệ thời gian chạy với nội dung: "XmlPullParserException: Dòng tệp nhị phân XML # 4 <gradient> yêu cầu thuộc tính 'angle' là bội số của 45" .. Dễ dàng khắc phục bằng cách thay đổi góc thành 270.
allclaws

Cảm ơn đã sửa chữa ... Nhưng tôi không biết tại sao điều đó có thể xảy ra .. Bạn có tìm thấy lý do cụ thể nào không?
Truyền thuyết

@teedyay: Bất cứ lúc nào bạn ơi :)
Truyền thuyết

1
giống như allclaws, angle phải là bội số của 45: "XmlPullParserException: Dòng tệp nhị phân XML # 4 <gradient> yêu cầu thuộc tính 'angle' là bội số của 45"
Youssef

29
Mặc dù vậy, nó không hoạt động tốt với làm nổi bật lựa chọn: Khi mục trên cùng hoặc dưới cùng được chọn, nền màu của nó là hình chữ nhật và được vẽ trên nền của góc tròn.
Kris Van Bael

56

Mặc dù điều đó đã làm việc, nó cũng lấy ra toàn bộ màu nền. Tôi đang tìm cách để chỉ làm đường viền và chỉ cần thay thế mã bố cục XML đó bằng mã này và tôi đã rất tốt để đi!

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

Ngoài ra hãy xem câu trả lời này
ThomasRS

12

@ kris-van-bael

Đối với những người có vấn đề với tô sáng lựa chọn cho hàng trên cùng và dưới cùng, nơi hình chữ nhật nền hiển thị trên vùng chọn, bạn cần đặt bộ chọn cho chế độ xem của bạn thành màu trong suốt.

listView.setSelector(R.color.transparent);

Trong color.xml chỉ cần thêm vào như sau -

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

5
nó không làm việc cho tôi Tuy nhiên, tôi đã thêm dòng sau đây và nó đã thoát khỏi nó:android:cacheColorHint="@android:color/transparent"
mổ lấy thai

1
Điều này chắc chắn đã khắc phục vấn đề lựa chọn cho tôi - cảm ơn! Bạn cũng có thể sử dụng android.R.color.transparent cho màu Selector thay vì tạo màu của riêng bạn.
greg7gkb

3
Thay vì thực hiện theo cách lập trình, hãy thêm phần này vào ListView của bạn trong bố cục XML để ẩn màu lựa chọn: android: listSelector = "# 00000000"
Elad Nava

@alvins Có cách nào để bố trí có thể chọn để làm nổi bật như mục xem danh sách không?
Bharat Dodeja

Tôi nên làm gì nếu tôi muốn sử dụng màu đục cho listSelector?
suitianshi

3

Các câu trả lời khác rất hữu ích, nhờ các tác giả!

Nhưng tôi không thể thấy cách tùy chỉnh hình chữ nhật khi làm nổi bật một mục khi lựa chọn thay vì vô hiệu hóa phần tô sáng @alvins @bharat dojeha.

Các công việc sau đây để tôi tạo một thùng chứa mục xem danh sách tròn không có viền ngoài và màu xám nhạt hơn khi được chọn có cùng hình dạng:

Xml của bạn cần chứa một bộ chọn, ví dụ: (trong 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>

Sau đó, bạn cần triển khai bộ điều hợp danh sách và ghi đè phương thức getView để đặt bộ chọn tùy chỉnh làm nền

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

và cũng cần 'ẩn' hình chữ nhật của bộ chọn mặc định, ví dụ như trong onCreate (Tôi cũng ẩn dòng chia màu xám mỏng giữa các mục):

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

Cách tiếp cận này giải quyết một giải pháp chung cho các drawable, không chỉ ListViewItem với các trạng thái lựa chọn khác nhau.


3

Cập nhật

Giải pháp hiện nay là sử dụng CardViewhỗ trợ cho các góc tròn được tích hợp sẵn.


Câu trả lời gốc *

Một cách khác tôi tìm thấy là che giấu bố cục của bạn bằng cách vẽ một hình ảnh trên đầu bố cục. Nó có thể giúp bạn. Kiểm tra các góc được cắt tròn của Android XML


2

Một giải pháp khác để lựa chọn làm nổi bật các vấn đề với các mục đầu tiên và cuối cùng trong danh sách:

Thêm phần đệm vào trên cùng và dưới cùng của nền danh sách của bạn bằng hoặc lớn hơn bán kính. Điều này đảm bảo việc tô sáng vùng chọn không trùng với các đường cong góc của bạn.

Đây là giải pháp đơn giản nhất khi bạn cần làm nổi bật lựa chọn không minh bạch.

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

Điều này là vô cùng tiện dụng với tôi. Tôi muốn đề xuất một cách giải quyết khác để làm nổi bật hoàn hảo các góc tròn nếu bạn đang sử dụng của riêng bạn CustomAdapter.

Xác định tệp XML

Trước hết, hãy vào trong thư mục có thể vẽ của bạn và tạo 4 hình dạng khác nhau:

  • hình dạng

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

  • hình dạng bất thường

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

  • hình dạng_bottom

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

  • hình dạng_rounded

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

Bây giờ, tạo một bố cục hàng khác nhau cho mỗi hình dạng, tức là cho shape_top:

  • Bạn cũng có thể làm điều này theo chương trình thay đổi nền.

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

Và xác định một bộ chọn cho mỗi danh sách hình, tức là cho 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>

Thay đổi Chương trình tùy chỉnh của bạn

Cuối cùng, xác định các tùy chọn bố trí bên trong 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);
}

Và thế là xong!


1

để tạo đường viền, bạn phải tạo một tệp xml khác có thuộc tính solid và angle trong thư mục drawable và gọi nó ở chế độ nền


0

Tôi đang sử dụng chế độ xem tùy chỉnh mà tôi bố trí trên các chế độ khác và chỉ vẽ 4 góc nhỏ cùng màu với nền. Điều này hoạt động cho dù nội dung xem là gì và không phân bổ nhiều bộ nhớ.

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);
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.