Пользовательские getFilter в пользовательский адаптер массива в Android

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

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;

    }
}

И вот этот класс, чтобы.

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
                    }
                });

Спасибо.

Комментарии к вопросу (4)
Решение

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

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

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

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

Первое, что вам нужно сделать, это реализует фильтрация из массива адаптер.

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

Filter myFilter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
         FilterResults filterResults = new FilterResults();   
         ArrayList tempList=new ArrayList();
         //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 0) {
           notifyDataSetChanged();
          } else {
              notifyDataSetInvalidated();
          }  
      }
     };

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

@Override
     public Filter getFilter() {
        return myFilter;
    }
Комментарии (8)

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

Добавить код следующие 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)

Не нужно писать массив адаптер. написать 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
    }

}
Комментарии (2)

попробуйте это:

     public class Adptr extends BaseAdapter implements Filterable {
public ArrayList modelValues;

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

public Adptr (ArrayList 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) results.values; // has

            notifyDataSetChanged();
        }

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

            if (mOriginalValues == null) {
                mOriginalValues = new ArrayList(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;
  }

     }
Комментарии (1)

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

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

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

adapter.getFilter().filter(Charsequence c);
Комментарии (2)

Я искал довольно много ответов на так, чтобы получить все необходимые фрагменты. Так вот'ы на версию Котлин пользовательского фильтра для регистрации мой класс`. Это на самом деле работает и всю информацию, вам нужно в этот код.

class RegistrationArrayAdapter(context: Context, private val layoutResId: Int, registrations: List) :
    ArrayAdapter(context, layoutResId, registrations) {

    private val filter = RegistrationFilter(registrations)

    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
        val registration = getItem(position)
        val view = convertView ?: LayoutInflater.from(context).inflate(layoutResId, null)
        (view as TextView).text = registration?.mainGuest?.name ?: ""
        return view
    }

    override fun getFilter() = filter

    inner class RegistrationFilter(private val originalList: List) : Filter() {

        private val sourceObjects: ArrayList = ArrayList()

        init {
            synchronized (this) {
                sourceObjects.addAll(originalList)
            }
        }

        override fun performFiltering(constraint: CharSequence?): FilterResults {
            if (constraint == null) return FilterResults()

            val result = FilterResults()

            if (constraint.isNotEmpty()) {
                val filteredList = ArrayList()

                sourceObjects.filterTo(filteredList) { isWithinConstraint(it, constraint) }

                result.count = filteredList.size
                result.values = filteredList

            } else {
                synchronized(this) {
                    result.values = sourceObjects
                    result.count = sourceObjects.size
                }

            }
            return result
        }

        override fun publishResults(constraint: CharSequence?, results: FilterResults) {
            if (results.values == null) return

            @Suppress("UNCHECKED_CAST")
            val filtered = results.values as ArrayList

            if (results.count > 0) {
                clear()
                addAll(filtered)
                notifyDataSetChanged()
            } else {
                notifyDataSetInvalidated()
            }

        }

        override fun convertResultToString(resultValue: Any?): CharSequence {
            return (resultValue as Registration).mainGuest.name
        }

        private fun isWithinConstraint(registration: Registration, constraint: CharSequence): Boolean {
            return registration.mainGuest.name.toLowerCase().contains(constraint, true)
        }

    }
}
Комментарии (0)

Как ты сказал "Я хочу, чтобы реализовать функцию, как функция, используемая в Google, но вот из списка. – Переделано и"

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

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

Выход будет выглядеть так

main.xml





auto_textview.xml


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(this,
                R.layout.auto_textview, getHeading()));
    }

    /**
     * @return
     */
    public List getHeading() {
        List list = new ArrayList();
        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;
    }

}

Надеюсь, что это поможет вам.

Комментарии (1)