如何在Android中防止活动启动时EditText获取焦点?

3161

我在Android中有一个Activity,其中包含两个元素:

  1. EditText
  2. ListView

当我的Activity启动时,EditText立即具有输入焦点(闪烁光标)。我不希望任何控件在启动时具有输入焦点。我尝试过:

EditText.setSelected(false);
EditText.setFocusable(false);

没有成功。我该如何说服EditTextActivity启动时不选择自己?

54个回答

2844

在父布局中添加标签android:focusableInTouchMode="true"android:focusable="true",例如以下示例中的LinearLayoutConstraintLayout,将解决问题。

<!-- Dummy item to prevent AutoCompleteTextView from receiving focus -->
<LinearLayout
    android:focusable="true" 
    android:focusableInTouchMode="true"
    android:layout_width="0px" 
    android:layout_height="0px"/>

<!-- :nextFocusUp and :nextFocusLeft have been set to the id of this component
to prevent the dummy from receiving focus again -->
<AutoCompleteTextView android:id="@+id/autotext"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content"
    android:nextFocusUp="@id/autotext" 
    android:nextFocusLeft="@id/autotext"/>

757
父级布局设置为android:focusableInTouchMode="true",如何? - Muhammad Babar
@MuhammadBabar android:focusableInTouchMode="true" 在模拟器中创建一个缩放视图 - John Smith
在我的情况下,即使是添加到文本视图也可以工作。 - Arjun Verma
如果SO允许我多次给问题点赞,那么我会给这个答案点赞两次。谢谢兄弟。 - D_K

1739

你的实际问题是不想让EditText获得焦点吗?还是因为焦点在EditText上会导致虚拟键盘弹出?我认为在开始时,EditText获得焦点没有问题,但如果用户没有明确请求焦点并打开键盘,则强制打开软输入窗口就是一个问题。

如果问题是关于虚拟键盘的,可以查看AndroidManifest.xml<activity>元素文档。

android:windowSoftInputMode="stateHidden" - 进入活动时始终隐藏它。

或者 android:windowSoftInputMode="stateUnchanged" - 不更改它(例如,如果它尚未显示,则不要展示它,但如果在进入活动时已经打开了它,请保持其打开)。


27
尽管键盘未显示,但光标仍然位于布局中的第一个EditText中。 - martyglaubitz
45
@Anderson: 答案并未暗示它会防止EditText获得焦点。实际上,它清楚地说明了这是如何防止软件键盘IME在焦点上自动弹出的方法;因为更可能的问题是软键盘意外弹出,而不是焦点本身。如果你的问题是EditText是否实际上拥有焦点,那么请使用其他人的答案。 - Joe
如果EditText位于Fragment中,则无法正常工作。 - undefined

1204

有一个更简单的解决方案。在你的父布局中设置这些属性:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mainLayout"
    android:descendantFocusability="beforeDescendants"
    android:focusableInTouchMode="true" >

现在,当activity启动时,此主要布局将默认获取焦点。

另外,我们可以通过再次给主布局获取焦点来在运行时从子视图中移除焦点(例如,在完成子编辑后),如下所示:

findViewById(R.id.mainLayout).requestFocus();

来自Guillaume Perrot的好评论:

android:descendantFocusability="beforeDescendants" 似乎是默认值(整数值为0),只需添加 android:focusableInTouchMode="true" 即可生效。

实际上,我们可以看到在 ViewGroup.initViewGroup() 方法中设置了默认的 beforeDescendants 值(Android 2.2.2版本)。但它不等于0。ViewGroup.FOCUS_BEFORE_DESCENDANTS = 0x20000;

感谢Guillaume。


455

我找到的唯一解决方案是:

  • 创建一个LinearLayout(我不知道其他类型的布局是否有效)
  • 设置属性android:focusable="true"android:focusableInTouchMode="true"

这样,当启动活动后,EditText将不会获得焦点。


谢谢,也适用于其他布局。在约束布局上进行了测试。 - iamnaran
你也可以将根布局设置为可聚焦的。 - Konstantin Konopko

100

问题似乎出现在我只能在布局的XML表单中看到的一个属性。

请确保在EditText XML标记内声明的末尾删除此行:

<requestFocus />

那应该会得到类似这样的东西:

<EditText
   android:id="@+id/emailField"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:inputType="textEmailAddress">

   //<requestFocus /> /* <-- without this line */
</EditText>

89

借鉴其他帖子提供的信息,我使用了以下解决方案:

在布局XML中

<!-- Dummy item to prevent AutoCompleteTextView from receiving focus -->
<LinearLayout
    android:id="@+id/linearLayout_focus"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:layout_width="0px"
    android:layout_height="0px"/>

<!-- AUTOCOMPLETE -->
<AutoCompleteTextView
    android:id="@+id/autocomplete"
    android:layout_width="200dip"
    android:layout_height="wrap_content"
    android:layout_marginTop="20dip"
    android:inputType="textNoSuggestions|textVisiblePassword"/>

在onCreate()中

private AutoCompleteTextView mAutoCompleteTextView;
private LinearLayout mLinearLayout;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mylayout);

    //get references to UI components
    mAutoCompleteTextView = (AutoCompleteTextView) findViewById(R.id.autocomplete);
    mLinearLayout = (LinearLayout) findViewById(R.id.linearLayout_focus);
}

最后,在onResume()方法中

@Override
protected void onResume() {
    super.onResume();

    //do not give the editbox focus automatically when activity starts
    mAutoCompleteTextView.clearFocus();
    mLinearLayout.requestFocus();
}

2
这实际上是唯一对我有效的答案。添加android:focusable="true" android:focusableInTouchMode="true"可以防止EditText在某些设备上获得焦点,但在某些设备上仍然无法正常工作。我已经寻找解决方案很长时间了,这个方法完美地解决了我的问题。非常感谢。 - DIRTY DAVE
这比其他技术更有效!例如,使用onResume()强制文本字段失焦大多可以工作,但它会破坏第二次及以后使用adjustPan功能(将窗口内容滚动以适应带有软键盘的文本字段),至少在API 22-23上是如此。 - Jerry101

85
尝试使用 clearFocus() 替代 setSelected(false)。Android 中的每个视图都具有焦点和选择性,我认为你只想清除焦点。

1
听起来很有前途,但在Activity生命周期的哪个阶段应该调用它呢?如果我在onCreate()中调用它,EditText仍然具有焦点。它应该在onResume()或其他位置调用吗?谢谢! - Mark
9
我将已接受的答案与此答案结合起来。我在活动的onResume中调用了myEditText.clearFocus(); myDummyLinearLayout.requestFocus();,以确保EditText不会在手机旋转时保持焦点。 - teedyay

84
以下代码将阻止EditText在创建时获取焦点,但当您点击它们时会获得焦点。
<EditText
    android:id="@+id/et_bonus_custom"
    android:focusable="false" />

所以你在xml中设置了focusable为false,但关键在于java代码,你需要添加以下监听器:

etBonus.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        v.setFocusable(true);
        v.setFocusableInTouchMode(true);
        return false;
    }
});
因为你返回了 false,也就是没有消费该事件,所以焦点行为将会像正常情况一样继续进行。

7
但这在未来永远不会成为焦点,如何只停止对初始活动(开始活动)的关注? - Jayesh
1
在其他触摸操作之前会调用onTouchListener。因此,通过在触摸上启用focusable,标准焦点会在第一次触摸时发生。键盘将弹出并且一切都会正常。 - MinceMan
不错!这个可用(虽然似乎会将字段从焦点处理TAB序列中移除)。这可以在一个地方完成,而无需布局XML部分:if (Build.VERSION.SDK_INT <= 27) {et.setFocusable(false); et.setOnTouchListener(...);} - Jerry101

76

我曾尝试过多个解决方案,但焦点仍在EditText上。只有同时使用以下两种解决方案才成功解决了问题。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/mainLayout"
  android:descendantFocusability="beforeDescendants"
  android:focusableInTouchMode="true" >

(参考自Silver https://dev59.com/iHI_5IYBdhLWcg3wBub4#8639921)
并删除
<requestFocus />

在EditText中

(参考自floydaddicthttps://dev59.com/iHI_5IYBdhLWcg3wBub4#9681809)


2
我必须在上面的代码中添加edittext.clearFocus()才能使其正常工作 :) - Nav

74

虽然有些晚,但最简单的答案就是将以下代码添加到XML的父布局中。

android:focusable="true" 
android:focusableInTouchMode="true"

如果这篇文章对你有帮助,请点赞!祝你编程愉快 :)


4
对我来说完美地运作了。还有一件事要注意,不要将这些行添加到滚动视图中。它在滚动视图中不起作用,但在线性布局中完美运作。 - Karthic Srinivasan

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