当应用程序到达前台时,保持EditText的键盘打开/关闭状态

时间:2013-03-04 13:40:08

标签: android android-widget

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

在DialogFragment的onActivityCreated我打电话:

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

A)如果我打开键盘然后当我将应用程序放入背景然后将其带到foregournd然后我希望键盘仍然显示

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

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

提前感谢有关如何实现这一目标的任何建议。我也希望在旋转时保持这种键盘状态,但是我要离开那一天了。彼得。

修改 请注意,我希望阻止在配置更改时重新创建活动。

我还尝试了WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED,它在手机上旋转时保持键盘打开/关闭状态(单窗格布局)但是a)不适用于双窗格布局b)没有维持键盘状态将应用程序带到前台时。

6 个答案:

答案 0 :(得分:10)

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

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

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)中测试,欲望s(ics),galaxy y(2.3.6)

最终评论:

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

答案 1 :(得分:6)

您应该使用标记(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?

答案 2 :(得分:2)

班级宣布 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

答案 3 :(得分:2)

可能我会检查onPause,如果键盘是打开的并设置了一个标志(我认为只有像这样的例子的hacky方式):

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

答案 4 :(得分:2)

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

 android:windowSoftInputMode="stateAlwaysVisible|adjustPan">

这将处理问题的轮换部分,并且也应该在onResume上工作。 stateAlwaysVisible将启动onCrate上的键盘,adjustPan将处理旋转。

以下是我的Manifest文件中的一个活动示例:

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

希望这有帮助。

在我的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">

答案 5 :(得分:2)

我会通过覆盖和创建您自己的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...
} 

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