Android AutoCompleteTextView实现自动补全

辛苦堆砌,转载请注明出处,谢谢!

最近工作用到了自动补全,这里做一个简单记录,首先上我们的布局

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:padding="20dp"
    tools:context="com.yjp.autocompletetextviewdemo.MainActivity">

    <AutoCompleteTextView
        android:id="@+id/auto_complete_text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:completionThreshold="2"
        android:layout_gravity="top" />
</FrameLayout>
只有我们的主角,这样更能突出主题,需要注意的是我们通过android:completionThreshold设置了只有输入两个以上文字,才会弹出自动补全框。其他属性可以从官方文档了解一下。


我们的示例主要通过在SQLite中模糊搜索来实现自动补全功能,先看看我们的SQLiteHelper

package com.yjp.autocompletetextviewdemo;

import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DbHelper extends SQLiteOpenHelper {

    //大学表
    public static final String SCHOOLS_TABLE_NAME = "table_schools";
    public static final String COL_SCHOOL_NAME = "school_name";

    private static final String DB_NAME = "auto_complete_text_view_app_db";
    private static final int DB_VERSION = 1;

    private static final String STRING_CREATE_SCHOOL_TABLE =
            "CREATE TABLE " + SCHOOLS_TABLE_NAME + " (_id INTEGER PRIMARY KEY AUTOINCREMENT, "
            + COL_SCHOOL_NAME + " TEXT);";

    public DbHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(STRING_CREATE_SCHOOL_TABLE);

        //伪造一些数据
        ContentValues cv = new ContentValues(1);
        cv.put(COL_SCHOOL_NAME, "大连理工大学");
        db.insert(SCHOOLS_TABLE_NAME, COL_SCHOOL_NAME, cv);

        cv.put(COL_SCHOOL_NAME, "太原理工大学");
        db.insert(SCHOOLS_TABLE_NAME, COL_SCHOOL_NAME, cv);

        cv.put(COL_SCHOOL_NAME, "天津理工大学");
        db.insert(SCHOOLS_TABLE_NAME, COL_SCHOOL_NAME, cv);

        cv.put(COL_SCHOOL_NAME, "河北工业大学");
        db.insert(SCHOOLS_TABLE_NAME, COL_SCHOOL_NAME, cv);

        cv.put(COL_SCHOOL_NAME, "天津大学");
        db.insert(SCHOOLS_TABLE_NAME, COL_SCHOOL_NAME, cv);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + STRING_CREATE_SCHOOL_TABLE);
    }
}
一个很简单的例子,数据库除了_id列只有一列,表示大学,而且我们伪造了一些数据。


然后看看我们需要一个CursorAdapter来给我们的AutoCompleteTextView使用,如下所示

package com.yjp.autocompletetextviewdemo;

import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.TextView;

public class AutoCompleteAdapter extends CursorAdapter {

    public AutoCompleteAdapter(Context context) {
        super(context, null, 0);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        LayoutInflater inflater = LayoutInflater.from(context);
        TextView view = (TextView) inflater.inflate(
                android.R.layout.simple_dropdown_item_1line, parent, false);
        return view;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        ((TextView) view).setText(cursor.getString(cursor.getColumnIndex(DbHelper.COL_SCHOOL_NAME)));
    }
}
依然很简单,我们使用了Android提供的布局,显示我们自动补全的弹出框的行,这也是AutoCompleteTextView默认使用的,如果应用场景不像我这里描述的复杂,只要AutoCompleteTextView调用setAdapter设置一个ArrayAdapter即可,ArrayAdapter关联的数据就会显示在弹出框中。


最后,看看我们的MainActivity

package com.yjp.autocompletetextviewdemo;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
import android.widget.FilterQueryProvider;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private AutoCompleteTextView mAutoCompleteTextView;

    //一定要使用一个成员变量,不然DbHelper内存回收会导致DB无法使用
    private DbHelper mDbHelper;
    private SQLiteDatabase mDb;

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

        mAutoCompleteTextView = (AutoCompleteTextView) findViewById(R.id.auto_complete_text_view);

        //实际上设置的是弹出的列表的OnItemClickListener
        //另外千万注意,不要使用OnItemSelectedListener
        //看源码中该监听器虽然可以设置,但是没有用到
        mAutoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                //这里设置文本值,否则默认显示赋值的文本是Cursor的toString()
                TextView textView = (TextView) view;
                mAutoCompleteTextView.setText(textView.getText());
            }
        });

        AutoCompleteAdapter adapter = new AutoCompleteAdapter(this);

        //这里设置FilterQueryProvider可以自定义自己的Cursor创建逻辑
        //而不是使用默认设置给Adapter的Cursor,实现动态处理
        adapter.setFilterQueryProvider(new FilterQueryProvider() {
            @Override
            public Cursor runQuery(CharSequence constraint) {
                if (constraint == null || constraint.length() == 0) {
                    return null;
                }

                //模糊查找,千万加入_id列,否则无法正常使用
                return mDb.rawQuery("SELECT _id," + DbHelper.COL_SCHOOL_NAME
                        + " FROM " + DbHelper.SCHOOLS_TABLE_NAME
                        + " WHERE " + DbHelper.COL_SCHOOL_NAME
                        + " LIKE \'%" + constraint.toString() +"%\'", null);
            }
        });
        mAutoCompleteTextView.setAdapter(adapter);
    }

    @Override
    protected void onStart() {
        super.onStart();
        mDbHelper = new DbHelper(this);

        //使用getWritableDatabase,如果表不存在会自动创建
        mDb = mDbHelper.getWritableDatabase();
    }

    @Override
    protected void onStop() {
        super.onStop();

        //资源回收
        mDb.close();
        mDbHelper.close();
    }
}
注释已经尽可能详细了,大家可以看一下,这样,我们就实现了AutoCompleteTextView的自动补全。如下图所示


可以看到,实现了我们最初的设想,另外,从这次使用中,也总结了一些经验,遇到问题,查看官方文档,有些文档中没有写的,自己去尝试。当时遇到问题,点选提示框中的一项时,发现没有显示提示框条目中的内容,而是显示了Cursor的地址信息,很显然是Cursor的toString的结果,所以想到,需要对点选之后的内容进行转换,当时尝试设置OnItemSelectedListener,但是发现没有用处,之后查看AutoCompleteTextView源码才发现,这个监听器,实现中使用一个成员变量保存了,但是没有任何地方调用,不过发现OnItemClickListener被调用,因此改而使用OnItemClickListener。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值