2013-10-01 2 views
35

У меня возникли проблемы с реализацией пользовательского getFilter в пользовательском массиве. На самом деле я понятия не имею, как его реализовать. Пробовал разные коды, но все равно не повезло. Вот мой пользовательский адаптер массива.Пользовательский getFilter в пользовательском ArrayAdapter в android

package com.test.FilterableList.Adapters; 

import java.util.ArrayList; 
import android.content.Context; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ArrayAdapter; 
import android.widget.TextView; 

import com.test.FilterableList.Models.ListTO; 
import com.test.FilterableList.R; 

import android.widget.Filterable; 


public class FilterableAdapter extends ArrayAdapter<ListTO> implements Filterable { 

    // declaring our ArrayList of items 
    public ArrayList<ListTO> objects; 

    /* here we must override the constructor for ArrayAdapter 
    * the only variable we care about now is ArrayList<Item> objects, 
    * because it is the list of objects we want to display. 
    */ 
    public FilterableAdapter(Context context, int textViewResourceId, ArrayList<ListTO> objects) { 
     super(context, textViewResourceId, objects); 
     this.objects = objects; 
    } 

    /* 
    * we are overriding the getView method here - this is what defines how each 
    * list item will look. 
    */ 
    public View getView(int position, View convertView, ViewGroup parent){ 

     // assign the view we are converting to a local variable 
     View v = convertView; 

     // first check to see if the view is null. if so, we have to inflate it. 
     // to inflate it basically means to render, or show, the view. 
     if (v == null) { 
      LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      v = inflater.inflate(R.layout.list_item, null); 
     } 

     /* 
     * Recall that the variable position is sent in as an argument to this method. 
     * The variable simply refers to the position of the current object in the list. (The ArrayAdapter 
     * iterates through the list we sent it) 
     * 
     * Therefore, i refers to the current Item object. 
     */ 
     ListTO i = objects.get(position); 

     if (i != null) { 

      // This is how you obtain a reference to the TextViews. 
      // These TextViews are created in the XML files we defined. 

      TextView tt = (TextView) v.findViewById(R.id.list_name); 
      if (tt != null){ 
       tt.setText(i.FileName); 
      } 



     } 

     // the view must be returned to our activity 
     return v; 

    } 
} 

И вот класс ListTO.

package com.test.FilterableList.Models; 

public class ListTO { 

    public int Id; 
    public String FileName; 
    public String FileUri; 

    public ListTO(int id, String fileName, String fileUri) { 

     Id = id; 
     FileName = fileName; 
     FileUri = fileUri; 

    } 

} 

И вот макет.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" 
    android:background="@drawable/blacklikenbackground" 
    tools:context=".AllListActivity" > 

    <EditText 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:text="Search" 
     android:id="@+id/inputSearch" 
     /> 


    <ListView 
     android:id="@+id/test_list" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content"> 
    </ListView> 

</LinearLayout> 

Здесь ключевое слово поиска происходит из «inputSearch» EditText.

Вот текст, поменявший слушателя.

inputSearch.addTextChangedListener(new TextWatcher() { 

        @Override 
        public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) { 
         // When user changed the Text 
         // Toast.makeText(getActivity(), cs.toString(), Toast.LENGTH_LONG).show(); 
         m_adapter.getFilter().filter(cs); 
        } 

        @Override 
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, 
                int arg3) { 
         // TODO Auto-generated method stub 

        } 

        @Override 
        public void afterTextChanged(Editable arg0) { 
         // TODO Auto-generated method stub 
        } 
       }); 

Спасибо.

+0

, что именно вы хотите достичь? Откуда берутся данные фильтра и что вы хотите от фильтра? – Axarydax

+1

Я также предлагаю вам взглянуть на этот отличный ответ: http://stackoverflow.com/a/14369336/72746 - это может быть то, что вы ищете. – Axarydax

+0

@Axarydax Извините, что макет был добавлен в вопрос. На самом деле ключевое слово «Поиск» происходит из «EditText» «InputSearch». Я хочу реализовать автоматическую подсказку как функцию, используемую в google; Но вот из списка. – Redone

ответ

42

Вы имеете проблему, главным образом потому, что вы используете пользовательский объект. Если вы передаете значение String или int для адаптера массива, вы знаете, как его фильтровать. Но если вы передаете пользовательский фильтр по умолчанию для фильтра объектов, не представляете, как с этим справиться.

Хотя неясно, что вы пытаетесь сделать в своем фильтре, я рекомендую вам следующие шаги.

  1. Правильная реализация ListTO, хотя это не имеет ничего общего с вашей целью прямо сейчас
  2. Реализовать пользовательский фильтр
  3. вернуть фильтр

Реализации пользовательских фильтров

Первых вам нужно сделать, implementsFilterable от вашего адаптера массива э.

Во-вторых, обеспечить реализацию Вашего Filter

Filter myFilter = new Filter() { 
     @Override 
     protected FilterResults performFiltering(CharSequence constraint) { 
     FilterResults filterResults = new FilterResults(); 
     ArrayList<ListTO> tempList=new ArrayList<ListTO>(); 
     //constraint is the result from text you want to filter against. 
     //objects is your data set you will filter from 
     if(constraint != null && objects!=null) { 
      int length=objects.size(); 
      int i=0; 
       while(i<length){ 
        ListTO item=objects.get(i); 
        //do whatever you wanna do here 
        //adding result set output array  

        tempList.add(item); 

        i++; 
       } 
       //following two lines is very important 
       //as publish result can only take FilterResults objects 
       filterResults.values = tempList; 
       filterResults.count = tempList.size(); 
      } 
      return filterResults; 
     } 

     @SuppressWarnings("unchecked") 
     @Override 
     protected void publishResults(CharSequence contraint, FilterResults results) { 
      objects = (ArrayList<ListTO>) results.values; 
      if (results.count > 0) { 
      notifyDataSetChanged(); 
      } else { 
       notifyDataSetInvalidated(); 
      } 
     } 
    }; 

Последний шаг,

@Override 
    public Filter getFilter() { 
     return myFilter; 
    } 
+0

Могли бы вы помочь в моей проблеме здесь: http://stackoverflow.com/questions/20524417/listview- это-заготовки в то время, используя-getfilter-функции. Я следовал методу, но ListView просто исчезает. – Si8

+4

@minhaz Я реализовал ваше решение, и оно работает хорошо. Однако у меня проблема. Если я ищу строку, а затем обратно обратно в ничто, она не покажет мне ВСЕ элементы массива. – Zapnologica

+0

Я также сталкиваюсь с той же проблемой, когда я возвращаюсь в космос, ничего не работает. –

7

Вам необходимо переопределить способ getFilter() в адаптере и предоставить собственный фильтр. Взгляните на это Filterable Example, чтобы увидеть реальную реализацию.

Добавьте следующий getFilter() код в ваш FilterableAdapter класса и заполнить его с помощью фильтрации:

/* (non-Javadoc) 
* @see android.widget.ArrayAdapter#getFilter() 
*/ 
@Override 
public Filter getFilter() { 
    return new Filter() { 

     /* (non-Javadoc) 
     * @see android.widget.Filter#performFiltering(java.lang.CharSequence) 
     */ 
     @Override 
     protected FilterResults performFiltering(CharSequence constraint) { 
      // TODO Auto-generated method stub 
      /* 
      * Here, you take the constraint and let it run against the array 
      * You return the result in the object of FilterResults in a form 
      * you can read later in publichResults. 
      */ 
      return null; 
     } 

     /* (non-Javadoc) 
     * @see android.widget.Filter#publishResults(java.lang.CharSequence, android.widget.Filter.FilterResults) 
     */ 
     @Override 
     protected void publishResults(CharSequence constraint, FilterResults results) { 
      // TODO Auto-generated method stub 
      /* 
      * Here, you take the result, put it into Adapters array 
      * and inform about the the change in data. 
      */ 
     } 

    }; 
} 

Я добавил подсказки, что делать в комментариях.

+0

Спасибо. Я попробую код. – Redone

5

попробовать это:

 public class Adptr extends BaseAdapter implements Filterable { 
public ArrayList<Model> modelValues; 

private Activity activity; 
private LayoutInflater layoutinflater; 
private List<Model> mOriginalValues; 
private int PositionSelected = 0; 

public Adptr (ArrayList<Model> modelValues, Activity activity) { 
    super(); 
    this.modelValues = modelValues; 
    this.activity = activity; 


} 

@Override 
public int getCount() { 

    return modelValues.size(); 
} 

@Override 
public Object getItem(int position) { 

    return modelValues.get(position); 
} 

@Override 
public long getItemId(int position) { 

    return position; 
} 


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

    layoutinflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    ViewHolder holder = null; 
    Model model = modelValues.get(position); 

    if (convertView == null || !(convertView.getTag() instanceof ViewHolder)) { 
     convertView = layoutinflater.inflate(R.layout.row_search, null); 
     holder = new ViewHolder(); 
     holder.txtName = (TextView) convertView.findViewById(R.id.row_serch_txt_name); 




     convertView.setTag(holder); 
     convertView.setTag(R.id.row_serch_txt_name, holder.txtName); 

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

    holder.txtArtistName.setText("" + modelValue.get_NAME()); 




    return convertView; 
} 

class ViewHolder { 
    TextView txtName; 


} 

@Override 
public Filter getFilter() { 

    Filter filter = new Filter() { 

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

      modelValues = (ArrayList<ModelValueArtist>) results.values; // has 

      notifyDataSetChanged(); 
     } 

     @Override 
     protected FilterResults performFiltering(CharSequence constraint) { 
      FilterResults results = new FilterResults(); // Holds the 
                  // results of a 
                  // filtering 
                  // operation in 
                  // values 
      // List<String> FilteredArrList = new ArrayList<String>(); 
      List<Model> FilteredArrList = new ArrayList<Model>(); 

      if (mOriginalValues == null) { 
       mOriginalValues = new ArrayList<Model>(modelValues); // saves 

      } 

      /******** 
      * 
      * If constraint(CharSequence that is received) is null returns 
      * the mOriginalValues(Original) values else does the Filtering 
      * and returns FilteredArrList(Filtered) 
      * 
      ********/ 
      if (constraint == null || constraint.length() == 0) { 

       // set the Original result to return 
       results.count = mOriginalValues.size(); 
       results.values = mOriginalValues; 
      } else { 
       Locale locale = Locale.getDefault(); 
       constraint = constraint.toString().toLowerCase(locale); 
       for (int i = 0; i < mOriginalValues.size(); i++) { 
        Model model = mOriginalValues.get(i); 

        String data = model.get_NAME(); 
        if (data.toLowerCase(locale).contains(constraint.toString())) { 

         FilteredArrList.add(modelMyMall); 
        } 
       } 
       // set the Filtered result to return 
       results.count = FilteredArrList.size(); 
       results.values = FilteredArrList; 

      } 
      return results; 
     } 
    }; 
    return filter; 
    } 

    } 
+0

отлично это сработало для меня –

+0

Я использовал это слово в слово, и это не сработало. Было предложено переопределить 'getCount()' 'ArrayAdapter', который просто отфильтровал количество результатов, а не результаты. Я закончил «mThis.clear(); mThis.addAll (customList);' in 'publishResults()' – surfer190

-1

Как вы сказали: «Я хочу, чтобы реализовать автоматический предложить как функция используется в гугле, но здесь с точки зрения списка ,- Redone»

Существует еще один способ сделать это с помощью AutoCompleteTextView

Для более подробной информации перейдите по AutoCompleteTextView

Результат будет выглядеть как этот

If enter charachter 'a' it will show the list of words start with 'a'

enter image description here

main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/listitem_layout" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:background="#e2e2e2" 
    android:orientation="vertical" > 

    <AutoCompleteTextView 
      android:id="@+id/autocomplete" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:layout_margin="10dp" 
      android:background="@drawable/text_area" 
      android:inputType="text|textNoSuggestions|textMultiLine" 
      android:paddingLeft="10dp" 
      android:popupBackground="#EFEEEC" 
      android:textColor="#333333" 
      android:textColorHint="#9c9c9c" 
      android:textSize="18sp" 
      android:completionThreshold="1" /> 

</LinearLayout> 

auto_textview.xml

<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:padding="12dp" 
    android:textColor="#333333" 
    android:layout_margin="15dp" 
    android:textSize="16sp" > 
</TextView> 

MainActivity.java

public class MainActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     AutoCompleteTextView seachView = (AutoCompleteTextView) findViewById(R.id.autocomplete); 
     seachView.setAdapter(new ArrayAdapter<String>(this, 
       R.layout.auto_textview, getHeading())); 
    } 

    /** 
    * @return 
    */ 
    public List<String> getHeading() { 
     List<String> list = new ArrayList<String>(); 
     list.add("Android"); 
     list.add("Arnold"); 
     list.add("Blackberry"); 
     list.add("Blackpearl"); 
     list.add("Country"); 
     list.add("Canada"); 
     list.add("City"); 
     list.add("Street Address"); 
     list.add("Objective C"); 
     return list; 
    } 

} 

Надеется, что это поможет.

+0

Помогите с моим вопросом здесь: http://stackoverflow.com/questions/20524417/listview-is-blank-while-using-getfilter-function – Si8

7

Не нужно писать адаптер массива. напишите метод toString(), который должен вернуть значение имени файла.

Как

public class ListTO { 

    public int Id; 
    public String FileName; 
    public String FileUri; 

    public ListTO(int id, String fileName, String fileUri) { 

     Id = id; 
     FileName = fileName; 
     FileUri = fileUri; 

    } 

    public String toString(){ 
     return FileName 
    } 

} 
+0

Это отличное и простое решение, если вам просто нужен базовый поиск. +1 –

+0

Это не просто здорово, это не изобретать колесо правильный ответ – albfan

4

Вы можете переопределить ToString() в вас пользовательский класс объекта и вернуть объект String, который вы хотите получить отфильтрованы.

@Override 
public void toString(){ 
     return this.toBeFilteredString; 
} 

А затем просто использовать по умолчанию встроенный фильтр arrayAdapter и вызвать его с помощью

adapter.getFilter().filter(Charsequence c); 
+0

Только то, что я искал! :) –

+0

То же самое! После написания принятого решения я искал что-то более простое ... спасибо! –

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