[英]When the soft keyboard appears, it makes my EditText field lose focus
I've got a few EditText fields in a ListView.我在 ListView 中有一些 EditText 字段。 When I tap on one of the EditText fields, the keyboard slides into view (as it should), but the EditText field I tapped loses focus.
当我点击 EditText 字段之一时,键盘会滑入视图(应该如此),但我点击的 EditText 字段失去焦点。 I've tried using various InputMethodManager methods to make the keyboard start out in view (in order to get around the problem rather than truly solve it), but that didn't work - the keyboard was not in view when the Activity appeared.
我尝试使用各种 InputMethodManager 方法使键盘在视图中启动(为了解决问题而不是真正解决它),但这不起作用 - 当 Activity 出现时键盘不在视图中。
The EditText's type is number
, and when the keyboard is sliding in, it is a number keyboard, but when it finishes sliding and the EditText loses focus, it changes to the alphabetical keyboard (which reinforces the idea that the EditText no longer has focus). EditText 的类型是
number
,当键盘滑入时,它是一个数字键盘,但是当它完成滑动并且 EditText 失去焦点时,它变为字母键盘(这加强了 EditText 不再有焦点的想法) .
My questions are these:我的问题是这些:
1) How can I make the selection of my EditText field and the subsequent sliding in of the soft keyboard not make my EditText lose focus? 1) 如何使我的 EditText 字段的选择和软键盘的后续滑入不会使我的 EditText 失去焦点?
... failing that... ……失败了……
2) How can I make the keyboard start out in view so it never has to slide in (thus avoiding the behavior I find so objectionable)? 2) 我怎样才能让键盘从视野中开始,这样它就不必滑入(从而避免我觉得如此令人反感的行为)?
My manifest does include android:windowSoftInputMode="stateAlwaysVisible"
, but the keyboard does not appear until I tap on an EditText.我的清单确实包括
android:windowSoftInputMode="stateAlwaysVisible"
,但在我点击 EditText 之前键盘不会出现。 This ignoring of the 'stateAlwaysVisible' attribute seems to only occur in the emulator - on my provisioned device, it is honored so question number 2 above does work on the device... but not in the emulator.这种对 'stateAlwaysVisible' 属性的忽略似乎只发生在模拟器中 - 在我配置的设备上,它很荣幸,所以上面的问题 2 确实适用于设备......但不适用于模拟器。
Thanks for any help you can provide!感谢您的任何帮助,您可以提供!
You need to change in your AndroidManifest.xml您需要在 AndroidManifest.xml 中进行更改
Add android:windowSoftInputMode="adjustPan" in the activity holding the listview.在持有列表视图的活动中添加 android:windowSoftInputMode="adjustPan"。 This will solve your problem.
这将解决您的问题。
<activity android:name=".MyEditTextInListView"
android:label="@string/app_name"
android:windowSoftInputMode="adjustPan">
Regards问候
Here is how I did it.这是我如何做到的。 The
onFocusChangeListener()
is called several times when you touch a EditText
to type text into it.当您触摸
EditText
以在其中键入文本时, onFocusChangeListener()
会被多次调用。 The sequence is:顺序是:
Target finally gains focus目标终于获得焦点
////////////////////////////////////////////////////////////////// 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(); } }); } } } };
The code above works well for the keyboard pop-ups.上面的代码适用于键盘弹出窗口。 However, it does not detect the speech-to-text pop-up.
但是,它不会检测到语音到文本的弹出窗口。
In my case, this is happening because when the ListView resizes, it re-creates all of the list items (ie it calls getView() again for each visible list item).在我的情况下,发生这种情况是因为当 ListView 调整大小时,它会重新创建所有列表项(即它为每个可见列表项再次调用 getView())。
Because the EditText is within the layout that I'm returning from getView(), this means that it's a different instance of EditText than the one which had the focus previously.因为 EditText 位于我从 getView() 返回的布局内,这意味着它是 EditText 的一个不同实例,而不是以前具有焦点的实例。 A secondary consequence is that when the soft-keyboard appears or disappears I found that I was losing the contents of the EditText.
第二个后果是当软键盘出现或消失时,我发现我丢失了 EditText 的内容。
Because I wanted my view to remain fully accessible (ie I want it to be resized instead of hidden behind the keyboard window with some parts not accessible), I couldn't use Frank's answer, which otherwise seems like the best approach.因为我希望我的视图保持完全可访问(即我希望它被调整大小而不是隐藏在键盘窗口后面,某些部分不可访问),我不能使用弗兰克的答案,否则这似乎是最好的方法。
I solved this by using an OnFocusChangeListener on the EditText to record the timestamp when the focus was lost, and then in getView() when recreating the list item, if the current time is within some threshold from when the focus was lost, call requestFocus() to give it back to the EditText in question.我通过在 EditText 上使用 OnFocusChangeListener 记录焦点丢失时的时间戳来解决这个问题,然后在重新创建列表项时在 getView() 中,如果当前时间在焦点丢失时的某个阈值内,请调用 requestFocus( ) 将其返回给有问题的 EditText。
You can also grab the text from the previous instance of the EditText at that point and transfer it to the new instance.您还可以在那时从 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();
}
}
In AndroidManifest.xml use adjustNothing in the activity that contain the views在 AndroidManifest.xml 中,在包含视图的活动中使用 adjustNothing
<activity
android:name=".ActivityName"
android:windowSoftInputMode="adjustNothing">
If the editText inside the listView just make sure that you inflate the View in the getView method with this way.如果 listView 中的 editText 只是确保使用这种方式在 getView 方法中膨胀 View 。
if (convertView == null)
convertView = LayoutInflater.from(context).inflate(R.layout.yourItemListLayout,
parent, false);
Edit: this work for some mobiles not all I use the answer from Mr.Frank above.编辑:这项工作适用于某些手机,并非所有我都使用上面 Mr.Frank 的答案。
You should test this code on a device with hardware keyboard always visible.您应该在硬件键盘始终可见的设备上测试此代码。 The behavior may also happen here.
这种行为也可能发生在这里。
To avoid this you can have the keyboard always visible.. but that is not very easy as you can see by this thread:为避免这种情况,您可以让键盘始终可见。
https://groups.google.com/forum/#!topic/android-developers/FyENeEdmYC0 https://groups.google.com/forum/#!topic/android-developers/FyENeEdmYC0
Theoretically you may have to create your own Android keyboard (although using as base the stock Android keyboard) as described here: Android: How to make the keypad always visible?从理论上讲,您可能需要创建自己的 Android 键盘(尽管使用 Android 键盘作为基础),如下所述: Android:如何使键盘始终可见?
Add android:windowSoftInputMode="adjustResize" in the activity holding the listview or EditText.在包含列表视图或 EditText 的活动中添加 android:windowSoftInputMode="adjustResize"。 This will solve your problem.
这将解决您的问题。
<activity android:name=".MainActivity"
android:windowSoftInputMode="adjustResize">
</activity>
For those who come here with Xamarin or Xamarin.Forms:对于那些带着 Xamarin 或 Xamarin.Forms 来到这里的人:
I had the same issue as well but only with Android 5.x - all newer Versions including 8.1 worked well.我也遇到了同样的问题,但仅限于 Android 5.x - 包括 8.1 在内的所有较新版本都运行良好。
Obviously sheltond was right by saying:显然,谢尔顿说得对:
In my case, this is happening because when the ListView resizes, it re-creates all of the list items (ie it calls getView() again for each visible list item).
在我的情况下,发生这种情况是因为当 ListView 调整大小时,它会重新创建所有列表项(即它为每个可见列表项再次调用 getView())。
My listview was resizing as well and no, Frank s solution to set windowSoftInputMode="adjustPan"
was no option for me because that means that the keyboard moves the listview partly off the screen.我的列表视图也在调整大小,不,弗兰克设置
windowSoftInputMode="adjustPan"
的解决方案对我来说不是选择,因为这意味着键盘将列表视图部分移出屏幕。
All I had to do after hours of focus-debugging was setting the cell caching strategy of the Xamarin Forms ListView:经过数小时的焦点调试后,我所要做的就是设置 Xamarin Forms ListView 的单元格缓存策略:
From从
CachingStrategy="RecycleElement"
To到
CachingStrategy="RetainElement"
This will stop the cells from being recreated.这将阻止重新创建单元格。 However, this might result in bad performance and high memory consumption for huge lists.
但是,这可能会导致巨大的列表性能不佳和内存消耗高。 Be aware.
意识到。
In my case, I had called root_scrollview.fullScroll(View.FOCUS_DOWN)
on my root ScrollView when Keyboard appears.就我而言,当键盘出现时,我在我的根 ScrollView 上调用了
root_scrollview.fullScroll(View.FOCUS_DOWN)
。 I replaced it with我用
login_scrollview.post(new Runnable() {
@Override
public void run() {
root_scrollview.scrollTo(0,root_container.bottom)
}
});
where root_container is the immediate child of root_scrollview.其中 root_container 是 root_scrollview 的直接子级。 This solved the problem for me.
这为我解决了这个问题。
Note: Directly calling root_scrollview.scrollTo(0,root_container.bottom)
was not working.注意:直接调用
root_scrollview.scrollTo(0,root_container.bottom)
不起作用。
I believe that loss of focus on show or hide of the keyboard is not expected behavior and either should have been (or should be) a reported Android issue.我相信失去对键盘显示或隐藏的关注不是预期的行为,并且应该是(或应该是)报告的 Android 问题。
But too late now, 10 years after OP encountered it!但是现在已经晚了,10年后OP遇到了!
In my case, the disadvantage of switching from SOFT_INPUT_ADJUST_RESIZE
to SOFT_INPUT_ADJUST_PAN
outweighed the advantage of not losing focus.在我的情况下,开关的缺点
SOFT_INPUT_ADJUST_RESIZE
到SOFT_INPUT_ADJUST_PAN
胜过不失去焦点的优势。
Why?为什么?
ADJUST_RESIZE
is the officially preferred approach because ADJUST_PAN
blocks part of your view and may prevent scrolling. ADJUST_RESIZE
是官方首选的方法,因为ADJUST_PAN
阻止部分视图并可能阻止滚动。
But thanks to an earlier answer to this question I became intensely suspicious of ListView
.但是由于早先对这个问题的回答,我对
ListView
强烈的怀疑。
To prove my suspicions I spent a day converting a complex ListView
-based editor to RecyclerView
.为了证明我的怀疑,我花了一天时间将一个复杂的基于
ListView
的编辑器转换为RecyclerView
。
I can confirm that soft keyboard state changes no longer affect EditText
focus even though I am using ADJUST_RESIZE
.我可以确认软键盘状态更改不再影响
EditText
焦点,即使我正在使用ADJUST_RESIZE
。
Seemingly painful I know - but perhaps the final result is nicer than sub-classing or tricky workarounds?我知道看起来很痛苦 - 但也许最终结果比子分类或棘手的解决方法更好?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.