getSearchableInfo()返回null

时间:2017-05-05 12:16:28

标签: java android xml searchview android-appbarlayout

我的第四天试图解决这个问题:(我正在尝试向我的应用栏添加搜索功能。在进程中,我需要获取searchManager.getSearchableInfo()但它返回null,因此我无法获得我的搜索工作。我知道有类似的问题,但没有一个工作。

我迫切需要你的帮助!

摘要:

  • 我要搜索FROM的活动:ListActivity(扩展 AppCompatActivity)
  • 活动我正在处理搜索:SearchResultsActivity(扩展ListActivity)
  • 对于应用栏,我正在使用支持库1。这正确加载,我没有任何其他菜单项的问题。这是代码:
      

    toolbar =(工具栏)findViewById(R.id.list_toolbar);       setSupportActionBar(栏);

的AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="etchee.com.weightlifty">

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="25" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_app_logo"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <meta-data
            android:name="android.app.default_searchable"
            android:value=".Search.SearchResultsActivity">

        </meta-data>

        <activity
            android:name=".Activity.MainActivity"
            android:label="@string/app_name">

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name=".data.DBviewer" />

        <activity
            android:name=".Search.SearchResultsActivity"
            android:label="@string/input_event"
            android:launchMode="singleTop">

            <meta-data
                android:name="android.app.default_searchable"
                android:resource="@xml/searchable" />
        </activity>



        <activity android:name=".Activity.ListActivity"
            android:theme="@style/Theme.AppCompat.Light.NoActionBar">

            <meta-data
                android:name="android.app.default_searchable"
                android:value=".Search.SearchResultsActivity" />

            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>

        </activity>

        <provider
            android:name=".Search.SuggestionProvider"
            android:authorities="suggestionProviderAuthority"
            android:syncable="false" />

        <activity android:name=".Activity.EditEventActivity" />
        <activity android:name=".Activity.ChooseEventActivity" />

        <provider
            android:name=".data.DataProvider"
            android:authorities="etchee.com.weightlifty"
            android:exported="false" />
    </application>

</manifest>
来自ListActivity.java

与选项相关的代码:

    private void deleteOptionRed(Menu menu) {
        //set delete menu text to red color
        MenuItem delete_all_events = menu.findItem(R.id.menu_delete_all_events);
        SpannableString string = new SpannableString(delete_all_events.getTitle());
        string.setSpan(
                new ForegroundColorSpan(ContextCompat.getColor(ListActivity.this, R.color.colorPrimary)),
                0,
                string.length(),
                Spanned.SPAN_PRIORITY);

        delete_all_events.setTitle(string);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        deleteOptionRed(menu);
        return super.onPrepareOptionsMenu(menu);
    }


    /**
     *  When creating the option, define the searchView. 
     * @param menu menu layout
     * @return  true
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_list, menu);

        searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        searchView = (SearchView) menu.findItem(R.id.action_search_button).getActionView();

        ComponentName componentName = new ComponentName(getApplicationContext(), ListActivity.class);

        //checking logger
        if (searchManager.getSearchableInfo(componentName) == null) {
            throw new IllegalArgumentException(TAG + ": getSearchableInfo() returns null. " +
                    "Cannot start search");
        }

        //Get searchableInfo Object created from the searchable.xml config file
        searchView.setSearchableInfo(searchManager.getSearchableInfo(componentName));
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {

            case R.id.action_search_button:
//                Intent intent = new Intent(Intent.ACTION_SEARCH);
//                intent.putExtra(SearchManager.QUERY, "Test");
                onSearchRequested();
//                startActivity(intent);
                break;

            case R.id.menu_delete_all_events:
                int numOfDeletedRows = deleteEventTable();
                Toast.makeText(ListActivity.this, String.valueOf(numOfDeletedRows) + " deleted.",
                        Toast.LENGTH_SHORT).show();
                break;
            case R.id.menu_insert_event:
                event_insertDummyValues();
                break;

            case R.id.menu_view_tables:
                Intent intent = new Intent(getApplicationContext(), DBviewer.class);
                startActivity(intent);
                break;
        }
        return super.onOptionsItemSelected(item);
    }

menu_list,在ListActivity中用于从以下位置获取菜单资源:

<?xml version="1.0" encoding="utf-8"?>

<item android:id="@+id/action_search_button"
    android:title="@string/search_events"
    android:icon="@drawable/ic_add_list"
    app:showAsAction="ifRoom|collapseActionView"
    app:actionViewClass="android.support.v7.widget.SearchView" />

<item
    android:title="@string/insert_event_values"
    android:id="@+id/menu_insert_event"
    app:showAsAction="never"
    />

<item android:title="@string/view_tables"
    android:id="@+id/menu_view_tables"
    app:showAsAction="never" />

<item
    android:title="@string/delete_all_events"
    android:id="@+id/menu_delete_all_events"
    app:showAsAction="never" />

最后,我的 searchable.xml配置文件。 (它在res / xml下。我确定了。)

    <?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_name"
    android:hint="@string/hint_search_events"
    android:searchSuggestAuthority="@string/suggestion_provider_authority"
    >
</searchable>

1 个答案:

答案 0 :(得分:0)

试试这个:

创建一个菜单 search_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<item
    android:id="@+id/action_search"
    android:title="@string/search"
    android:icon="@drawable/search"
    android:orderInCategory="100"
    app:actionViewClass="android.support.v7.widget.SearchView"
    app:showAsAction="always" />
</menu>

在列表活动中对此菜单进行充气

活动类:

`implements SearchView.OnQueryTextListener`

然后:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.search, menu);

    final MenuItem item = menu.findItem(R.id.action_search);

    MenuItemCompat.expandActionView(item);

    final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);

    searchView.setQueryHint(getString(R.string.search_orders));

    searchView.setOnQueryTextListener(this);

    return true;
}

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

@Override
public boolean onQueryTextChange(String newText) {

    if (newText.equals("")){
        initProductCatalog();
        return true;
    }else{
        final List<ProductItemObject> filteredModelList = filter(productItemObjects, newText);

        itemsAdapter.notifyDataSetChanged();
        mRecyclerView.setAdapter(itemsAdapter);
        itemsAdapter.animateTo(filteredModelList);
        mRecyclerView.scrollToPosition(0);
        return true;
    }
}

private List<ProductItemObject> filter(List<ProductItemObject> models, String query) {

    query = query.toLowerCase();

    final List<ProductItemObject> filteredModelList = new ArrayList<>();

    if(query.equals("")) { return productItemObjects; }

    for (ProductItemObject model : models) {
        final String text = model.getName().toLowerCase();
        if (text.contains(query)) {
            filteredModelList.add(model);
        }
    }
    return filteredModelList;
}

现在,你的适配器就是魔术发生的地方:

请记住用您自己的变量组件替换它们。我也在这里使用RecyclerViewer,而不是旧的列表视图:

适配器

public class ProductItemsAdapter extends RecyclerView.Adapter<ProductViewHolder>{

private List<ProductItemObject> products;
private Context context;

public ProductItemsAdapter(List<ProductItemObject> products, Context context) {
    this.products = products;
    this.context = context;
}

@Override
public ProductViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.product_catalog_card, parent, false);

    return new ProductViewHolder(view);
}

@Override
public void onBindViewHolder(ProductViewHolder holder, int position) {
    holder.name.setText(products.get(position).getName());
    holder.prices.setText(products.get(position).getPrice());

    Picasso.with(context)
            .load(products.get(position).getUrl())
            .placeholder(R.drawable.fry_mate_cooking)
            .centerCrop()
            .resize(100, 100)
            .error(R.drawable.product_sample)
            .into(holder.image);
}

public ProductItemObject get(int position){
    return products.get(position);
}

public void remove(int position){
    products.remove(position);
    notifyDataSetChanged();
}

@Override
public int getItemCount() {
    return products.size();
}

public ProductItemObject getItem(int position){
    return products.get(position);
}

public void setModels(List<ProductItemObject> orders){
    products = new ArrayList<>(orders);
}

public void animateTo(List<ProductItemObject> models) {
    applyAndAnimateRemovals(models);
    applyAndAnimateAdditions(models);
    applyAndAnimateMovedItems(models);
}

private void applyAndAnimateRemovals(List<ProductItemObject> newModels) {
    for (int i = products.size() - 1; i >= 0; i--) {
        final ProductItemObject model = products.get(i);
        if (!newModels.contains(model)) {
            removeItem(i);
        }
    }
}

private void applyAndAnimateAdditions(List<ProductItemObject> newModels) {
    for (int i = 0, count = newModels.size(); i < count; i++) {
        final ProductItemObject model = newModels.get(i);
        if (!products.contains(model)) {
            addItem(i, model);
        }
    }
}

private void applyAndAnimateMovedItems(List<ProductItemObject> newModels) {
    for (int toPosition = newModels.size() - 1; toPosition >= 0; toPosition--) {
        final ProductItemObject model = newModels.get(toPosition);
        final int fromPosition = products.indexOf(model);
        if (fromPosition >= 0 && fromPosition != toPosition) {
            moveItem(fromPosition, toPosition);
        }
    }
 }

 private ProductItemObject removeItem(int position) {
    final ProductItemObject model = products.remove(position);
    notifyItemRemoved(position);
    return model;
 }

 private void addItem(int position, ProductItemObject model) {
    products.add(position, model);
    notifyItemInserted(position);
 }

  private void moveItem(int fromPosition, int toPosition) {
    final ProductItemObject model = products.remove(fromPosition);
    products.add(toPosition, model);
    notifyItemMoved(fromPosition, toPosition);
  }
}

照常创建视图

public class ProductViewHolder extends RecyclerView.ViewHolder{

  @BindView(R.id.product_image)
  CircleImageView image;

  @BindView(R.id.product_name)
  SalesLifeTextView name;

  @BindView(R.id.price)
  SalesLifeTextView prices;

  @BindView(R.id.buy)
  CircleImageView buy;

  public ProductViewHolder(View itemView) {
    super(itemView);

    ButterKnife.bind(this, itemView);
  }
}

最后,在我的案例中创建一个java类(POJO)来表示 ProductItemObject

此代码可让您只使用操作栏搜索图标搜索列表中的项目。

这是很多代码,但一旦你开始工作,你会很高兴你做到了!