カスタムarrayAdapterにカスタム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;
}
}
そして、これが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
}
});
ありがとう。
主にカスタムオブジェクトを使用しているため、問題が発生しています。 Stringまたはint値を配列アダプターに渡すと、フィルター処理の方法がわかります。ただし、カスタムオブジェクトを渡す場合、既定のフィルターの実装では、その処理方法を理解する必要はありません。
フィルターで何をしようとしているかは明確ではありませんが、次の手順に従うことをお勧めします。
ListTO
の適切な実装。ただし、現在の目標とは関係ありませんカスタムフィルターの実装
最初に行う必要があるのは、アレイアダプタからのimplements
Filterable
です。
次に、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;
}
アレイアダプターを記述する必要はありません。 filenameの値を返す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
}
}
アダプターの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.
*/
}
};
}
コメントに何をすべきかのヒントを追加しました。
これを試して:
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;
}
}
カスタムオブジェクトクラスでtoString()をオーバーライドして、フィルターで除外するStringオブジェクトを返すことができます。
@Override
public void toString(){
return this.toBeFilteredString;
}
そして、単にarrayAdapterのデフォルトの組み込みフィルターを使用し、それを使用して呼び出します
adapter.getFilter().filter(Charsequence c);
SOでかなりの数の回答を検索して、必要なすべてのスニペットを取得しました。クラスRegistration
のカスタムフィルターのKotlinバージョンは次のとおりです。必要な情報はこのコードにあります。
class RegistrationArrayAdapter(context: Context, private val layoutResId: Int, registrations: List<Registration>) :
ArrayAdapter<Registration>(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<Registration>) : Filter() {
private val sourceObjects: ArrayList<Registration> = 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<Registration>()
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<Registration>
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)
}
}
}