Android控件与布局——基础控件AutoCompleteTextView与MultiAutoCompleteTextView

        最近在用原生的控件和布局绘制一些界面并使用,虽然这些都是Android基本知识,但是有的时候真的感觉力不从心,感觉有必要对Android常用的控件和布局做一个系统的了解。后续一个月甚至更多的时间都会围绕这个主题展开,毕竟这里面还是有不少高级控件的,我也会尽量结合应用深入的进行了解。

项目GitHub地址入口

上一篇:EditText    下一篇:ImageView

在上一篇中,我们介绍了非常重要的一个控件EditText,今天我们来介绍一下它的子类AutoCompleteTextView,还是一样,首先看一下官方文档对其的描述:

* <p>An editable text view that shows completion suggestions automatically
* while the user is typing. The list of suggestions is displayed in a drop
* down menu from which the user can choose an item to replace the content
* of the edit box with.</p>
*
* <p>The drop down can be dismissed at any time by pressing the back key or,
* if no item is selected in the drop down, by pressing the enter/dpad center
* key.</p>

一个可以实现自动补全功能的EditText,自动补全的数据通过一个下拉弹窗显示,用户可以选择提示内容替换掉EditText中的内容。下拉弹窗可以通过按返回键或者下拉弹窗中没有选中项时按下enter实现。

上面说的其实已经比较清楚了,就是根据你当前的输入自动下拉显示你可以或者想要输入的内容,当然弹出的内容你的提前编辑好并且添加进去。下面接着看:

* <p>The list of suggestions is obtained from a data adapter and appears
* only after a given number of characters defined by
* {@link #getThreshold() the threshold}.</p>
*
* <p>The following code snippet shows how to create a text view which suggests
* various countries names while the user is typing:</p>

弹出的提示数据来自于你设置的适配器,并且是在一定的输入字符过后才会有提示,这个字符数量可以通过setThreshold()来设置,也可以通过getThreshold()来查看当前的设置。下面的代码演示的具体的实现

好了,下面就来具体看看具体的代码实现(先看摘自文档的内容):

*         ArrayAdapter&lt;String&gt; adapter = new ArrayAdapter&lt;String&gt;(this,
*                 android.R.layout.simple_dropdown_item_1line, COUNTRIES);
*         AutoCompleteTextView textView = (AutoCompleteTextView)
*                 findViewById(R.id.countries_list);
*         textView.setAdapter(adapter);
*     }
*
*     private static final String[] COUNTRIES = new String[] {
*         "Belgium", "France", "Italy", "Germany", "Spain"
*     };

上面的代码很简单

  • 初始化构建适配器所需的数据
  • 构建AutoCompleteTextView的适配器ArrayAdaptor实例
  • AutoCompleteTextView添加适配器即可

说了那么多,我们就来看看AutoCompleteTextView展示样式:

 <AutoCompleteTextView
        android:id="@+id/autoCompleteTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:dropDownSelector="@color/colorPrimary"
        android:hint="Please edit your country" />
        autoCompleteTextView=findViewById(R.id.autoCompleteTextView);
        ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,
        android.R.layout.simple_dropdown_item_1line,
        getResources().getStringArray(R.array.country_array));
        autoCompleteTextView.setAdapter(adapter);

运行的结果:

上面就是AutoCompleteTextView的使用方式和展示样式了,那我们看看有哪些重要属性需要学习了,我们的参考还是文档描述:

* @attr ref android.R.styleable#AutoCompleteTextView_completionHint:推荐选项提示
* @attr ref android.R.styleable#AutoCompleteTextView_completionThreshold:最少开始提示字符数目
* @attr ref android.R.styleable#AutoCompleteTextView_completionHintView:推荐提示的View
* @attr ref android.R.styleable#AutoCompleteTextView_dropDownSelector:下拉选中项背景
* @attr ref android.R.styleable#AutoCompleteTextView_dropDownWidth:下拉框宽度
* @attr ref android.R.styleable#AutoCompleteTextView_dropDownHeight:下拉框高度
* @attr ref android.R.styleable#ListPopupWindow_dropDownVerticalOffset:垂直上下边距
* @attr ref android.R.styleable#ListPopupWindow_dropDownHorizontalOffset:水平左右边距

我们就按照上面的一个一个展开学习,首先看第一个

@attr ref android.R.styleable#AutoCompleteTextView_completionHint:推荐选项提示

在控件的具体属性中我们可以通过XML或者接口实现设置:

 android:completionHint="你是不是要找China?"
或者
 autoCompleteTextView.setCompletionHint("你是不是要找China?");

如果感觉单词的文本提示不好看,可以通过以下属性来设置View实现推荐的效果

@attr ref android.R.styleable#AutoCompleteTextView_completionHintView:推荐提示的View

使用方式是通过xml实现

android:completionHintView="@layout/hint_view_layout"

关于这个属性有一些需要注意的地方,我们首先看一下AutoCompleteTextView的部分源码

 private TextView mHintView;
 public void setCompletionHint(CharSequence hint) {
        mHintText = hint;
        if (hint != null) {
            if (mHintView == null) {//如果mHintView为null
                final TextView hintView = (TextView) LayoutInflater.from(mPopupContext).inflate(
                        mHintResource, null).findViewById(R.id.text1);//找到mHintResource中id为text1的TextView
                hintView.setText(mHintText);
                mHintView = hintView;//赋值给mHintView
                mPopup.setPromptView(hintView);//弹出自定义的TextView
            } else {
                mHintView.setText(hint);
            }
        } else {
            mPopup.setPromptView(null);
            mHintView = null;
        }
    }

可见,我们设置的这个completionHintView本质是一个TextView,且id必须为text1的id,否则就会报空指针异常。具体的解释可参照AutocompleteTextview and CompletionHintView

从上面看出,我们至少要输入两个字符才会有提示,我们可以通过第二个属性进行设置,方式有以下两种:

android:completionThreshold="1"
或者
autoCompleteTextView.setThreshold(1);

好了,我们接着往下看

 @attr ref android.R.styleable#AutoCompleteTextView_dropDownSelector:下拉选中项背景

使用方式:

android:dropDownSelector="@color/colorPrimary"

好了,从上面我们可以看到,当推荐的内容过多时,下拉框的高度太高,影响用户体验,我们可以通过下面两个属性对下拉框的尺寸进行设置

* @attr ref android.R.styleable#AutoCompleteTextView_dropDownWidth:下拉框宽度

* @attr ref android.R.styleable#AutoCompleteTextView_dropDownHeight:下拉框高度

使用方式:

        android:dropDownHeight="300dp"
        android:dropDownWidth="200dp"
或者
        autoCompleteTextView.setDropDownHeight(300);
        autoCompleteTextView.setDropDownWidth(200);

最后两个时设置边距的属性,使用方式如下:

        autoCompleteTextView.setDropDownHorizontalOffset(50);
        autoCompleteTextView.setDropDownVerticalOffset(50);

可见,这是下拉框相对于EditText的边距,看一下源码解释就知道了(水平间距接口)

* <p>Sets the horizontal offset used for the auto-complete drop-down list.</p>

好了,到这里,关于AutoCompleteTextView的介绍就到这里了,下面我们接着把MultiAutoCompleteTextView也随带介绍一下,官方文档描述如下:

* An editable text view, extending {@link AutoCompleteTextView}, that
* can show completion suggestions for the substring of the text where
* the user is typing instead of necessarily for the entire thing.
* <p>
* You must provide a {@link Tokenizer} to distinguish the
* various substrings.

一个扩展了AutoCompleteTextView的EditText,也是能够更加你输入的字符进行提示,且其选择的内容是追加在EditText文本后面。不是替换,新增加内容与之前内容可以通过设置Tokenizer来实现分割。

下面,我们直接看运行效果对比

  <MultiAutoCompleteTextView
        android:id="@+id/multiAutoCompleteTextView"
        android:dropDownSelector="@color/colorPrimary"
        android:hint="Please edit your hobbies"
        android:completionThreshold="1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
   ArrayAdapter<String> adapter1=new ArrayAdapter<String>(this,android.
                R.layout.simple_dropdown_item_1line,
                getResources().getStringArray(R.array.hobby_array));
        multiAutoCompleteTextView.setAdapter(adapter1);
        multiAutoCompleteTextView.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
        multiAutoCompleteTextView.setDropDownHorizontalOffset(50);
        multiAutoCompleteTextView.setDropDownVerticalOffset(50);

总结使用步骤也比较简单:

  • 初始化构建适配器所需的数据
  • 构建MultiAutoCompleteTextView的适配器ArrayAdaptor实例
  • MultiAutoCompleteTextView添加适配器
  • MultiAutoCompleteTextView设置分隔符(可以自定义样式)

下面我们就来自定义一个分隔符样式,因为上面采用的MultiAutoCompleteTextView类中自带的分隔符CommaTokenizer,我们想自定义,因为setTokenizer()接收的参数是一个MultiAutoCompleteTextView.Tokenizer的一个子类,所以我们自定义的分隔符类需要实现它,实现的方式我们结合上面使用的MultiAutoCompleteTextView.CommaTokenizer();具体代码如下:

package aoto.com.commonwidgetandlayout.basic_widget.autoText;

import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.widget.MultiAutoCompleteTextView;

/**
 * author:why
 * created on: 2019/6/5 14:34
 * description:
 */
public class SelfTokenizer implements MultiAutoCompleteTextView.Tokenizer {
    @Override
    public int findTokenStart(CharSequence text, int cursor) {
        int i = cursor;

        while (i > 0 && text.charAt(i - 1) != '-') {
            i--;
        }
        while (i < cursor && text.charAt(i) == ' ') {
            i++;
        }

        return i;
    }

    @Override
    public int findTokenEnd(CharSequence text, int cursor) {
        int i = cursor;
        int len = text.length();

        while (i < len) {
            if (text.charAt(i) == '-') {
                return i;
            } else {
                i++;
            }
        }

        return len;
    }

    @Override
    public CharSequence terminateToken(CharSequence text) {
        int i = text.length();

        while (i > 0 && text.charAt(i - 1) == ' ') {
            i--;
        }

        if (i > 0 && text.charAt(i - 1) == '-') {
            return text;
        } else {
            if (text instanceof Spanned) {
                SpannableString sp = new SpannableString(text + "-");
                TextUtils.copySpansFrom((Spanned) text, 0, text.length(),
                        Object.class, sp, 0);
                return sp;
            } else {
                return text + "-";
            }
        }
    }
}

使用效果如下:

主要代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="aoto.com.commonwidgetandlayout.basic_widget.autoText.AutoTextActivity">

    <AutoCompleteTextView
        android:id="@+id/autoCompleteTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:completionThreshold="1"
        android:dropDownSelector="@color/colorPrimary"
        android:hint="Please enter your country"
        android:lines="1"
        android:singleLine="true" />

    <MultiAutoCompleteTextView
        android:id="@+id/multiAutoCompleteTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:completionThreshold="1"
        android:dropDownSelector="@color/colorPrimary"
        android:hint="Please edit your birthday"
        android:lines="1"
        android:singleLine="true" />


</LinearLayout>
package aoto.com.commonwidgetandlayout.basic_widget.autoText;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.MultiAutoCompleteTextView;
import android.widget.TextView;

import java.util.ArrayList;

import aoto.com.commonwidgetandlayout.R;
import aoto.com.commonwidgetandlayout.basic_widget.checkedTextView.MyAdaptor;

/**
 * @author why
 * @date 2019-6-5 10:07:09
 */
public class AutoTextActivity extends AppCompatActivity {

    private static final String TAG = "AutoTextActivityWhy";
    AutoCompleteTextView autoCompleteTextView;
    MultiAutoCompleteTextView multiAutoCompleteTextView;
    private String content="";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_auto_text);
        autoCompleteTextView=findViewById(R.id.autoCompleteTextView);
        multiAutoCompleteTextView=findViewById(R.id.multiAutoCompleteTextView);
        ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,
                android.R.layout.simple_dropdown_item_1line,
                getResources().getStringArray(R.array.country_array));
        autoCompleteTextView.setAdapter(adapter);
        autoCompleteTextView.setDropDownHorizontalOffset(50);
        autoCompleteTextView.setDropDownVerticalOffset(50);
        ArrayAdapter<String> adapter1=new ArrayAdapter<String>(this,android.
                R.layout.simple_dropdown_item_1line,
                getResources().getStringArray(R.array.time_array));
        multiAutoCompleteTextView.setAdapter(adapter1);
        //multiAutoCompleteTextView.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
        multiAutoCompleteTextView.setTokenizer(new SelfTokenizer());

      multiAutoCompleteTextView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
          @Override
          public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
              content=multiAutoCompleteTextView.getText().toString();
              multiAutoCompleteTextView.setText(content.substring(0,content.lastIndexOf("-")));
              multiAutoCompleteTextView.setSelection(content.length()-1);
              return false;
          }
      });
    }
}

好了,端午节放假前的一天,终于写完了,还是有点累的,喜欢的扫码关注一波哟。

注:欢迎扫码关注

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值