วิธีใช้ ArrayAdapter <myClass>


129
ArrayList<MyClass> myList = new ArrayList<MyClass>();

ListView listView = (ListView) findViewById(R.id.list);

ArrayAdapter<MyClass> adapter = new ArrayAdapter<MyClass>(this, R.layout.row,
    to, myList.);
listView.setAdapter(adapter);

คลาส: MyClass

class MyClass {
    public String reason;
    public long long_val;
}

ฉันสร้าง row.xml ในเลย์เอาต์แล้ว แต่ไม่รู้วิธีแสดงทั้งเหตุผลและ long_val ใน ListView โดยใช้ ArrayAdapter

คำตอบ:


155

ใช้อะแดปเตอร์แบบกำหนดเองสำหรับคลาสของคุณ:

public class MyClassAdapter extends ArrayAdapter<MyClass> {

    private static class ViewHolder {
        private TextView itemView;
    }

    public MyClassAdapter(Context context, int textViewResourceId, ArrayList<MyClass> items) {
        super(context, textViewResourceId, items);
    }

    public View getView(int position, View convertView, ViewGroup parent) {

        if (convertView == null) {
            convertView = LayoutInflater.from(this.getContext())
            .inflate(R.layout.listview_association, parent, false);

            viewHolder = new ViewHolder();
            viewHolder.itemView = (TextView) convertView.findViewById(R.id.ItemView);

            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        MyClass item = getItem(position);
        if (item!= null) {
            // My layout has only one TextView
                // do whatever you want with your string and long
            viewHolder.itemView.setText(String.format("%s %d", item.reason, item.long_val));
        }

        return convertView;
    }
}

สำหรับผู้ที่ไม่คุ้นเคยกับ Android กรอบนี้จะอธิบายในรายละเอียดที่ดีกว่าที่นี่: https://github.com/codepath/android_guides/wiki/Using-an-ArrayAdapter-with-ListView


2
ขออภัยรายการ MyClass = items.get (ตำแหน่ง) แก้ไขข้อผิดพลาดไม่ตรงกับตัวแปรของฉัน
Sumit M Asok

1
ฉันได้ลบช่องรายการออกจากโค้ดด้านบนแล้วเพราะอาจทำให้เกิดข้อผิดพลาดได้ง่ายตัวอย่างเช่นหากมีคนเปลี่ยนรายการภายในโดยใช้ adapter.clear () หรือ
adapter.add

1
ฉันถูกต้องหรือtextViewResourceIdไม่หากไม่ได้ใช้ข้างต้น
gerrytan

8
viewHolder มาจากไหน
Gerry

2
R.layout.listview_association คืออะไร นั่นคือเค้าโครงที่คุณกำหนดเองหรือไม่? ฉันสามารถแทนที่ด้วย android.R.layout.simple_list_item_1 ได้หรือไม่
Donato

76

คุณสามารถเพิ่มtoString()วิธีการใน MyClass ได้ตามhttp://developer.android.com/reference/android/widget/ArrayAdapter.html :

อย่างไรก็ตาม TextView อ้างอิงมันจะเต็มไปด้วย toString () ของแต่ละออบเจ็กต์ในอาร์เรย์ คุณสามารถเพิ่มรายการหรืออาร์เรย์ของออบเจ็กต์แบบกำหนดเอง แทนที่เมธอด toString () ของอ็อบเจ็กต์ของคุณเพื่อกำหนดว่าจะแสดงข้อความใดสำหรับไอเท็มในรายการ

class MyClass {

 @Override
 public String toString() {
  return "Hello, world.";
 }
}

20
แม้ว่าวิธีแก้ปัญหาที่ง่ายที่สุดก็คือ (IMHO) ไม่ใช่ความคิดที่ดีนัก เหตุผลสามประการ: หากคุณต้องการการแปลเป็นภาษาท้องถิ่นคุณจะต้องทำการ refactor วิธีนี้ใช้ได้เฉพาะเมื่อคุณมีอะแดปเตอร์ 1 ตัวหากคุณมีอะแดปเตอร์ 2 ตัวที่แตกต่างกันMyClassคุณจะต้องทำการ refactor สุดท้ายแล้วการผูกตรรกะการนำเสนอกับโมเดลของคุณเป็นความคิดที่ไม่ดี นางแบบไม่ควรตระหนักถึงวิธีการนำเสนอต่อผู้ใช้
fernandohur

2
ไปยังที่อยู่บางส่วนของความกังวล @fernandohur คุณก็สามารถสร้างระดับมุมมองเฉพาะสำหรับ ArrayAdapter ... ดังนั้นการเรียนรูปแบบของประเภทMyClassจะต้องให้คุณสามารถเพิ่มระดับเฉพาะที่เรียกว่าMyClassViewซึ่ง wraps รูปแบบพื้นฐาน (และให้toString( )การดำเนินงาน
วอล

คำตอบนี้มาจากปี 2011 และฉันเห็นด้วยกับ @fernandohur ตอนนี้มีวิธีจัดการที่ดีกว่านี้

ฉันคิดว่านี่เป็นคำตอบที่ดีเพราะหลายครั้งแต่ละคลาสมีแอตริบิวต์มากกว่าที่จะแสดงชื่อของอ็อบเจ็กต์
Jhon Fredy Trujillo Ortega

นี่ควรเป็นคำตอบที่ได้รับการยอมรับ การแทนที่อะแด็ปเตอร์เพื่อผูกชื่อที่พิมพ์ออกมาเป็นการเข้ารหัสที่ไม่ถูกต้อง
L.Grillo

22

ฉันคิดว่านี่เป็นแนวทางที่ดีที่สุด การใช้คลาส ArrayAdapter ทั่วไปและขยายอแดปเตอร์ออบเจ็กต์ของคุณเองทำได้ง่ายๆดังนี้:

public abstract class GenericArrayAdapter<T> extends ArrayAdapter<T> {

  // Vars
  private LayoutInflater mInflater;

  public GenericArrayAdapter(Context context, ArrayList<T> objects) {
    super(context, 0, objects);
    init(context);
  }

  // Headers
  public abstract void drawText(TextView textView, T object);

  private void init(Context context) {
    this.mInflater = LayoutInflater.from(context);
  }

  @Override public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder vh;
    if (convertView == null) {
      convertView = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
      vh = new ViewHolder(convertView);
      convertView.setTag(vh);
    } else {
      vh = (ViewHolder) convertView.getTag();
    }

    drawText(vh.textView, getItem(position));

    return convertView;
  }

  static class ViewHolder {

    TextView textView;

    private ViewHolder(View rootView) {
      textView = (TextView) rootView.findViewById(android.R.id.text1);
    }
  }
}

และนี่คืออะแดปเตอร์ของคุณ (ตัวอย่าง):

public class SizeArrayAdapter extends GenericArrayAdapter<Size> {

  public SizeArrayAdapter(Context context, ArrayList<Size> objects) {
    super(context, objects);
  }

  @Override public void drawText(TextView textView, Size object) {
    textView.setText(object.getName());
  }

}

และสุดท้ายวิธีการเริ่มต้น:

ArrayList<Size> sizes = getArguments().getParcelableArrayList(Constants.ARG_PRODUCT_SIZES);
SizeArrayAdapter sizeArrayAdapter = new SizeArrayAdapter(getActivity(), sizes);
listView.setAdapter(sizeArrayAdapter);

ฉันได้สร้าง Gist ด้วยโครงร่าง TextView แรงโน้มถ่วงที่ปรับแต่งได้ ArrayAdapter:

https://gist.github.com/m3n0R/8822803


1
ฉันชอบรหัสของคุณมาก แต่ฉันใช้เวลาสักพักกว่าจะคิดออกว่าทำไมมันถึงขัดข้องกับ android.content.res.Resources $ NotFoundException: Resource ID # 0x0 คุณมีในการเรียกใช้อะแดปเตอร์ทั่วไปใน super (.. , 0, .. ) โดยที่ 0 เป็นทรัพยากรโครงร่างซึ่งไม่มีอยู่จริงดังนั้นจึงต้องเปลี่ยนเป็นอย่างอื่น .. นอกจากนี้ส่วนสำคัญของคุณคือ 404
Ev0oD

ในที่สุดฉันก็เปลี่ยนไปมาก - เลย์เอาท์ของเมนูแบบเลื่อนลงแตกต่างจากเลย์เอาต์ของรายการที่แสดง drawText ถูกเรียกที่ส่วนหัวของสปินเนอร์เท่านั้นไม่ใช่ในรายการเมื่อคลิก ..
Ev0oD

สิ่งนี้ควรจะใช้ได้เหมือนกับอะแดปเตอร์ทั่วไป คุณสามารถแก้ปัญหาได้หรือไม่?
cesards

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

โดยค่าเริ่มต้นควรระบุไว้
Goddard

6

ซับคลาสArrayAdapterและแทนที่เมธอดgetView ()เพื่อส่งคืนมุมมองของคุณเองที่มีเนื้อหาที่คุณต้องการแสดง


5

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

class MyClass extends Activity {
    private ArrayAdapter<String> mAdapter = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mAdapter = new ArrayAdapter<String>(getApplicationContext(),
            android.R.layout.simple_dropdown_item_1line, android.R.id.text1);

        final ListView list = (ListView) findViewById(R.id.list);
        list.setAdapter(mAdapter);

        //Add Some Items in your list:
        for (int i = 1; i <= 10; i++) {
            mAdapter.add("Item " + i);
        }

        // And if you want selection feedback:
        list.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                //Do whatever you want with the selected item
                Log.d(TAG, mAdapter.getItem(position) + " has been selected!");
            }
        });
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.