ฉันจะสร้าง ListView ด้วยมุมที่โค้งมนใน Android ได้อย่างไร


คำตอบ:


371

นี่คือวิธีหนึ่งในการทำมัน (ขอบคุณเอกสาร Android แม้ว่า!):

เพิ่มสิ่งต่อไปนี้ลงในไฟล์ (พูด customshape.xml) แล้ววางลงใน (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> 

เมื่อคุณสร้างไฟล์นี้เสร็จแล้วให้ตั้งค่าพื้นหลังด้วยวิธีใดวิธีหนึ่งต่อไปนี้:

ผ่านรหัส: listView.setBackgroundResource(R.drawable.customshape);

ผ่าน XMLเพียงแค่เพิ่มแอททริบิวต่อไปนี้ลงในคอนเทนเนอร์ (เช่น LinearLayout หรือฟิลด์ใด ๆ ):

android:background="@drawable/customshape"

หวังว่าใครบางคนพบว่ามันมีประโยชน์ ...


2
ขอบคุณสำหรับเคล็ดลับที่ดี เพียงแค่ FYI การคัดลอกวางทำให้ฉันมีข้อยกเว้นรันไทม์บอกว่า "XmlPullParserException: ไฟล์บรรทัด XML # 4 แท็ก <gradient> แท็กต้องมีแอตทริบิวต์ 'มุม' เป็นหลาย 45" .. แก้ไขได้อย่างง่ายดายโดยการเปลี่ยนมุมเป็น 270
allclaws

ขอบคุณสำหรับการแก้ไข ... แต่ฉันไม่รู้ว่าทำไมมันอาจจะเกิดขึ้น .. คุณหาเหตุผลเฉพาะหรือไม่
ตำนาน

@teedyay: เพื่อนได้ตลอดเวลา :)
ตำนาน

1
เช่นเดียวกับ allclaws มุมควรเป็นทวีคูณของ 45: "XmlPullParserException: บรรทัดไฟล์ XML แบบ # 4 แท็ก <gradient> ต้องใช้แอตทริบิวต์ 'angle' เป็นหลายมุม 45"
Youssef

29
มันไม่ทำงานได้ดีกับการเน้นการเลือกแม้ว่า: เมื่อรายการด้านบนหรือด้านล่างถูกเลือกพื้นหลังสีมันจะเป็นรูปสี่เหลี่ยมผืนผ้าและวาดที่ด้านบนของพื้นหลังแบบมุมโค้ง
Kris Van Bael

56

แม้ว่ามันจะใช้งานได้ แต่ก็ใช้สีพื้นหลังทั้งหมดเช่นกัน ฉันกำลังมองหาวิธีที่จะทำแค่ชายแดนและเพียงแค่แทนที่รหัสเค้าโครง 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> 


12

@ kris-รถตู้มะตูม

สำหรับผู้ที่มีปัญหาเกี่ยวกับการเลือกไฮไลต์สำหรับแถวบนและล่างที่สี่เหลี่ยมผืนผ้าพื้นหลังแสดงขึ้นมาในการเลือกคุณต้องตั้งค่าตัวเลือกสำหรับ listview ของคุณเป็นสีโปร่งใส

listView.setSelector(R.color.transparent);

ใน color.xml เพียงเพิ่มต่อไปนี้ -

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

5
มันไม่ทำงานสำหรับฉัน อย่างไรก็ตามฉันได้เพิ่มบรรทัดต่อไปนี้แล้วและมันก็กำจัดมันออกไปได้android:cacheColorHint="@android:color/transparent"
ซีซาร์

1
นี่เป็นการแก้ไขปัญหาการเลือกสำหรับฉันอย่างแน่นอน - ขอบคุณ! คุณยังสามารถใช้ android.R.color.transparent สำหรับสี Selector แทนที่จะสร้างด้วยตัวคุณเอง
greg7gkb

3
แทนที่จะทำแบบเป็นทางการให้เพิ่มส่วนนี้ลงใน ListView ของคุณในรูปแบบ XML เพื่อซ่อนสีของส่วนที่เลือก: android: listSelector = "# 00000000"
Elad Nava

@alvins มีวิธีใดบ้างที่จะทำให้เลือกเค้าโครงได้สำหรับการเน้นเช่นรายการในมุมมองรายการ
Bharat Dodeja

ฉันควรทำอย่างไรถ้าฉันต้องการใช้สีทึบสำหรับ listSelector
suitianshi

3

คำตอบอื่น ๆ มีประโยชน์มากขอบคุณผู้เขียน!

แต่ฉันไม่เห็นวิธีการปรับแต่งสี่เหลี่ยมเมื่อทำการไฮไลต์ไอเท็มตามการเลือกแทนที่จะปิดใช้งานการไฮไลต์ @alvins @bharat dojeha

ต่อไปนี้ใช้งานได้สำหรับฉันในการสร้างคอนเทนเนอร์ไอเท็มมุมมองรายการแบบโค้งมนที่ไม่มีเค้าร่างและสีเทาอ่อนเมื่อเลือกรูปร่างเดียวกัน

xml ของคุณต้องมีตัวเลือกเช่นเช่น (ใน 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>

จากนั้นคุณจะต้องใช้ตัวแปลงรายการและแทนที่เมธอด 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);

วิธีการนี้จะแก้ปัญหาทั่วไปสำหรับ drawable ไม่ใช่แค่ ListViewItem กับสถานะการเลือกที่หลากหลาย


3

ปรับปรุง

การแก้ปัญหาวันนี้คือการใช้CardViewด้วยการสนับสนุนสำหรับมุมโค้งมนในตัว


คำตอบเดิม *

อีกวิธีหนึ่งที่ฉันพบคือการปกปิดเลย์เอาต์ของคุณโดยการวาดภาพที่ด้านบนของเลย์เอาต์ มันอาจช่วยคุณได้ ตรวจสอบAndroid XML มุมที่ถูกปัดเศษ


2

อีกวิธีการหนึ่งในการเลือกเน้นปัญหากับรายการแรกและรายการสุดท้ายในรายการ:

เพิ่มช่องว่างภายในด้านบนและด้านล่างของพื้นหลังรายการของคุณเท่ากับหรือมากกว่ารัศมี สิ่งนี้ทำให้มั่นใจได้ว่าการไฮไลต์ที่เลือกจะไม่ทับซ้อนกับเส้นโค้งมุมของคุณ

นี่เป็นวิธีที่ง่ายที่สุดเมื่อคุณต้องการเน้นการเลือกที่ไม่โปร่งใส

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

จริงๆแล้วฉันคิดว่าทางออกที่ดีที่สุดมีอธิบายไว้ในลิงก์นี้:

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

ในระยะสั้นจะใช้พื้นหลังที่แตกต่างกันสำหรับรายการด้านบนกลางและด้านล่างดังนั้นด้านบนและด้านล่างจะถูกปัดเศษ


1

นี่เป็นประโยชน์กับฉันอย่างไม่น่าเชื่อ ฉันอยากจะแนะนำวิธีแก้ปัญหาอื่นเพื่อเน้นมุมที่โค้งมนอย่างสมบูรณ์แบบถ้าคุณใช้ของคุณเองCustomAdapterผมอยากจะขอแนะนำวิธีแก้ปัญหาอีกครั้งเพื่อให้ได้อย่างสมบูรณ์แบบเน้นมุมโค้งมนถ้าคุณกำลังใช้ของคุณเอง

การกำหนดไฟล์ XML

ก่อนอื่นให้เข้าไปในโฟลเดอร์ drawable ของคุณและสร้างรูปร่างที่แตกต่างกัน 4 แบบ:

  • shape_top

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

  • shape_normal

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

  • shape_bottom

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

  • shape_rounded

    <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 ของคุณ

สุดท้ายกำหนดตัวเลือกเค้าโครงภายในของคุณ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);
}

และนั่นก็เสร็จแล้ว!


1

เพื่อทำให้เส้นขอบคุณต้องสร้างไฟล์ xml อีกไฟล์ด้วยคุณสมบัติของ solid และมุมในโฟลเดอร์ drawable และเรียกมันในพื้นหลัง


0

ฉันใช้มุมมองที่กำหนดเองที่ฉันวางเลย์เอาต์ด้านบนของมุมมองอื่นและเพียงแค่ดึงมุมเล็ก ๆ 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);
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.