2011-06-27 38 views
28

Tôi là một kẻ ăn xin trong Android nhưng tôi đã cố gắng để thực hiện một bộ lọc listview tùy chỉnh và tôi nó làm việc bằng cách nào đó. Vấn đề duy nhất tôi có là ArrayList mà tôi giữ tất cả các giá trị ("bản gốc" ArrayList), là nhận được thấp hơn và thấp hơn trên các mục trong mỗi lọc. Tôi không thể giải thích điều này nhưng tôi nghĩ rằng bạn có thể giúp tôi bằng cách nào đó.Custom Filtering ArrayAdapter trong ListView

Dù sao đây là ArrayAdaptor tùy chỉnh:

public class PkmnAdapter extends ArrayAdapter<Pkmn> { 

private ArrayList<Pkmn> original; 
private ArrayList<Pkmn> fitems; 
private Filter filter; 

public PkmnAdapter(Context context, int textViewResourceId, ArrayList<Pkmn> items) { 
     super(context, textViewResourceId, items); 
     this.original = items;//new ArrayList<Pkmn>(); 
     this.fitems = items;//new ArrayList<Pkmn>(); 
} 

@Override 
public void add(Pkmn item){ 
    original.add(item); 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
     View v = convertView; 
     if (v == null) { 
      LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      v = vi.inflate(R.layout.row, null); 
     } 
     Pkmn pkmn = original.get(position); 
     if (pkmn != null) { 
       TextView tt = (TextView) v.findViewById(R.id.RlabPName); 
       TextView dex = (TextView)v.findViewById(R.id.RlabDex); 
       ImageView img = (ImageView)v.findViewById(R.id.RimgPkmn); 

       if (tt != null) { tt.setText(pkmn.getName()); } 
       if (dex != null){ dex.setText(CalcDex(pkmn.getId())); } 
       if (img != null){ 
        int resId = getContext().getResources().getIdentifier("dex" + pkmn.getId(), "drawable", "com.compileguy.pokebwteam"); 
        img.setImageResource(resId); 
       } 
     } 
     return v; 
} 

@Override 
public Filter getFilter() 
{ 
    if (filter == null) 
     filter = new PkmnNameFilter(); 

    return filter; 
} 

private class PkmnNameFilter extends Filter 
{ 
     @Override 
     protected FilterResults performFiltering(CharSequence constraint) 
     { 
      FilterResults results = new FilterResults(); 
      String prefix = constraint.toString().toLowerCase(); 

      if (prefix == null || prefix.length() == 0) 
      { 
       ArrayList<Pkmn> list = new ArrayList<Pkmn>(original); 
       results.values = list; 
       results.count = list.size(); 
      } 
      else 
      { 
       final ArrayList<Pkmn> list = original; 

       int count = list.size(); 
       final ArrayList<Pkmn> nlist = new ArrayList<Pkmn>(count); 

       for (int i=0; i<count; i++) 
       { 
        final Pkmn pkmn = list.get(i); 
        final String value = pkmn.getName().toLowerCase(); 

        if (value.startsWith(prefix)) 
        { 
         nlist.add(pkmn); 
        } 
       } 
       results.values = nlist; 
       results.count = nlist.size(); 
      } 
      return results; 
     } 

     @SuppressWarnings("unchecked") 
     @Override 
     protected void publishResults(CharSequence constraint, FilterResults results) { 
      fitems = (ArrayList<Pkmn>)results.values; 
      clear(); 
      int count = fitems.size(); 
      for (int i=0; i<count; i++) 
      { 
       Pkmn pkmn = (Pkmn)fitems.get(i); 
       add(pkmn); 
      } 

      if (fitems.size() > 0) 
       notifyDataSetChanged(); 
      else 
       notifyDataSetInvalidated(); 
     } 

    } 


private String CalcDex(int id){ 
    String s = String.valueOf(id); 
    if (s.length() == 1) 
     s = "00"+s; 
    else if (s.length() == 2) 
     s = "0"+s; 
    return '#'+s; 
} 

}

LƯU Ý: Các listview đang hiển thị đúng nội dung nhưng khi cho exaple tôi loại bỏ một lá thư trong editbox (mà gây nên lọc) này là nơi các vấn đề bắt đầu.

--- CHỈNH SỬA ---

@Janusz: Rất cám ơn câu trả lời của bạn. Điều đó đã giải quyết được vấn đề của tôi.

Đây là mã nguồn mà làm việc cho tôi, vì vậy nếu có ai có cùng một vấn đề họ có thể thử cái này:

private ArrayList<Pkmn> original; 
private ArrayList<Pkmn> fitems; 
private Filter filter; 

public PkmnAdapter(Context context, int textViewResourceId, ArrayList<Pkmn> items) { 
     super(context, textViewResourceId, items); 
     this.original = new ArrayList<Pkmn>(items); 
     this.fitems = new ArrayList<Pkmn>(items); 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
     View v = convertView; 
     if (v == null) { 
      LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      v = vi.inflate(R.layout.row, null); 
     } 
     Pkmn pkmn = fitems.get(position); 
     if (pkmn != null) { 
       TextView tt = (TextView) v.findViewById(R.id.RlabPName); 
       TextView dex = (TextView)v.findViewById(R.id.RlabDex); 
       ImageView img = (ImageView)v.findViewById(R.id.RimgPkmn); 

       if (tt != null) { tt.setText(pkmn.getName()); } 
       if (dex != null){ dex.setText(CalcDex(pkmn.getId())); } 
       if (img != null){ 
        int resId = getContext().getResources().getIdentifier("dex" + pkmn.getId(), "drawable", "com.compileguy.pokebwteam"); 
        img.setImageResource(resId); 
       } 
     } 
     return v; 
} 

@Override 
public Filter getFilter() 
{ 
    if (filter == null) 
     filter = new PkmnNameFilter(); 

    return filter; 
} 

private class PkmnNameFilter extends Filter 
{ 
     @Override 
     protected FilterResults performFiltering(CharSequence constraint) 
     { 
      FilterResults results = new FilterResults(); 
      String prefix = constraint.toString().toLowerCase(); 

      if (prefix == null || prefix.length() == 0) 
      { 
       ArrayList<Pkmn> list = new ArrayList<Pkmn>(original); 
       results.values = list; 
       results.count = list.size(); 
      } 
      else 
      { 
       final ArrayList<Pkmn> list = new ArrayList<Pkmn>(original); 
       final ArrayList<Pkmn> nlist = new ArrayList<Pkmn>(); 
       int count = list.size(); 

       for (int i=0; i<count; i++) 
       { 
        final Pkmn pkmn = list.get(i); 
        final String value = pkmn.getName().toLowerCase(); 

        if (value.startsWith(prefix)) 
        { 
         nlist.add(pkmn); 
        } 
       } 
       results.values = nlist; 
       results.count = nlist.size(); 
      } 
      return results; 
     } 

     @SuppressWarnings("unchecked") 
     @Override 
     protected void publishResults(CharSequence constraint, FilterResults results) { 
      fitems = (ArrayList<Pkmn>)results.values; 

      clear(); 
      int count = fitems.size(); 
      for (int i=0; i<count; i++) 
      { 
       Pkmn pkmn = (Pkmn)fitems.get(i); 
       add(pkmn); 
      } 
     } 

    } 
} 
+0

gì là công việc của 'clear()' và 'thêm()' chức năng. –

+0

@compileGuy, ý nghĩa của "Pkmn" là gì? Tôi không thể chạy ví dụ này. bạn có thể tải lên mã hoàn toàn không? –

+0

Triển khai tuyệt vời @compileguy, thêm và xóa là các chức năng của bộ điều hợp, bạn không cần phải vượt qua chúng. pkmn là một lớp mô hình để giữ các giá trị dữ liệu trong danh sách – Naruto

Trả lời

16

Vấn đề của bạn là những dòng này:

this.original = items; 
this.fitems = items; 

Items là danh sách bạn sử dụng cho ListView của bạn và đặt nó trong hai biến khác nhau không làm cho hai danh sách khác nhau ra khỏi nó. Bạn chỉ cho các mục danh sách hai tên khác nhau.

Bạn có thể sử dụng:

this.fitems = new ArrayList(items); 

rằng nên tạo một danh sách mới và những thay đổi trong danh sách này sẽ chỉ thay đổi danh sách fitems.

+0

Cảm ơn Janusz, nó hoạt động nhờ rất nhiều lời cảm ơn – Naruto

+0

Không hoạt động cho tôi, ListView của tôi biến mất và khi tôi xóa toàn bộ chuỗi, nó không đến quay lại lần nữa. http://stackoverflow.com/questions/20524417/listview-is-blank-while-using-getfilter-function – Si8

+0

@ SiKni8 tôi cũng nhận được kết quả tương tự. Hãy giúp tôi –

2

bạn có thể thực hiện tác dụng tương tự bằng cách chỉ cần tạo phương thức toString() trên lớp Pkmn của bạn trả về giá trị bạn muốn lọc theo.

0

Cách tốt nhất mà tôi tìm thấy để lọc ArrayAdapter là tạo lớp lọc của riêng tôi:

private class MyFilter extends Filter 

sau đó trong hàm tạo mảng đối tượng mới để hiển thị sau khi lọc (bạn có thể tìm thấy thực hiện tốt trong mã nguồn của class ArrayAdapter)

@Override 
protected FilterResults performFiltering(CharSequence prefix) 

nay là Bí quyết là ở phương pháp này

@Override 
protected void publishResults(CharSequence constraint, FilterResults results) 

khi bạn sử dụng adapter Mảng bạn không thể làm điều này:

myAdapterData = results.values 

kể từ đó bạn ngắt kết nối dữ liệu của bạn từ các dữ liệu siêu, bạn phải làm điều này để giữ cho bạn tham khảo đến các mảng dữ liệu siêu ban đầu:

data.clear(); 
data.addAll((List<YourType>) results.values); 

và sau đó ghi đè

getFilter()

trong adapter của bạn, ví dụ:

@Override 
public Filter getFilter() { 
    if (filter == null) { 
     filter = new MyFilter(); 
    } 
    return filter; 
} 
Các vấn đề liên quan