zoukankan      html  css  js  c++  java
  • Android 自定义EditText实现类iOS风格搜索框

    最近在项目中有使用到搜索框的地方,由于其样式要求与iOS的UISearchBar的风格一致。默认情况下,搜索图标和文字是居中的,在获取焦点的时候,图标和文字左移。但是在Android是并没有这样的控件(可能见识少,并不知道有)。通常情况下我们使用组合控件,使用ReleativeLayout或者FrameLayout来实现。此篇并不是使用上述方法实现,其核心是继承系统EditText,重写onDraw方法,来改变默认的左上右下的drawable,实现平移到中间位置。这里暂时只实现了drawableLeft的情况,后续将对其进行更新。先来看看实现效果图: 
     

    直接来看代码实现

    package com.jinlin.custom.iconcenterview;
    
    import android.view.View;
    import android.widget.EditText;
    import android.widget.Toast;
    
    public class MainActivity extends BaseActivity{
        private EditText et_search;
    
        private IconCenterEditText icet_search;
    
        @Override
        public void iniView() {
            setContentView(R.layout.activity_main);
    
            et_search = (EditText) findViewById(R.id.et_search);
            icet_search = (IconCenterEditText) findViewById(R.id.icet_search);
    
            // 实现TextWatcher监听即可
            icet_search.setOnSearchClickListener(new IconCenterEditText.OnSearchClickListener() {
                @Override
                public void onSearchClick(View view) {
                    Toast.makeText(MainActivity.this, "i'm going to seach", Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
    这是主Activity的代码,其继承自BaseActivity基类,BaseActivity的实现详细见上篇博文Android点击空白区域,隐藏输入法软键盘只是在isShouldHideKeyboard(View v, MotionEvent event)方法内部增加一行v.clearFocus();代码进行去除焦点处理,其他均一致。
    private boolean isShouldHideKeyboard(View v, MotionEvent event) {
            if (v != null && (v instanceof EditText)) {
                int[] l = {0, 0};
                v.getLocationInWindow(l);
                int left = l[0],
                        top = l[1],
                        bottom = top + v.getHeight(),
                        right = left + v.getWidth();
                if (event.getX() > left && event.getX() < right
                        && event.getY() > top && event.getY() < bottom) {
                    // 点击EditText的事件,忽略它。
                    return false;
                } else {
                    v.clearFocus();
                    return true;
                }
            }
            // 如果焦点不是EditText则忽略,这个发生在视图刚绘制完,第一个焦点不在EditText上,和用户用轨迹球选择其他的焦点
            return false;
        }

    接下来是自定义View的代码实现


    IconCenterEditText.java

    package com.jinlin.custom.iconcenterview;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.drawable.Drawable;
    import android.text.TextUtils;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.KeyEvent;
    import android.view.View;
    import android.view.inputmethod.InputMethodManager;
    import android.widget.EditText;
    
    /**
     * Created by J!nl!n on 2015/1/26.
     */
    public class IconCenterEditText extends EditText implements View.OnFocusChangeListener, View.OnKeyListener {
        private static final String TAG = IconCenterEditText.class.getSimpleName();
        /**
         * 是否是默认图标再左边的样式
         */
        private boolean isLeft = false;
        /**
         * 是否点击软键盘搜索
         */
        private boolean pressSearch = false;
        /**
         * 软键盘搜索键监听
         */
        private OnSearchClickListener listener;
    
        public void setOnSearchClickListener(OnSearchClickListener listener) {
            this.listener = listener;
        }
    
        public IconCenterEditText(Context context) {
            this(context, null);
            init();
        }
    
        public IconCenterEditText(Context context, AttributeSet attrs) {
            this(context, attrs, android.R.attr.editTextStyle);
            init();
        }
    
        public IconCenterEditText(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init() {
            setOnFocusChangeListener(this);
            setOnKeyListener(this);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            if (isLeft) { // 如果是默认样式,则直接绘制
                super.onDraw(canvas);
            } else { // 如果不是默认样式,需要将图标绘制在中间
                Drawable[] drawables = getCompoundDrawables();
                if (drawables != null) {
                    Drawable drawableLeft = drawables[0];
                    if (drawableLeft != null) {
                        float textWidth = getPaint().measureText(getHint().toString());
                        int drawablePadding = getCompoundDrawablePadding();
                        int drawableWidth = drawableLeft.getIntrinsicWidth();
                        float bodyWidth = textWidth + drawableWidth + drawablePadding;
                        canvas.translate((getWidth() - bodyWidth - getPaddingLeft() - getPaddingRight()) / 2, 0);
                    }
                }
                super.onDraw(canvas);
            }
        }
    
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            Log.d(TAG, "onFocusChange execute");
            // 恢复EditText默认的样式
            if (!pressSearch && TextUtils.isEmpty(getText().toString())) {
                isLeft = hasFocus;
            }
        }
    
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            pressSearch = (keyCode == KeyEvent.KEYCODE_ENTER);
            if (pressSearch && listener != null) {
                /*隐藏软键盘*/
                InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                if (imm.isActive()) {
                    imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), 0);
                }
                listener.onSearchClick(v);
            }
            return false;
        }
    
        public interface OnSearchClickListener {
            void onSearchClick(View view);
        }
    
    }

    此View重写onDraw(Canvas canvas)方法,并实现OnFocusChangeListener, OnKeyListener监听接口,在onFocusChange(View v, boolean hasFocus)方法判断是否需要恢复样式,然后在onDraw(Canvas canvas)进行重绘,实现焦点失去和获取时,平移图标和文字。同时还会判断软键盘搜索键的操作进行处理。其核心代码也就是一下这一小段:

    Drawable[] drawables = getCompoundDrawables();
    if (drawables != null) {
         Drawable drawableLeft = drawables[0];
         if (drawableLeft != null) {
             float textWidth = getPaint().measureText(getHint().toString());
             int drawablePadding = getCompoundDrawablePadding();
             int drawableWidth = drawableLeft.getIntrinsicWidth();
             float bodyWidth = textWidth + drawableWidth + drawablePadding;
             canvas.translate((getWidth() - bodyWidth - getPaddingLeft() - getPaddingRight()) / 2, 0);
          }
    }

    activity_main.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:focusableInTouchMode="true"
        android:orientation="vertical"
        android:padding="@dimen/activity_vertical_margin"
        tools:context=".MainActivity">
    
        <TextView
            style="@style/StyleTextView"
            android:text="默认样式" />
    
        <EditText
            android:id="@+id/et_search"
            style="@style/StyleEditText" />
    
        <TextView
            style="@style/StyleTextView"
            android:text="居中样式" />
    
        <com.jinlin.custom.iconcenterview.IconCenterEditText
            android:id="@+id/icet_search"
            style="@style/StyleEditText" />
    
    </LinearLayout>

    bg_search_bar.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android">
        <solid android:color="@android:color/white" />
        <stroke
            android:width="1px"
            android:color="@android:color/darker_gray" />
        <corners android:radius="3dp" />
    </shape>

    styles.xml

    <resources>
    
        <!-- Base application theme. -->
        <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
            <!-- Customize your theme here. -->
        </style>
    
        <style name="StyleEditText">
            <item name="android:layout_width">match_parent</item>
            <item name="android:layout_height">wrap_content</item>
            <item name="android:background">@drawable/bg_search_bar</item>
            <item name="android:drawablePadding">5dp</item>
            <item name="android:drawableStart">@mipmap/icon_search</item>
            <item name="android:gravity">center_vertical</item>
            <item name="android:imeOptions">actionSearch</item>
            <item name="android:padding">5dp</item>
            <item name="android:singleLine">true</item>
            <item name="android:textColorHint">@color/gray_white</item>
            <item name="android:textSize">16sp</item>
            <item name="android:hint">搜索</item>
        </style>
    
        <style name="StyleTextView">
            <item name="android:layout_width">match_parent</item>
            <item name="android:layout_height">40dp</item>
            <item name="android:gravity">center</item>
            <item name="android:textSize">20sp</item>
        </style>
    
    </resources>

    colors.xml

     <?xml version="1.0" encoding="utf-8"?>
        <resources>
            <color name="gray_white">#ffcccccc</color>
        </resources>

    示例代码下载

  • 相关阅读:
    js 点击复制内容
    tp5 日志的用途以及简单使用
    iOS UIKit:TableView之表格创建(1)
    Linux平台的boost安装全解
    iOS UIKit:CollectionView之布局(2)
    iOS UIKit:CollectionView之设计 (1)
    iOS 网络编程:socket
    Objective-C:内存管理
    iOS UIKit:TabBar Controller
    iOS UIKit:Navigation Controllers
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/7344034.html
Copyright © 2011-2022 走看看