繁体   English   中英

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

[英]When the soft keyboard appears, it makes my EditText field lose focus

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

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

我的问题是这些:

1) 如何使我的 EditText 字段的选择和软键盘的后续滑入不会使我的 EditText 失去焦点?

……失败了……

2) 我怎样才能让键盘从视野中开始,这样它就不必滑入(从而避免我觉得如此令人反感的行为)?

我的清单确实包括android:windowSoftInputMode="stateAlwaysVisible" ,但在我点击 EditText 之前键盘不会出现。 这种对 'stateAlwaysVisible' 属性的忽略似乎只发生在模拟器中 - 在我配置的设备上,它很荣幸,所以上面的问题 2 确实适用于设备......但不适用于模拟器。

感谢您的任何帮助,您可以提供!

您需要在 AndroidManifest.xml 中进行更改

在持有列表视图的活动中添加 android:windowSoftInputMode="adjustPan"。 这将解决您的问题。

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

问候

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

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

    ////////////////////////////////////////////////////////////////// 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(); } }); } } } };

上面的代码适用于键盘弹出窗口。 但是,它不会检测到语音到文本的弹出窗口。

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

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

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

我通过在 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();
    }
}

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

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

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


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

编辑:这项工作适用于某些手机,并非所有我都使用上面 Mr.Frank 的答案。

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

为避免这种情况,您可以让键盘始终可见。

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

从理论上讲,您可能需要创建自己的 Android 键盘(尽管使用 Android 键盘作为基础),如下所述: Android:如何使键盘始终可见?

在包含列表视图或 EditText 的活动中添加 android:windowSoftInputMode="adjustResize"。 这将解决您的问题。

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

对于那些带着 Xamarin 或 Xamarin.Forms 来到这里的人:

我也遇到了同样的问题,但仅限于 Android 5.x - 包括 8.1 在内的所有较新版本都运行良好。

显然,谢尔顿说得对:

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

我的列表视图也在调整大小,不,弗兰克设置windowSoftInputMode="adjustPan"的解决方案对我来说不是选择,因为这意味着键盘将列表视图部分移出屏幕。

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

CachingStrategy="RecycleElement"

CachingStrategy="RetainElement"

这将阻止重新创建单元格。 但是,这可能会导致巨大的列表性能不佳和内存消耗高。 意识到。

就我而言,当键盘出现时,我在我的根 ScrollView 上调用了root_scrollview.fullScroll(View.FOCUS_DOWN) 我用

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)不起作用。

这家伙有同样的问题,而且还有更多。 他通过使用 ScrollView 和 LinearLayout 而不是 ListView 解决了这个问题。

转换为 RecyclerView

我相信失去对键盘显示隐藏的关注不是预期的行为,并且应该是(或应该是)报告的 Android 问题。

但是现在已经晚了,10年后OP遇到了!

在我的情况下,开关的缺点SOFT_INPUT_ADJUST_RESIZESOFT_INPUT_ADJUST_PAN胜过不失去焦点的优势。

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

但是由于早先对这个问题的回答,我对ListView强烈的怀疑。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM