Android搜索控件SearchView

由于項(xiàng)目很多地方需要搜索框,就自定義了一個(gè)SearchView控件,順便復(fù)習(xí)下自定義View的操作。

一.復(fù)用性

雖然我自己在多個(gè)地方進(jìn)行復(fù)制粘貼也很省時(shí),但是總覺(jué)得這樣的做法太Low了,所以還是抽出來(lái)自定義一個(gè)view,看看效果。

默認(rèn)情況

這是一個(gè)默認(rèn)樣式下的搜索框,當(dāng)然也可以改


image.png

抽離出以后再使用的話會(huì)比較方便。

二.默認(rèn)輸入框結(jié)構(gòu)

目錄
image.png

第一個(gè)是view,三個(gè)接口分別表示監(jiān)聽(tīng)搜索框的焦點(diǎn),監(jiān)聽(tīng)搜索框的搜索操作和擴(kuò)展自定義View時(shí)的行為。

View結(jié)構(gòu)

默認(rèn)的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>

簡(jiǎn)單說(shuō)說(shuō)這樣設(shè)計(jì)的理由,本來(lái)圖片和Edit是可以直接用一個(gè)EditText來(lái)完成的,但是為了考慮擴(kuò)展性所以分成了ImageView和EditText。
然后我是不想在中間多加一層的LinearLayout布局的,但是如果顯示在中間的情況布局就會(huì)看著挺別扭,而且直接用RelativeLayout 去動(dòng)態(tài)改變兩個(gè)子控件的布局的話就會(huì)做很多操作,所以在中間加了一層,我覺(jué)得性能方面也不會(huì)影響很大。

再講講這樣設(shè)計(jì)是為了確保存在ImageView和EditText,布局可以自定義進(jìn)行擴(kuò)展,不一定要使用默認(rèn)的,但是一定要有ImageView和EditText,這個(gè)之后會(huì)說(shuō)。

三.自定義屬性

添加部分自定義屬性,方便改變一些常用的樣式

<!-- 搜索框 -->
    <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表示展示的位置,其它都有注解。

不僅如此,還會(huì)在View內(nèi)部加入返回子控件的操作,可以在外部設(shè)置,因?yàn)槲矣X(jué)得如果在內(nèi)部定義太多屬性的話,要在View內(nèi)寫(xiě)很多變量,這種做法我覺(jué)得很不劃算,所以只寫(xiě)了一些常變化的,下面的方法返回控件。

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(""))
                ? "請(qǐng)輸入搜索內(nèi)容" : edtHint;
        edtSearch.setHint(edtHint);
        edtSearch.setHintTextColor(edtHintColor);
        edtSearch.setTextSize(edt_size);


    }

就是初始化設(shè)置那些常用的屬性。關(guān)鍵是下面的操作,為了增加擴(kuò)展性,我添加了一步類(lèi)似鉤子的操作。

 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();
        }
        // 初始化事件監(jiān)聽(tīng)
        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;
    }

開(kāi)發(fā)者可以寫(xiě)個(gè)類(lèi)繼承這個(gè)控件,然后重寫(xiě)上邊說(shuō)的SearchExtendImpl接口的4個(gè)方法

public interface SearchExtendImpl {

    int getLayoutId();

    ImageView getImageView();

    EditText getEditText();

    ViewGroup getSearchFrame();

}

如果布局和默認(rèn)布局很大程度不同的話,可以使用繼承的方式,但是要把搜索框的圖標(biāo)用getImageView來(lái)返給父類(lèi),輸入框用getEditText傳,搜索邊框用getSearchFrame傳。我這里這樣設(shè)計(jì)的目的是因?yàn)椋@東西子控件就兩三個(gè),所以在布局方面我沒(méi)必要做太多的擴(kuò)展,就幾個(gè)子控件,做過(guò)多的擴(kuò)展不如重做一個(gè)新的,但是邏輯是可以復(fù)用的。

五.搜索邏輯

這部分是可以服用的,所以不管是使用我寫(xiě)的默認(rèn)的搜索框樣式,還是開(kāi)發(fā)者自定義的布局都可以服用這個(gè)邏輯。

protected void initAllListener(){
        InputMethodManager imm = (InputMethodManager) getContext().getSystemService(getContext().INPUT_METHOD_SERVICE);
        if (edtSearch != null) {
            // 點(diǎn)擊事件
            edtSearch.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    edtSearch.setFocusable(true);//設(shè)置輸入框可聚集
                    edtSearch.setFocusableInTouchMode(true);//設(shè)置觸摸聚焦
                    edtSearch.requestFocus();//請(qǐng)求焦點(diǎn)
                    edtSearch.findFocus();//獲取焦點(diǎn)
                }
            });
            // 監(jiān)聽(tīng)焦點(diǎn)
            edtSearch.setOnFocusChangeListener(new OnFocusChangeListener() {
                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    if (hasFocus) {
                        imm.showSoftInput(v, InputMethodManager.SHOW_FORCED); //顯示軟鍵盤(pán)
                    } else {
                        imm.hideSoftInputFromWindow(v.getWindowToken(), 0); //隱藏軟鍵盤(pán)
                    }
                    if (onSearchFocusListener != null){
                        onSearchFocusListener.searchFocusChange(v,hasFocus);
                    }
                }
            });
            // 監(jiān)聽(tīng)軟鍵盤(pán)的按鍵
            edtSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() {
                @Override
                public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                    //回車(chē)等操作
                    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;
                }
            });
        }
    }

這里涉及兩個(gè)比較啰嗦的東西,光標(biāo)(焦點(diǎn))和軟鍵盤(pán),軟鍵盤(pán)的操做相關(guān)的一個(gè)類(lèi)InputMethodManager,我沒(méi)有很好去理解,只是查了一些大概的用法。

(1)我先給輸入框設(shè)置點(diǎn)擊之后獲取焦點(diǎn)
edtSearch.setFocusable(true);//設(shè)置輸入框可聚集
edtSearch.setFocusableInTouchMode(true);//設(shè)置觸摸聚焦
edtSearch.requestFocus();//請(qǐng)求焦點(diǎn)
edtSearch.findFocus();//獲取焦點(diǎn)

為什么要這樣做,因?yàn)槲抑笠鍪Ы共僮鳎绻粚?xiě)這個(gè)代碼的話,我這邊會(huì)出個(gè)BUG,失焦后就無(wú)法再重新獲取焦點(diǎn)。

(2)失焦操作
/**
     *  讓EditText失去焦點(diǎn)
     */
    public void lostRocus(){
        if(edtSearch != null) {
            edtSearch.setFocusable(false);
        }
    }
(3)關(guān)聯(lián)軟鍵盤(pán)
              public void onFocusChange(View v, boolean hasFocus) {
                    if (hasFocus) {
                        imm.showSoftInput(v, InputMethodManager.SHOW_FORCED); //顯示軟鍵盤(pán)
                    } else {
                        imm.hideSoftInputFromWindow(v.getWindowToken(), 0); //隱藏軟鍵盤(pán)
                    }
                }

獲取焦點(diǎn)后軟鍵盤(pán)彈起,失去焦點(diǎn)后軟鍵盤(pán)消失。

六.全部代碼

項(xiàng)目沒(méi)有放到gayhub,一是有些BUG,我等下會(huì)說(shuō),二是我沒(méi)寫(xiě)自定義布局的demo,三是我沒(méi)寫(xiě)文檔。所以我先寫(xiě)文章,過(guò)后完善了再把項(xiàng)目丟到gayhub。

1.默認(rèn)樣式布局

<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.三個(gè)定義的接口

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();
    }

    /**
     * 設(shè)置屬性
     */
    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);
        // 默認(rèn)的float是px,所以要轉(zhuǎn)成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();
        }
        // 初始化事件監(jiān)聽(tīng)
        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(""))
                ? "請(qǐng)輸入搜索內(nèi)容" : 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) {
            // 點(diǎn)擊事件
            edtSearch.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    edtSearch.setFocusable(true);//設(shè)置輸入框可聚集
                    edtSearch.setFocusableInTouchMode(true);//設(shè)置觸摸聚焦
                    edtSearch.requestFocus();//請(qǐng)求焦點(diǎn)
                    edtSearch.findFocus();//獲取焦點(diǎn)
                }
            });
            // 監(jiān)聽(tīng)焦點(diǎn)
            edtSearch.setOnFocusChangeListener(new OnFocusChangeListener() {
                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    if (hasFocus) {
                        imm.showSoftInput(v, InputMethodManager.SHOW_FORCED); //顯示軟鍵盤(pán)
                    } else {
                        imm.hideSoftInputFromWindow(v.getWindowToken(), 0); //隱藏軟鍵盤(pán)
                    }
                    if (onSearchFocusListener != null){
                        onSearchFocusListener.searchFocusChange(v,hasFocus);
                    }
                }
            });
            // 監(jiān)聽(tīng)軟鍵盤(pán)的按鍵
            edtSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() {
                @Override
                public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                    //回車(chē)等操作
                    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;
                }
            });
        }
    }

    /**
     *  獲取搜索框的內(nèi)容
     */
    public String getSearchContent(){
        if (edtSearch == null){
            return null;
        }
        return edtSearch.getText().toString();
    }

    /**
     *  清空搜索框
     */
    public void clearSearch(){
        edtSearch.setText("");
    }

    /**
     *  讓EditText失去焦點(diǎn)
     */
    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就是轉(zhuǎn)尺寸單位,這些命名就很明顯,自己寫(xiě)個(gè)工具類(lèi)轉(zhuǎn)就行。

伸手黨要用的話只能全抄了,gayhub沒(méi)這么快。

tmp2.gif

模擬一下,軟鍵盤(pán)回車(chē)后失去焦點(diǎn)。

六.BUG

我在玩的時(shí)候玩出個(gè)BUG,關(guān)鍵是這個(gè)BUG我還不知道要怎么去表達(dá),設(shè)置圖片的尺寸

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

我這里默認(rèn)填24dp是正常,我如果在控件中設(shè)置

app:img_size="24dp"
image.png

圖片大小沒(méi)變,但是間距莫名其妙變大了。還有文字也是,用sp的話比正常情況的sp大得多。所以我現(xiàn)在還不懂這個(gè)format="dimension"出了什么毛病,這是其中一個(gè)問(wèn)題。

還有一個(gè)問(wèn)題是軟鍵盤(pán),這個(gè)東西比較容易出BUG,我無(wú)法保證不同的軟鍵盤(pán)或者不同的版本不會(huì)出問(wèn)題,我是感覺(jué)之后可能要做適配的問(wèn)題。

暫時(shí)就這些,簡(jiǎn)單封裝了一下,完善也只能在之后碰到問(wèn)題再去完善,然后之后我有時(shí)間寫(xiě)個(gè)demo寫(xiě)個(gè)文檔再放到gayhub


更新

項(xiàng)目地址

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


BUG修改

之前說(shuō)有幾個(gè)傳資源時(shí)的BUG,我先在這寫(xiě)出來(lái),gayhub的過(guò)后我改了再傳。

1.背景資源的類(lèi)型寫(xiě)錯(cuò)了
seaBackgroup = typedArray.getResourceId(R.styleable.kylin_search_style_search_backgroup,R.drawable.bg_search_default);

這里我之前用getInteger用錯(cuò)了。

2.設(shè)置字體大小

我之前說(shuō)怎么設(shè)置字體大小總是出問(wèn)題,然后發(fā)現(xiàn)是setTextSize方法默認(rèn)是sp的,然后我用getDimension傳進(jìn)來(lái)的會(huì)轉(zhuǎn)成px,這樣就造成了px套到sp上,尺寸就錯(cuò)了,應(yīng)該把類(lèi)型再做一次轉(zhuǎn)換

edtSearch.setTextSize(TypedValue.COMPLEX_UNIT_PX,edt_size);

這個(gè)問(wèn)題我之前也碰到過(guò),只是忘了做筆記,所以不記得了。詳細(xì)的原因可以看下這篇博客,講得很不錯(cuò)。
http://www.itdecent.cn/p/7f2941dbfb17

3.設(shè)置自適應(yīng)大小

我發(fā)現(xiàn)用getDimension如果設(shè)默認(rèn)大小的話就擴(kuò)展性太差了,所以想改成自適應(yīng),但是我又不知道這個(gè)方法要怎么設(shè)置默認(rèn)值為自適應(yīng),所以我就投機(jī)用正負(fù)值來(lái)判斷,默認(rèn)為負(fù)數(shù)就是自適應(yīng)的情況。

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);

補(bǔ)充

我想做個(gè)功能的補(bǔ)充是關(guān)于軟鍵盤(pán)的,有很多時(shí)候,我們需要在軟鍵盤(pán)彈出的情況下,點(diǎn)擊空白處的話就隱藏軟鍵盤(pán)。
而這個(gè)操作我這邊不好一起封裝到searchView里面,我覺(jué)得可以直接在頁(yè)面中用攔截事件來(lái)實(shí)現(xiàn)這功能。

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN){
            // 收軟鍵盤(pán)
            InputMethodManager imm =  (InputMethodManager) getSystemService(this.INPUT_METHOD_SERVICE);
            if (imm.isActive()){
                imm.hideSoftInputFromWindow(searchView.getSearchEditText().getWindowToken(), 0); //隱藏軟鍵盤(pán)
            }
        }
        return super.dispatchTouchEvent(ev);
    }

這樣寫(xiě)就能實(shí)現(xiàn)點(diǎn)擊頁(yè)面時(shí)隱藏軟鍵盤(pán)的操作,比如美團(tuán)的搜索就是點(diǎn)頁(yè)面能隱藏軟鍵盤(pán)。

但是這里有個(gè)問(wèn)題,dispatchTouchEvent方法會(huì)頻繁的調(diào)用,只要一碰到這個(gè)頁(yè)面就會(huì)調(diào)用這個(gè)方法,而我在這里面創(chuàng)建InputMethodManager 的話是不是會(huì)一直創(chuàng)建對(duì)象。

我看Monitors來(lái)測(cè)試,其實(shí)我不是很會(huì)用Monitors,然后用我單身20年的手速不斷搓屏幕,發(fā)現(xiàn)內(nèi)存一直在增長(zhǎng),所以我覺(jué)得InputMethodManager 在dispatchTouchEvent中創(chuàng)建不是很好,把它抽出去,在全局中創(chuàng)建。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,765評(píng)論 25 709
  • 內(nèi)容抽屜菜單ListViewWebViewSwitchButton按鈕點(diǎn)贊按鈕進(jìn)度條TabLayout圖標(biāo)下拉刷新...
    皇小弟閱讀 47,133評(píng)論 22 665
  • 原文鏈接:https://github.com/opendigg/awesome-github-android-u...
    IM魂影閱讀 33,143評(píng)論 6 472
  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線程,因...
    小菜c閱讀 7,295評(píng)論 0 17
  • 大寶八歲一年級(jí) , 寶五個(gè)多月 。對(duì)孩子來(lái)說(shuō),每段時(shí)間都很重要。需要爸爸媽媽滴陪伴與愛(ài)護(hù),鑒于大寶小時(shí)候媽媽...
    hellokico閱讀 301評(píng)論 1 3

友情鏈接更多精彩內(nèi)容