ChatGPT解决这个技术问题 Extra ChatGPT

当活动在 Android 中启动时,如何阻止 EditText 获得焦点?

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

编辑文本列表视图

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

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

没运气。如何说服 EditTextActivity 启动时不选择自己?


J
Joundill

如下例所示,将标签 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"/>

parent 布局设置为 android:focusableInTouchMode="true" 怎么样!
@MuhammadBabar android:focusableInTouchMode="true" 在模拟器中创建缩放视图
在我的情况下,即使添加到文本视图也可以
如果允许我多次投票赞成问题,那么我将两次投票赞成这个答案。谢谢兄弟
R
Rahul

实际问题是您根本不希望它有焦点吗?或者您不希望它因为专注于 EditText 而显示虚拟键盘?我真的没有看到 EditText 关注开始有问题,但是当用户没有明确请求关注 EditText(并打开键盘)时,打开 softInput 窗口绝对是个问题因此)。

如果是虚拟键盘的问题,请参阅 AndroidManifest.xml <activity> element 文档。

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

android:windowSoftInputMode="stateUnchanged" - 不要更改它(例如,如果它尚未显示,则不要显示它,但如果它在进入活动时处于打开状态,则保持打开状态)。


但光标仍位于布局中的第一个 EditText 中 - 即使未显示键盘
@Anderson:答案没有暗示它会阻止 EditText 获得焦点。它实际上清楚地表明这是防止软件键盘输入法在焦点上自动打开的方式;因为更有可能更大的担忧是软键盘意外弹出,而不是焦点本身。如果您的问题是 EditText 实际上有焦点,那么请使用其他人的答案。
S
Samuel Liew

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

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

现在,当活动启动时,这个主布局将默认获得焦点。

此外,我们可以在运行时(例如,在完成子编辑之后)将焦点从子视图中移除,方法是再次将焦点赋予主布局,如下所示:

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

Guillaume Perrot好评

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

实际上,我们可以看到 beforeDescendantsViewGroup.initViewGroup() 方法中设置为默认值(Android 2.2.2)。但不等于 0。ViewGroup.FOCUS_BEFORE_DESCENDANTS = 0x20000;

感谢纪尧姆。


p
peterh

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

创建一个LinearLayout(我不知道其他类型的布局是否可行)

设置属性 android:focusable="true" 和 android:focusableInTouchMode="true"

并且 EditText 在启动活动后不会获得焦点


谢谢,也适用于其他布局。在约束布局上测试。
K
Keet Sugathadasa

问题似乎来自我只能在布局的 XML form 中看到的属性。

确保在 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>

Z
Ziem

使用其他海报提供的信息,我使用了以下解决方案:

在布局 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();
}

这实际上是唯一对我有用的答案。添加 android:focusable="true" android:focusableInTouchMode="true" 会阻止 EditTexts 在某些设备上获得焦点,但在某些设备上它仍然不起作用。我一直在寻找解决方案很长时间,并且效果很好。非常感谢。
K
Keet Sugathadasa

尝试 clearFocus() 而不是 setSelected(false)。 Android中的每个视图都具有可聚焦性和可选择性,我认为您只想清除焦点。


这听起来很有希望,但是应该在 Activity 生命周期的什么时候调用它?如果我在 onCreate() 中调用它,EditText 仍然具有焦点。应该在 onResume() 或其他位置调用它吗?谢谢!
我将接受的答案与这个答案结合起来。我在 Activity 的 onResume 中调用了 myEditText.clearFocus(); myDummyLinearLayout.requestFocus();。这确保了 EditText 在手机旋转时不会保持焦点。
Z
Ziem

以下将在创建时停止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,即不使用事件,所以聚焦行为将像往常一样进行。


但这在未来永远不会获得关注,如何只为初始(活动开始)停止关注?
onTouchListener 在其他触摸动作之前被调用。因此,通过启用可聚焦触摸,标准焦点发生在第一次触摸时。键盘会出现和一切。
好的!这一个有效(尽管它似乎使该领域脱离了焦点处理 TAB 序列)。这可以在一个地方完成,无需布局 XML 部分:if (Build.VERSION.SDK_INT <= 27) {et.setFocusable(false); et.setOnTouchListener(...);}
F
FullStackDeveloper

我已经单独尝试了几个答案,但重点仍然在 EditText 上。我只能通过同时使用以下两个解决方案来解决它。

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

(来自 Silver https://stackoverflow.com/a/8639921/15695 的参考)

并删除

 <requestFocus />

在 EditText

(来自 floydaddict https://stackoverflow.com/a/9681809 的参考)


除了上述内容之外,我还必须添加 edittext.clearFocus() 才能使其正常工作:)
R
Rishabh Saxena

迟到但最简单的答案,只需将其添加到 XML 的父布局中。

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

对你有帮助就点个赞吧!快乐编码:)


非常适合我。还有一点需要注意的是,不要将这些行添加到滚动视图中。它在滚动视图中不起作用。但与线性布局完美配合。
r
rallat

这些解决方案都不适合我。我修复自动对焦的方法是:

<activity android:name=".android.InviteFriendsActivity" android:windowSoftInputMode="adjustPan">
    <intent-filter >
    </intent-filter>
</activity>

android:windowSoftInputMode="adjustPan" 在 Android 清单中的任何活动上
P
Piyush

简单的解决方案:在 AndroidManifest 中的 Activity 标记使用

android:windowSoftInputMode="stateAlwaysHidden"

严格来说,这并不能解决问题。 OP 说:“我不希望任何控件在启动时具有输入焦点。”您的解决方案仅隐藏了键盘,存在细微差别。
@katzenhut 是的,这正是我对这个答案的问题。专注于我的编辑文本会打开一个 PlaceAutoComplete 活动,所以这个答案是不完整的
如果问题是:我如何始终确保我的活动从不显示键盘,则此答案将是完整的。哪个不是。
b
bofredo

您可以在 layout 的第一个 TextView 上将 "focusable""focusable in touch mode" 设置为 true。这样,当 Activity 启动时,TextView 将获得焦点,但由于其性质,您不会在屏幕上看到任何焦点,当然,不会显示 no 键盘...


P
Piyush

以下内容在 Manifest 中对我有用。写 ,

<activity
android:name=".MyActivity"
android:windowSoftInputMode="stateAlwaysHidden"/>

这不会使文本字段失去焦点:它只是隐藏了键盘。您仍然会得到一个被推出字段的提示,并且任何颜色状态选择器都将显示“focused=true”状态。
j
jakeneff

我需要以编程方式清除所有领域的焦点。我刚刚将以下两个语句添加到我的主要布局定义中。

myLayout.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
myLayout.setFocusableInTouchMode(true);

而已。立即解决了我的问题。谢谢,西尔弗,为我指明了正确的方向。


P
Piyush

Manifest.xml 文件的活动标记中添加 android:windowSoftInputMode="stateAlwaysHidden"

Source


这不会使文本字段失去焦点:它只是隐藏了键盘。您仍然会得到一个被推出字段的提示,并且任何颜色状态选择器都将显示“focused=true”状态。
b
bofredo

如果您对自己的 Activity 有其他视图,例如 ListView,您还可以执行以下操作:

ListView.requestFocus(); 

在您的 onResume() 中以从 editText 中获取焦点。

我知道这个问题已经得到解答,但只是提供了一个对我有用的替代解决方案:)


J
Jack Slater

在您的第一个可编辑字段之前尝试此操作:

<TextView  
        android:id="@+id/dummyfocus" 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" 
        android:text="@string/foo"
        />

----

findViewById(R.id.dummyfocus).setFocusableInTouchMode(true);
findViewById(R.id.dummyfocus).requestFocus();

P
Piyush

onCreate 方法中添加以下内容:

this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

这不会使文本字段失去焦点:它只是隐藏了键盘。您仍然会得到一个被推出字段的提示,并且任何颜色状态选择器都将显示“focused=true”状态。
T
Takhion

因为我不喜欢用与功能相关的东西来污染 XML,所以我创建了这个方法,它“透明地”从第一个可聚焦视图中窃取焦点,然后确保在必要时将其自身移除!

public static View preventInitialFocus(final Activity activity)
{
    final ViewGroup content = (ViewGroup)activity.findViewById(android.R.id.content);
    final View root = content.getChildAt(0);
    if (root == null) return null;
    final View focusDummy = new View(activity);
    final View.OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener()
    {
        @Override
        public void onFocusChange(View view, boolean b)
        {
            view.setOnFocusChangeListener(null);
            content.removeView(focusDummy);
        }
    };
    focusDummy.setFocusable(true);
    focusDummy.setFocusableInTouchMode(true);
    content.addView(focusDummy, 0, new LinearLayout.LayoutParams(0, 0));
    if (root instanceof ViewGroup)
    {
        final ViewGroup _root = (ViewGroup)root;
        for (int i = 1, children = _root.getChildCount(); i < children; i++)
        {
            final View child = _root.getChildAt(i);
            if (child.isFocusable() || child.isFocusableInTouchMode())
            {
                child.setOnFocusChangeListener(onFocusChangeListener);
                break;
            }
        }
    }
    else if (root.isFocusable() || root.isFocusableInTouchMode())
        root.setOnFocusChangeListener(onFocusChangeListener);

    return focusDummy;
}

V
Vishal Vaishnav

在您的父布局中写下这一行...

 android:focusableInTouchMode="true"

重复的答案
J
Jim

晚了,但也许有帮助。在布局顶部创建一个虚拟 EditText,然后在 onCreate() 中调用 myDummyEditText.requestFocus()

<EditText android:id="@+id/dummyEditTextFocus" 
android:layout_width="0px"
android:layout_height="0px" />

这似乎符合我的预期。无需处理配置更改等。对于具有冗长 TextView(说明)的 Activity,我需要此功能。


为什么不直接使用根视图本身呢?
b
bofredo

是的,我做了同样的事情——创建一个获得初始焦点的“虚拟”线性布局。此外,我设置了“下一个”焦点 ID,因此用户在滚动一次后无法再对其进行聚焦:

<LinearLayout 'dummy'>
<EditText et>

dummy.setNextFocusDownId(et.getId());

dummy.setNextFocusUpId(et.getId());

et.setNextFocusUpId(et.getId());

很多工作只是为了摆脱对视图的关注..

谢谢


a
android developer

对我来说,在所有设备上都有效的是:

    <!-- fake first focusable view, to allow stealing the focus to itself when clearing the focus from others -->

    <View
    android:layout_width="0px"
    android:layout_height="0px"
    android:focusable="true"
    android:focusableInTouchMode="true" />

只需将此作为一个视图放在有问题的重点视图之前,就是这样。


很有效,非常感谢
S
Satan Pandeya
<TextView
    android:id="@+id/TextView01"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:singleLine="true"
    android:ellipsize="marquee"
    android:marqueeRepeatLimit="marquee_forever"
    android:focusable="true"
    android:focusableInTouchMode="true"
    style="@android:style/Widget.EditText"/>

L
Lumis

我做的最简单的事情是在 onCreate 中将焦点设置在另一个视图上:

    myView.setFocusableInTouchMode(true);
    myView.requestFocus();

这停止了软键盘的出现,并且 EditText 中没有光标闪烁。


佚名

这是完美和最简单的解决方案。我总是在我的应用程序中使用它。

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);

这不会使文本字段失去焦点:它只是隐藏了键盘。您仍然会得到一个被推出字段的提示,并且任何颜色状态选择器都将显示“focused=true”状态。
S
Satan Pandeya

将此代码写入您不想打开键盘的 Activity 中的 Manifest 文件中。

android:windowSoftInputMode="stateHidden"

清单文件:

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.projectt"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="24" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
         <activity
            android:name=".Splash"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".Login"
            **android:windowSoftInputMode="stateHidden"**
            android:label="@string/app_name" >
        </activity>

    </application>

</manifest>

这不会使文本字段失去焦点:它只是隐藏了键盘。您仍然会得到一个被推出字段的提示,并且任何颜色状态选择器都将显示“focused=true”状态。
C
Compaq LE2202x

在您的 Activity 的 onCreate,只需在 EditText 元素上添加 use clearFocus()。例如,

edittext = (EditText) findViewById(R.id.edittext);
edittext.clearFocus();

如果您想将焦点转移到另一个元素,请使用 requestFocus()。例如,

button = (Button) findViewById(R.id.button);
button.requestFocus();

S
Sharath kumar

隐藏键盘的最简单方法是使用 setSoftInputMode

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

或者您可以使用 InputMethodManager 并像这样隐藏键盘。

InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);

问题不在于键盘