模糊搜索框 EditText动态过滤Listview并改变颜色(仿微信模糊搜索)

模糊搜索框

APP需要一个该控件,安卓端。

先上个图,看起来不错的效果。

图一为未点击状态,图二为点击之后的状态。图三为输入之后的状态。

 

主要的功能点有 :

1、点击直接悬浮层,当前Activity实现不能跳转。

2、实现模糊搜索,EditText动态输入,实现模糊搜索,过滤ListView的资源。

3、EditText的动态输入,Listview包含该字符的,颜色标识不同(高亮)。

4、Json封装传值。

5、EditText带清除按钮(类似ClearEditText),软键盘的自动显示与隐藏。

 

模糊搜索框 EditText动态过滤Listview并改变颜色(仿微信模糊搜索)_第1张图片   模糊搜索框 EditText动态过滤Listview并改变颜色(仿微信模糊搜索)_第2张图片   模糊搜索框 EditText动态过滤Listview并改变颜色(仿微信模糊搜索)_第3张图片

 

查看了一下微信等的模糊搜索,看起来不难,呵呵,但还是花费了点时间去弄出来的。

结合了相关资源,嵌入到工程去了。

提取了一下,记录一下,也希望能帮到有需要的朋友。

直接上代码。

 

首先是 控件(开源项目提取的)

EditSearchView:

 

private boolean mIsSearchOpen;
    private boolean mClearingFocus;
    private View mSearchLayout;
    private View view;
    private ListView mSuggestionsListView;
    private EditText mSearchSrcTextView;
    private ImageButton mEmptyBtn;
    private TextView search_cancel;
    private RelativeLayout mSearchTopBar;
    private CharSequence mOldQueryText;
    private CharSequence mUserQuery;
    private EditSearchView.OnQueryTextListener mOnQueryChangeListener;
    private EditSearchView.SearchViewListener mSearchViewListener;
    private BaseAdapter mAdapter;
    private EditSearchView.SavedState mSavedState;
    private Context mContext;
    private boolean shouldAnimate;
    private final OnClickListener mOnClickListener;

    public EditSearchView(Context context) {
        this(context, (AttributeSet) null);
    }

    public EditSearchView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public EditSearchView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs);
        this.mIsSearchOpen = false;
        this.mOnClickListener = new OnClickListener() {
            public void onClick(View v) {
                if (v == mEmptyBtn) {
                    EditSearchView.this.mSearchSrcTextView.setText(null);
                } else if (v == mSearchSrcTextView) {
                    EditSearchView.this.showSuggestions();
                } else if (v == search_cancel) {
                    EditSearchView.this.closeSearch();
                }
            }
        };
        this.mContext = context;
        this.shouldAnimate = true;
        this.initiateView();
    }

    private void initiateView() {
        LayoutInflater.from(this.mContext).inflate(R.layout.search_view_layout, this, true);
        this.mSearchLayout = this.findViewById(R.id.search_layout);
        this.mSearchTopBar = (RelativeLayout) this.mSearchLayout.findViewById(R.id.search_top_bar);
        this.mSuggestionsListView = (ListView) this.mSearchLayout.findViewById(R.id.suggestion_list);
        this.mSearchSrcTextView = (EditText) this.mSearchLayout.findViewById(R.id.searchTextView);
        this.mEmptyBtn = (ImageButton) this.mSearchLayout.findViewById(R.id.action_empty_btn);
        this.search_cancel = (TextView) this.mSearchLayout.findViewById(R.id.search_cancel);
        this.mSearchSrcTextView.setOnClickListener(this.mOnClickListener);
        this.mEmptyBtn.setOnClickListener(this.mOnClickListener);
        this.search_cancel.setOnClickListener(this.mOnClickListener);
        this.initSearchView();
        this.mSuggestionsListView.setVisibility(GONE);
    }

    private void initSearchView() {

        this.mSearchSrcTextView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (actionId == EditorInfo.IME_ACTION_SEARCH){
                    hideKeyboard(v);
                }
                return true;
            }
        });
        this.mSearchSrcTextView.addTextChangedListener(new TextWatcher() {
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            public void onTextChanged(CharSequence s, int start, int before, int count) {
                EditSearchView.this.mUserQuery = s;
                EditSearchView.this.startFilter(s);
                EditSearchView.this.onTextChanged(s);
            }

            public void afterTextChanged(Editable s) {
            }
        });
        this.mSearchSrcTextView.setOnFocusChangeListener(new OnFocusChangeListener() {
            public void onFocusChange(View v, boolean hasFocus) {
                if (hasFocus) {
                    EditSearchView.this.showKeyboard(EditSearchView.this.mSearchSrcTextView);
                    EditSearchView.this.showSuggestions();
                }

            }
        });

    }

    private void startFilter(CharSequence s) {
        if (this.mAdapter != null && this.mAdapter instanceof Filterable) {
            ((Filterable) this.mAdapter).getFilter().filter(s, this);
        }
    }

    private void onTextChanged(CharSequence newText) {
        Editable text = this.mSearchSrcTextView.getText();
        this.mUserQuery = text;
        boolean hasText = !TextUtils.isEmpty(text);
        if (hasText) {
            this.mEmptyBtn.setVisibility(VISIBLE);
        } else {
            this.mEmptyBtn.setVisibility(GONE);
        }

        if (this.mOnQueryChangeListener != null && !TextUtils.equals(newText, this.mOldQueryText)) {
            this.mOnQueryChangeListener.onQueryTextChange(newText.toString());
        }

        this.mOldQueryText = newText.toString();
    }

    private void onSubmitQuery() {
        Editable query = this.mSearchSrcTextView.getText();
        if (query != null && TextUtils.getTrimmedLength(query) > 0 &&
                (this.mOnQueryChangeListener == null ||
                        !this.mOnQueryChangeListener.onQueryTextSubmit(query.toString()))) {
            this.closeSearch();
            this.mSearchSrcTextView.setText(null);

        }
    }

    private void hideKeyboard(View view) {
        InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }

    private void showKeyboard(View view) {
        if (Build.VERSION.SDK_INT <= 10 && view.hasFocus()) {
            view.clearFocus();
        }
        view.requestFocus();
        InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showSoftInput(view, 0);
    }


    public void setBackgroundColor(int color) {
        this.mSearchTopBar.setBackgroundColor(color);
    }


    public void showSuggestions() {
        if (this.mAdapter != null && this.mAdapter.getCount() > 0
                && this.mSuggestionsListView.getVisibility() == GONE) {
            this.mSuggestionsListView.setVisibility(VISIBLE);
        }
    }

    public void setOnItemClickListener(AdapterView.OnItemClickListener listener) {
        this.mSuggestionsListView.setOnItemClickListener(listener);
    }

    public void setAdapter(BaseAdapter adapter) {
        this.mAdapter = adapter;
        this.mSuggestionsListView.setAdapter(adapter);
        this.startFilter(this.mSearchSrcTextView.getText());
    }

    public void dismissSuggestions() {
        if (this.mSuggestionsListView.getVisibility() == VISIBLE) {
            this.mSuggestionsListView.setVisibility(GONE);
        }
    }

    public void setQuery(CharSequence query, boolean submit) {
        this.mSearchSrcTextView.setText(query);
        if (query != null) {
            this.mSearchSrcTextView.setSelection(this.mSearchSrcTextView.length());
            this.mUserQuery = query;
        }

        if (submit && !TextUtils.isEmpty(query)) {
            this.onSubmitQuery();
        }

    }
    
    public void setMenuItem(View view) {
        this.view = view;
        EditSearchView.this.showSearch();
    }

    public boolean isSearchOpen() {
        return this.mIsSearchOpen;
    }

    public void showSearch() {
        if (this.shouldAnimate) {
            this.showSearch(true);
        } else {
            this.showSearch(false);
        }

    }

    public void showSearch(boolean animate) {
        if (!this.isSearchOpen()) {
            this.mSearchSrcTextView.setText(null);
            this.mSearchSrcTextView.requestFocus();
            if (animate) {
                Util.fadeInView(this.mSearchLayout, 150, new Util.AnimationListener() {
                    public boolean onAnimationStart(View view) {
                        return false;
                    }

                    public boolean onAnimationEnd(View view) {
                        if (EditSearchView.this.mSearchViewListener != null) {
                            EditSearchView.this.mSearchViewListener.onSearchViewShown();
                        }

                        return false;
                    }

                    public boolean onAnimationCancel(View view) {
                        return false;
                    }
                });
            } else {
                this.mSearchLayout.setVisibility(VISIBLE);
                if (this.mSearchViewListener != null) {
                    this.mSearchViewListener.onSearchViewShown();
                }
            }

            this.mIsSearchOpen = true;
        }
    }

    public void closeSearch() {
        if (this.isSearchOpen()) {
            this.mSearchSrcTextView.setText(null);
            this.dismissSuggestions();
            this.clearFocus();
            this.mSearchLayout.setVisibility(GONE);
            if (this.mSearchViewListener != null) {
                this.mSearchViewListener.onSearchViewClosed();
            }
            this.mIsSearchOpen = false;
        }
    }

    public void setOnQueryTextListener(EditSearchView.OnQueryTextListener listener) {
        this.mOnQueryChangeListener = listener;
    }

    public void setOnSearchViewListener(EditSearchView.SearchViewListener listener) {
        this.mSearchViewListener = listener;
    }

    public void onFilterComplete(int count) {
        if (count > 0) {
            this.showSuggestions();
        } else {
            this.dismissSuggestions();
        }
    }

    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
        return this.mClearingFocus ? false : (!this.isFocusable() ? false : this.mSearchSrcTextView.requestFocus(direction, previouslyFocusedRect));
    }

    public void clearFocus() {
        this.mClearingFocus = true;
        this.hideKeyboard(this);
        super.clearFocus();
        this.mSearchSrcTextView.clearFocus();
        this.mClearingFocus = false;
    }

    public Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();
        this.mSavedState = new EditSearchView.SavedState(superState);
        this.mSavedState.query = this.mUserQuery != null ? this.mUserQuery.toString() : null;
        this.mSavedState.isSearchOpen = this.mIsSearchOpen;
        return this.mSavedState;
    }

    public void onRestoreInstanceState(Parcelable state) {
        if (!(state instanceof EditSearchView.SavedState)) {
            super.onRestoreInstanceState(state);
        } else {
            this.mSavedState = (EditSearchView.SavedState) state;
            if (this.mSavedState.isSearchOpen) {
                this.showSearch(false);
                this.setQuery(this.mSavedState.query, false);
            }
            super.onRestoreInstanceState(this.mSavedState.getSuperState());
        }
    }

    public interface SearchViewListener {
        void onSearchViewShown();

        void onSearchViewClosed();
    }

    public interface OnQueryTextListener {
        boolean onQueryTextSubmit(String var1);

        boolean onQueryTextChange(String var1);
    }

    static class SavedState extends BaseSavedState {
        String query;
        boolean isSearchOpen;

        SavedState(Parcelable superState) {
            super(superState);
        }

        private SavedState(Parcel in) {
            super(in);
            this.query = in.readString();
            this.isSearchOpen = in.readInt() == 1;
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
            super.writeToParcel(out, flags);
            out.writeString(query);
            out.writeInt(isSearchOpen ? 1 : 0);
        }

        //required field that makes Parcelables from a Parcel
        public static final Parcelable.Creator CREATOR =
                new Parcelable.Creator() {
                    public SavedState createFromParcel(Parcel in) {
                        return new SavedState(in);
                    }

                    public SavedState[] newArray(int size) {
                        return new SavedState[size];
                    }
                };
    }


第二、使用到的地方

  private void initSearchEvent() {
        final List items = new ArrayList<>();
        adapter = new MyAdapter(items) {
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                ViewHolder holder;
                if (convertView == null) {
                    convertView = View.inflate(MainActivity.this, R.layout.list_item, null);
                    holder = new ViewHolder();
                    holder.text = (TextView) convertView.
                            findViewById(R.id.name);
                    convertView.setTag(holder);
                } else {
                    holder = (ViewHolder) convertView.getTag();
                }

                String _info = (String) adapter.getItem(position);
                if (!string.equals("") && string != null) {
                    int index = _info.toLowerCase().indexOf(string.toLowerCase());
                    int length = string.length();
                    Spanned temp = fromHtml(_info.substring(0, index)
                            + ""
                            + _info.substring(index, index + length)
                            + ""
                            + _info.substring(index + length,
                            _info.length()));
                    holder.text.setText(temp);
                } else {
                    holder.text.setText(_info);
                }

                return convertView;
            }

            @Override
            public Filter getFilter() {
                Filter filter;
                filter = new Filter() {
                    @Override
                    protected FilterResults performFiltering(CharSequence constraint) {
                        FilterResults filterResults = new FilterResults();
                        if (!TextUtils.isEmpty(constraint)) {
                            Pattern pattern = Pattern.compile(constraint.toString().toLowerCase());
                            JSONArray array = new JSONArray();
                            for (int i = 0; i < listData.size(); i++) {
                                String data =  (String) listData.get(i);
                                Matcher matcher = pattern.matcher(data.toLowerCase());
                                if (matcher.find()) {
                                    array.put(data);
                                }
                            }
                            JSONObject object = new JSONObject();
                            try {
                                object.put("data", array);
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                            filterResults.values = object;
                            filterResults.count = array.length();
                        }
                        return filterResults;
                    }

                    @Override
                    protected void publishResults(CharSequence constraint, FilterResults results) {
                        if (results.values != null) {
                            List list = new ArrayList<>();
                            JSONObject obj = (JSONObject) results.values;
                            if (obj.has("data")) {
                                try {
                                    JSONArray _ja = obj.getJSONArray("data");
                                    for (int i = 0; i < _ja.length(); i++) {
                                        String _info = (String) _ja.get(i);
                                        list.add(_info);
                                    }
                                } catch (JSONException e) {
                                    e.printStackTrace();
                                }
                            }
                            adapter.setData(list);
                        }
                    }
                };
                return filter;
            }
        };
        searchView.setAdapter(adapter);

        searchView.setOnQueryTextListener(new EditSearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String changeTxt) {
                string = changeTxt;
                return false;
            }
        });

        searchView.setOnSearchViewListener(new EditSearchView.SearchViewListener() {
            @Override
            public void onSearchViewShown() {
                searchView.setVisibility(View.VISIBLE);
            }

            @Override
            public void onSearchViewClosed() {
                searchView.setVisibility(View.GONE);
            }
        });

        searchView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View view, int position, long id) {
                String _info = (String) adapter.getItem(position);
                Toast.makeText(MainActivity.this, " " + _info, Toast.LENGTH_SHORT).show();
            }
        });
    } 
  

 

 

 

最后、工具是AS的。Demo传送

2019.10

对于平台把该项目的demo弄成50积分才能下载,我之前是不用积分下载的,
有知道怎样修改成1积分下载的同学,请在下面留言我,此积分我也很无奈。
其实就是当年练手的一个简单demo而已,若有需要学习的同学,
请到github上面搜一下,editSeach,相信你可以找得到你要实现的功能控件的,谢谢你的关注。

你可能感兴趣的:(模糊搜索框 EditText动态过滤Listview并改变颜色(仿微信模糊搜索))