继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

仿微信 - 触摸除输入框以外的其它区域自动隐藏软键盘

繁华开满天机
关注TA
已关注
手记 134
粉丝 15
获赞 68

5be0592d0001ea1003420678.jpg



很多应用里面每次输入完一段文本过后要自己去隐藏软键盘,各种输入法、各种切换输入类型后、各种找不到隐藏软件盘的按钮。看到微信的好友聊天的时候点击输入框以外其它区域自动隐藏软键盘的功能非常实用就自己实现了一个。

实现思路:利用ViewGroup的dispatchTouchEvent拦截触摸事件,然后检查软件盘状态和点击位置是否为EditText, 如果不是就隐藏软键盘。

不多说直接上代码:

自定义控件 LinearLayoutAutoHintInputMethod 完美实现自动隐藏软键盘的功能,只需要把这个控件替换根布局中使用的布局就可以了。

如果不想使用LinearLayout布局,只需要将LinearLayout替换成其它ViewGroup就可以了。

/** 自动隐藏软件盘的布局 */
public class LinearLayoutAutoHintInputMethod extends LinearLayout {
    /** 自动隐藏软件盘的布局 */
    public LinearLayoutAutoHintInputMethod(Context context) {
        this (context, null);
    }
    /** 自动隐藏软件盘的布局 */
    public LinearLayoutAutoHintInputMethod(Context context, AttributeSet attrs) {
        this (context, attrs, 0);
    }
    /** 自动隐藏软件盘的布局 */
    public LinearLayoutAutoHintInputMethod(Context context, AttributeSet attrs, int defStyle) {
        super (context, attrs, defStyle);
        setFocusable (true);
        setFocusableInTouchMode (true);
    }
    @Override
    protected void onAttachedToWindow(){
        super.onAttachedToWindow ();
        initFocusChangeListener (this);
    }
    /** 初始化焦点变化监听 */
    private void initFocusChangeListener(ViewGroup v){
        for ( int i = 0 ; i < v.getChildCount () ; i++ ) {
            View view = v.getChildAt (i);
            view.setOnFocusChangeListener (mFocusChangeListener);
            if (view instanceof ViewGroup) {
                initFocusChangeListener ((ViewGroup) view);
            } else {
                ArrayList<View> TouchableViews = view.getTouchables ();
                for ( View child : TouchableViews ) {
                    child.setOnFocusChangeListener (mFocusChangeListener);
                }
            }
        }
    }
    /** 当前获得焦点的View */
    private View                  mCurrentFouceView    = null;
    private OnFocusChangeListener mFocusChangeListener = new OnFocusChangeListener () {
                                                           public void onFocusChange(View v,boolean hasFocus){
                                                               if (!hasFocus) mCurrentFouceView = null;
                                                               else mCurrentFouceView = v;
                                                           }
                                                       };
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev){
        if (ev.getAction () == MotionEvent.ACTION_DOWN) {
            // View v = ((Activity) getContext ()).getCurrentFocus ();
            View v = mCurrentFouceView;
            if (isShouldHideInput (v, ev)) { // 如果虚拟键盘为弹出状态执行一下操作
                // 还需要判断当前点击的地方不为另外一个EditText,否则会出现虚拟键盘跳跃的错误
                boolean isNextEditText = false;
                View clickView = getViewAtViewGroup ((int) ev.getX (), (int) ev.getY ());
                if (clickView != null && clickView instanceof EditText) isNextEditText = true;
                if (!isNextEditText) { // 一下点击的控件不是一个EditText
                    InputMethodManager imm = (InputMethodManager) getContext ().getSystemService (Context.INPUT_METHOD_SERVICE);
                    if (imm != null) {
                        imm.hideSoftInputFromWindow (v.getWindowToken (), 0);
                        v.clearFocus ();
                    }
                }
            }
        }
        return super.dispatchTouchEvent (ev);
    }
    /** 判断虚拟键盘是否被弹出 */
    public boolean isShouldHideInput(View v,MotionEvent event){
        if (v != null && (v instanceof EditText)) {
            int[] fatherLeftTop = { 0, 0 }; // 父控件在屏幕中的绝对坐标
            getLocationOnScreen (fatherLeftTop);
            int[] chileLeftTop = { 0, 0 };
            v.getLocationOnScreen (chileLeftTop);
            // 子控件在屏幕中的绝对坐标需要减去父控件的绝对坐标才能匹配真正的坐标
            int left = chileLeftTop[0] - fatherLeftTop[0];
            int top = chileLeftTop[1] - fatherLeftTop[1];
            int right = left + v.getWidth ();
            int bottom = top + v.getHeight ();
            if (new RectF (left,top,right,bottom).contains (event.getX (), event.getY ())) {
                // 点击的是输入框区域,保留点击EditText的事件
                return false;
            } else {
                return true;
            }
        }
        return false;
    }
    /**
     * 根据坐标获取相对应的子控件 在重写ViewGroup使用
     * 
     * @param x坐标
     * @param y坐标
     * @return 目标View
     */
    public View getViewAtViewGroup(int x,int y){
        return findViewByXY (this, x, y);
    }
    private View findViewByXY(View view,int x,int y){
        View targetView = null;
        if (view instanceof ViewGroup) {
            ViewGroup v = (ViewGroup) view;
            for ( int i = 0 ; i < v.getChildCount () ; i++ ) {
                targetView = findViewByXY (v.getChildAt (i), x, y);
                if (targetView != null) {
                    break;
                }
            }
        } else {
            targetView = getTouchTarget (view, x, y);
        }
        return targetView;
    }
    private View getTouchTarget(View view,int x,int y){
        // 判断view是否可以聚焦
        ArrayList<View> TouchableViews = view.getTouchables ();
        for ( View child : TouchableViews ) {
            if (isTouchPointInView (child, x, y)) { return child; }
        }
        return null;
    }
    private boolean isTouchPointInView(View view,int x,int y){
        int[] fatherLeftTop = { 0, 0 }; // 父控件在屏幕中的绝对坐标
        getLocationOnScreen (fatherLeftTop);
        int[] location = new int[2];
        view.getLocationOnScreen (location);
        int left = location[0] - fatherLeftTop[0];
        int top = location[1] - fatherLeftTop[1];
        int right = left + view.getMeasuredWidth ();
        int bottom = top + view.getMeasuredHeight ();
        Rect R = new Rect (left,top,right,bottom);
        if (view.isClickable () && R.contains (x, y)) { return true; }
        return false;
    }
}


Demo下载地址:http://download.csdn.net/detail/ftmtshuashua/9067007

原文链接:http://www.apkbus.com/blog-202342-59407.html

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP