Android搜索控件SearchView

作者: 键盘上的麒麟臂 | 来源:发表于2018-02-23 17:47 被阅读1059次

    由于项目很多地方需要搜索框,就自定义了一个SearchView控件,顺便复习下自定义View的操作。

    一.复用性

    虽然我自己在多个地方进行复制粘贴也很省时,但是总觉得这样的做法太Low了,所以还是抽出来自定义一个view,看看效果。

    默认情况

    这是一个默认样式下的搜索框,当然也可以改


    image.png

    抽离出以后再使用的话会比较方便。

    二.默认输入框结构

    目录
    image.png

    第一个是view,三个接口分别表示监听搜索框的焦点,监听搜索框的搜索操作和扩展自定义View时的行为。

    View结构

    默认的View的布局如下

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/rl_search"
        android:focusable="true"
        android:focusableInTouchMode="true">
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center"
            android:id="@+id/ll_search"
            >
    
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/iv_search"
                android:layout_toLeftOf="@+id/edt_search"
                android:layout_marginRight="10dp"
                />
    
            <EditText
                android:gravity="top"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="14sp"
                android:textColor="@color/get_gray_code"
                android:background="@null"
                android:id="@+id/edt_search"
                android:maxLines="1"
                />
    
        </LinearLayout>
    
    </RelativeLayout>
    

    简单说说这样设计的理由,本来图片和Edit是可以直接用一个EditText来完成的,但是为了考虑扩展性所以分成了ImageView和EditText。
    然后我是不想在中间多加一层的LinearLayout布局的,但是如果显示在中间的情况布局就会看着挺别扭,而且直接用RelativeLayout 去动态改变两个子控件的布局的话就会做很多操作,所以在中间加了一层,我觉得性能方面也不会影响很大。

    再讲讲这样设计是为了确保存在ImageView和EditText,布局可以自定义进行扩展,不一定要使用默认的,但是一定要有ImageView和EditText,这个之后会说。

    三.自定义属性

    添加部分自定义属性,方便改变一些常用的样式

    <!-- 搜索框 -->
        <declare-styleable name="kylin_search_style">
            <attr name="img_src" format="reference"/><!-- 图片地址 -->
            <attr name="img_size" format="dimension"/><!-- 图片大小 -->
            <attr name="img_visibility" format="boolean"/><!-- 图片显示/隐藏 -->
            <attr name="show_location" format="enum">
                <enum name="left" value="0"/>
                <enum name="right" value="2"/>
                <enum name="centre" value="1"/>
            </attr>
            <attr name="edt_hint" format="string"/><!-- 提示文字 -->
            <attr name="edt_size" format="dimension"/><!-- 提示文字大小 -->
            <attr name="edt_hint_color" format="color"/><!-- 提示文字的颜色 -->
            <attr name="search_backgroup" format="reference"/><!-- 搜索框背景 -->
            <attr name="search_padding" format="reference"/><!-- 搜索框背景 -->
        </declare-styleable>
    

    show_location表示展示的位置,其它都有注解。

    不仅如此,还会在View内部加入返回子控件的操作,可以在外部设置,因为我觉得如果在内部定义太多属性的话,要在View内写很多变量,这种做法我觉得很不划算,所以只写了一些常变化的,下面的方法返回控件。

    public EditText getSearchEditText() {
            return edtSearch;
        }
    
        public ImageView getSearchImageView() {
            return ivSearch;
        }
    
        public ViewGroup getSearchFrameView() {
            return rlSearch;
        }
    

    四.初始化操作

        protected void initView() {
            // 初始化搜索边框
            rlSearch.setBackgroundResource(seaBackgroup);
            rlSearch.setPadding((int) seaPadding, (int) seaPadding, (int) seaPadding, (int) seaPadding);
    
            ViewGroup.LayoutParams llLp = llSearch.getLayoutParams();
            if (showType == 0){
                ((RelativeLayout.LayoutParams) llLp).addRule(RelativeLayout.ALIGN_PARENT_LEFT);
            }else if (showType == 1) {
                ((RelativeLayout.LayoutParams) llLp).addRule(RelativeLayout.CENTER_IN_PARENT);
            }else if (showType == 2){
                ((RelativeLayout.LayoutParams) llLp).addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
            }
            llSearch.setLayoutParams(llLp);
    
            // 初始化图片
            ViewGroup.LayoutParams lp = ivSearch.getLayoutParams();
            lp.width = (int) imgSize;
            lp.height = (int) imgSize;
            ivSearch.setLayoutParams(lp);
            ivSearch.setImageResource(imgRid);
    
            // 初始化输入框
            edtHint = (edtHint == null || edtHint == "" || edtHint.equals(null) || edtHint.equals(""))
                    ? "请输入搜索内容" : edtHint;
            edtSearch.setHint(edtHint);
            edtSearch.setHintTextColor(edtHintColor);
            edtSearch.setTextSize(edt_size);
    
    
        }
    

    就是初始化设置那些常用的属性。关键是下面的操作,为了增加扩展性,我添加了一步类似钩子的操作。

     private void init(){
            // 提供自定义样式的钩子
            int layoutId = getLayoutId();
            if (layoutId == -1){
                seachView = LayoutInflater.from(getContext()).inflate(R.layout.layout_base_seach,this,false);
                this.addView(seachView);
                ivSearch = (ImageView) seachView.findViewById(R.id.iv_search);
                edtSearch = (EditText) seachView.findViewById(R.id.edt_search);
                rlSearch = (RelativeLayout) seachView.findViewById(R.id.rl_search);
                llSearch = (LinearLayout) seachView.findViewById(R.id.ll_search);
                initView();
            }else {
                seachView = LayoutInflater.from(getContext()).inflate(layoutId,this,false);
                this.addView(seachView);
                ivSearch = getImageView();
                edtSearch = getEditText();
                rlSearch = getSearchFrame();
            }
            // 初始化事件监听
            initAllListener();
        }
    
        @Override
        public int getLayoutId(){
            return -1;
        }
    
        @Override
        public ImageView getImageView(){
            return null;
        }
    
        @Override
        public EditText getEditText(){
            return null;
        }
    
        @Override
        public ViewGroup getSearchFrame(){
            return null;
        }
    
    

    开发者可以写个类继承这个控件,然后重写上边说的SearchExtendImpl接口的4个方法

    public interface SearchExtendImpl {
    
        int getLayoutId();
    
        ImageView getImageView();
    
        EditText getEditText();
    
        ViewGroup getSearchFrame();
    
    }
    

    如果布局和默认布局很大程度不同的话,可以使用继承的方式,但是要把搜索框的图标用getImageView来返给父类,输入框用getEditText传,搜索边框用getSearchFrame传。我这里这样设计的目的是因为,这东西子控件就两三个,所以在布局方面我没必要做太多的扩展,就几个子控件,做过多的扩展不如重做一个新的,但是逻辑是可以复用的。

    五.搜索逻辑

    这部分是可以服用的,所以不管是使用我写的默认的搜索框样式,还是开发者自定义的布局都可以服用这个逻辑。

    protected void initAllListener(){
            InputMethodManager imm = (InputMethodManager) getContext().getSystemService(getContext().INPUT_METHOD_SERVICE);
            if (edtSearch != null) {
                // 点击事件
                edtSearch.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        edtSearch.setFocusable(true);//设置输入框可聚集
                        edtSearch.setFocusableInTouchMode(true);//设置触摸聚焦
                        edtSearch.requestFocus();//请求焦点
                        edtSearch.findFocus();//获取焦点
                    }
                });
                // 监听焦点
                edtSearch.setOnFocusChangeListener(new OnFocusChangeListener() {
                    @Override
                    public void onFocusChange(View v, boolean hasFocus) {
                        if (hasFocus) {
                            imm.showSoftInput(v, InputMethodManager.SHOW_FORCED); //显示软键盘
                        } else {
                            imm.hideSoftInputFromWindow(v.getWindowToken(), 0); //隐藏软键盘
                        }
                        if (onSearchFocusListener != null){
                            onSearchFocusListener.searchFocusChange(v,hasFocus);
                        }
                    }
                });
                // 监听软键盘的按键
                edtSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() {
                    @Override
                    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                        //回车等操作
                        if (actionId == EditorInfo.IME_ACTION_SEND
                                || actionId == EditorInfo.IME_ACTION_DONE
                                || actionId == EditorInfo.IME_ACTION_SEARCH
                                || actionId == EditorInfo.IME_ACTION_GO
                                || (event != null && KeyEvent.KEYCODE_ENTER == event.getKeyCode()
                                && KeyEvent.ACTION_DOWN == event.getAction())) {
                            // 搜索
                            search();
                        }
                        return true;
                    }
                });
            }
        }
    

    这里涉及两个比较啰嗦的东西,光标(焦点)和软键盘,软键盘的操做相关的一个类InputMethodManager,我没有很好去理解,只是查了一些大概的用法。

    (1)我先给输入框设置点击之后获取焦点
    edtSearch.setFocusable(true);//设置输入框可聚集
    edtSearch.setFocusableInTouchMode(true);//设置触摸聚焦
    edtSearch.requestFocus();//请求焦点
    edtSearch.findFocus();//获取焦点
    

    为什么要这样做,因为我之后要做失焦操作,如果不写这个代码的话,我这边会出个BUG,失焦后就无法再重新获取焦点。

    (2)失焦操作
    /**
         *  让EditText失去焦点
         */
        public void lostRocus(){
            if(edtSearch != null) {
                edtSearch.setFocusable(false);
            }
        }
    
    (3)关联软键盘
                  public void onFocusChange(View v, boolean hasFocus) {
                        if (hasFocus) {
                            imm.showSoftInput(v, InputMethodManager.SHOW_FORCED); //显示软键盘
                        } else {
                            imm.hideSoftInputFromWindow(v.getWindowToken(), 0); //隐藏软键盘
                        }
                    }
    

    获取焦点后软键盘弹起,失去焦点后软键盘消失。

    六.全部代码

    项目没有放到gayhub,一是有些BUG,我等下会说,二是我没写自定义布局的demo,三是我没写文档。所以我先写文章,过后完善了再把项目丢到gayhub。

    1.默认样式布局

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/rl_search"
        android:focusable="true"
        android:focusableInTouchMode="true">
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center"
            android:id="@+id/ll_search"
            >
    
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/iv_search"
                android:layout_toLeftOf="@+id/edt_search"
                android:layout_marginRight="10dp"
                />
    
            <EditText
                android:gravity="top"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="14sp"
                android:textColor="@color/get_gray_code"
                android:background="@null"
                android:id="@+id/edt_search"
                android:maxLines="1"
                />
    
        </LinearLayout>
    
    </RelativeLayout>
    

    2.自定义属性

    在attrs中添加

    <!-- 搜索框 -->
        <declare-styleable name="kylin_search_style">
            <attr name="img_src" format="reference"/><!-- 图片地址 -->
            <attr name="img_size" format="dimension"/><!-- 图片大小 -->
            <attr name="img_visibility" format="boolean"/><!-- 图片显示/隐藏 -->
            <attr name="show_location" format="enum">
                <enum name="left" value="0"/>
                <enum name="right" value="2"/>
                <enum name="centre" value="1"/>
            </attr>
            <attr name="edt_hint" format="string"/><!-- 提示文字 -->
            <attr name="edt_size" format="dimension"/><!-- 提示文字大小 -->
            <attr name="edt_hint_color" format="color"/><!-- 提示文字的颜色 -->
            <attr name="search_backgroup" format="reference"/><!-- 搜索框背景 -->
            <attr name="search_padding" format="reference"/><!-- 搜索框背景 -->
        </declare-styleable>
    

    3.三个定义的接口

    public interface OnSearchFocusListener {
    
        void searchFocusChange(View v, boolean hasFocus);
    
    }
    
    public interface OnSearchListener {
        void search(String content);
    }
    
    public interface SearchExtendImpl {
    
        int getLayoutId();
    
        ImageView getImageView();
    
        EditText getEditText();
    
        ViewGroup getSearchFrame();
    
    }
    

    4.View代码

    /**
     * Created by kylin on 2018/2/23.
     */
    
    public class KylinSearchView extends FrameLayout implements SearchExtendImpl{
    
        protected Context context;
        protected View seachView;
        protected ImageView ivSearch;
        protected EditText edtSearch;
        protected ViewGroup rlSearch;
        protected LinearLayout llSearch;
        /**
         *  属性定义
         */
        protected int seaBackgroup;
        protected int imgRid;
        protected float imgSize;
        protected String edtHint;
        protected int edtHintColor;
        protected float seaPadding;
        protected int showType;
        protected float edt_size;
        /**
         *  事件
         */
        protected OnSearchListener onSearchListener;
        protected OnSearchFocusListener onSearchFocusListener;
    
    
        public KylinSearchView(Context context) {
            super(context);
            init();
        }
    
        public KylinSearchView(Context context, AttributeSet attrs) {
            super(context, attrs);
            initAttrs(context, attrs);
            init();
        }
    
        public KylinSearchView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initAttrs(context, attrs);
            init();
        }
    
        /**
         * 设置属性
         */
        private void initAttrs(Context context,AttributeSet attrs)  {
            TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.kylin_search_style);
    
            imgRid = typedArray.getInteger(R.styleable.kylin_search_style_img_src,R.mipmap.product_serch);
            // 默认的float是px,所以要转成dp
            imgSize = typedArray.getDimension(R.styleable.kylin_search_style_img_size,  DimensionUtils.dip2px(context,24));
            edtHint = typedArray.getString(R.styleable.kylin_search_style_edt_hint);
            edtHintColor = typedArray.getColor(R.styleable.kylin_search_style_edt_hint, getResources().getColor(R.color.get_gray_code));
            seaBackgroup = typedArray.getInteger(R.styleable.kylin_search_style_search_backgroup,R.drawable.bg_search_default);
            seaPadding = typedArray.getDimension(R.styleable.kylin_search_style_img_size, DimensionUtils.dip2px(context,8));
            showType = typedArray.getInteger(R.styleable.kylin_search_style_show_location,0);
            edt_size = typedArray.getDimension(R.styleable.kylin_search_style_edt_size, 18);
    
            typedArray.recycle();
    
        }
    
        /**
         *  初始化操作
         */
        private void init(){
            // 提供自定义样式的钩子
            int layoutId = getLayoutId();
            if (layoutId == -1){
                seachView = LayoutInflater.from(getContext()).inflate(R.layout.layout_base_seach,this,false);
                this.addView(seachView);
                ivSearch = (ImageView) seachView.findViewById(R.id.iv_search);
                edtSearch = (EditText) seachView.findViewById(R.id.edt_search);
                rlSearch = (RelativeLayout) seachView.findViewById(R.id.rl_search);
                llSearch = (LinearLayout) seachView.findViewById(R.id.ll_search);
                initView();
            }else {
                seachView = LayoutInflater.from(getContext()).inflate(layoutId,this,false);
                this.addView(seachView);
                ivSearch = getImageView();
                edtSearch = getEditText();
                rlSearch = getSearchFrame();
            }
            // 初始化事件监听
            initAllListener();
        }
    
        @Override
        public int getLayoutId(){
            return -1;
        }
    
        @Override
        public ImageView getImageView(){
            return null;
        }
    
        @Override
        public EditText getEditText(){
            return null;
        }
    
        @Override
        public ViewGroup getSearchFrame(){
            return null;
        }
    
        protected void initView() {
            // 初始化搜索边框
            rlSearch.setBackgroundResource(seaBackgroup);
            rlSearch.setPadding((int) seaPadding, (int) seaPadding, (int) seaPadding, (int) seaPadding);
    
            ViewGroup.LayoutParams llLp = llSearch.getLayoutParams();
            if (showType == 0){
                ((RelativeLayout.LayoutParams) llLp).addRule(RelativeLayout.ALIGN_PARENT_LEFT);
            }else if (showType == 1) {
                ((RelativeLayout.LayoutParams) llLp).addRule(RelativeLayout.CENTER_IN_PARENT);
            }else if (showType == 2){
                ((RelativeLayout.LayoutParams) llLp).addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
            }
            llSearch.setLayoutParams(llLp);
    
            // 初始化图片
            ViewGroup.LayoutParams lp = ivSearch.getLayoutParams();
            lp.width = (int) imgSize;
            lp.height = (int) imgSize;
            ivSearch.setLayoutParams(lp);
            ivSearch.setImageResource(imgRid);
    
            // 初始化输入框
            edtHint = (edtHint == null || edtHint == "" || edtHint.equals(null) || edtHint.equals(""))
                    ? "请输入搜索内容" : edtHint;
            edtSearch.setHint(edtHint);
            edtSearch.setHintTextColor(edtHintColor);
            edtSearch.setTextSize(edt_size);
    
    
        }
    
        protected void initAllListener(){
            InputMethodManager imm = (InputMethodManager) getContext().getSystemService(getContext().INPUT_METHOD_SERVICE);
            if (edtSearch != null) {
                // 点击事件
                edtSearch.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        edtSearch.setFocusable(true);//设置输入框可聚集
                        edtSearch.setFocusableInTouchMode(true);//设置触摸聚焦
                        edtSearch.requestFocus();//请求焦点
                        edtSearch.findFocus();//获取焦点
                    }
                });
                // 监听焦点
                edtSearch.setOnFocusChangeListener(new OnFocusChangeListener() {
                    @Override
                    public void onFocusChange(View v, boolean hasFocus) {
                        if (hasFocus) {
                            imm.showSoftInput(v, InputMethodManager.SHOW_FORCED); //显示软键盘
                        } else {
                            imm.hideSoftInputFromWindow(v.getWindowToken(), 0); //隐藏软键盘
                        }
                        if (onSearchFocusListener != null){
                            onSearchFocusListener.searchFocusChange(v,hasFocus);
                        }
                    }
                });
                // 监听软键盘的按键
                edtSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() {
                    @Override
                    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                        //回车等操作
                        if (actionId == EditorInfo.IME_ACTION_SEND
                                || actionId == EditorInfo.IME_ACTION_DONE
                                || actionId == EditorInfo.IME_ACTION_SEARCH
                                || actionId == EditorInfo.IME_ACTION_GO
                                || (event != null && KeyEvent.KEYCODE_ENTER == event.getKeyCode()
                                && KeyEvent.ACTION_DOWN == event.getAction())) {
                            // 搜索
                            search();
                        }
                        return true;
                    }
                });
            }
        }
    
        /**
         *  获取搜索框的内容
         */
        public String getSearchContent(){
            if (edtSearch == null){
                return null;
            }
            return edtSearch.getText().toString();
        }
    
        /**
         *  清空搜索框
         */
        public void clearSearch(){
            edtSearch.setText("");
        }
    
        /**
         *  让EditText失去焦点
         */
        public void lostRocus(){
            if(edtSearch != null) {
                edtSearch.setFocusable(false);
            }
        }
    
        /**
         *  搜索
         */
        public void search(){
            lostRocus();
            if (onSearchListener != null){
                onSearchListener.search(getSearchContent());
            }
        }
    
        public void setOnSearchListener(OnSearchListener onSearchListener) {
            this.onSearchListener = onSearchListener;
        }
    
        public void setOnSearchFocusListener(OnSearchFocusListener onSearchFocusListener) {
            this.onSearchFocusListener = onSearchFocusListener;
        }
    
        public EditText getSearchEditText() {
            return edtSearch;
        }
    
        public ImageView getSearchImageView() {
            return ivSearch;
        }
    
        public ViewGroup getSearchFrameView() {
            return rlSearch;
        }
    
        public void setImgSize(float size){
            ViewGroup.LayoutParams lp = ivSearch.getLayoutParams();
            lp.width = (int) size;
            lp.height = (int) size;
            ivSearch.setLayoutParams(lp);
        }
    
        public void setTextSize(float size){
            edtSearch.setTextSize(size);
        }
        
    }
    

    之中有些操作,比如 DimensionUtils.dip2px就是转尺寸单位,这些命名就很明显,自己写个工具类转就行。

    伸手党要用的话只能全抄了,gayhub没这么快。

    tmp2.gif

    模拟一下,软键盘回车后失去焦点。

    六.BUG

    我在玩的时候玩出个BUG,关键是这个BUG我还不知道要怎么去表达,设置图片的尺寸

    imgSize = typedArray.getDimension(R.styleable.kylin_search_style_img_size,  DimensionUtils.dip2px(context,24));
    

    我这里默认填24dp是正常,我如果在控件中设置

    app:img_size="24dp"
    
    image.png

    图片大小没变,但是间距莫名其妙变大了。还有文字也是,用sp的话比正常情况的sp大得多。所以我现在还不懂这个format="dimension"出了什么毛病,这是其中一个问题。

    还有一个问题是软键盘,这个东西比较容易出BUG,我无法保证不同的软键盘或者不同的版本不会出问题,我是感觉之后可能要做适配的问题。

    暂时就这些,简单封装了一下,完善也只能在之后碰到问题再去完善,然后之后我有时间写个demo写个文档再放到gayhub


    更新

    项目地址

    https://github.com/994866755/handsomeYe.SearchView


    BUG修改

    之前说有几个传资源时的BUG,我先在这写出来,gayhub的过后我改了再传。

    1.背景资源的类型写错了
    seaBackgroup = typedArray.getResourceId(R.styleable.kylin_search_style_search_backgroup,R.drawable.bg_search_default);
    

    这里我之前用getInteger用错了。

    2.设置字体大小

    我之前说怎么设置字体大小总是出问题,然后发现是setTextSize方法默认是sp的,然后我用getDimension传进来的会转成px,这样就造成了px套到sp上,尺寸就错了,应该把类型再做一次转换

    edtSearch.setTextSize(TypedValue.COMPLEX_UNIT_PX,edt_size);
    

    这个问题我之前也碰到过,只是忘了做笔记,所以不记得了。详细的原因可以看下这篇博客,讲得很不错。
    https://www.jianshu.com/p/7f2941dbfb17

    3.设置自适应大小

    我发现用getDimension如果设默认大小的话就扩展性太差了,所以想改成自适应,但是我又不知道这个方法要怎么设置默认值为自适应,所以我就投机用正负值来判断,默认为负数就是自适应的情况。

    imgSize = typedArray.getDimension(R.styleable.kylin_search_style_img_size, -1);
    
     // 初始化图片
            ViewGroup.LayoutParams lp = ivSearch.getLayoutParams();
            if (imgSize >= 0) {
                lp.width = (int) imgSize;
                lp.height = (int) imgSize;
            }else {
                lp.width = ViewGroup.LayoutParams.WRAP_CONTENT;
                lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
            }
            ivSearch.setLayoutParams(lp);
    

    补充

    我想做个功能的补充是关于软键盘的,有很多时候,我们需要在软键盘弹出的情况下,点击空白处的话就隐藏软键盘。
    而这个操作我这边不好一起封装到searchView里面,我觉得可以直接在页面中用拦截事件来实现这功能。

        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            if (ev.getAction() == MotionEvent.ACTION_DOWN){
                // 收软键盘
                InputMethodManager imm =  (InputMethodManager) getSystemService(this.INPUT_METHOD_SERVICE);
                if (imm.isActive()){
                    imm.hideSoftInputFromWindow(searchView.getSearchEditText().getWindowToken(), 0); //隐藏软键盘
                }
            }
            return super.dispatchTouchEvent(ev);
        }
    

    这样写就能实现点击页面时隐藏软键盘的操作,比如美团的搜索就是点页面能隐藏软键盘。

    但是这里有个问题,dispatchTouchEvent方法会频繁的调用,只要一碰到这个页面就会调用这个方法,而我在这里面创建InputMethodManager 的话是不是会一直创建对象。

    我看Monitors来测试,其实我不是很会用Monitors,然后用我单身20年的手速不断搓屏幕,发现内存一直在增长,所以我觉得InputMethodManager 在dispatchTouchEvent中创建不是很好,把它抽出去,在全局中创建。

    相关文章

      网友评论

      • 丽丽哥个丽丽哥:自定义view直接继承edittext,改一下背景,增加一个图标不行吗?为什么嵌套两层还要加个imageview的?
        键盘上的麒麟臂:@丽丽哥个丽丽哥 我这个是为了之后扩展,这里加一层影响不大。其实都行的,看个人喜欢吧

      本文标题:Android搜索控件SearchView

      本文链接:https://www.haomeiwen.com/subject/bfvxxftx.html