【问题标题】:Android actionbar Search with listview使用列表视图进行 Android 操作栏搜索
【发布时间】:2015-08-11 13:31:12
【问题描述】:

我是安卓开发新手。我想要的是使用操作栏搜索视图小部件搜索我的列表视图。我如何实现搜索功能。我缺少的是搜索功能。我看到了一些搜索功能,但它是基于 editText 的。请帮忙。

这是我的代码:

menu.xml

   <item android:id="@+id/menu_search"
          android:title="@string/menu_search"
          android:icon="@android:drawable/ic_menu_search"
          android:showAsAction="ifRoom|collapseActionView"
          android:actionViewClass="android.widget.SearchView" />

在我的 manifest.xml 中

<activity
            android:name=".MainActivity"
             <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
            <meta-data
                android:name="android.app.searchable"
                android:resource="@xml/searchable">
            </meta-data>
        </activity>

在我的 MainActivity.java 上

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

                this.lv = (ListView) findViewById(R.id.listView);

                this.databaseAccess = DatabaseAccess.getInstance(getApplicationContext());
                this.persons= getPersonList();

                Adapter adapter = new Adapter(this, persons);
                this.lv.setAdapter(adapter);
}
    public List<Person> getPersonList(){
            databaseAccess.open();
            List<Person> person= databaseAccess.getPersons();
            databaseAccess.close();
            return person;
        }

 private class Adapter extends ArrayAdapter<Person> {

        public Adapter(Context context, List<Person> objects) {
            super(context, 0, objects);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = getLayoutInflater().inflate(R.layout.persons, parent, false);
            }

            TextView id = (TextView) convertView.findViewById(R.id.id);
            TextView name= (TextView) convertView.findViewById(R.id.name);
            TextView lastname = (TextView) convertView.findViewById(R.id.latname);

            Person p = persons.get(position);
            id.setText(p.getId());
            name.setText(p.getName());
            lastname.setText(p.getLastName());

            return convertView;
        }

【问题讨论】:

    标签: android listview search


    【解决方案1】:

    您需要在您的适配器中实现Filterable 接口。

    然后膨胀菜单:

      @Override
      public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        MenuItem searchMenuItem = menu.findItem(R.id.menu_search);
        if (searchMenuItem == null) {
            return;
        }
    
        searchView = (SearchView) searchMenuItem.getActionView();
        if (searchView != null) {
            searchView.setQueryHint(getString(R.string.search_hint));
            searchView.setMaxWidth(2129960); // https://stackoverflow.com/questions/18063103/searchview-in-optionsmenu-not-full-width
            searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                @Override
                public boolean onQueryTextSubmit(String s) {
                    return false;
                }
    
                @Override
                public boolean onQueryTextChange(String s) {
                    SearchFragment.this.onQueryTextChange(s);
                    return false;
                }
            });
        }
    }
    

    然后指定处理查询文本更改事件的方法,例如:

    void onQueryTextChange(String query) {
        searchAdapter.getFilter().filter(query);
    }
    

    了解更多信息here

    【讨论】:

      【解决方案2】:

      您必须使用带有过滤功能的模型、列表视图和自定义适配器。我为此创建了一个演示,假设您有一个名为 Product 的模型,并且您在自定义列表视图中显示其内容,其中名称、价格显示在 textview 中。我的意思是在具有两个文本视图的自定义行中。并且您想要过滤自定义行字段之一的列表。这里我用“名称”过滤了

      源代码

      //这是你的模型

      public class Product {
      
          public String name;
          public Integer price;
          public Product(String name, Integer price) {
              super();
              this.name = name;
              this.price = price;
          }
          public String getName() {
              return name;
          }
          public void setName(String name) {
              this.name = name;
          }
          public Integer getPrice() {
              return price;
          }
          public void setPrice(Integer price) {
              this.price = price;
          }
      
      }
      

      //这是您使用自定义适配器和列表视图的活动

      public class MainActivity extends Activity{
      private LinearLayout llContainer;
      private EditText etSearch;
      private ListView lvProducts;
      
      private ArrayList<Product> mProductArrayList = new ArrayList<Product>();
      private MyAdapter adapter1;
      
      
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
      
      
          initialize();
      
      
      
          // Add Text Change Listener to EditText
          etSearch.addTextChangedListener(new TextWatcher() {
      
              @Override
              public void onTextChanged(CharSequence s, int start, int before, int count) {
                  // Call back the Adapter with current character to Filter
                  adapter1.getFilter().filter(s.toString());
              }
      
              @Override
              public void beforeTextChanged(CharSequence s, int start, int count,int after) {
              }
      
              @Override
              public void afterTextChanged(Editable s) {
              }
          });
      }
      
      private void initialize() {
          etSearch = (EditText) findViewById(R.id.etSearch);
          lvProducts = (ListView)findViewById(R.id.lvOS);
      }
      
      @Override
      protected void onResume() {
          // TODO Auto-generated method stub
          super.onResume();
      
          mProductArrayList.add(new Product("a", 100));
          mProductArrayList.add(new Product("b", 200));
          mProductArrayList.add(new Product("c", 300));
          mProductArrayList.add(new Product("d", 400));
          mProductArrayList.add(new Product("e", 500));
          mProductArrayList.add(new Product("f", 600));
          mProductArrayList.add(new Product("g", 700));
          mProductArrayList.add(new Product("h", 800));
          mProductArrayList.add(new Product("i", 900));
          mProductArrayList.add(new Product("j", 1000));
          mProductArrayList.add(new Product("k", 1100));
          mProductArrayList.add(new Product("l", 1200));
          mProductArrayList.add(new Product("m", 1000));
          mProductArrayList.add(new Product("n", 1300));
          mProductArrayList.add(new Product("o", 1400));
          mProductArrayList.add(new Product("p", 1500));
      
      
          adapter1 = new MyAdapter(MainActivity.this, mProductArrayList);
          lvProducts.setAdapter(adapter1);
      }
      
      
      // Adapter Class            
      public class MyAdapter extends BaseAdapter implements Filterable {
      
          private ArrayList<Product> mOriginalValues; // Original Values
          private ArrayList<Product> mDisplayedValues;    // Values to be displayed
          LayoutInflater inflater;
      
          public MyAdapter(Context context, ArrayList<Product> mProductArrayList) {
              this.mOriginalValues = mProductArrayList;
              this.mDisplayedValues = mProductArrayList;
              inflater = LayoutInflater.from(context);
          }
      
          @Override
          public int getCount() {
              return mDisplayedValues.size();
          }
      
          @Override
          public Object getItem(int position) {
              return position;
          }
      
          @Override
          public long getItemId(int position) {
              return position;
          }
      
          private class ViewHolder {
              LinearLayout llContainer;
              TextView tvName,tvPrice;
          }
      
          @Override
          public View getView(final int position, View convertView, ViewGroup parent) {
      
              ViewHolder holder = null;
      
              if (convertView == null) {
      
                  holder = new ViewHolder();
                  convertView = inflater.inflate(R.layout.row, null);
                  holder.llContainer = (LinearLayout)convertView.findViewById(R.id.llContainer);
                  holder.tvName = (TextView) convertView.findViewById(R.id.tvName);
                  holder.tvPrice = (TextView) convertView.findViewById(R.id.tvPrice);
                  convertView.setTag(holder);
              } else {
                  holder = (ViewHolder) convertView.getTag();
              }
              holder.tvName.setText(mDisplayedValues.get(position).name);
              holder.tvPrice.setText(mDisplayedValues.get(position).price+"");
      
              holder.llContainer.setOnClickListener(new OnClickListener() {
      
                  public void onClick(View v) {
      
                      Toast.makeText(MainActivity.this, mDisplayedValues.get(position).name, Toast.LENGTH_SHORT).show();
                  }
              });
      
              return convertView;
          }
      
          @Override
          public Filter getFilter() {
              Filter filter = new Filter() {
      
                  @SuppressWarnings("unchecked")
                  @Override
                  protected void publishResults(CharSequence constraint,FilterResults results) {
      
                      mDisplayedValues = (ArrayList<Product>) 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<Product> FilteredArrList = new ArrayList<Product>();
      
                      if (mOriginalValues == null) {
                          mOriginalValues = new ArrayList<Product>(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).name;
                              if (data.toLowerCase().startsWith(constraint.toString())) {
                                  FilteredArrList.add(new Product(mOriginalValues.get(i).name,mOriginalValues.get(i).price));
                              }
                          }
                          // set the Filtered result to return
                              results.count = FilteredArrList.size();
                              results.values = FilteredArrList;
                          }
                          return results;
                      }
                  };
                  return filter;
              }
          }
      }
      

      //这是你的activity_main.xml

      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:orientation="vertical" >
      
          <EditText 
              android:id="@+id/etSearch"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"/>
      
          <ListView 
              android:id="@+id/lvProducts"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"></ListView>    
      
      </LinearLayout>
      

      //这是你的row.xml

      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/llContainer"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="horizontal" >
      
          <TextView 
              android:id="@+id/tvName"
              android:layout_width="0dp"
              android:layout_height="wrap_content"
              android:singleLine="true"
              android:layout_weight="1"/>
      
          <TextView 
              android:id="@+id/tvPrice"
              android:layout_width="0dp"
              android:layout_height="wrap_content"
              android:singleLine="true"
              android:layout_weight="1"/>
      
      </LinearLayout>
      

      【讨论】:

        【解决方案3】:

        试试这个示例。 Sample search widget

        【讨论】:

        • 代码正在运行,但是当我在我的代码上实现它时,搜索结果没有显示 onTextChange() 和 onTextQuery()。它返回空白
        【解决方案4】:

        使用 SearchView (默认操作栏功能)在此链接中可以很好地解释您要查找的内容。

        http://blog.lovelyhq.com/implementing-a-live-list-search-in-android-action-bar/

        希望对你有帮助。

        【讨论】:

          猜你喜欢
          • 2016-11-05
          • 1970-01-01
          • 2023-03-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-04-03
          • 1970-01-01
          • 2015-10-05
          相关资源
          最近更新 更多