พื้นหลังรายการ ListView ผ่านตัวเลือกที่กำหนดเอง


98

เป็นไปได้ไหมที่จะใช้พื้นหลังแบบกำหนดเองกับรายการ Listview แต่ละรายการผ่านตัวเลือกรายการ

ตัวเลือกเริ่มต้นระบุ@android:color/transparentสำหรับstate_focused="false"กรณีและปัญหา แต่การเปลี่ยนค่านี้เป็นแบบวาดเองบางรายการจะไม่มีผลกับรายการที่ไม่ได้เลือก Romain Guy ดูเหมือนจะแนะนำในคำตอบนี้ว่าเป็นไปได้

ขณะนี้ฉันได้รับผลกระทบเดียวกันโดยใช้พื้นหลังที่กำหนดเองในแต่ละมุมมองและซ่อนไว้เมื่อรายการถูกเลือก / โฟกัส / อะไรก็ตามที่แสดงตัวเลือก แต่จะดีกว่าหากกำหนดสิ่งนี้ทั้งหมดไว้ในที่เดียว

สำหรับการอ้างอิงนี่คือตัวเลือกที่ฉันใช้เพื่อลองใช้งาน:

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_focused="false"
        android:drawable="@drawable/list_item_gradient" />

    <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
    <item android:state_focused="true" android:state_enabled="false"
        android:state_pressed="true"
        android:drawable="@drawable/list_selector_background_disabled" />
    <item android:state_focused="true" android:state_enabled="false"
        android:drawable="@drawable/list_selector_background_disabled" />

    <item android:state_focused="true" android:state_pressed="true"
        android:drawable="@drawable/list_selector_background_transition" />
    <item android:state_focused="false" android:state_pressed="true"
        android:drawable="@drawable/list_selector_background_transition" />

    <item android:state_focused="true"
        android:drawable="@drawable/list_selector_background_focus" />

</selector>

และนี่คือวิธีที่ฉันตั้งค่าตัวเลือก:

<ListView
    android:id="@android:id/list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:listSelector="@drawable/list_selector_background" />    

ขอบคุณล่วงหน้าสำหรับความช่วยเหลือ!

คำตอบ:


128

ฉันเคยผิดหวังกับเรื่องนี้และในที่สุดก็แก้ไขได้ ตามที่ Romain Guy บอกใบ้มีอีกสถานะหนึ่ง"android:state_selected"ที่คุณต้องใช้ ใช้สถานะที่วาดได้สำหรับพื้นหลังของรายการของคุณและใช้สถานะอื่นที่สามารถดึงได้สำหรับlistSelectorรายการของคุณ:

list_row_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:background="@drawable/listitem_background"
    >
...
</LinearLayout>

listitem_background.xml:

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

layout.xml ที่มี ListView:

...
<ListView 
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:listSelector="@drawable/listitem_selector"
   />
...

listitem_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="@drawable/listitem_pressed" />
    <item android:state_focused="true" android:drawable="@drawable/listitem_selected" />
</selector>

1
ขอบคุณสำหรับการตอบสนองเชิงลึก ดังที่ฉันได้กล่าวไว้ในคำถามของฉันนี่คือสิ่งที่ฉันกำลังทำอยู่ในขณะนี้เช่นกันและมันก็ใช้ได้ดีทีเดียว
shilgapira

ขออภัยฉันยังประสบปัญหาในการปรับแต่งมุมมองรายการของฉัน ฉันโพสต์ปัญหาเฉพาะของฉันที่นี่: stackoverflow.com/questions/5426385/… ; ฉันจะขอบคุณข้อมูลใด ๆ ที่คุณมี
LostNomad311

ไม่ได้ผลเมื่อคุณใช้ 9-patch drawables ที่มี padding เป็นพื้นหลัง ฉันพบทางออกที่ดีที่สุดฉันคิดว่าดูคำตอบของฉัน
Michał K

สิ่งนี้ใช้ได้กับ post-ICS แต่สำหรับ Gingerbread รายการทั้งหมดจะมีสีด้วยการกดหรือเลือกที่วาดได้
gunar

มีวิธีใดบ้างสำหรับ pre-ICS?
Lonli-Lokli

78

วิธีแก้ปัญหาโดย dglmtn ใช้ไม่ได้เมื่อคุณมี 9-patch drawable โดยมี padding เป็นพื้นหลัง มีเรื่องแปลก ๆ เกิดขึ้นฉันไม่อยากพูดถึงมันด้วยซ้ำถ้าคุณมีปัญหาแบบนี้คุณก็รู้ดี

ตอนนี้ถ้าคุณต้องการมี listview ที่มีสถานะต่างกันและ 9-patch drawables (ฉันคิดว่ามันจะใช้ได้กับ drawables และสีใด ๆ ) คุณต้องทำ 2 สิ่ง:

  1. ตั้งค่าตัวเลือกสำหรับรายการในรายการ
  2. กำจัดตัวเลือกเริ่มต้นสำหรับรายการ

สิ่งที่คุณควรทำคือตั้งค่า row_selector.xml ก่อน:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_enabled="true" 
     android:state_pressed="true" android:drawable="@drawable/list_item_bg_pressed" />
    <item android:state_enabled="true"
     android:state_focused="true" android:drawable="@drawable/list_item_bg_focused" />
    <item android:state_enabled="true"
     android:state_selected="true" android:drawable="@drawable/list_item_bg_focused" />
    <item
     android:drawable="@drawable/list_item_bg_normal" />
</selector>

อย่าลืมandroid:state_selected. ทำงานเหมือนandroid:state_focusedรายการ แต่ใช้กับรายการ

ตอนนี้ใช้ตัวเลือกกับรายการ (row.xml):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@drawable/row_selector"
>
...
</RelativeLayout>

เลือกตัวเลือกแบบโปร่งใสสำหรับรายการ:

<ListView
    android:id="@+id/android:list"
    ...
    android:listSelector="@android:color/transparent"
    />

สิ่งนี้ควรทำสิ่งนี้


1
+1 ฉันไม่เห็นคำตอบของคุณมาก่อนฉันเจอผลลัพธ์เดียวกันกับฉันเอง แต่ขอบคุณที่พูดถึง drawables 9-patch ฉันแน่ใจว่ามันจะมีประโยชน์ในการใช้งานในอนาคตของฉัน นี่น่าจะเป็นคำตอบที่ดีที่สุดเพราะวิธีนี้สะอาดกว่าและดูแลรักษาได้
IsaacCisneros

28
ฉันขอโทษ แต่นี่เป็นสิ่งที่ทำให้บางครั้งคิดว่าทำไม UI apis เจ้ากรรมเหล่านี้ถึงต้องเส็งเคร็ง Android ยังคงมีอะไรให้ทำมากมาย สิ่งพื้นฐานดังกล่าวไม่ควรเป็น PITA
Gubatron

2
+1 ขอบคุณขอบคุณขอบคุณ กระโดดผ่านห่วงเหล่านี้ทั้งหมดเพื่อให้บรรลุสิ่งที่เป็นพื้นฐาน รัฐทั้งหมดนี้สับสนมาก
Moritz

3
แทนที่จะเป็น android: listSelector = "@ drawable / list_selector" เพียงแค่เขียน android: listSelector = "@ android: color / transparent" ไม่จำเป็นต้องมี list_selector.xml เพิ่มเติม
Sofi Software LLC

1
ถูกต้องตัวเลือกรายการที่ไม่ทำลายสามารถเป็น @android: color / transparent แทนที่จะเป็นตัวเลือก xml ของคุณเอง เพิ่งลองใช้. สิ่งที่ใช้ไม่ได้คือ @ null ซึ่งทำให้ฉันประหลาดใจเพราะสิ่งนี้ควรระบุว่า: "no list selector" และเนื่องจากตัวเลือกรายการถูกดึงไว้ด้านหลังรายการจึงไม่ควรวาดสิ่งใด แต่ไม่ได้ผลตัวเลือกเริ่มต้นกลับมาแล้ว ...
Zordid

17

ไม่เคยใช้ "สีพื้นหลัง" สำหรับแถวมุมมองรายการของคุณ ...

สิ่งนี้จะบล็อกทุกการกระทำของตัวเลือก (เป็นปัญหาของฉัน!)

โชคดี!


3
นี่ไม่เป็นความจริง. เพียงใช้ตัวเลือกเป็นพื้นหลังไม่ใช่สีคงที่หรือวาดได้
Michał K

สิ่งนี้ตั้งใจให้มีความหมายโดย "สีพื้นหลัง" ยอมรับคำพูดของคุณอย่างสมบูรณ์
cV2

ฉันมาที่นี่เพราะฉันต้องการตัวเลือกที่ฉันใช้setBackgroundColorกับ "สี" เฮ้อ ... ใช้setBackgroundหรือsetBackgroundDrawableตามเวอร์ชัน API ของคุณด้วยตัวเลือก
EpicPandaForce

5

บทความ"เหตุใดรายการของฉันจึงเป็นสีดำการเพิ่มประสิทธิภาพ Android"ในบล็อกนักพัฒนา Android มีคำอธิบายอย่างละเอียดว่าเหตุใดพื้นหลังรายการจึงเปลี่ยนเป็นสีดำเมื่อเลื่อน คำตอบง่ายๆ: ตั้งค่า cacheColorHint ในรายการของคุณให้โปร่งใส (# 00000000)


1
ความเรียบง่ายที่เป็นแบบอย่าง แต่ใช้งานได้ดี ขอบคุณสำหรับ Romain Guy ... <ListView ... android: cacheColorHint = "# 00000000"> </ListView> ได้เลย!
Eric JOYÉ

อย่าขอบคุณ Romain Guy เขาเป็นส่วนหนึ่งของปัญหา ไม่ควรมี "เทคนิคซ่อนเร้น" หรือแฮ็กอื่น ๆ ในระบบปฏิบัติการเช่นนี้ แม้ว่าฉันจะรัก Android แต่มันก็เป็นกองขยะชิ้นใหญ่เมื่อเทียบกับ SDK อื่น ๆ (แม้จะใหม่กว่า / โตน้อยกว่า!)
StackOverflowed

5

ก็เพียงพอแล้วถ้าคุณใส่เข้าไป list_row_layout.xml :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:background="@drawable/listitem_background">... </LinearLayout>

listitem_selector.xml:

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

2
น่ากลัว ... ตัวอย่างที่ง่ายที่สุด
Shihab Uddin

1
และทำให้ตัวเลือกมุมมองรายการโปร่งใส
Sayka


4

คุณสามารถเขียนธีม:

<pre>

    android:name=".List10" android:theme="@style/Theme"

theme.xml

<style name="Theme" parent="android:Theme">
        <item name="android:listViewStyle">@style/MyListView</item>
</style>

styles.xml

 <style name="MyListView" parent="@android:style/Widget.ListView">
<item name="android:listSelector">@drawable/my_selector</item>

my_selector คือตัวเลือกที่คุณต้องการกำหนดเองฉันขอโทษฉันไม่รู้วิธีเขียนโค้ดของฉัน


ขอบคุณสำหรับความช่วยเหลือ แต่สิ่งนี้ไม่ได้ช่วยโดยตรงในการตั้งค่าพื้นหลังรายการเริ่มต้นผ่านตัวเลือก
shilgapira

3

ฉันมักจะใช้วิธีการเดียวกันและได้ผลทุกครั้งทุกที่: ฉันแค่ใช้ตัวเลือกแบบนี้

<item android:state_activated="true"  android:color="@color/your_selected_color" />
<item android:state_pressed="true" android:color="@color/your_pressed_color" />
<item android:color="@color/your_normal_color"></item>

และตั้งค่าบน ListView (สิ่งนี้สำคัญมากในการทำให้มันทำงานได้) แอตทริบิวต์

android:choiceMode="singleChoice"

สำหรับ textColor เพียงแค่ใส่ในโฟลเดอร์สี (สำคัญไม่ใช่โฟลเดอร์ที่วาดได้!) ตัวเลือกเช่นนี้

<item android:state_activated="true"  android:color="@color/your_selected_textColor" />
<item android:state_pressed="true" android:color="@color/your_pressed_textColor" />
<item android:color="@color/your_normal_textColor"></item>

นี่คือเทมเพลตแถวตัวอย่าง

<ImageView
    android:id="@+skinMenu/lblIcon"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:src="@drawable/menu_catalog" />

<TextView
    android:id="@+skinMenu/lblTitle"
    style="@style/superlabelStyle"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_marginLeft="20dp"
    android:gravity="center_vertical"
    android:text="test menu testo"
    android:textColor="@color/menu_textcolor_selector"
    android:textSize="20dp"
    android:textStyle="bold" />

ทุกอย่างทำงานได้โดยไม่ต้องแก้ปัญหาที่น่าเบื่อ หวังว่าจะช่วยได้


2

ฉันไม่แน่ใจว่าจะบรรลุเอฟเฟกต์ที่คุณต้องการผ่านตัวเลือกได้อย่างไร - ตามความหมายแล้วมีตัวเลือกเดียวสำหรับรายการทั้งหมด

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


อันที่จริงมันสมเหตุสมผลดีที่จะมีตัวเลือกมากที่สุดเพียงหนึ่งตัวเท่านั้น ฉันเดาว่าฉัน (หรือ) สับสนเล็กน้อยกับการมีอยู่ของ<item android:state_focused="false" android:drawable="@android:color/transparent" />ประโยคในตัวเลือกเริ่มต้น
shilgapira

ทำเครื่องหมายเล่นรอบ ๆ (มีปัญหาเดียวกับ Gil) ฉันลองวิธีแก้ปัญหาของคุณแล้วมันเป็นเพียงบางส่วนสำหรับแทร็กบอลเท่านั้นไม่มีสิ่งใดที่จะถูกเรียกเมื่อคุณสัมผัสรายการโดยใช้การสัมผัสเท่านั้นและ onItemClicked จะเริ่มทำงานหากคุณต้องการบางอย่างในประเภทนั้นส่วนใหญ่ คุณต้องติดตามตำแหน่งที่เลือกและกดภายใน ListView และวาดสิ่งที่คุณต้องการในรายการเอง (ทำให้เป็นมุมมองแบบกำหนดเอง) และใน dispatchDraw ของ ListView
codeScriber

@codeScriber: "nothingSeelected ถูกเรียกเมื่อคุณแตะรายการโดยใช้การสัมผัสเท่านั้นและ onItemClicked จะเริ่มทำงาน" - นี่เป็นพฤติกรรมปกติอย่างสมบูรณ์เนื่องจากการสัมผัสไม่มีส่วนเกี่ยวข้องกับการเลือก
CommonsWare

-3

FrostWire Team ที่นี่

api ตัวเลือกทั้งหมดไม่ทำงานตามที่คาดไว้ หลังจากลองใช้วิธีแก้ปัญหาทั้งหมดที่นำเสนอในเธรดนี้แล้วเราก็แก้ปัญหาได้ในขณะที่ขยายรายการมุมมองรายการ

  1. ตรวจสอบให้แน่ใจว่ารายการของคุณยังคงเป็นสถานะเราทำเป็นตัวแปรสมาชิกของ MenuItem (บูลีนที่เลือก)

  2. เมื่อคุณขยายตัวให้ถามว่ามีการเลือกรายการพื้นฐานหรือไม่หากเป็นเช่นนั้นเพียงตั้งค่าทรัพยากรที่วาดได้ที่คุณต้องการเป็นพื้นหลัง (ไม่ว่าจะเป็น 9patch หรืออะไรก็ตาม) ตรวจสอบให้แน่ใจว่าอะแดปเตอร์ของคุณรับรู้ถึงสิ่งนี้และเรียกใช้ alertDataChanged () เมื่อมีการเลือกบางอย่าง

        @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View rowView = convertView;
        if (rowView == null) {
            LayoutInflater inflater = act.getLayoutInflater();
            rowView = inflater.inflate(R.layout.slidemenu_listitem, null);
            MenuItemHolder viewHolder = new MenuItemHolder();
            viewHolder.label = (TextView) rowView.findViewById(R.id.slidemenu_item_label);
            viewHolder.icon = (ImageView) rowView.findViewById(R.id.slidemenu_item_icon);
            rowView.setTag(viewHolder);
        }
    
        MenuItemHolder holder = (MenuItemHolder) rowView.getTag();
        String s = items[position].label;
        holder.label.setText(s);
        holder.icon.setImageDrawable(items[position].icon);
    
        //Here comes the magic
        rowView.setSelected(items[position].selected);
    
        rowView.setBackgroundResource((rowView.isSelected()) ? R.drawable.slidemenu_item_background_selected : R.drawable.slidemenu_item_background);
    
        return rowView;
    }
    

คงจะดีมากถ้าตัวเลือกใช้งานได้จริงในทางทฤษฎีแล้วมันเป็นทางออกที่ดีและสง่างาม แต่ดูเหมือนว่ามันจะเสีย จูบ.


ฉันอยากลองวิธีนี้คุณช่วยอธิบายรายละเอียดเพิ่มเติมหรือวิธีแก้ปัญหาที่สมบูรณ์ได้ไหม ขอบคุณ
Andrew Lam
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.