IME关于输入法横屏全屏显示问题-Android14
1、输入法全屏模式updateFullscreenMode1.1 全屏模式判断1.2 全屏模式布局设置
2、应用侧关闭输入法全屏模式2.1 调用输入法的应用设置flag2.2 继承InputMethodService.java的输入法应用覆盖onEvaluateFullscreenMode方法
InputMethodManagerService启动-Android12
1、输入法全屏模式updateFullscreenMode
frameworks/base/core/java/android/inputmethodservice/InputMethodService.java
1.1 全屏模式判断
boolean isFullscreen = mShowInputRequested && onEvaluateFullscreenMode();: 判断是否全屏显示输入法,其中mShowInputRequested请求一般就是 true 。onEvaluateFullscreenMode(): 默认横屏全屏模式显示,若在横屏下有EditorInfo.IME_FLAG_NO_FULLSCREEN或者EditorInfo.IME_INTERNAL_FLAG_APP_WINDOW_PORTRAIT不使用fullscreen-mode模式
/**
* Override this to control when the input method should run in
* fullscreen mode. The default implementation runs in fullsceen only
* when the screen is in landscape mode. If you change what
* this returns, you will need to call {@link #updateFullscreenMode()}
* yourself whenever the returned value may have changed to have it
* re-evaluated and applied.
*/
public boolean onEvaluateFullscreenMode() {
Configuration config = getResources().getConfiguration();
if (config.orientation != Configuration.ORIENTATION_LANDSCAPE) {
return false;
}
if (mInputEditorInfo != null
&& ((mInputEditorInfo.imeOptions & EditorInfo.IME_FLAG_NO_FULLSCREEN) != 0
// If app window has portrait orientation, regardless of what display orientation
// is, IME shouldn't use fullscreen-mode.
|| (mInputEditorInfo.internalImeOptions
& EditorInfo.IME_INTERNAL_FLAG_APP_WINDOW_PORTRAIT) != 0)) {
return false;
}
return true;
}
1.2 全屏模式布局设置
设置mFullscreenArea的LayoutParams属性,全屏模式下lp.height = 0;、lp.weight = 1;添加ExtractView,即布局frameworks/base/core/res/res/layout/input_method_extract_view.xml
/**
* Re-evaluate whether the input method should be running in fullscreen
* mode, and update its UI if this has changed since the last time it
* was evaluated. This will call {@link #onEvaluateFullscreenMode()} to
* determine whether it should currently run in fullscreen mode. You
* can use {@link #isFullscreenMode()} to determine if the input method
* is currently running in fullscreen mode.
*/
public void updateFullscreenMode() {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.updateFullscreenMode");
boolean isFullscreen = mShowInputRequested && onEvaluateFullscreenMode();
boolean changed = mLastShowInputRequested != mShowInputRequested;
if (mIsFullscreen != isFullscreen || !mFullscreenApplied) {
changed = true;
mIsFullscreen = isFullscreen;
reportFullscreenMode();
mFullscreenApplied = true;
initialize();
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
mFullscreenArea.getLayoutParams();
if (isFullscreen) {
mFullscreenArea.setBackgroundDrawable(mThemeAttrs.getDrawable(
com.android.internal.R.styleable.InputMethodService_imeFullscreenBackground));
lp.height = 0;
lp.weight = 1;
} else {
mFullscreenArea.setBackgroundDrawable(null);
lp.height = LinearLayout.LayoutParams.WRAP_CONTENT;
lp.weight = 0;
}
((ViewGroup)mFullscreenArea.getParent()).updateViewLayout(
mFullscreenArea, lp);
if (isFullscreen) {
if (mExtractView == null) {
View v = onCreateExtractTextView();
if (v != null) {
setExtractView(v);
}
}
startExtractingText(false);
}
updateExtractFrameVisibility();
}
if (changed) {
onConfigureWindow(mWindow.getWindow(), isFullscreen, !mShowInputRequested);
mLastShowInputRequested = mShowInputRequested;
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
2、应用侧关闭输入法全屏模式
2.1 调用输入法的应用设置flag
设置EditorInfo.IME_FLAG_NO_FULLSCREEN属性,而EditorInfo.IME_INTERNAL_FLAG_APP_WINDOW_PORTRAIT属性是framework内部使用。 即xml布局中 android:imeOptions="flagNoFullscreen" ,或者代码设置mEdtView.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN);
imeOptions 属性并不只有IME_FLAG_NO_FULLSCREEN功能: IME_ACTION_UNSPECIFIED actionUnspecified IME_ACTION_NONE actionNone IME_ACTION_GO actionGo IME_ACTION_SEARCH actionSearch IME_ACTION_SEND actionSend IME_ACTION_NEXT actionNext IME_ACTION_DONE actionDone IME_ACTION_PREVIOUS actionPrevious IME_FLAG_NO_PERSONALIZED_LEARNING flagNoPersonalizedLearning IME_FLAG_NO_FULLSCREEN flagNoFullscreen IME_FLAG_NAVIGATE_PREVIOUS flagNavigatePrevious IME_FLAG_NAVIGATE_NEXT flagNavigateNext IME_FLAG_NO_EXTRACT_UI flagNoExtractUi IME_FLAG_NO_ACCESSORY_ACTION flagNoAccessoryAction IME_FLAG_NO_ENTER_ACTION flagNoEnterAction IME_FLAG_FORCE_ASCII flagForceAscii
设置 imeOptions 属性并不一定生效,假如输入法应用覆盖了 onEvaluateFullscreenMode 方法
frameworks/base/core/java/android/view/inputmethod/EditorInfo.java
/**
* Flag of {@link #imeOptions}: used to request that the IME never go
* into fullscreen mode.
* By default, IMEs may go into full screen mode when they think
* it's appropriate, for example on small screens in landscape
* orientation where displaying a software keyboard may occlude
* such a large portion of the screen that the remaining part is
* too small to meaningfully display the application UI.
* If this flag is set, compliant IMEs will never go into full screen mode,
* and always leave some space to display the application UI.
* Applications need to be aware that the flag is not a guarantee, and
* some IMEs may ignore it.
*/
public static final int IME_FLAG_NO_FULLSCREEN = 0x2000000;
/**
* Masks for {@link imeOptions}
*
*
* |-------|-------|-------|-------|
* 1111 IME_MASK_ACTION
* |-------|-------|-------|-------|
* IME_ACTION_UNSPECIFIED
* 1 IME_ACTION_NONE
* 1 IME_ACTION_GO
* 11 IME_ACTION_SEARCH
* 1 IME_ACTION_SEND
* 1 1 IME_ACTION_NEXT
* 11 IME_ACTION_DONE
* 111 IME_ACTION_PREVIOUS
* 1 IME_FLAG_NO_PERSONALIZED_LEARNING
* 1 IME_FLAG_NO_FULLSCREEN
* 1 IME_FLAG_NAVIGATE_PREVIOUS
* 1 IME_FLAG_NAVIGATE_NEXT
* 1 IME_FLAG_NO_EXTRACT_UI
* 1 IME_FLAG_NO_ACCESSORY_ACTION
* 1 IME_FLAG_NO_ENTER_ACTION
* 1 IME_FLAG_FORCE_ASCII
* |-------|-------|-------|-------|
*/
/**
* Extended type information for the editor, to help the IME better
* integrate with it.
*/
public int imeOptions = IME_NULL;
/**
* A string supplying additional information options that are
* private to a particular IME implementation. The string must be
* scoped to a package owned by the implementation, to ensure there are
* no conflicts between implementations, but other than that you can put
* whatever you want in it to communicate with the IME. For example,
* you could have a string that supplies an argument like
* "com.example.myapp.SpecialMode=3"
. This field is can be
* filled in from the {@link android.R.attr#privateImeOptions}
* attribute of a TextView.
*/
public String privateImeOptions = null;
/**
* Masks for {@link internalImeOptions}
*
*
* 1 IME_INTERNAL_FLAG_APP_WINDOW_PORTRAIT
* |-------|-------|-------|-------|
*/
/**
* Same as {@link android.R.attr#imeOptions} but for framework's internal-use only.
* @hide
*/
public int internalImeOptions = IME_NULL;
frameworks/base/core/java/android/widget/TextView.java
case com.android.internal.R.styleable.TextView_imeOptions:
createEditorIfNeeded();
mEditor.createInputContentTypeIfNeeded();
mEditor.mInputContentType.imeOptions = a.getInt(attr,
mEditor.mInputContentType.imeOptions);
break;
/**
* Change the editor type integer associated with the text view, which
* is reported to an Input Method Editor (IME) with {@link EditorInfo#imeOptions}
* when it has focus.
* @see #getImeOptions
* @see android.view.inputmethod.EditorInfo
* @attr ref android.R.styleable#TextView_imeOptions
*/
public void setImeOptions(int imeOptions) {
createEditorIfNeeded();
mEditor.createInputContentTypeIfNeeded();
mEditor.mInputContentType.imeOptions = imeOptions;
}
frameworks/base/core/res/res/values/attrs.xml
2.2 继承InputMethodService.java的输入法应用覆盖onEvaluateFullscreenMode方法
覆盖onEvaluateFullscreenMode方法,返false就可以了。如Android14上google输入法LatinImeGoogle.apk
frameworks/base/core/java/android/inputmethodservice/InputMethodService.java
/**
* Override this to control when the input method should run in
* fullscreen mode. The default implementation runs in fullsceen only
* when the screen is in landscape mode. If you change what
* this returns, you will need to call {@link #updateFullscreenMode()}
* yourself whenever the returned value may have changed to have it
* re-evaluated and applied.
*/
public boolean onEvaluateFullscreenMode() {
Configuration config = getResources().getConfiguration();
if (config.orientation != Configuration.ORIENTATION_LANDSCAPE) {
return false;
}
if (mInputEditorInfo != null
&& ((mInputEditorInfo.imeOptions & EditorInfo.IME_FLAG_NO_FULLSCREEN) != 0
// If app window has portrait orientation, regardless of what display orientation
// is, IME shouldn't use fullscreen-mode.
|| (mInputEditorInfo.internalImeOptions
& EditorInfo.IME_INTERNAL_FLAG_APP_WINDOW_PORTRAIT) != 0)) {
return false;
}
return true;
}