Android api 28 9.0 EditText无法自动弹出软键盘(windowSoftInputMod stateAlwaysVisible targetSdkVersion)

编程入门 行业动态 更新时间:2024-10-08 14:44:54

Android api 28 9.0 EditText无法<a href=https://www.elefans.com/category/jswz/34/1652880.html style=自动弹出软键盘(windowSoftInputMod stateAlwaysVisible targetSdkVersion)"/>

Android api 28 9.0 EditText无法自动弹出软键盘(windowSoftInputMod stateAlwaysVisible targetSdkVersion)

很简单的需求:打开界面就弹出软键盘

于是:

//build.gradle中
targetSdkVersion 27//Mainfest中
android:windowSoftInputMode="adjustResize|stateVisible"//xml中
<EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"/>

很开心的就去玩耍了。

有一天,心血来潮把targetSdkVersion升级到28了。

然后就是在9.0及以上的手机上无论怎么骚键盘都不鸟你?

改适配版本还能影响代码逻辑?一万只草泥马奔腾而过

查看日志发现一句报错:

InputMethodManagerService: SOFT_INPUT_STATE_VISIBLE is ignored because there is no focused view that also returns true from View#onCheckIsTextEditor()

打开TextView的onCheckIsTextEditor方法,天真的以为需要加上inputType就行了

    @Overridepublic boolean onCheckIsTextEditor() {return mEditor != null && mEditor.mInputType != EditorInfo.TYPE_NULL;}

然而现实是残酷的...(啪啪啪打脸中)

打开InputMethodManagerService,找到报错的代码(需要api28及以上的源码),如下:

                            if (InputMethodUtils.isSoftInputModeStateVisibleAllowed(unverifiedTargetSdkVersion, controlFlags)) {if (attribute != null) {res = startInputUncheckedLocked(cs, inputContext,missingMethods, attribute, controlFlags,startInputReason);didStart = true;}showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);} else {Slog.e(TAG, "SOFT_INPUT_STATE_VISIBLE is ignored because"+ " there is no focused view that also returns true from"+ " View#onCheckIsTextEditor()");}

打开isSoftInputModeStateVisibleAllowed方法

    public static boolean isSoftInputModeStateVisibleAllowed(int targetSdkVersion, int controlFlags) {if (targetSdkVersion < Build.VERSION_CODES.P) {// for compatibility.return true;}if ((controlFlags & CONTROL_WINDOW_VIEW_HAS_FOCUS) == 0) {return false;}if ((controlFlags & CONTROL_WINDOW_IS_TEXT_EDITOR) == 0) {return false;}return true;}

小于28的就返回正常,否则就需要满足2个条件。又一万只草泥马奔腾而过...

controlFlags是个什么鬼玩意?

在InputMethodManager的onPostWindowFocus里有

    public void onPostWindowFocus(View rootView, View focusedView,@SoftInputModeFlags int softInputMode, boolean first, int windowFlags) {...int controlFlags = 0;if (focusedView != null) {controlFlags |= CONTROL_WINDOW_VIEW_HAS_FOCUS;if (focusedView.onCheckIsTextEditor()) {controlFlags |= CONTROL_WINDOW_IS_TEXT_EDITOR;}}...}

原来是由focusedView决定的,此时灵光一现,focusedView肯定是EditText了,继续翻源码,果然在ViewRootImpl的handleWindowFocusChanged方法里出现了

    private void handleWindowFocusChanged() {...if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) {imm.onPostWindowFocus(mView, mView.findFocus(),mWindowAttributes.softInputMode,!mHasHadWindowFocus, mWindowAttributes.flags);}...}

此时更验证了我的猜想,于是很愉快的在EditText加上了获取焦点的方法:

<EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:focusableInTouchMode="true"android:focusable="true"/>

再次运行,脸都被打肿了...

debug才发现mView.findFocus()里的mFocused一直是null并不是EditText

//ViewGroup@Overridepublic View findFocus() {if (DBG) {System.out.println("Find focus in " + this + ": flags="+ isFocused() + ", child=" + mFocused);}if (isFocused()) {return this;}if (mFocused != null) {return mFocused.findFocus();}return null;}

为什么是null

在api23的ViewRootImpl的performTraversals方法里这样写的:第一次的时候,没有焦点就默认调用获取焦点的逻辑

...if (mFirst) {// handle first focus requestif (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: mView.hasFocus()="+ mView.hasFocus());if (mView != null) {//根布局,肯定不是nullif (!mView.hasFocus()) {mView.requestFocus(View.FOCUS_FORWARD);if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: requested focused view="+ mView.findFocus());} else {if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: existing focused view="+ mView.findFocus());}}}
...

但在api28就变了:sAlwaysAssignFocus是false,!isInTouchMode()也是false,然后焦点就被go...吃了

...sAlwaysAssignFocus = mTargetSdkVersion < Build.VERSION_CODES.P;
...if (mFirst) {if (sAlwaysAssignFocus || !isInTouchMode()) {//isInTouchMode表示手机是不是触摸模式,肯定是true,取反就变成false了// handle first focus requestif (DEBUG_INPUT_RESIZE) {Log.v(mTag, "First: mView.hasFocus()=" + mView.hasFocus());}if (mView != null) {if (!mView.hasFocus()) {mView.restoreDefaultFocus();if (DEBUG_INPUT_RESIZE) {Log.v(mTag, "First: requested focused view=" + mView.findFocus());}} else {if (DEBUG_INPUT_RESIZE) {Log.v(mTag, "First: existing focused view=" + mView.findFocus());}}}}
...

仔细理一下思路:配置文件配置打开Activity要弹出键盘>api28却不给EditText焦点>逻辑判断没有焦点就不弹键盘...

******奔腾而过

 

经过博主最强大脑的深思熟虑,最终只要加上如下一行即可:

mEt.requestFocus();

...........................................................................................

更多推荐

Android api 28 9.0 EditText无法自动弹出软键盘(windowSoftInputMod stateAlwaysVisible targe

本文发布于:2024-03-08 03:53:45,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1719768.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:自动弹出   键盘   Android   api   stateAlwaysVisible

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!