具有自定义适配器的 ListView 中的 SearchView

Posted

技术标签:

【中文标题】具有自定义适配器的 ListView 中的 SearchView【英文标题】:SearchView In ListView having a custom Adapter 【发布时间】:2014-06-18 18:42:55 【问题描述】:

伙计们,我需要一些帮助。我一直在尝试在我的项目中实现 SearchView。但是我的项目包含一个带有自定义适配器的列表视图。我搜索了许多站点,但都有使用实现的示例一个 arrayadapter..假设我有一个 Employee 类,它包含姓名和年龄字段..我如何只使用他们的姓名过滤员工..

public class MainActivity extends Activity implements SearchView.OnQueryTextListener

SearchView mSearchView;
ListView mListView;
//String mStrings[]= "abc","def","efg","ghi","ijk","apple","agxhsdgc","abbbcc";
ArrayList<Employee> emp_list=null;
EmployeeAdapter emp_adapter=null;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mSearchView=(SearchView) findViewById(R.id.searchView1);
        mListView=(ListView) findViewById(R.id.listView1);

        emp_list=new ArrayList<Employee>();
        emp_list.add(new Employee("ABC", 24));
        emp_list.add(new Employee("ACB", 24));
        emp_list.add(new Employee("BVF", 28));
        emp_list.add(new Employee("BRT", 28));
        emp_list.add(new Employee("ANM", 23));

        emp_adapter=new EmployeeAdapter(MainActivity.this, emp_list);
        mListView.setAdapter(emp_adapter);

//      mListView.setAdapter(new ArrayAdapter<String>(this,
//                android.R.layout.simple_list_item_1,
//                mStrings));
        mListView.setTextFilterEnabled(true);
        setupSearchView();


    
     private void setupSearchView() 
     
            mSearchView.setIconifiedByDefault(false);
            mSearchView.setOnQueryTextListener(this);
            mSearchView.setSubmitButtonEnabled(true); 
            mSearchView.setQueryHint("Search Here");
        

        @Override
        public boolean onQueryTextChange(String newText) 
        

            if (TextUtils.isEmpty(newText.toString())) 
                mListView.clearTextFilter();
             else 
                mListView.setFilterText(newText.toString());
            
            return true;
        

        @Override
        public boolean onQueryTextSubmit(String query) 
        
            return false;
        


    

这是我扩展 BaseAdapter 的适配器类..

public class EmployeeAdapter extends BaseAdapter 

    Context ctx;
    ArrayList<Employee> emp_list;
    LayoutInflater linf=null;
    EmployeeHolder holder=null;






    public EmployeeAdapter(Context ctx, ArrayList<Employee> emp_list) 
        super();
        this.ctx = ctx;
        this.emp_list = emp_list;
        linf=(LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    

    public class EmployeeHolder
    
        TextView name;
        TextView age;

    



    @Override
    public int getCount() 
        // TODO Auto-generated method stub
        return emp_list.size();
    

    @Override
    public Object getItem(int position) 
        // TODO Auto-generated method stub
        return emp_list.get(position);
    

    @Override
    public long getItemId(int position) 
        // TODO Auto-generated method stub
        return position;
    

    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
        // TODO Auto-generated method stub

        if(convertView==null)
        
            convertView=linf.inflate(R.layout.row, parent, false);
            holder=new EmployeeHolder();
            holder.name=(TextView) convertView.findViewById(R.id.name);
            holder.age=(TextView) convertView.findViewById(R.id.age);

            convertView.setTag(holder);
        
        else
        
            holder=(EmployeeHolder) convertView.getTag();
        

        Employee e=(Employee) getItem(position);


        holder.name.setText(e.getName());
        holder.age.setText(String.valueOf(e.getAge()));

        return convertView;

    


提前致谢..

【问题讨论】:

【参考方案1】:

试试这个方法,希望对你有帮助...

activity_main.xml

    <SearchView
        android:id="@+id/searchView1"
        android:layout_
        android:layout_/>


    <ListView
        android:id="@+id/listView1"
        android:layout_
        android:layout_
        android:layout_weight="1"/>


</LinearLayout>

row.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_
    android:layout_>

    <TextView
        android:id="@+id/txtName"
        android:layout_
        android:layout_ />

    <TextView
        android:id="@+id/txtAge"
        android:layout_
        android:layout_
        android:layout_marginTop="5dp"/>

</LinearLayout>

MainActivity.java

public class MainActivity extends Activity implements SearchView.OnQueryTextListener

    private SearchView mSearchView;
    private ListView mListView;
    private ArrayList<Employee> employeeArrayList;
    private EmployeeAdapter employeeAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mSearchView=(SearchView) findViewById(R.id.searchView1);
        mListView=(ListView) findViewById(R.id.listView1);

        employeeArrayList=new ArrayList<Employee>();
        employeeArrayList.add(new Employee("ABC", 24));
        employeeArrayList.add(new Employee("ACB", 24));
        employeeArrayList.add(new Employee("BVF", 28));
        employeeArrayList.add(new Employee("BRT", 28));
        employeeArrayList.add(new Employee("ANM", 23));

        employeeAdapter=new EmployeeAdapter(MainActivity.this, employeeArrayList);
        mListView.setAdapter(employeeAdapter);

        mListView.setTextFilterEnabled(true);
        setupSearchView();


    
    private void setupSearchView()
    
        mSearchView.setIconifiedByDefault(false);
        mSearchView.setOnQueryTextListener(this);
        mSearchView.setSubmitButtonEnabled(true);
        mSearchView.setQueryHint("Search Here");
    

    @Override
    public boolean onQueryTextChange(String newText)
    

        if (TextUtils.isEmpty(newText)) 
            mListView.clearTextFilter();
         else 
            mListView.setFilterText(newText);
        
        return true;
    

    @Override
    public boolean onQueryTextSubmit(String query)
    
        return false;
    



EmployeeAdapter.java

public class EmployeeAdapter extends BaseAdapter implements Filterable 

    public Context context;
    public ArrayList<Employee> employeeArrayList;
    public ArrayList<Employee> orig;

    public EmployeeAdapter(Context context, ArrayList<Employee> employeeArrayList) 
        super();
        this.context = context;
        this.employeeArrayList = employeeArrayList;
    


    public class EmployeeHolder
    
        TextView name;
        TextView age;
    

    public Filter getFilter() 
        return new Filter() 

            @Override
            protected FilterResults performFiltering(CharSequence constraint) 
                final FilterResults oReturn = new FilterResults();
                final ArrayList<Employee> results = new ArrayList<Employee>();
                if (orig == null)
                    orig = employeeArrayList;
                if (constraint != null) 
                    if (orig != null && orig.size() > 0) 
                        for (final Employee g : orig) 
                            if (g.getName().toLowerCase()
                                    .contains(constraint.toString()))
                                results.add(g);
                        
                    
                    oReturn.values = results;
                
                return oReturn;
            

            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint,
                                          FilterResults results) 
                employeeArrayList = (ArrayList<Employee>) results.values;
                notifyDataSetChanged();
            
        ;
    

    public void notifyDataSetChanged() 
        super.notifyDataSetChanged();
    


    @Override
    public int getCount() 
        return employeeArrayList.size();
    

    @Override
    public Object getItem(int position) 
        return employeeArrayList.get(position);
    

    @Override
    public long getItemId(int position) 
        return position;
    

    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
        EmployeeHolder holder;
        if(convertView==null)
        
            convertView=LayoutInflater.from(context).inflate(R.layout.row, parent, false);
            holder=new EmployeeHolder();
            holder.name=(TextView) convertView.findViewById(R.id.txtName);
            holder.age=(TextView) convertView.findViewById(R.id.txtAge);
            convertView.setTag(holder);
        
        else
        
            holder=(EmployeeHolder) convertView.getTag();
        

        holder.name.setText(employeeArrayList.get(position).getName());
        holder.age.setText(String.valueOf(employeeArrayList.get(position).getAge()));

        return convertView;

    


Employee.java

public class Employee 

    private String name;
    private int age;

    public  Employee(String name,int age)
        this.name = name;
        this.age = age;
    

    public String getName()
        return name;
    

    public int getAge()
        return age;
    

【讨论】:

@Haresh:在我的情况下,我使用 Imageview 是否可以过滤 但是有一个问题,当用户点击过滤列表中的项目进行过滤后,它仍然从原始列表中打开项目。!我用谷歌搜索并找到了解决方案,但无法解决我的问题。 您好,在搜索视图中单击交叉时,我没有返回完整列表。需要紧急帮助..谢谢 你有没有尝试调用mListView.clearTextFilter();点击十字架? @HareshChhelana 非常感谢您的回答!我一直在寻找几个小时如何做到这一点,这对我有很大帮助!不过有一个问题,我如何摆脱“搜索”文本覆盖?【参考方案2】:

那里有很好的答案,但仍然存在评论部分提到的一些问题(onclick时位置错误,serchview文本覆盖),因此您也可以通过以下方式进行此操作

更多信息请参考:searchview listview android

我已经测试过了,目前没有发现任何问题,如果你发现任何问题,请在评论部分提及。

模型类:MovieNames.java

public class MovieNames 
    private String movieName;

    public MovieNames(String movieName) 
        this.movieName = movieName;
    

    public String getAnimalName() 
        return this.movieName;
    


2:listview_item.xml 文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:padding="10dp">


    <TextView
        android:id="@+id/name"
        android:layout_
        android:layout_ />

</RelativeLayout>

    ListViewAdapter.java 列表视图的类适配器:

       import android.content.Context;
       import android.view.LayoutInflater;
       import android.view.View;
       import android.view.ViewGroup;
       import android.widget.BaseAdapter;
       import android.widget.TextView;
       import java.util.ArrayList;
       import java.util.Locale;
    
    
    
    public class ListViewAdapter extends BaseAdapter 
    
    // Declare Variables
    
    Context mContext;
    LayoutInflater inflater;
    private ArrayList<MovieNames> arraylist;
    
    public ListViewAdapter(Context context ) 
        mContext = context;
        inflater = LayoutInflater.from(mContext);
        this.arraylist = new ArrayList<MovieNames>();
        this.arraylist.addAll(MainActivity.movieNamesArrayList);
    
    
    public class ViewHolder 
        TextView name;
    
    
    @Override
    public int getCount() 
        return MainActivity.movieNamesArrayList.size();
    
    
    @Override
    public MovieNames getItem(int position) 
        return MainActivity.movieNamesArrayList.get(position);
    
    
    @Override
    public long getItemId(int position) 
        return position;
    
    
    public View getView(final int position, View view, ViewGroup parent) 
        final ViewHolder holder;
        if (view == null) 
            holder = new ViewHolder();
            view = inflater.inflate(R.layout.listview_item, null);
            // Locate the TextViews in listview_item.xml
            holder.name = (TextView) view.findViewById(R.id.name);
            view.setTag(holder);
         else 
            holder = (ViewHolder) view.getTag();
        
        // Set the results into TextViews
        holder.name.setText(MainActivity.movieNamesArrayList.get(position).getAnimalName());
        return view;
    
    
    // Filter Class
    public void filter(String charText) 
        charText = charText.toLowerCase(Locale.getDefault());
        MainActivity.movieNamesArrayList.clear();
        if (charText.length() == 0) 
            MainActivity.movieNamesArrayList.addAll(arraylist);
         else 
            for (MovieNames wp : arraylist) 
                if (wp.getAnimalName().toLowerCase(Locale.getDefault()).contains(charText)) 
                    MainActivity.movieNamesArrayList.add(wp);
                
            
        
        notifyDataSetChanged();
         
    
      
    

    MainActivity.java 类:

          import android.support.v7.app.AppCompatActivity;
          import android.os.Bundle;
          import android.view.View;
          import android.widget.AdapterView;
          import android.widget.ListView;
          import android.widget.SearchView;
          import android.widget.Toast;
          import java.util.ArrayList;
    
           public class MainActivity extends AppCompatActivity implements SearchView.OnQueryTextListener 
    
           // Declare Variables
         private ListView list;
      private ListViewAdapter adapter;
      private SearchView editsearch;
          private String[] moviewList;
         public static ArrayList<MovieNames> movieNamesArrayList = new ArrayList<MovieNames>();
    
          @Override
       public void onCreate(Bundle savedInstanceState) 
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
    
    // Generate sample data
    
    moviewList = new String[]"Xmen", "Titanic", "Captain America",
            "Iron man", "Rocky", "Transporter", "Lord of the rings", "The jungle book",
            "Tarzan","Cars","Shreck";
    
    // Locate the ListView in listview_main.xml
    list = (ListView) findViewById(R.id.listview);
    
    movieNamesArrayList = new ArrayList<>();
    
    for (int i = 0; i < moviewList.length; i++) 
        MovieNames movieNames = new MovieNames(moviewList[i]);
        // Binds all strings into an array
        movieNamesArrayList.add(movieNames);
    
    
    // Pass results to ListViewAdapter Class
    adapter = new ListViewAdapter(this);
    
    // Binds the Adapter to the ListView
    list.setAdapter(adapter);
    
    // Locate the EditText in listview_main.xml
    editsearch = (SearchView) findViewById(R.id.search);
    editsearch.setOnQueryTextListener(this);
    
    list.setOnItemClickListener(new AdapterView.OnItemClickListener() 
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
            Toast.makeText(MainActivity.this, movieNamesArrayList.get(position).getAnimalName(), Toast.LENGTH_SHORT).show();
        
    );
              
    
         @Override
        public boolean onQueryTextSubmit(String query) 
    
                  return false;
         
    
    
    
        @Override
        public boolean onQueryTextChange(String newText) 
              String text = newText;
              adapter.filter(text);
             return false;
         
       
    

【讨论】:

【参考方案3】:

源代码

https://drive.google.com/open?id=0BzBKpZ4nzNzUOFlxeHhuWmF0Q1U

package example.abhiandroid.searchviewexample;

import android.database.Cursor;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.ListView;
import android.widget.SearchView;

import java.util.ArrayList;

public class SearchViewActivity extends AppCompatActivity implements SearchView.OnQueryTextListener 

    // Declare Variables
    ListView list;
    ListViewAdapter adapter;
    public static SearchView editsearch;
    String[] animalNameList;
    ArrayList<AnimalNames> arraylist = new ArrayList<AnimalNames>();

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);
        // Generate sample data

        animalNameList = new String[]"Lion", "Tiger", "Dog",
                "Cat", "Tortoise", "Rat", "Elephant", "Fox",
                "Cow","Donkey","Monkey";

        // Locate the ListView in listview_main.xml
        list = (ListView) findViewById(R.id.listview);

        for (int i = 0; i < animalNameList.length; i++) 
            AnimalNames animalNames = new AnimalNames(animalNameList[i]);
            // Binds all strings into an array
            arraylist.add(animalNames);
        

        // Pass results to ListViewAdapter Class
        adapter = new ListViewAdapter(this, arraylist);

        // Binds the Adapter to the ListView
        list.setAdapter(adapter);

        // Locate the EditText in listview_main.xml
        editsearch = (SearchView) findViewById(R.id.search);
        editsearch.setOnQueryTextListener(this);

        editsearch.setOnSuggestionListener(new SearchView.OnSuggestionListener() 

            @Override
            public boolean onSuggestionSelect(int position) 
                return true;
            

            @Override
            public boolean onSuggestionClick(int position) 
                Cursor cursor= editsearch.getSuggestionsAdapter().getCursor();
                cursor.moveToPosition(position);
                String suggestion =cursor.getString(2);//2 is the index of col containing suggestion name.
                editsearch.setQuery(suggestion,true);//setting suggestion
                return true;
            
        );

    

    @Override
    public boolean onQueryTextSubmit(String query) 
        Log.e("keshav","query ->"+query);
        return false;
    

    @Override
    public boolean onQueryTextChange(String newText) 
        String text = newText;

        Log.e("keshav","newText ->"+newText);

        adapter.filter(text);
        return false;
    



package example.abhiandroid.searchviewexample;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class ListViewAdapter extends BaseAdapter 

    // Declare Variables
    Context mContext;
    LayoutInflater inflater;
    private List<AnimalNames> animalNamesList = null;
    private ArrayList<AnimalNames> arraylist;

    public ListViewAdapter(Context context, List<AnimalNames> animalNamesList) 
        mContext = context;
        this.animalNamesList = animalNamesList;
        inflater = LayoutInflater.from(mContext);
        this.arraylist = new ArrayList<AnimalNames>();
        this.arraylist.addAll(animalNamesList);
    

    public class ViewHolder 
        TextView name;
    

    @Override
    public int getCount() 
        return animalNamesList.size();
    

    @Override
    public AnimalNames getItem(int position) 
        return animalNamesList.get(position);
    

    @Override
    public long getItemId(int position) 
        return position;
    

    public View getView(final int position, View view, ViewGroup parent) 
        final ViewHolder holder;
        if (view == null) 
            holder = new ViewHolder();
            view = inflater.inflate(R.layout.search_list_view_item, null);
            // Locate the TextViews in search_list_view_itemiew_item.xml
            holder.name = (TextView) view.findViewById(R.id.name);
            view.setTag(holder);
         else 
            holder = (ViewHolder) view.getTag();
        
        // Set the results into TextViews

        holder.name.setText(animalNamesList.get(position).getAnimalName());

        view.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                Log.e("keshav","click  list item ->"+animalNamesList.get(position).getAnimalName());
                SearchViewActivity.editsearch.setQuery(animalNamesList.get(position).getAnimalName(), false);

                Log.e("keshav","click  size ->"+animalNamesList.size());
                // TOdo size always 1 Important See cs Electric Project in Holostik
                Log.e("keshav","click  size ->"+animalNamesList.get(0).getAnimalName());
            
        );
        return view;
    

    // Filter Class
    public void filter(String charText) 
        charText = charText.toLowerCase(Locale.getDefault());
        animalNamesList.clear();
        if (charText.length() == 0) 
            animalNamesList.addAll(arraylist);
         else 
            for (AnimalNames wp : arraylist) 
                if (wp.getAnimalName().toLowerCase(Locale.getDefault()).contains(charText)) 
                    animalNamesList.add(wp);
                
            
        
        notifyDataSetChanged();
    



package example.abhiandroid.searchviewexample;

public class AnimalNames

    private String animalName;

    public AnimalNames(String animalName) 
        this.animalName = animalName;
    

    public String getAnimalName() 
        return this.animalName;
    



<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_>

    <SearchView
        android:id="@+id/search"
        android:layout_
        android:layout_
        android:iconifiedByDefault="false">

        <requestFocus />
    </SearchView>

    <ListView
        android:id="@+id/listview"
        android:layout_
        android:layout_
        android:layout_below="@+id/search" />

</RelativeLayout>


list item.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:padding="10dp">

    <TextView
        android:id="@+id/nameLabel"
        android:layout_
        android:layout_
        android:text="Animal : " />

    <TextView
        android:id="@+id/name"
        android:layout_
        android:layout_
        android:layout_toRightOf="@+id/nameLabel" />

</RelativeLayout>

快乐编码

【讨论】:

【参考方案4】:

菜单:menu_doctor_list.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_search"
        android:icon="@drawable/ic_search_white_24dp"
        app:showAsAction="always|collapseActionView"
        app:actionViewClass="android.support.v7.widget.SearchView"
        android:title="Search"/>
</menu>

活动:

public class ListActivity extends AppActivity implements SearchView.OnQueryTextListener  

public boolean onCreateOptionsMenu(Menu menu) 
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.menu_doctor_list, menu);

        MenuItem searchItem = menu.findItem(R.id.action_search);

        SearchView searchView = (SearchView) searchItem.getActionView();
        searchView.setQueryHint("Search Doctor by Name or Specialization");
        searchView.setOnQueryTextListener(this);
        searchView.setOnCloseListener(this);
        searchView.setIconified(false);

        return true;
    

@Override
    public boolean onQueryTextSubmit(String query) 
        System.out.println("query = " + query);
        doctorListAdapter.getFilter().filter(query);
        return true;
    

    @Override
    public boolean onQueryTextChange(String newText) 
        System.out.println("query = " + newText);
        doctorListAdapter.getFilter().filter(newText);
        return true;
    

适配器:

public class ListAdapter extends RecyclerView.Adapter<ListAdapter.BindingHolder> implements Filterable 

private List<DoctorInfo> mOriginalValues; // Original Values
    private List<DoctorInfo> mDisplayedValues;    // Values to be displayed use this in onBindViewHolder()

    public DoctorListAdapter(Context context, List<DoctorInfo> appointmentList) 
        this.mOriginalValues = appointmentList;
        this.mDisplayedValues = appointmentList;
    

@Override
    public Filter getFilter() 
        Filter filter = new Filter() 

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

                mDisplayedValues = (ArrayList<DoctorInfo>) results.values; // has the filtered values
                notifyDataSetChanged();  // notifies the data with new filtered values
            

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

                if (mOriginalValues == null) 
                    mOriginalValues = new ArrayList<DoctorInfo>(mDisplayedValues); // saves the original data in mOriginalValues
                

                /********
                 *
                 *  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 
                    constraint = constraint.toString().toLowerCase();
                    for (int i = 0; i < mOriginalValues.size(); i++) 
                        String data = mOriginalValues.get(i).getFirstname() + " " + mOriginalValues.get(i).getLastname();
                        if (data.toLowerCase().startsWith(constraint.toString())) 
                            FilteredArrList.add(mOriginalValues.get(i));
                        
                    
                    // set the Filtered result to return
                    results.count = FilteredArrList.size();
                    results.values = FilteredArrList;
                
                return results;
            
        ;
        return filter;
    

【讨论】:

以上是关于具有自定义适配器的 ListView 中的 SearchView的主要内容,如果未能解决你的问题,请参考以下文章

片段中的自定义列表适配器

自定义 ListView 适配器中的 ImageButton

ListView自定义适配器,包括库中的图像

使用自定义适配器更改 ListView 中特定行中的 ImageView

使用自定义适配器更改ListView中特定行中的ImageView

如何为随机自定义 ListView 适配器设置按钮单击事件?