当软键盘出现时,它会使我的EditText字段失去焦点

时间:2011-04-10 23:28:26

标签: android android-emulator android-edittext

我在ListView中有一些EditText字段。当我点击其中一个EditText字段时,键盘会滑入视图(应该如此),但我点击的EditText字段会失去焦点。我已经尝试使用各种InputMethodManager方法使键盘在视图中启动(为了解决问题而不是真正解决它),但这不起作用 - 当Activity出现时键盘不在视图中。 / p>

EditText的类型是number,当键盘滑入时,它是一个数字键盘,但当它完成滑动并且EditText失去焦点时,它会变为字母键盘(这强化了EditText不再具有焦点。)

我的问题是这些:

1)如何选择我的EditText字段并随后滑入软键盘而不是使我的EditText失去焦点?

...失败了......

2)如何让键盘在视图中开始播放,从而不必滑入(从而避免了我觉得令人反感的行为)?

我的清单包含android:windowSoftInputMode="stateAlwaysVisible",但在点击EditText之前键盘才会出现。忽略'stateAlwaysVisible'属性似乎只出现在模拟器中 - 在我的配置设备上,它很荣幸,因此上面的问题2可以在设备上工作......但不在模拟器中。

感谢您提供的任何帮助!

11 个答案:

答案 0 :(得分:120)

您需要更改AndroidManifest.xml

在持有listview的活动中添加android:windowSoftInputMode =“adjustPan”。 这将解决您的问题。

    <activity android:name=".MyEditTextInListView"
              android:label="@string/app_name"
              android:windowSoftInputMode="adjustPan">

此致

答案 1 :(得分:13)

我是这样做的。当您触摸onFocusChangeListener()以在其中键入文本时,会多次调用EditText。顺序是:

  1. 如果焦点位于不同的视图上,则该视图会失去焦点
  2. 目标获得焦点
  3. 弹出软键盘。
  4. 这会导致目标失去焦点
  5. 代码检测到这种情况并调用target.requestFocus()
  6. 由于Android废话
  7. ,最左边的最顶层视图会获得焦点
  8. 由于requestFocus被称为
  9. ,最左边的视图失去焦点
  10. 目标最终获得焦点

    //////////////////////////////////////////////////////////////////
    private final int minDelta = 300;           // threshold in ms
    private long focusTime = 0;                 // time of last touch
    private View focusTarget = null;
    
    View.OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View view, boolean hasFocus) {
            long t = System.currentTimeMillis();
            long delta = t - focusTime;
            if (hasFocus) {     // gained focus
                if (delta > minDelta) {
                    focusTime = t;
                    focusTarget = view;
                }
            }
            else {              // lost focus
                if (delta <= minDelta  &&  view == focusTarget) {
                    focusTarget.post(new Runnable() {   // reset focus to target
                        public void run() {
                            focusTarget.requestFocus();
                        }
                    });
                }
            }
        }
    };
    
  11. 上面的代码适用于键盘弹出窗口。但是,它不会检测语音到文本弹出窗口。

答案 2 :(得分:9)

就我而言,这种情况正在发生,因为当ListView调整大小时,它会重新创建所有列表项(即它再次为每个可见列表项调用getView())。

因为EditText在我从getView()返回的布局中,这意味着它是EditText的一个不同实例,而不是之前具有焦点的实例。第二个后果是,当软键盘出现或消失时,我发现我丢失了EditText的内容。

因为我希望我的视图保持完全可访问(即我想要调整大小而不是隐藏在键盘窗口后面,某些部分无法访问),我无法使用Frank的答案,否则这似乎是最好的方法。

我通过在EditText上使用OnFocusChangeListener来记录焦点丢失时的时间戳,然后在重新创建列表项时使用getView(),如果当前时间在焦点丢失时的某个阈值内,调用requestFocus()将其返回给有问题的EditText。

您还可以从该点的上一个EditText实例中获取文本并将其传输到新实例。

private class MyAdapter<Type> extends ArrayAdapter<String>
    implements OnFocusChangeListener
{
    private EditText mText;
    private long mTextLostFocusTimestamp;
    private LayoutInflater mLayoutInflater;

    public MyAdapter(Context context, int resource, int textResourceId, ArrayList<String> data, LayoutInflater li) {
        super(context, resource, textResourceId, data);
        mLayoutInflater = li;
        mTextLostFocusTimestamp = -1;
    }

    private void reclaimFocus(View v, long timestamp) {
        if (timestamp == -1)
            return;
        if ((System.currentTimeMillis() - timestamp) < 250)
            v.requestFocus();
    }

    @Override public View getView (int position, View convertView, ViewGroup parent)
    {
        View v = mLayoutInflater.inflate(R.layout.mylayout, parent, false);

        EditText newText = (EditText) v.findViewById(R.id.email);
        if (mText != null)
            newText.setText(mText.getText());
        mText = newText;
        mText.setOnFocusChangeListener(this);
        reclaimFocus(mText, mTextLostFocusTimestamp);

        return v;
    }

    @Override public void onFocusChange(View v, boolean hasFocus) {
        if ((v == mText) && !hasFocus)
            mTextLostFocusTimestamp = System.currentTimeMillis();
    }
}

答案 3 :(得分:1)

您应该在硬件键盘始终可见的设备上测试此代码。这种行为也可能发生在这里。

为了避免这种情况,您可以让键盘始终可见..但这不是很容易,因为您可以通过此主题看到:

https://groups.google.com/forum/#!topic/android-developers/FyENeEdmYC0

从理论上讲,您可能需要创建自己的Android键盘(尽管使用Android键盘作为基础),如下所述:Android: How to make the keypad always visible?

答案 4 :(得分:1)

在AndroidManifest.xml中,在包含视图的活动中使用adjustNothing

<activity
            android:name=".ActivityName"
            android:windowSoftInputMode="adjustNothing">

答案 5 :(得分:1)

如果listView中的editText只是确保用这种方式在getView方法中膨胀View。

        if (convertView == null)
        convertView = LayoutInflater.from(context).inflate(R.layout.yourItemListLayout,
                parent, false);   

编辑:对于某些手机而言,这项工作并非我所有人都使用了弗兰克先生的答案。

答案 6 :(得分:0)

This guy也遇到了同样的问题。他通过使用ScrollView和LinearLayout而不是ListView来解决它。

答案 7 :(得分:0)

添加android:windowSoftInputMode =&#34; adjustResize&#34;在持有listview或EditText的活动中。这将解决您的问题。

<activity android:name=".MainActivity"
        android:windowSoftInputMode="adjustResize">
</activity>

答案 8 :(得分:0)

对于那些来Xamarin或Xamarin.Forms的人来说:

我也有同样的问题,但只有Android 5.x - 包括8.1在内的所有新版本都运行良好。

显然 sheltond 是正确的说法:

  

就我而言,这种情况正在发生,因为当ListView调整大小时,它会重新创建所有列表项(即它再次为每个可见列表项调用getView())。

我的列表视图也正在调整大小并且没有, Frank 设置windowSoftInputMode="adjustPan"的解决方案对我来说没有选择,因为这意味着键盘将listview部分移出屏幕。

经过数小时的焦点调试后,我所要做的就是设置Xamarin Forms ListView的单元缓存策略:

CachingStrategy="RecycleElement"

CachingStrategy="RetainElement"

这将停止重建单元格。但是,这可能会导致大型列表的性能不佳和内存消耗过高。请注意。

答案 9 :(得分:0)

就我而言,我曾打电话给 root_scrollview.fullScroll(View.FOCUS_DOWN) 当出现键盘时,在我的根ScrollView上。 我将其替换为

login_scrollview.post(new Runnable() { 
    @Override
    public void run() {
        root_scrollview.scrollTo(0,root_container.bottom)
    }
});

其中root_container是root_scrollview的直接子级。这为我解决了问题。

注意:直接致电 root_scrollview.scrollTo(0,root_container.bottom)无法正常工作。

答案 10 :(得分:0)

转换为RecyclerView

我认为,失去对键盘的 show hide 的关注不是预期的行为,并且应该是(或应该是)已报告的Android问题。< / p>

但是现在已经太晚了,在OP遇到它十年后!

就我而言,从SOFT_INPUT_ADJUST_RESIZE切换到SOFT_INPUT_ADJUST_PAN的缺点胜过不失去焦点的优点。

为什么? ADJUST_RESIZEofficially的首选方法,因为ADJUST_PAN会阻塞部分视图并可能阻止滚动。

但是由于早先的answer这个问题,我对ListView产生了极大的怀疑。

为了证明自己的怀疑,我花了一天的时间将基于ListView的复杂编辑器转换为RecyclerView

即使我正在使用EditText,我也可以确认软键盘状态更改不再影响ADJUST_RESIZE的焦点。

我知道似乎很痛苦-但也许最终结果比子类化或棘手的解决方法更好?