2013-04-23 2 views
0

Так что у меня есть пользовательский адаптер, который я пытаюсь реализовать поиск фильтра, где элемент поиска ключевого слова пользователя из edittext. И фильтрация работает просто отлично. Однако в моем списке я также устанавливаю флажок.пользовательский адаптер фильтр получить неправильную позицию id

Скажем, у меня есть список

Bar 
Tar 
Foo 
Kay 

По умолчанию список будет получить позицию правильно, так что не проблема. Проблема начинается, когда я ищу слова a, и список будет.

Bar 
Tar 
Kay 

И если я проверил на Kay после поиска, он вместо этого вернет меня Foo.

И вот мой код для моего адаптера и фильтра, что не так?

public class MyMediaAdapter extends ArrayAdapter<Media> implements Filterable { 

      private List<Media> list; 
      private final Activity context; 
      private Filter mediaFilter; 
      private List<Media> origMediaList; 

      public MyMediaAdapter(Activity context, List<Media> list) { 
       super(context, R.layout.media_view, list); 
       this.context = context; 
       this.list = list; 
       this.origMediaList = list; 
      } 

      public int getCount() { 
       return list.size(); 
      } 

      public Media getItem(int position) { 
       return list.get(position); 
      } 

      public long getItemId(int position) { 
       return list.get(position).hashCode(); 
      } 

      private class ViewHolder { 
       protected TextView fName, fSub, fDuration, fSize; 
       protected CheckBox checkbox; 
       // protected CheckBox checkbox1; 
      } 

      @Override 
      public View getView(int position, View convertView, ViewGroup parent) { 
       View view = null; 
       // Moved here to ensure the checkbox is persistent 
       ViewHolder viewHolder = new ViewHolder(); 
       if (convertView == null) { 
        LayoutInflater inflator = context.getLayoutInflater(); 
        view = inflator.inflate(R.layout.media_view, null); 
        // Moved out of the if-else to solve the problem 
        // view being recycled each time it scrolls 
        // final ViewHolder viewHolder = new ViewHolder(); 
        viewHolder.fName = (TextView) view.findViewById(R.id.tvfname); 
        viewHolder.fSub = (TextView) view.findViewById(R.id.tvsub); 
        viewHolder.fDuration = (TextView) view.findViewById(R.id.tvduration); 
        viewHolder.fSize = (TextView) view.findViewById(R.id.tvsize); 
        viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check); 



        view.setTag(viewHolder); 
        // Moved out of the if-else to solve the problem 
        // view being recycled each time it scrolls 
        // viewHolder.checkbox.setTag(list.get(position)); 
       } else { 
        view = convertView; 
        // Moved out of the if-else to solve the problem 
        // view being recycled each time it scrolls 
        // ((ViewHolder) view.getTag()).checkbox.setTag(list.get(position)); 
        viewHolder = (ViewHolder) view.getTag(); 
       } 



       // Moved here to ensure the checkbox is persistent 
       viewHolder.checkbox.setId(position); 
       viewHolder.checkbox.setTag(list.get(position)); 

       ViewHolder holder = (ViewHolder) view.getTag(); 
       holder.fName.setText(list.get(position).getName()); 
       holder.fSub.setText(list.get(position).getPath()); 
       // Converting duration from String to Long 
       long milli = Long.valueOf(list.get(position).getDuration()); 
       // Put it in % min, % sec format to display 
       holder.fDuration.setText(util.readableTime(milli)); 
       // Convert data size from String to Long 
       long datasize = Long.valueOf(list.get(position).getData()); 
       // Put in human readable format 
       holder.fSize.setText(util.readableFileSize(datasize)); 
       holder.checkbox.setChecked(list.get(position).isSelected()); 

       // viewHolder.checkbox.setId(position); 
       viewHolder.checkbox.setOnClickListener(new OnClickListener() { 
        public void onClick(View v) { 
         // TODO Auto-generated method stub 
         CheckBox cb = (CheckBox) v; 
         int id = cb.getId(); 
         if (selection[id]) { 
          cb.setChecked(false); 
          selection[id] = false; 
          list.get(id).setSelected(false); 
         } else { 
          cb.setChecked(true); 
          selection[id] = true; 
          list.get(id).setSelected(true); 
         } 
        } 
       }); 

       // Implement SelectAll/DeselectAll feature 
       final CheckBox checkbox1 = (CheckBox) findViewById(R.id.cb_selectall); 

       checkbox1.setOnCheckedChangeListener(new OnCheckedChangeListener() { 

        @Override 
        public void onCheckedChanged(CompoundButton button, boolean checked) { 
         // TODO Auto-generated method stub 

         if (checked) { 
          checkbox1.setText("Click to Deselect All"); 

          for (int i = 0; i < list.size(); i++) { 
           selection[i] = true; 
           list.get(i).setSelected(true); 
          } 
          // Called to notify checkbox changes so the view gets updated immediately 
          notifyDataSetChanged(); 

          Toast.makeText(getApplicationContext(), "All files are selected", Toast.LENGTH_LONG).show(); 
         } else { 
          checkbox1.setText("Click to Select All"); 

          for (int i = 0; i < list.size(); i++) { 
           selection[i] = false; 
           list.get(i).setSelected(false); 
          } 
          notifyDataSetChanged(); 

          Toast.makeText(getApplicationContext(), "All files are deselected", Toast.LENGTH_LONG).show(); 
         } 

        } 

       }); 

       return view; 
      } 

      public void resetData() { 
       list = origMediaList; 
      } 

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

       return mediaFilter; 
      } 

      private class mediaFilter extends Filter { 

       @Override 
       protected FilterResults performFiltering(CharSequence constraint) { 
        FilterResults results = new FilterResults(); 
        // We implement here the filter logic 
        if (constraint == null || constraint.length() == 0) { 
         // No filter implemented we return all the list 
         results.values = origMediaList; 
         results.count = origMediaList.size(); 
        } 
        else { 
         // We perform filtering operation 
         List<Media> nMediaList = new ArrayList<Media>(); 

         for (Media m : list) { 
          if (m.getName().toUpperCase().contains(constraint.toString().toUpperCase())) 
           nMediaList.add(m); 
         } 

         results.values = nMediaList; 
         results.count = nMediaList.size(); 

        } 
        return results; 
       } 

       @SuppressWarnings("unchecked") 
       @Override 
       protected void publishResults(CharSequence constraint, 
         FilterResults results) { 

        // Now we have to inform the adapter about the new list filtered 
        if (results.count == 0) 
         notifyDataSetInvalidated(); 
        else { 
         list = (List<Media>) results.values; 
         notifyDataSetChanged(); 
        } 
       } 
      } 
     } 

У меня есть следующая настройка, поэтому я знаю, что было выбрано.

private boolean[] selection; 
private int count; 

// After I fetch my list 
count = getMediaList.size(); 
selection = new boolean[count]; 

// Inside onOptionsItemSelected 

@Override 
    public boolean onOptionsItemSelected(MenuItem item) { 

     final ArrayList<Integer> posSel = new ArrayList<Integer>(); 

     posSel.clear(); 
     storeSelectedMedia.clear(); 

     /* 
     * Construct the list of selected items 
     */ 
     boolean noSelect = false; 
     //Log.i("MediaSelection", "" + selection.length); 
     for (int i = 0; i < selection.length; i++) { 
      //Log.i("MediaSelect", "" + getMediaList.get(i).isSelected()); 
      if (selection[i] == true) { 
       //if (getMediaList.get(i).isSelected() == true) { 
       noSelect = true; 
       Log.e("Mediasel pos thu-->", "" + i); 
       posSel.add(i); 
       storeSelectedMedia.add(getMediaList.get(i).getPath()); 

      } 
     } 

     switch (item.getItemId()) { 

case R.id.action_sfd: 
      if (noSelect) { 
       AlertDialog.Builder builder = new AlertDialog.Builder(this); 

       final ScrollView s_view = new ScrollView(getApplicationContext()); 
       final TextView t_view = new TextView(getApplicationContext()); 

       StringBuilder sBuilder = new StringBuilder(); 

       sBuilder.append("\n Name: \t " + getMediaList.get(posSel.get(0)).getName()); 
       sBuilder.append("\n Parent: \t " + getMediaList.get(posSel.get(0)).getParent()); 
       sBuilder.append("\n Type: \t " + getMediaList.get(posSel.get(0)).getType()); 
       sBuilder.append("\n Size: \t\t " + util.readableFileSize(getMediaList.get(posSel.get(0)).getSize())); 
       sBuilder.append("\n "); 

       t_view.setText(sBuilder); 
       t_view.setTextSize(14);  
       s_view.addView(t_view); 

       builder.setTitle("File Properties") 
         .setView(s_view); 

       AlertDialog dialog = builder.create(); 
       dialog.show(); 

      Toast.makeText(this, 
        "Selected Items:" + storeSelectedMedia.toString(), 
        Toast.LENGTH_LONG).show(); 
      } else { 
       Toast.makeText(this, 
         "No files selected", 
         Toast.LENGTH_SHORT).show(); 
      } 
      break; 

Надеюсь, этого будет достаточно информации.

У кого-нибудь есть идеи по этому вопросу? Цените это очень!

+0

Не могли бы вы показать код onItemClickListener, который вы используете для своих списков просмотров? –

+0

@LeonLucardie Привет, у меня нет встроенного onItemClickListener. – user1778855

ответ

1

Я решил свою проблему. Поскольку я использовал getMediaList, чтобы отобразить элемент, я забыл, что у меня нет обновления my getMediaList в списке «после фильтрации».

Таким образом, по методу publishResult, перед notifyDataSetChanged() ;, я в основном просто назначаю список getMediaList =.

@SuppressWarnings("unchecked") 
      @Override 
      protected void publishResults(CharSequence constraint, 
        FilterResults results) { 

       // Now we have to inform the adapter about the new list filtered 
       if (results.count == 0) 
        notifyDataSetInvalidated(); 
       else { 
        list = (List<Media>) results.values; 
        // HERE 
        getMediaList = list; 
        notifyDataSetChanged(); 
       } 
      } 

Проверено в течение довольно долгого времени, прежде чем я осознаю эту глупую ошибку. Надеюсь, это поможет кому-то в будущем.

Смежные вопросы