Android:使用AppCompatAutoCompleteTextView

Let's take a look at the effect achieved.
[The external link image transfer failed, the source site may have an anti-leech mechanism, it is recommended to save the image and upload it directly (img-MUbDEIhT-1614134109259)(https://img-blog.csdn.net /20161219001816589?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbmV3X0FpZGVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) [The source site may fail to save the chain image, anti-theft mechanism It is recommended to save the picture and upload it directly (img-exmfZ1S3-1614134109262)(https://img-blog.csdn.net/20161219001827886?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbmV3X0FpZGVu/font/5a6L5L2T/font0size=400 /dissolve/70/gravity/SouthEast)]

It is the automatic prompt function as we say . Here I realized that when clicking AppCompatAutoCompleteTextView, a prompt box will pop up, and the prompt box will be displayed when no content is entered. Here is mainly familiar with the usage. There are many more APIs, please understand by yourself. . .

Because the content suggested in the example is Language, the class
Language.java is created

public class Language {
    public String name;
    public int icon;
}

The layout file item.xml of the child item. It seems very simple here.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:gravity="center_vertical"
        android:layout_weight="1"
        android:id="@+id/name"
        android:layout_width="0dp"
        android:layout_height="50dp" />

    <ImageView
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_weight="1"
        android:id="@+id/icon"/>
</LinearLayout>

Activity layout file activity_main.xml

<com.test.MyAutoCompleteTextView 
    xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/tv_test"
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:dropDownHeight="200dp"
        android:hint="language" />

Why do you need to inherit AppCompatAutoCompleteTextView? It is because when the system comes with AppCompatAutoCompleteTextView to prompt, the content length of the input box must be at least greater than 1. But sometimes we need to give a prompt without entering content, so we need to rewrite AppCompatAutoCompleteTextView.

MyAutoCompleteTextView .java

public class MyAutoCompleteTextView extends AppCompatAutoCompleteTextView  {

    public MyAutoCompleteTextView(Context context) {
        super(context);
    }

    public MyAutoCompleteTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyAutoCompleteTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean enoughToFilter() {
        return true;
    }
}

In fact, it shows that the MyAutoCompleteTextView class is a bit redundant, that is, it rewrites the enoughToFilter() method and always returns true. If you are interested, you can take a look at what AutoCompleteTextView that comes with it returns.

Then we write Adapter for MyAutoCompleteTextView. Use ArrayAdapter directly here. In fact, if there are no special needs, ArrayAdapter can meet our great needs. In fact, the above functions definitely need to use Filter (filtering function). The ArrayAdapter has declared to implement the Filterable interface. But in order to better understand the function, I still declare to implement the Filterable interface.
MyAdapter.java
first needs to declare several variables

// 经过过滤的数组
private ArrayList<Language> languages;
// 没有经过过滤的数组
private ArrayList<Language> origin;
private Context context;
private int layoutId;

The core variables are languages ​​and origin.

The constructor assigns values ​​to these variables in turn.

	public MyAdapter(Context context, int resource, ArrayList<Language> languages) {
        super(context, resource);
        this.languages = languages;
        this.origin = languages;
        this.context = context;
        this.layoutId = resource;
    }

It is best to rewrite two methods here, one is getItem() and the other is getCount(). If you do not write, it may cause no display

	@Override
    public Language getItem(int position) {
        return languages == null ? null : languages.get(position);
    }

    @Override
    public int getCount() {
        return languages == null ? 0 : languages.size();
    }

In order to achieve caching, we must write the getView method. So we have to define viewHolder first, as the inner class of MyAdapter

	private class ViewHolder {
        TextView name;
        ImageView icon;
    }

Okay, write getView()

	@NonNull
    @Override
    public View getView(int position, View convertView, @NonNull ViewGroup parent) {
        ViewHolder holder;

        if(null == convertView) {
            convertView = LayoutInflater.from(context).inflate(layoutId, parent, false);
            holder = new ViewHolder();
            holder.name = (TextView) convertView.findViewById(R.id.name);
            holder.icon = (ImageView) convertView.findViewById(R.id.icon);
            convertView.setTag(holder);
        }
        else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.name.setText(languages.get(position).name);
        holder.icon.setBackgroundResource(languages.get(position).icon);
        return convertView;
    }

Realize view reuse through the setTag and getTag methods that come with the view.
As mentioned earlier, the declaration of MyAdapter is like this

public class MyAdapter extends ArrayAdapter implements Filterable

To rewrite the getFilter () method.
Let's customize the Filter first

	private class MyFilter extends Filter {

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();
            if(null == constraint || 0 == constraint.length()) {
                constraint = "";
            }
            // 这里做一些简单的过滤
            String condition = String.valueOf(constraint).toLowerCase();
            List<Language> temp = new ArrayList<>();
            for (Language language : origin) {
                if (language.name.toLowerCase().contains(condition)) {
                    temp.add(language);
                }
            }
            results.values = temp;
            results.count = temp.size();
            // 返回的results会在publishResult()函数中得到
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            languages = (ArrayList<Language>) results.values;
            // 更新视图
            notifyDataSetChanged();
        }
    }

This is simple, just return a MyFilter object from the getFilter() method.

	public Filter getFilter() {
        return new MyFilter();
    }

Well, the above words, MyAdapter is completed.
Then we can use it in Activity.
MainActivity.java

// 初始化数据
		final ArrayList<Language> languages = new ArrayList<>();
        Language one = new Language();
        one.name = "Java";
        one.icon = R.mipmap.java;
        languages.add(one);

        Language two = new Language();
        two.name = "c";
        two.icon = R.mipmap.c;
        languages.add(two);

        Language three = new Language();
        three.name = "Python";
        three.icon = R.mipmap.python;
        languages.add(three);

        Language four = new Language();
        four.name = "gradle";
        four.icon = R.mipmap.gradle;
        languages.add(four);

        Language five = new Language();
        five.name = "php";
        five.icon = R.mipmap.php;
        languages.add(five);

        Language six = new Language();
        six.name = "groovy";
        six.icon = R.mipmap.groovy;
        languages.add(six);

The above icons are all downloaded by myself, so I downloaded some at will.

Use Adapter

		MyAdapter myAdapter = new MyAdapter(this, R.layout.item, languages);
        final MyAutoCompleteTextView textView = (MyAutoCompleteTextView) this.findViewById(R.id.tv_test);
        textView.setAdapter(myAdapter);

In order to further improve the interaction process, clicking MyAutoCompleteTextView should also pop up the prompt content.

		textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                textView.showDropDown();
            }
        });

Also, the sub-items of MyAutoCompleteTextView should also be displayed when they are clicked? The good news is that MyAutoCompleteTextView has a setOnItemClickListener method, which is a bit similar to ListView

		textView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Language language = myAdapter.getItem(position);
                textView.setText(language.name);
            }
        });

Finally, why use AppCompatAutoCompleteTextView instead of AutoCompleteTextView here. Because AppCompatAutoCompleteTextView is more compatible with a good version of the Android system, so use AppCompatAutoCompleteTextView

As for AppCompatAutoCompleteTextView, there are other powerful functions, you need to explore it yourself, know the basic usage, and the others should not be difficult.

To add, in fact, there is a ListPopupWindow inside AppCompatAutoCompleteTextView, and the content of the prompt is realized by ListPopupWindow. And ListPopupWindow can be understood as ListView+PopupWindow. In fact, that is to say, we can implement AppCompatAutoCompleteTextView by ourselves and customize a View, which contains an input box and PopupWindow, and there is a ListView in PopupWindow. . . If you don't consider compatibility issues, it shouldn't be too difficult to implement.

Guess you like

Origin blog.csdn.net/new_Aiden/article/details/53732000