Android点击前一个焦点之外的地方使之失去焦点并隐藏软键盘

package matroleox.bscalculator;

import android.app.Activity;
import android.content.Context;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;

public class FocusCleaner {
    private View previousFocus;

    /**
     * the default is to hide softKeyboard.
     * @see #cleanFocus(Activity, MotionEvent, boolean)
     * */
    public void cleanFocus(Activity activity, MotionEvent currentMotionEvent) {
        cleanFocus(activity, currentMotionEvent, true);
    }

    /**
    * The method must be put in the method dispatchTouchEvent of an Activity
    * and the method dispatchTouchEvent must call super.dispatchTouchEvent(ev) at its first line.
    * For example
    * public boolean dispatchTouchEvent(MotionEvent ev) {
    *    boolean isConsumed = super.dispatchTouchEvent(ev);
    *    focusCleaner.cleanFocus(this, ev);
    *    return isConsumed;
    * }
    * */
    public void cleanFocus(Activity activity, MotionEvent currentMotionEvent, boolean hideSoftKeyboard) {
        final int action = currentMotionEvent.getAction();
        if (action == MotionEvent.ACTION_DOWN) {
            previousFocus = activity.getCurrentFocus();
            if (isOutsidePreviousFocus(previousFocus, currentMotionEvent)) previousFocus.clearFocus();
        } else if (hideSoftKeyboard
            && action == MotionEvent.ACTION_UP
            && activity.getCurrentFocus() == null
        ) {
            hideSoftKeyboard(previousFocus, activity);
        }
    }

    private boolean isOutsidePreviousFocus(View previousFocus, MotionEvent currentMotionEvent) {
        if (previousFocus == null) return false;
        final int X = 0;
        final int Y = 1;
        final int[] previousFocusStart = new int[2];
        previousFocus.getLocationInWindow(previousFocusStart);
        final int[] previousFocusEnd = new int[2];
        previousFocusEnd[X] = previousFocusStart[X] + previousFocus.getWidth();
        previousFocusEnd[Y] = previousFocusStart[Y] + previousFocus.getHeight();
        final float currentTouchX = currentMotionEvent.getX();
        final float currentTouchY = currentMotionEvent.getY();

        return !(currentTouchX > previousFocusStart[X]
            && currentTouchX < previousFocusEnd[X]
            && currentTouchY > previousFocusStart[Y]
            && currentTouchY < previousFocusEnd[Y]);
    }

    private void hideSoftKeyboard(View v, Activity activity) {
        if (v == null) return;
        InputMethodManager im =
                (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
        if(im != null) im.hideSoftInputFromWindow(v.getWindowToken(), 0);
    }
}

down 中是之前的焦点
up 中是当前焦点

使用

在Activity中重写dispatchTouchEvent

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    boolean isConsumed = super.dispatchTouchEvent(ev);
    focusCleaner.cleanFocus(this, ev);
    return isConsumed;
}
posted @ 2022-04-04 23:32  MatroLeox  阅读(291)  评论(0编辑  收藏  举报