1

このチュートリアルの CustomArrayAdapter を実装して、リスト ビューのエントリごとにサムネイルと 2 行を表示しました。そして、フィルタリングを除いて完全に機能します。thisthis、およびthisの質問に従ってフィルタリングを実装しようとしましたが、リストビューは更新されません。

これは、複数行レイアウトの私のコードです:

<?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:padding="6dip">

<ImageView
    android:id="@+id/thumb"
    android:background="@drawable/thumb"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_marginRight="6dip"
    android:layout_marginTop="2dip"
    android:layout_marginBottom="2dip"/>

<LinearLayout
    android:orientation="vertical"
    android:layout_width="0dip"
    android:layout_weight="1"
    android:layout_height="fill_parent">

    <TextView
        android:id="@+id/custom_title"
        android:layout_width="fill_parent"
        android:layout_height="0dip"
        android:layout_weight="1"
        android:textColor="@color/black"
        android:gravity="center_vertical"
        />

    <TextView  
        android:id="@+id/desc"
        android:layout_width="fill_parent"
        android:layout_height="0dip"
        android:layout_weight="1" 
        android:textColor="@color/darkgray"
        android:textStyle="italic"
        android:singleLine="true"
        android:ellipsize="marquee"
         />

</LinearLayout>

これは私のcustomListAdapterのコードです(最初のリンクをたどります)

public class CustomListAdapter extends ArrayAdapter implements Filterable{

private static ArrayList<CustomListItem> searchArrayList;
private static ArrayList<CustomListItem> subItems;
private PTypeFilter filter;


 private LayoutInflater mInflater;

 public CustomListAdapter(Context context, int textViewResourceId, ArrayList<CustomListItem> results) {
     super(context,textViewResourceId, results);
  searchArrayList = results;
  mInflater = LayoutInflater.from(context);
 }
 public int getCount() {
      return searchArrayList.size();
     }

     public Object getItem(int position) {
      return searchArrayList.get(position);
     }

     public long getItemId(int position) {
      return position;
     }

     public View getView(int position, View convertView, ViewGroup parent) {
      ViewHolder holder;
      if (convertView == null) {
       convertView = mInflater.inflate(R.layout.custom_row, null);
       holder = new ViewHolder();
       holder.txtTitle = (TextView) convertView.findViewById(R.id.custom_title);
       holder.txtDesc = (TextView) convertView.findViewById(R.id.desc);
       holder.thumb = (ImageView) convertView.findViewById(R.id.thumb);

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

      holder.txtTitle.setText(searchArrayList.get(position).getTitle());
      holder.txtDesc.setText(searchArrayList.get(position).getDesc());
      holder.thumb.setImageBitmap(searchArrayList.get(position).getThumb());
      //holder.thumb.setBackgroundColor(Color.BLACK);

      return convertView;
     }

     static class ViewHolder {
      TextView txtTitle;
      TextView txtDesc;
      ImageView thumb;
     }       

     @Override
     public Filter getFilter() {
         Log.i("CustomListAdapter", "testing filter");
         if (filter == null){
           filter  = new PTypeFilter();
         }
         return filter;
       }

  private class PTypeFilter extends Filter{


@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence prefix,
                              FilterResults results) {
  // NOTE: this function is *always* called from the UI thread.
   subItems =  (ArrayList<CustomListItem>)results.values;

    notifyDataSetChanged();
}

@SuppressWarnings("unchecked")
protected FilterResults performFiltering(CharSequence prefix) {
      // NOTE: this function is *always* called from a background thread, and
      // not the UI thread. 

      FilterResults results = new FilterResults();
      ArrayList<CustomListItem> i = new ArrayList<CustomListItem>();

      if (prefix!= null && prefix.toString().length() > 0) {

          for (int index = 0; index < searchArrayList.size(); index++) {
              CustomListItem si = searchArrayList.get(index);
              if(si.toString().compareTo(prefix.toString()) == 0){
                i.add(si);  
              }
          }
          results.values = i;
          results.count = i.size();                   
      }
      else{
          synchronized (searchArrayList){
              results.values = searchArrayList;
              results.count = searchArrayList.size();
          }
      }

      return results;
   }
 }     
}

そして、私の主なアクティビティから、次のようにカスタム ベース アダプターを呼び出します。

adapter = new CustomListAdapter(this, R.id.custom_title, DATA);
setListAdapter(adapter);

R.id.custom_title(それが私がそこに置くべきIDであると100%確信しているわけではありません。

デバッグ メッセージを追加し、getFilter() メソッドとして TextChange を呼び出しています。だから私は自分が間違っていることを知りません。ListAdapter から CustomListAdapter に切り替える前は、フィルタリングは正常に機能していました:(

ご協力いただきありがとうございます

4

1 に答える 1

2

ListViewアダプタクラスで使用されないフィルタリングの結果を設定し、アダプタの観点からはデータがそのままであるsubItemsため、への呼び出しが機能しないため、はフィルタリングされません。notifyDataSetChanged古い値を保持するために別のリストを使用するのは正しいです。古い値をすべて保持するために必要になります。問題を解決するには、次の行を追加します。

subItems = new ArrayList<CustomListItem>(searchArrayList);

アダプターのコンストラクターでは、これは、後で使用するために完全な値のコピーを持っているためです。次に、このpublishResultsメソッドでリストを使用しsearchArrayListます。これは、アダプターをサポートするリストであるためです。

searchArrayList =  (ArrayList<CustomListItem>)results.values;
notifyDataSetChanged();

次に、performFilteringメソッドで:

  if (prefix!= null && prefix.toString().length() > 0) {
      // use the initial values !!! 
      for (int index = 0; index < subItems.size(); index++) {
          CustomListItem si = subItems.get(index);
          final int length = prefix.length();
          // if you compare the Strings like you did it will never work as you compare the full item string(you'll have a match only when you write the EXACT word)
          // keep in mind that you take in consideration capital letters!
          if(si.toString().substring(0, prefixLength).compareTo(prefix.toString()) == 0){
            i.add(si);  
          }
      }
      results.values = i;
      results.count = i.size();                   
  }
  else{
      // revert to the old values 
      synchronized (searchArrayList){
          results.values = subItems;
          results.count = subItems.size();
      }
  }

私はそれがうまくいくことを願っています。

(R.id.custom_titleが私がそこに置くべきIDであると100%確信しているわけではありません。

独自のカスタムアダプタを使用するため、問題ありません。

于 2012-09-11T04:04:01.583 に答える