当前位置: 首页 > article >正文

IME关于输入法横屏全屏显示问题-Android14

IME关于输入法横屏全屏显示问题-Android14

  • 1、输入法全屏模式updateFullscreenMode
    • 1.1 全屏模式判断
    • 1.2 全屏模式布局设置
  • 2、应用侧关闭输入法全屏模式
    • 2.1 调用输入法的应用设置flag
    • 2.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 全屏模式布局设置

  • 设置mFullscreenAreaLayoutParams属性,全屏模式下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

  1. 设置EditorInfo.IME_FLAG_NO_FULLSCREEN属性,而EditorInfo.IME_INTERNAL_FLAG_APP_WINDOW_PORTRAIT属性是framework内部使用。 即xml布局中 android:imeOptions="flagNoFullscreen" ,或者代码设置mEdtView.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN);

  2. 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

  3. 设置 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}
 *
 * <pre>
 * |-------|-------|-------|-------|
 *                              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
 * |-------|-------|-------|-------|</pre>
 */

/**
 * 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
 * <code>"com.example.myapp.SpecialMode=3"</code>.  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}
 *
 * <pre>
 *                                 1 IME_INTERNAL_FLAG_APP_WINDOW_PORTRAIT
 * |-------|-------|-------|-------|</pre>
 */

/**
 * 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

<!-- Additional features you can enable in an IME associated with an editor
      to improve the integration with your application.  The constants
      here correspond to those defined by
      {@link android.view.inputmethod.EditorInfo#imeOptions}. -->
 <attr name="imeOptions">
     <!-- There are no special semantics associated with this editor. -->
     <flag name="normal" value="0x00000000" />
     <!-- There is no specific action associated with this editor, let the
          editor come up with its own if it can.
          Corresponds to
          {@link android.view.inputmethod.EditorInfo#IME_NULL}. -->
     <flag name="actionUnspecified" value="0x00000000" />
     <!-- This editor has no action associated with it.
          Corresponds to
          {@link android.view.inputmethod.EditorInfo#IME_ACTION_NONE}. -->
     <flag name="actionNone" value="0x00000001" />
     <!-- The action key performs a "go"
          operation to take the user to the target of the text they typed.
          Typically used, for example, when entering a URL.
          Corresponds to
          {@link android.view.inputmethod.EditorInfo#IME_ACTION_GO}. -->
     <flag name="actionGo" value="0x00000002" />
     <!-- The action key performs a "search"
          operation, taking the user to the results of searching for the text
          the have typed (in whatever context is appropriate).
          Corresponds to
          {@link android.view.inputmethod.EditorInfo#IME_ACTION_SEARCH}. -->
     <flag name="actionSearch" value="0x00000003" />
     <!-- The action key performs a "send"
          operation, delivering the text to its target.  This is typically used
          when composing a message.
          Corresponds to
          {@link android.view.inputmethod.EditorInfo#IME_ACTION_SEND}. -->
     <flag name="actionSend" value="0x00000004" />
     <!-- The action key performs a "next"
          operation, taking the user to the next field that will accept text.
          Corresponds to
          {@link android.view.inputmethod.EditorInfo#IME_ACTION_NEXT}. -->
     <flag name="actionNext" value="0x00000005" />
     <!-- The action key performs a "done"
          operation, closing the soft input method.
          Corresponds to
          {@link android.view.inputmethod.EditorInfo#IME_ACTION_DONE}. -->
     <flag name="actionDone" value="0x00000006" />
     <!-- The action key performs a "previous"
          operation, taking the user to the previous field that will accept text.
          Corresponds to
          {@link android.view.inputmethod.EditorInfo#IME_ACTION_PREVIOUS}. -->
     <flag name="actionPrevious" value="0x00000007" />
     <!-- Used to request that the IME should not update any personalized data such as typing
          history and personalized language model based on what the user typed on this text
          editing object. Typical use cases are:
          <ul>
              <li>When the application is in a special mode, where user's activities are expected
              to be not recorded in the application's history. Some web browsers and chat
              applications may have this kind of modes.</li>
              <li>When storing typing history does not make much sense.  Specifying this flag in
              typing games may help to avoid typing history from being filled up with words that
              the user is less likely to type in their daily life.  Another example is that when
              the application already knows that the expected input is not a valid word (e.g. a
              promotion code that is not a valid word in any natural language).</li>
          </ul>
          <p>Applications need to be aware that the flag is not a guarantee, and some IMEs may
          not respect it.</p> -->
     <flag name="flagNoPersonalizedLearning" value="0x1000000" />
     <!-- Used to request that the IME never go
          into fullscreen mode.  Applications need to be aware that the flag is not
          a guarantee, and not all IMEs will respect it.
          <p>Corresponds to
          {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_FULLSCREEN}. -->
     <flag name="flagNoFullscreen" value="0x2000000" />
     <!-- Like flagNavigateNext, but
          specifies there is something interesting that a backward navigation
          can focus on.  If the user selects the IME's facility to backward
          navigate, this will show up in the application as an actionPrevious
          at {@link android.view.inputmethod.InputConnection#performEditorAction(int)
          InputConnection.performEditorAction(int)}.
          <p>Corresponds to
          {@link android.view.inputmethod.EditorInfo#IME_FLAG_NAVIGATE_PREVIOUS}. -->
     <flag name="flagNavigatePrevious" value="0x4000000" />
     <!-- Used to specify that there is something
          interesting that a forward navigation can focus on. This is like using
          actionNext, except allows the IME to be multiline (with
          an enter key) as well as provide forward navigation.  Note that some
          IMEs may not be able to do this, especially when running on a small
          screen where there is little space.  In that case it does not need to
          present a UI for this option.  Like actionNext, if the
          user selects the IME's facility to forward navigate, this will show up
          in the application at
          {@link android.view.inputmethod.InputConnection#performEditorAction(int)
          InputConnection.performEditorAction(int)}.
          <p>Corresponds to
          {@link android.view.inputmethod.EditorInfo#IME_FLAG_NAVIGATE_NEXT}. -->
     <flag name="flagNavigateNext" value="0x8000000" />
     <!-- Used to specify that the IME does not need
          to show its extracted text UI.  For input methods that may be fullscreen,
          often when in landscape mode, this allows them to be smaller and let part
          of the application be shown behind.  Though there will likely be limited
          access to the application available from the user, it can make the
          experience of a (mostly) fullscreen IME less jarring.  Note that when
          this flag is specified the IME may <em>not</em> be set up to be able
          to display text, so it should only be used in situations where this is
          not needed.
          <p>Corresponds to
          {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_EXTRACT_UI}. -->
     <flag name="flagNoExtractUi" value="0x10000000" />
     <!-- Used in conjunction with a custom action, this indicates that the
          action should not be available as an accessory button when the
          input method is full-screen.
          Note that by setting this flag, there can be cases where the action
          is simply never available to the user.  Setting this generally means
          that you think showing text being edited is more important than the
          action you have supplied.
          <p>Corresponds to
          {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_ACCESSORY_ACTION}. -->
     <flag name="flagNoAccessoryAction" value="0x20000000" />
     <!-- Used in conjunction with a custom action,
          this indicates that the action should not be available in-line as
          a replacement for the "enter" key.  Typically this is
          because the action has such a significant impact or is not recoverable
          enough that accidentally hitting it should be avoided, such as sending
          a message.    Note that {@link android.widget.TextView} will
          automatically set this flag for you on multi-line text views.
          <p>Corresponds to
          {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_ENTER_ACTION}. -->
     <flag name="flagNoEnterAction" value="0x40000000" />
     <!-- Used to request that the IME should be capable of inputting ASCII
          characters.  The intention of this flag is to ensure that the user
          can type Roman alphabet characters in a {@link android.widget.TextView}
          used for, typically, account ID or password input.  It is expected that IMEs
          normally are able to input ASCII even without being told so (such IMEs
          already respect this flag in a sense), but there could be some cases they
          aren't when, for instance, only non-ASCII input languages like Arabic,
          Greek, Hebrew, Russian are enabled in the IME.  Applications need to be
          aware that the flag is not a guarantee, and not all IMEs will respect it.
          However, it is strongly recommended for IME authors to respect this flag
          especially when their IME could end up with a state that has only non-ASCII
          input languages enabled.
          <p>Corresponds to
          {@link android.view.inputmethod.EditorInfo#IME_FLAG_FORCE_ASCII}. -->
     <flag name="flagForceAscii" value="0x80000000" />
 </attr>

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;
}

http://www.kler.cn/a/523232.html

相关文章:

  • 挂载mount
  • 《Java核心技术 卷II》日期和时间API的时间线
  • 低代码系统-产品架构案例介绍、明道云(十一)
  • 文本左右对齐
  • 【Docker】快速部署 Nacos 注册中心
  • -bash: ./uninstall.command: /bin/sh^M: 坏的解释器: 没有那个文件或目录
  • C++中函数返回值当引用
  • 每日一题-判断是否是平衡二叉树
  • NoSQL与SQL比较
  • 家居EDI:Hom Furniture EDI需求分析
  • 深入理解 SQL 中的子查询
  • python读取ATL15.nc数据并保存为
  • unity学习21:Application类与文件存储的位置
  • WS2812 梳理和颜色表示方法的对比:RGB和HSV
  • 两数之和II-输入有序数组
  • Linux一键巡检脚本
  • c++学习第十四天
  • Android Studio 新版本24.2.2 运行后自动切到 LogCat
  • K8S中数据存储之配置存储
  • 【股票数据API接口33】如何获取股票当天逐笔交易数据之Python、Java等多种主流语言实例代码演示通过股票数据接口获取数据
  • Object类(3)
  • 24-25出差交流体会-25-01-28
  • 虚拟世界中的社交互动:Facebook如何改变元宇宙中的沟通方式
  • 网络工程师 (5)系统可靠性
  • 神经网络|(七)概率论基础知识-贝叶斯公式
  • Deepseek-R1模型背后的中国AI突围之路