2

我正在尝试显示我的自定义搜索框建议,但我收到的结果是空的。我遵循了一些指南来实现此功能,即:

这导致了以下代码:

添加搜索框:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getSupportMenuInflater().inflate(R.menu.building_search, menu);

    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    SearchView searchView = new SearchView(getSupportActionBar().getThemedContext());

    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
    searchView.setSuggestionsAdapter(new BuildingSuggestionsAdapter(this, searchManager.getSearchableInfo(getComponentName()), searchView));

    return super.onCreateOptionsMenu(menu);
}

将建筑物添加到我的数据库中:

for (Resto resto : restos) {
    ContentValues values = new ContentValues();
    values.put(TableBuildings.Buildings.NAME, resto.name);
    values.put(TableBuildings.Buildings.DISTANCE, "3");
    getContentResolver().insert(TableBuildings.Buildings.CONTENT_URI, values);
}

BuildingSuggestionAdapter:

public class BuildingSuggestionsAdapter extends CursorAdapter {

    private static final int QUERY_LIMIT = 50;
    private LayoutInflater inflater;
    private SearchView searchView;
    private SearchableInfo searchable;

    public BuildingSuggestionsAdapter(Context context, SearchableInfo info, SearchView searchView) {
        super(context, null, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        this.searchable = info;
        this.searchView = searchView;
        this.inflater = LayoutInflater.from(context);
    }

    @Override
    public void bindView(View v, Context context, Cursor c) {
        String name = c.getString(c.getColumnIndex(TableBuildings.Buildings.NAME));
        TextView namet = (TextView) v.findViewById(R.id.resto_search_name);
        namet.setText(name);

        String man = c.getString(c.getColumnIndex(TableBuildings.Buildings.DISTANCE));
        TextView manuf = (TextView) v.findViewById(R.id.resto_search_distance);
        manuf.setText(man);

        Toast.makeText(context, name + " " + man, Toast.LENGTH_LONG).show();
    }

    @Override
    public View newView(Context arg0, Cursor arg1, ViewGroup arg2) {
        return this.inflater.inflate(R.layout.resto_search_suggestion_view, null);
    }

    /**
     * Use the search suggestions provider to obtain a live cursor. This will be called in a worker
     * thread, so it's OK if the query is slow (e.g. round trip for suggestions). The results will
     * be processed in the UI thread and changeCursor() will be called.
     */
    @Override
    public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
        String query = (constraint == null) ? "" : constraint.toString();
        /**
         * for in app search we show the progress spinner until the cursor is returned with the
         * results.
         */
        Cursor cursor = null;
        if (searchView.getVisibility() != View.VISIBLE
            || searchView.getWindowVisibility() != View.VISIBLE) {
            return null;
        }
        try {
            cursor = getSuggestions(searchable, query, QUERY_LIMIT);
            // trigger fill window so the spinner stays up until the results are copied over and
            // closer to being ready
            if (cursor != null) {
                cursor.getCount();
                return cursor;
            }
        } catch (RuntimeException e) {
        }
        // If cursor is null or an exception was thrown, stop the spinner and return null.
        // changeCursor doesn't get called if cursor is null
        return null;
    }


    public Cursor getSuggestions(SearchableInfo searchable, String query, int limit) {

        if (searchable == null) {
            return null;
        }

        String authority = searchable.getSuggestAuthority();
        if (authority == null) {
            return null;
        }

        Uri.Builder uriBuilder = new Uri.Builder()
            .scheme(ContentResolver.SCHEME_CONTENT)
            .authority(authority)
            .query("")
            .fragment("");

        // if content path provided, insert it now
        final String contentPath = searchable.getSuggestPath();
        if (contentPath != null) {
            uriBuilder.appendEncodedPath(contentPath);
        }

        // append standard suggestion query path
        uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY);

        // get the query selection, may be null
        String selection = searchable.getSuggestSelection();
        // inject query, either as selection args or inline
        String[] selArgs = null;
        if (selection != null) {    // use selection if provided
            selArgs = new String[]{query};
        } else {                    // no selection, use REST pattern
            uriBuilder.appendPath(query);
        }

        if (limit > 0) {
            uriBuilder.appendQueryParameter("limit", String.valueOf(limit));
        }

        Uri uri = uriBuilder.build();

        // finally, make the query
        return mContext.getContentResolver().query(uri, null, selection, selArgs, null);
    }
}

提供者:

public class BuildingSuggestionProvider extends ContentProvider {

    private SQLiteDatabase sqlDB;
    private DatabaseHelper dbHelper;
    private static final String DATABASE_NAME = "Buildings.db";
    private static final int DATABASE_VERSION = 1;
    private static final String TABLE_NAME = "Buildings";

    private static class DatabaseHelper extends SQLiteOpenHelper {

        DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            //create table to store user names
            db.execSQL("Create table " + TABLE_NAME + "( _id INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, DISTANCE TEXT);");
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
            onCreate(db);
        }
    }

    @Override
    public int delete(Uri uri, String s, String[] as) {
        return 0;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues contentvalues) {
        // get database to insert records
        sqlDB = dbHelper.getWritableDatabase();
        // insert record in user table and get the row number of recently inserted record
        long rowId = sqlDB.insert(TABLE_NAME, "", contentvalues);
        if (rowId > 0) {
            Uri rowUri = ContentUris.appendId(TableBuildings.Buildings.CONTENT_URI.buildUpon(), rowId).build();
            getContext().getContentResolver().notifyChange(rowUri, null);
            return rowUri;
        }
        throw new SQLException("Failed to insert row into " + uri);
    }

    @Override
    public boolean onCreate() {
        dbHelper = new DatabaseHelper(getContext());
        return (dbHelper == null) ? false : true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        qb.setTables(TABLE_NAME);
        Cursor c = qb.query(db, projection, selection, null, null, null, sortOrder);
        c.setNotificationUri(getContext().getContentResolver(), uri);
        return c;
    }

    @Override
    public int update(Uri uri, ContentValues contentvalues, String s, String[] as) {
        return 0;
    }
}

餐桌建筑:

import android.net.Uri;
import android.provider.BaseColumns;
public class TableBuildings {

    public static final String AUTHORITY = "be.ugent.zeus.hydra.ui.map.suggestions.BuildingSuggestionProvider";

    // BaseColumn contains _id.
    public static final class Buildings implements BaseColumns {

        public static final Uri CONTENT_URI = Uri.parse("content://be.ugent.zeus.hydra.ui.map.suggestions.BuildingSuggestionProvider");
        // Table column
        public static final String NAME = "NAME";
        public static final String DISTANCE = "DISTANCE";
    }
}

最后是用于定义搜索框的 XML,然后是我的应用程序中用于提供程序的 xml:

<?xml version="1.0" encoding="UTF-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
            android:label="@string/resto_search_label"
            android:hint="@string/resto_search_hint" 
            android:searchSuggestAuthority="be.ugent.zeus.hydra.ui.map.suggestions.BuildingSuggestionProvider" />



<provider
            android:name=".ui.map.suggestions.BuildingSuggestionProvider"
            android:authorities="be.ugent.zeus.hydra.ui.map.suggestions.BuildingSuggestionProvider" />

我得到的结果如下:没有错误;它打开 searchview 并查询 contentprovider。奇怪的是,Provider 中的查询方法被调用,但它没有从适配器调用,例如,当我放置断点时,我的程序不会停止。视觉上,我的键盘弹出,我看到一个列表,但列表只包含空项目......

有人有什么主意吗?

提前致谢。

4

1 回答 1

0

我知道这已经很晚了,但我遇到了同样的问题,并通过使用SearchManager类提供的常量作为我数据库中的列名解决了这个问题。请参阅Android 开发者网站上的搜索教程

SUGGEST_COLUMN_TEXT_1是您特别需要的这是 ContentProvider 需要在结果 ListView 中显示的主要文本以及它将搜索的内容。

于 2015-08-17T08:48:34.917 回答