[英]How to lose the focus of a edittext when "done" button in the soft keyboard is pressed?
[英]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()
会被多次调用。 顺序是:
目标终于获得焦点
////////////////////////////////////////////////////////////////// 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 解决了这个问题。
我相信失去对键盘显示或隐藏的关注不是预期的行为,并且应该是(或应该是)报告的 Android 问题。
但是现在已经晚了,10年后OP遇到了!
在我的情况下,开关的缺点SOFT_INPUT_ADJUST_RESIZE
到SOFT_INPUT_ADJUST_PAN
胜过不失去焦点的优势。
为什么? ADJUST_RESIZE
是官方首选的方法,因为ADJUST_PAN
阻止部分视图并可能阻止滚动。
但是由于早先对这个问题的回答,我对ListView
强烈的怀疑。
为了证明我的怀疑,我花了一天时间将一个复杂的基于ListView
的编辑器转换为RecyclerView
。
我可以确认软键盘状态更改不再影响EditText
焦点,即使我正在使用ADJUST_RESIZE
。
我知道看起来很痛苦 - 但也许最终结果比子分类或棘手的解决方法更好?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.