Android进阶之路 - 常见软键盘操作行为

在开发中关于软键盘的需求层出不穷,有些东西以前已经记录过了,最近又遇到一些新的索性一起重新记录一下吧 ~

我的那些软键盘Blog ~

自动弹出软键盘

/**
* 查看当前键盘状态, 如显示则影藏,如影藏则展示~
*/
private void showKeyboard(){
        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        inputMethodManager.showSoftInput(editText, 0);
    }

隐藏软键盘

  • a方式
   /**
    *隐藏软键盘
    */
    void hintKeyboard() {
        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        if (inputMethodManager.isActive()) {
            inputMethodManager.hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), 0);
        }
    }
  • b方式
  /**
     * des:隐藏软键盘,这种方式参数为activity
     */
    public static void hideInputForce(Activity activity) {
        if (activity == null || activity.getCurrentFocus() == null) {
            return;
        }
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(INPUT_METHOD_SERVICE);
        if (imm != null) {
            imm.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }

获取软键盘的高度

  • 常规方式
     et.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener(){
            //当键盘弹出隐藏的时候会 调用此方法。
            @Override
            public void onGlobalLayout() {
                Rect r = new Rect();
                //获取当前界面可视部分
                MainActivity.this.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
                //获取屏幕的高度
                int screenHeight =  MainActivity.this.getWindow().getDecorView().getRootView().getHeight();
                //此处就是用来获取键盘的高度的, 在键盘没有弹出的时候 此高度为0 键盘弹出的时候为一个正数
                int heightDifference = screenHeight - r.bottom;
                Log.d("Keyboard Size", "Size: " + heightDifference);
            } 
	 });
  • b方式(2022-亲测)

来源很多,我主要借鉴自这里 - >

注册监听:一般我们在 Activity 的 onCreate()方法中开始监听

 @Override
 protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //......
    getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener);
}

注销监听:当 Activity 被销毁的时候,一定要移除监听,否则就会产生内存泄漏

@Override
protected void onDestroy() {
    super.onDestroy();
    getWindow().getDecorView().getViewTreeObserver().removeOnGlobalLayoutListener(mGlobalLayoutListener);
}

监听事件

 //记录原始窗口高度
    private var mWindowHeight = 0
    private val mGlobalLayoutListener =
    	ViewTreeObserver.OnGlobalLayoutListener {
            val r = Rect()
            //获取当前窗口实际的可见区域
            window.decorView.getWindowVisibleDisplayFrame(r)
            val height = r.height()
            if (mWindowHeight == 0) {
                //一般情况下,这是原始的窗口高度
                mWindowHeight = height
            } else {
                if (mWindowHeight != height) {
                    //两次窗口高度相减,就是软键盘高度
                    val softKeyboardHeight = mWindowHeight - height
                    println("SoftKeyboard height = $softKeyboardHeight")
                }
            }
        }
  • c方式(未亲测)
//一个静态变量存储高度
public static int keyboardHeight = 0;
    boolean isVisiableForLast = false;
    ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = null;
    public void addOnSoftKeyBoardVisibleListener() {
        getKeyboradHeight();
        if(keyboardHeight>0){
            return;
        }
        final View decorView = getWindow().getDecorView();
        onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect rect = new Rect();
                decorView.getWindowVisibleDisplayFrame(rect);
                //计算出可见屏幕的高度
                int displayHight = rect.bottom - rect.top;
                //获得屏幕整体的高度
                int hight = decorView.getHeight();
                boolean visible = (double) displayHight / hight < 0.8;
                int statusBarHeight = 0;
                try {
                    Class<?> c = Class.forName("com.android.internal.R$dimen");
                    Object obj = c.newInstance();
                    Field field = c.getField("status_bar_height");
                    int x = Integer.parseInt(field.get(obj).toString());
                    statusBarHeight = getContext().getResources().getDimensionPixelSize(x);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                if(visible&&visible!= isVisiableForLast){
                    //获得键盘高度
                    keyboardHeight = hight - displayHight-statusBarHeight;
                    Logger.sl(Log.DEBUG,"MMSL",keyboardHeight);

                }
                isVisiableForLast = visible;
            }
        };
        decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
    }

监听软键盘状态(弹出收回)

Android开发之监听软键盘状态(弹出收回)

  • 自定义监听类 KeyboardStateObserver(可直接Copy使用)
package 自己的当前的包名
/**
 * @author MrLiu
 * @date 2019/9/12
 * desc
 */
import android.app.Activity;
import android.graphics.Rect;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;

public class KeyboardStateObserver {

    private static final String TAG = KeyboardStateObserver.class.getSimpleName();

    public static KeyboardStateObserver getKeyboardStateObserver(Activity activity) {
        return new KeyboardStateObserver(activity);
    }

    private View mChildOfContent;
    private int usableHeightPrevious;
    private OnKeyboardVisibilityListener listener;

    public void setKeyboardVisibilityListener(OnKeyboardVisibilityListener listener) {
        this.listener = listener;
    }

    private KeyboardStateObserver(Activity activity) {
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
        mChildOfContent = content.getChildAt(0);
        mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            public void onGlobalLayout() {
                possiblyResizeChildOfContent();
            }
        });
    }

    private void possiblyResizeChildOfContent() {
        int usableHeightNow = computeUsableHeight();
        if (usableHeightNow != usableHeightPrevious) {
            int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;
            if (heightDifference > (usableHeightSansKeyboard / 4)) {
                if (listener != null) {
                    listener.onKeyboardShow();
                }
            } else {
                if (listener != null) {
                    listener.onKeyboardHide();
                }
            }
            usableHeightPrevious = usableHeightNow;
            Log.d(TAG,"usableHeightNow: " + usableHeightNow + " | usableHeightSansKeyboard:" + usableHeightSansKeyboard + " | heightDifference:" + heightDifference);
        }
    }

    private int computeUsableHeight() {
        Rect r = new Rect();
        mChildOfContent.getWindowVisibleDisplayFrame(r);

        Log.d(TAG,"rec bottom>" + r.bottom + " | rec top>" + r.top);
        return (r.bottom - r.top);// 全屏模式下: return r.bottom
    }

    public interface OnKeyboardVisibilityListener {
        void onKeyboardShow();

        void onKeyboardHide();
    }
}

  • 使用方式

注意:此方式必须在弹出键盘时候,使页面原有布局发生变动,所以如果不起作用的话可以试着在AndroidManifest.xml文件中设置android:windowSoftInputMode=”adjustResize|stateHidden“”

@Override
 protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);

     KeyboardStateObserver.getKeyboardStateObserver(this).
             setKeyboardVisibilityListener(new KeyboardStateObserver.OnKeyboardVisibilityListener() {
         @Override
         public void onKeyboardShow() {
             Toast.makeText(MainActivity.this,"键盘弹出",Toast.LENGTH_SHORT).show();
         }

         @Override
         public void onKeyboardHide() {
             Toast.makeText(MainActivity.this,"键盘收回",Toast.LENGTH_SHORT).show();
         }
     });
 }

EditText点击外部时候失去焦点

借鉴于此

open class BaseActivity: AppCompatActivity() {

    var editText: EditText? = null

    //使editText点击外部时候失去焦点
    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        if (ev.action == MotionEvent.ACTION_DOWN) {
            val v = currentFocus
            if (isShouldHideInput(v, ev)) { //点击editText控件外部
                val imm: InputMethodManager =
                    getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                if (imm != null) {
                    assert(v != null)
                    hideInput(this)
                    if (editText != null) {
                        editText!!.clearFocus()
                    }
                }
            }
            return super.dispatchTouchEvent(ev)
        }
        // 必不可少,否则所有的组件都不会有TouchEvent了
        return window.superDispatchTouchEvent(ev) || onTouchEvent(ev)
    }

    fun isShouldHideInput(v: View?, event: MotionEvent): Boolean {
        if (v != null && v is EditText) {
            editText = v
            val leftTop = intArrayOf(0, 0)
            //获取输入框当前的location位置
            v.getLocationInWindow(leftTop)
            val left = leftTop[0]
            val top = leftTop[1]
            val bottom = top + v.getHeight()
            val right = left + v.getWidth()
            return !(event.x > left && event.x < right && event.y > top && event.y < bottom)
        }
        return false
    }

    /**
     * 隐藏键盘
     */
    fun hideInput(activity: Activity) {
        val imm = MyApplication.context.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
        val v: View ?= activity.window.peekDecorView()
        if (null != v) {
            imm.hideSoftInputFromWindow(v.windowToken, 0)
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

远方那座山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值