1. 程式人生 > >AutoCompleteTextView實現歷史記錄提示

AutoCompleteTextView實現歷史記錄提示

今天心血來潮用as自動建立了一個登陸介面,一看xml佈局,臥槽原來google用的是AutoCompleteTextView來當賬號的控制元件的。馬上查資料,應用場景就很多了,比如歷史記錄提示、搜尋聯想、文字自動完成(郵箱自動下拉一堆@qq.com,@163.com字尾)等等。

言歸正傳,文字自動完成需要實現寫好字符集,搜尋聯想需要伺服器配合獲取資料,為了鞏固記憶,今天實現把使用者輸入的作為歷史記錄儲存,然後顯示。

效果圖:

佈局程式碼

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android
="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft
="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.yang.app.autocompletetextview.MainActivity">
<android.support.design.widget.TextInputLayout android:layout_width
="match_parent" android:layout_height="wrap_content">
<AutoCompleteTextView android:id="@+id/auto_main_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/hint" android:maxLines="1" android:singleLine="true" /> </android.support.design.widget.TextInputLayout> <Button android:background="#119999" android:layout_gravity="center" android:id="@+id/btn_main_save" android:layout_width="150dp" android:layout_height="wrap_content" android:text="save" /> </LinearLayout>

程式碼

public class MainActivity extends AppCompatActivity {

    private AutoCompleteTextView mAutoTv;
    private Button mBtnSave;

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

    private void initView() {
        mAutoTv = (AutoCompleteTextView) findViewById(R.id.auto_main_text);
        mBtnSave = (Button) findViewById(R.id.btn_main_save);
    }

    private void initData() {
        initHistory();
    }

    private void initEvent() {
        //有焦點時才會顯示記錄
        mAutoTv.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                AutoCompleteTextView view = (AutoCompleteTextView) v;
                if (hasFocus) {
                    SharedPreferences sp = getSharedPreferences("auto_text", MODE_PRIVATE);
                    String history = sp.getString("history", "");
                    //history不為空才顯示
                    if (!TextUtils.isEmpty(history))
                        view.showDropDown();
                }
            }
        });
        mBtnSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                saveHistory(mAutoTv);
            }
        });
    }

    /**
     * 初始化歷史記錄,最多顯示3項提示,採用sp儲存
     */
    int nearHistory = 3;//顯示記錄條數

    private void initHistory() {
        SharedPreferences sp = getSharedPreferences("auto_text", MODE_PRIVATE);
        String history = sp.getString("history", "");
        String[] hisArrays = history.split(",");
        ArrayAdapter<String> hisAdapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, hisArrays);
        //TODO:這個字串會越來越長,開發中最好提供清理歷史記錄的功能
        if (hisArrays.length > nearHistory) {
            String[] newArrays = new String[nearHistory];
            System.arraycopy(hisArrays, 0, newArrays, 0, nearHistory);
             //佈局可以自己建立,用android自帶的也行
            hisAdapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, newArrays);
        }
        mAutoTv.setAdapter(hisAdapter);//這裡要傳遞的adapter引數必須是繼承ListAdapter和Filterable的
//        mAutoTv.setDropDownHeight(350);//設定提示下拉框的高度,注意,這只是限制了提示下拉框的高度,提示資料集的個數並沒有變化
        mAutoTv.setThreshold(1);//當輸入一個字元時就開始搜尋歷史,預設是2個
        mAutoTv.setCompletionHint("最近的3條記錄");

//        TODO:一些AutoCompleteTextView的方法解釋
//        clearListSelection,去除selector樣式,只是暫時的去除,當用戶再輸入時又重新出現
//        dismissDropDown,關閉下拉提示框
//        enoughToFilter,這是一個是否滿足過濾條件的方法,sdk建議我們可以重寫這個方法
//        getAdapter,得到一個可過濾的列表介面卡
//        getDropDownAnchor,得到下拉框的錨計的view的id
//        getDropDownBackground,得到下拉框的背景色
//        setDropDownBackgroundDrawable,設定下拉框的背景色
//        setDropDownBackgroundResource,設定下拉框的背景資源
//        setDropDownVerticalOffset,設定下拉表垂直偏移量,即是list裡包含的資料項數目
//        getDropDownVerticalOffset ,得到下拉表垂直偏移量
//        setDropDownHorizontalOffset,設定水平偏移量
//        setDropDownAnimationStyle,設定下拉框的彈出動畫
//        getThreshold,得到過濾字元個數
//        setOnItemClickListener,設定下拉框點選事件
//        getListSelection,得到下拉框選中為位置
//        getOnItemClickListener。得到單項點選事件
//        getOnItemSelectedListener得到單項選中事件
//        getAdapter,得到那個設定的介面卡


    }

    /**
     * 把內容儲存到sp中
     */
    private void saveHistory(AutoCompleteTextView autoTv) {
        String text = autoTv.getText().toString();
        SharedPreferences sp = getSharedPreferences("auto_text", MODE_PRIVATE);
        String history = sp.getString("history", "");
        //先判斷是否已經存過一樣的文字
        if (!TextUtils.isEmpty(text)&&!history.contains(text + ",")) {
            StringBuilder sb = new StringBuilder(history);
            sb.insert(0, text + ",");//插入到第一個,代表最新
            sp.edit().putString("history", sb.toString()).apply();
            Toast.makeText(MainActivity.this, "存好了", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(MainActivity.this, "存過了", Toast.LENGTH_SHORT).show();
        }
    }
}

是不是很簡單,並沒有多少需要寫的。但是特別注意的是:控制元件的setAdapter()方法,引數必須是繼承ListAdapter和Filterable的,其中arrayAdapter和simpleAdapter都能滿足要求,推薦用arrayAdapter,simpleAdapte還要設定他的顯示位置和textview元件。

另外還查到了MultiAutoCompleteTextView,一個可支援選擇多個值(在多次輸入的情況下),分別用分隔符分開,並且在每個值選中的時候再次輸入值時會自動去匹配。這個可用在發簡訊,發郵件時選擇聯絡人這種型別當中。使用時需要執行設定分隔符方法。