在Android 4.x上,ListView中的EditText在被按下时会失去焦点。

65

我知道这里有很多类似的问题,但我在一个简单的样例应用程序中无法使任何提供的解决方案生效。

问题出现在第一次显示软键盘时。一旦它显示出来,只有再次按下 editText 才能编辑。

尝试了以下方法:

 android:windowSoftInputMode="adjustPan|adjustResize"

这并没有解决任何问题。看起来这行代码是在软键盘弹出后重设活动的大小是必须的。不幸的是,它也会导致任何EditTexts失去焦点。这可能是因为ListView在调整大小过程中获得了焦点。因此,我尝试了以下解决方法:

 listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);

这总是导致ListView包含的第一个可见EditText获得焦点,这是不希望发生的。按下时,应该使第二行中的第二个EditText获得焦点,但事实并非如此。而且,如果最终设法将焦点集中在另一个EditText上(例如通过在softkeyboard上按“下一步”),则在键盘消失并ListView重新调整到其完整大小后,第一个可见EditText将再次接收到焦点。

我尝试了其他几种方法,例如拦截ListView的onFocusChange()事件,同时通过其TouchListener知道哪个EditText被按下。再次请求某个特定EditText的焦点也没有任何成功。

像其他用户建议的那样,使用ScrollView而不是ListView对于相关项目也不是一个选项。


嗨,我猜这里发生的并不是需要再按一次EditText才能使用,而是因为软键盘出现了,因为它被一个可编辑的、首先获得焦点的字段触发。您可以尝试使用以下代码隐藏软键盘:public void hideSoftKeyboard(View v) { Activity activity = (Activity) v.getContext(); InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0); } - g00dy
它将防止软键盘首先出现,我猜EditText只需按下即可触发其中的编辑。 - g00dy
@g00dy,问题不在于键盘最初出现,而是输入文本无法正常工作。 - Display name
好的,那么你确定有问题的“EditText”第一次出现键盘时获得了焦点吗?我的意思是 - “RequestFocus”在哪里? - g00dy
这里可以找到相关链接-> http://developer.android.com/guide/topics/resources/layout-resource.html#requestfocus-element - g00dy
9个回答

44

在这种情况下,一个经典的解决方法是使用处理程序和postDelayed()。在您的适配器中:

private int lastFocussedPosition = -1;
private Handler handler = new Handler();

public View getView(final int position, View convertView, ViewGroup parent) {

    // ...

    edittext.setOnFocusChangeListener(new OnFocusChangeListener() {

        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (hasFocus) {
                handler.postDelayed(new Runnable() {

                    @Override
                    public void run() {
                        if (lastFocussedPosition == -1 || lastFocussedPosition == position) {
                            lastFocussedPosition = position;
                            edittext.requestFocus();
                        }
                    }
                }, 200);

            } else {
                lastFocussedPosition = -1;
            }
        }
    });

    return convertView;
}

这在我的设备上运行良好,但请勿将此代码用于生产。我也不会感到惊讶,如果焦点错误在不同的Android版本或ROM中表现不同。

ListView中嵌入EditText还存在许多其他问题,解决方案感觉像是一个hack。请看看所有其他人们的困扰。

这种事情也很容易发生:

like this.

经过多次类似的尝试,我基本放弃了试图覆盖任何默认键盘行为或怪癖的努力。如果可能的话,建议您在应用程序中找到替代解决方案。

您是否考虑过让ListView行只是一个样式化的TextView,然后在单击行时显示带有EditText的对话框,并根据需要更新TextView?


谢谢您的回答,不幸的是我们无法更改应用程序的布局,因此我们必须使用listViews来实现这个目的。而且我们已经在使用对话框输入文本 :) 尽管很多问题的答案都被接受了,但我想知道它是否适用于这些人。 - Display name
2
@GrafOrlov,你可能不想在生产中使用这个解决方案。考虑在单击行时在对话框中显示一个EditText。 - Kyle Ivey
@KyleIvey,你能帮忙回答一下这个问题吗? https://dev59.com/q5ffa4cB1Zd3GeqP5kUJ - sudoExclaimationExclaimation

40

当我在ListView行内按下EditText时,ActionBar会“窃取”焦点,我遇到了问题。上述解决方案无法解决我的问题,但是以下解决方案对我有效:

http://www.mysamplecode.com/2013/02/android-edittext-listview-loses-focus.html

基本上,我将以下内容添加到我的ListView中:

android:descendantFocusability="beforeDescendants"

然后我把这个添加到我的活动中:

android:windowSoftInputMode="adjustPan"

7
如果 EditText 在列表底部,这将导致键盘阻挡它。 - Rick

19

修改您的清单XML,在活动中添加windowSoftInputMode:

<activity
    android:name=".YourActivity"
    android:windowSoftInputMode="adjustPan">
</activity>

8

我知道这是一个非常古老的帖子,但是这个答案可能对某些人有所帮助,所以在这里分享:

切换到RecyclerView,你就不用再担心ListView这些烦人的问题了。它不需要创建新的视图,而是回收和重新使用旧的视图。


2
在我看来,这是最好的选择。其他解决方案只是权宜之计。它们并没有改变ListView在notifyDataSetChanged期间批量创建/销毁视图的事实。而有了RecyclerView,您可以通知有关单个插入、更新和删除的信息。聚焦视图不会被重新创建,所以没有焦点问题。 - Pēteris Caune
1
@PēterisCaune Listview永远不会批量销毁视图,而是进行回收利用。我见过的99%的回收视图代码都是一样的。回收视图可以更加专注,但实际上这种方式并不容易实现。 - Gabe Sechan
2
同样会发生在回收视图中。 - Omer

4

我遇到了与recyclerView有关的问题,并尝试了所有建议的解决方案。

最终,我发现我的问题在于XML中recyclerView的高度值意外地设置为wrap_content;将其更改为match_parent后,它开始按预期工作,没有设置focusable值,并使用android:windowSoftInputMode="adjustResize"


2
使用 RecyclerView,这解决了列表和 gridview 的几个问题。你甚至可以使用交错的 gridviews。你可以很容易地开始使用this

1
欢迎来到SO!请注意,这个问题是2013年的(将近2年前)。当然,您仍然可以回答,特别是当技术和可用函数发展并为更好的解决方案开辟空间时。在这种情况下,请提供更详细的解释,说明为什么它比以前的解决方案更好。最后,请在此处友好地重现解决方案的要点,因为链接可能会失效,防止未来用户访问资源。 - ghybs

1
当列表足够长以覆盖软键盘时,在Android 4.x上按下Listview中的EditText会失去焦点。
一种解决方法是将Listview包装在高度为屏幕一半的线性布局中。
每当Listview没有覆盖软键盘时,一切都正常。

1

我遇到了相同的问题。搜索了所有与inputMode、focusability等相关的解决方案。最好的解决方案是迁移到RecyclerView。


我同意。我尝试了所有方法来修复ListViewEditText的行为,但是没有任何效果。我转而使用RecyclerView(请参见https://developer.android.com/guide/topics/ui/layout/recyclerview),现在一切都像梦一样顺畅,没有任何恶心的技巧。而且,由于我已经在我的`ListView`适配器中使用了`ViewHolder`模型,所以迁移非常容易。 - drmrbrewer

0
在我的情况下,我已经在适配器中添加了本地值currentlyFocusedRow。 在getView()方法中,我已经为每个editText添加了以下代码:
   if (currentlyFocusedRow == position) {
        editText.requestFocus();
   }

        editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {

            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (hasFocus) {
                    if (currentlyFocusedRow == -1) {
                        currentlyFocusedRow = position;
                    }
                } else {
                    currentlyFocusedRow = -1;
                }
            }
        });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接