Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android:使用AppCompatAutoCompleteTextView

Android:使用AppCompatAutoCompleteTextView

編輯:關於Android編程

Android:使用AppCompatAutoCompleteTextView:我們先看看實現的效果吧,也就是我們俗話說的自動提示功能。這裡我實現了點擊AppCompatAutoCompleteTextView就會彈出提示框,以及不輸入內容時也顯示提示框。這裡主要是熟悉用法。還有很多很多api,請大家自行了解。

 

因為例子中提示的內容是Language,所以就建立類了
Language.java

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

子項的布局文件item.xml。這裡就顯得很簡單了。



    

    

Activity布局文件activity_main.xml

為什麼需要繼承AppCompatAutoCompleteTextView呢?是因為系統自帶的AppCompatAutoCompleteTextView給提示的時候,輸入框的內容長度至少要大於1。但是我們有時候是需要不輸入內容就給出提示的,所以就需要重寫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;
    }
}

其實又顯示MyAutoCompleteTextView 類有點冗余了,也就是重寫了enoughToFilter()方法,一直返回true。有興趣的,可以看看自帶的AutoCompleteTextView 返回的是什麼。

接著我們為MyAutoCompleteTextView寫Adapter了。這裡直接使用ArrayAdapter好了。其實如果沒有特殊需求,ArrayAdapter能滿足我們很大的需求。其實上述功能肯定是需要用到Filter的(過濾功能)。而ArrayAdapter已經申明了實現Filterable接口了。不過為了更好的理解功能,我還是聲明實現Filterable接口。
MyAdapter.java
首先需要聲明幾個變量

// 經過過濾的數組
private ArrayList languages;
// 沒有經過過濾的數組
private ArrayList origin;
private Context context;
private int layoutId;

核心變量是languages和origin。

構造函數就是依次為這些變量賦值。

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

這裡最好重寫兩個方法,一個是getItem(),另一個是getCount()。如果不寫,可能會導致不顯示

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

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

為了實現緩存,我們肯定是要寫getView方法的。所以我們得先定義viewHolder,作為MyAdapter的內部類

    private class ViewHolder {
        TextView name;
        ImageView icon;
    }

好了,寫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;
    }

通過view自帶的setTag和getTag方法實現view的復用。
前面說到,MyAdapter的聲明是這樣的

public class MyAdapter extends ArrayAdapter implements Filterable

要就要重寫getFilter()方法了。
我們先自定義Filter

    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 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) results.values;
            // 更新視圖
            notifyDataSetChanged();
        }
    }

這下簡單了,getFilter()方法返回一個MyFilter對象就行了。

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

好了,上述的話,MyAdapter就實現完畢了。
那我們可以在Activity中使用了。
MainActivity.java

// 初始化數據
        final ArrayList 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);

上述的圖標都是自己下載的,就隨意下載了一些。

使用Adapter

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

為了進一步改善交互過程,點擊MyAutoCompleteTextView也應該彈出提示內容才行。

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

並且,點擊了MyAutoCompleteTextView的子項也應該要顯示出來吧?值得開心的是MyAutoCompleteTextView有setOnItemClickListener方法,有點類似於ListView

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

最後說道,這裡為什麼要用到AppCompatAutoCompleteTextView,而不是AutoCompleteTextView。因為AppCompatAutoCompleteTextView更能兼容好版本的Android系統,所以就使用AppCompatAutoCompleteTextView

至於AppCompatAutoCompleteTextView還有其他強大的功能,就需要自己去探索了,會了基本用法,其他的應該不難。

補充一下,其實AppCompatAutoCompleteTextView內部有一個ListPopupWindow,提示的內容就是用ListPopupWindow實現的。而ListPopupWindow我們可以理解為是ListView+PopupWindow。其實也就是說,我們可以自己實現AppCompatAutoCompleteTextView,自定義一個View,裡面是一個輸入框和PopupWindow,PopupWindow裡面又有ListView。如果不考慮兼容問題的話,實現起來應該不算太難。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved