【问题标题】:Maintain keyboard open/closed state for EditText when app comes to foreground当应用程序进入前台时,保持 EditText 的键盘打开/关闭状态
【发布时间】:2013-02-18 14:52:52
【问题描述】:

我有一个Activity,它是在配置更改时重新创建的(需要)。我有一个DialogFragment,它调用setRetainInstance(true),其布局中有一个EditText

在DialogFragment的onActivityCreated我调用:

getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);

A) 如果我打开键盘,那么当我将应用程序置于后台然后将其带到前台时,我希望键盘仍然显示

B) 如果我关闭键盘(EditText 仍然有焦点并显示所需行为的光标)然后 我希望键盘仍然关闭如果我将应用程序置于后台然后将把它放到前台。

我似乎无法同时实现 A) 和 B)。当我将应用程序带到前台时,键盘总是关闭。我试过 .SOFT_INPUT_STATE_ALWAYS_VISIBLE 但是键盘总是打开的。

在此先感谢您就如何实现这一目标提出任何建议。我也希望在旋转过程中保持这种键盘状态,但我将把它留到另一天。彼得。

编辑 请注意,我确实不想阻止在配置更改时重新创建活动。

我还尝试了WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED,它确实在手机旋转期间保持键盘打开/关闭状态(单窗格布局),但 a) 不适用于双窗格布局 b) 带入时不保持键盘状态应用到前台。

【问题讨论】:

  • onCreate方法中使用getDialog()不应该返回null?
  • 谢谢,改成onActivityCreated
  • 我建议看一下HIDE_IMPLICIT_ONLYHIDE_NOT_ALWAYSSHOW_FORCEDSHOW_IMPLICITof InputMethodManagerdeveloper.android.com/reference/android/view/inputmethod/…,并告知此功能在所有设备中的行为可能不同因为某些 ROM(官方/非官方)可能会在切换活动时强制更改键盘。
  • 与您的问题无关,但您不应在其中包含视图小部件的片段上使用 setRetainInstance(true)。

标签: android android-widget


【解决方案1】:

您好,首先感谢您提出一个有趣的问题。它让我尝试了代码。我在这里描述我的解决方案。

要找到解决方案,我必须知道两件事

1.如何检测软键盘是否可见

2.如何设置软键盘可见或隐藏。

我通过以下步骤得到了解决方案 经过一番搜索,我意识到检测softkeyboardstate(可见/隐藏)的最佳解决方案是使用ViewTreeObserver。如果您不知道,我直接指向一个如此答案以了解它。这是link

并设置softkeyboardstate 我刚刚使用了Window.setSoftInputMode 方法。

要了解用户交互,我会覆盖 onUserInteraction 方法

保留两个标志。一个标志是保留keyboardstate 另一个是知道应用程序是否进入后台

代码:

1.变量声明

int lastDiff = 0;
volatile boolean flag = false;
volatile int flag2 = 0;

2。 ViewTreeObserver

activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
    new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            Rect r = new Rect();
            activityRootView.getWindowVisibleDisplayFrame(r);

            int heightDiff = activityRootView.getRootView()
                    .getHeight() - (r.bottom - r.top);
            if (lastDiff == heightDiff)
                return;
            lastDiff = heightDiff;
            Log.i("aerfin","arefin "+lastDiff);
            if (heightDiff > 100) { // if more than 100 pixels, its
                                    // probably a keyboard...
                flag2 = 0;
            } else {
                if (flag == false)
                    flag2 = 1;
            }
        }
    });

3.处理用户交互

 @Override
 public void onUserInteraction() {
     super.onUserInteraction();
     flag = true;
 }

4.最后是onPauseonResume

@Override
protected void onPause() {
    super.onPause();
    flag = true;
}

@Override
protected void onResume() {
    flag = false;

    switch (flag2) {
    case 0:
        getWindow().setSoftInputMode(
                WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        break;
    case 1:
        getWindow().setSoftInputMode(
                WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);

        break;
    default:
        break;
    }

    super.onResume();
}

说明:

这里我使用了两个标志(flag2flag)。 flag2 保留 keyboardstateflag 保留应用程序是否进入后台或是否有任何用户交互。使用flag 是因为当应用程序进入后台时,首先它会隐藏键盘。其他的东西可以通过上面的代码很容易理解。

测试:

在 s2(ics)、desire s (ics)、galaxy y (2.3.6) 中测试

最后的评论:

我快速编写代码,因此可能会错过一些其他优化。也有可能出现特殊情况。如果屏幕因键盘以外的其他原因发生变化,则可能无法检测到键盘状态。

【讨论】:

  • 感谢您的结论性回答。我同意,解决方案似乎确实取决于知道键盘何时打开。但是,我确实想知道,提出的此类解决方案是否适用于大屏幕设备上的对话框,其中在出现键盘时对话框的布局高度不会发生变化。
  • 我没有检查。所以暂时说不出来。也许您可以使用我的解决方案进行检查并发布结果:)。
  • 全面回答,详细说明如何调用键盘以及必要的注意事项,因为我同意在某些情况下键盘检测可能不起作用。
  • 这也适用于设备旋转的情况吗?我在那里也看到了类似的行为。移动到横向会关闭键盘。
【解决方案2】:

您应该使用标志(boolean kbShowing)来保持当前的键盘状态,例如在键盘显示时设置kbShowing = true,否则设置kbShowing = false

onCreate

    showKB(); // if keyboard is not showed automatically. 

onRestart

    if(kbShowing)
        showKb(); // if keyboard is not showed automatically. 
    else 
        hideKb(); // if keyboard is showed automatically.

如果您不知道如何检测键盘何时显示或隐藏,请查看 Stefan 对此主题的回答 How to capture the "virtual keyboard show/hide" event in Android?

【讨论】:

  • 我确实想知道 Stefan 的回答是否有助于确定键盘是否从大屏幕设备上的小对话框中显示出来,其布局测量不会受到键盘存在的影响。
【解决方案3】:

类级别声明您的EditText ...

EditText editText;

现在覆盖 onResume()onPause() 活动方法 ...

    @Override
    protected void onResume() 
    {
        // TODO Auto-generated method stub
        super.onResume();
        editText.requestFocus();

        editText.postDelayed(new Runnable() {
            @Override
            public void run() {
                InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.showSoftInput(editText, InputMethodManager.SHOW_FORCED);
            }   
        }, 100);
    }

    @Override
    protected void onPause() 
    {
        // TODO Auto-generated method stub
        super.onPause();
        editText.postDelayed(new Runnable() {
            @Override
            public void run() {
                InputMethodManager imm = (InputMethodManager)getSystemService(
                          Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
            }   
        }, 200);
    }

这段代码非常适合我。

享受 - :D

【讨论】:

  • 也许我的问题不够清楚,但这不是在应用程序进入前台时显示键盘吗?如果在将应用程序置于后台之前关闭键盘,那么我希望在返回前台时将其关闭。
【解决方案4】:

您是否尝试在 Activity 的 Manifest 文件中添加键盘状态:

 android:windowSoftInputMode="stateAlwaysVisible|adjustPan">

这将处理您的问题的轮换部分,并且应该也适用于 onResume。 stateAlwaysVisible 将启动 onCrate 上的键盘,而 adjustPan 将处理旋转。

这是我的清单文件中的一个活动示例:

<activity
        android:name=".GMax3Main"
        android:label="@string/app_name" 
        android:windowSoftInputMode="stateAlwaysVisible|adjustPan">
        <intent-filter>
            <action android:name="com.medeasy.GMax3.MAIN" />

            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

希望这会有所帮助。

在我的活动类中,我在我的类的 onCreate 方法上打开我的软键盘,如下所示:

 @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    new UserSync().execute();
    setContentView(R.layout.main);

    InputMethodManager imm = (InputMethodManager)
            GMax3Main.this.getSystemService(Context.INPUT_METHOD_SERVICE);

        if (imm != null){
            imm.toggleSoftInput(InputMethodManager.RESULT_SHOWN, 0);
        }

然后我打电话给我的android:windowSoftInputMode="stateAlwaysVisible|adjustPan"&gt;,如上面我的清单文件中所示。

【讨论】:

  • 但是如果键盘在旋转之前关闭,那么它不会在旋转之后再次打开吗?
  • 我会在回到办公室后做更多研究。
  • 我正在使用 7 级应用程序,它确实有效。如果我关闭键盘并在后台运行我的应用程序,然后恢复我的应用程序,即使在旋转时键盘也会恢复。我正在运行 2.3.3 的 G-Tablet 上进行测试。
  • 您能否澄清一下,如果您关闭键盘并将应用程序置于后台,那么当您将应用程序返回时,键盘是否仍然关闭?
  • 我确实在水平视图中关闭了键盘,然后将应用程序放在后台并转到浏览器应用程序。然后我关闭了我的浏览器应用程序并恢复了我的应用程序,其中键盘提出了意图。然后我旋转了设备,键盘仍然在那里。我认为这就是你想要做的,对吗?
【解决方案5】:

我将通过覆盖和创建您自己的 EditText 小部件来扩展 Wayne 的方法,您应该在整个应用程序中使用该小部件。

public class PJLsEditText extends EditText 
{
    public PJLsEditText(Context context) {
        super(context);
        saveKbState();
    }

    public PJLsEditText(Context context, AttributeSet attrs) 
    {
        super(context, attrs);
        saveKbState();
    }

    private void saveKbState() 
    {
        //get keyboard state and set a flag either in a static class or as SharedPreference
    }

    // I'm not sure if EditText objects get destroyed on configuration change. 
    // If so, you might need to overwrite the onConfigurationChanged method here, 
    // as well...
} 

我认为这应该可以帮助您始终了解键盘的最后状态,即使通过对话框进行了更改。您可以根据onResumeonPause 方法中的此标志隐藏或显示键盘。

【讨论】:

    【解决方案6】:

    如果键盘打开并设置一个标志,我可能会检查 onPause (我认为只有像下面的示例那样的黑客方法):

    final View activityRootView = findViewById(R.id.activityRoot);
    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
        if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
            ... do something here
        }
     }
    });
    

    根据这里的答案: How to check visibility of software keyboard in Android?

    在 onResume() 中设置:

    getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
    

    或:

    getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
    

    【讨论】:

      猜你喜欢
      • 2021-07-17
      • 1970-01-01
      • 2023-04-11
      • 2013-10-21
      • 2019-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多