关于android:停止EditText在Activity启动时获得关注

Stop EditText from gaining focus at Activity startup

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

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

    1
    EditText.setSelected(false);

    运气不好。我怎样才能说服EditTextActivity启动时不选择自己呢?


    Luc和Mark给出了很好的答案,但是缺少了一个好的代码示例。像下面的例子一样,将标签android:focusableInTouchMode="true"添加到中可以解决问题。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <!-- 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"/>


    你真的不想让它集中注意力吗?或者您不希望它在聚焦EditText时显示虚拟键盘?我并不认为EditText的焦点在启动上有问题,但是当用户没有明确要求聚焦于EditText时,打开软输入窗口肯定是一个问题(因此打开键盘)。

    如果是虚拟键盘的问题,请参阅AndroidManifest.xml元素文档。

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

    或者android:windowSoftInputMode="stateUnchanged"—不要更改它(例如,如果还没有显示就不要显示它,但是如果在进入活动时它是打开的,就不要显示它)。


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

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

    现在,当活动开始时,默认情况下,主布局将获得焦点。

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

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

    来自Guillaume Perrot的好评:

    android:descendantFocusability="beforeDescendants" seems to be the
    default (integer value is 0). It works just by adding
    android:focusableInTouchMode="true".

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

    多亏了桂林。


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

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

    EditText在活动开始后就没有得到关注。


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

    确保在EditTextXML标记中声明的末尾删除这一行:

    1
    <requestFocus />

    应该是这样的:

    1
    2
    3
    4
    5
    6
    7
    8
    <EditText
       android:id="@+id/emailField"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:inputType="textEmailAddress">

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

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

    在布局XML中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <!-- 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"/>

    在OnCeRead()中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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()中

    1
    2
    3
    4
    5
    6
    7
    8
    @Override
    protected void onResume() {
        super.onResume();

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

    尝试clearFocus()而不是setSelected(false)。安卓系统中的每一个视图都有焦点可用性和可选择性,我认为您只想清除焦点。


    以下内容将阻止EditText在创建时获得焦点,但在触摸它们时将其抓取。

    1
    2
    3
    <EditText
        android:id="@+id/et_bonus_custom"
        android:focusable="false" />

    因此,您在XML中设置了可聚焦到false,但是该键位于Java中,您添加了以下监听器:

    1
    2
    3
    4
    5
    6
    7
    8
    etBonus.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            v.setFocusable(true);
            v.setFocusableInTouchMode(true);
            return false;
        }
    });

    因为你返回错误,即不消耗事件,聚焦行为将像正常一样进行。


    我试过几个答案,但重点仍然在编辑文本上。我只能通过同时使用下面的两个解决方案来解决这个问题。

    1
    2
    3
    4
    <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)

    去除

    1
     <requestFocus />

    在EditText

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


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

    1
    2
    3
        <intent-filter >
        </intent-filter>
    </activity>


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

    1
    android:windowSoftInputMode="stateAlwaysHidden"


    您只需将"Focusable"和"Focusable in Touch Mode"设置为在layout的第一个TextView上为真。这样,当活动开始时,TextView将被聚焦,但由于其性质,您将看不到任何聚焦在屏幕上的内容,当然,也不会显示键盘…


    以下是我在Manifest的工作。写,

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


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

    1
    2
    android:focusable="true"
    android:focusableInTouchMode="true"


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

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

    就是这样。立即解决了我的问题。谢谢,西尔弗,你指点我的方向。


    Manifest.xml文件的activity标签中添加android:windowSoftInputMode="stateAlwaysHidden"

    来源


    如果您对自己的活动有另一种看法,如ListView,您也可以这样做:

    1
    ListView.requestFocus();

    在你的onResume()中,从EditText中获取焦点。

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


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <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();

    onCreate方法中增加以下内容:

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


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    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;
    }

    晚了,但可能会有帮助。在布局顶部创建一个虚拟的edittext,然后在onCreate()中调用myDummyEditText.requestFocus()

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

    这似乎和我期望的一样。不需要处理配置更改等。对于具有长文本视图(说明)的活动,我需要这样做。


    是的,我做了同样的事情-创建一个"虚拟"的线性布局,得到初始焦点。此外,我还设置了"下一个"焦点ID,这样用户在滚动一次之后就不能再聚焦它了:

    1
    2
    3
    4
    5
    6
    7
    8
    <LinearLayout 'dummy'>
    <EditText et>

    dummy.setNextFocusDownId(et.getId());

    dummy.setNextFocusUpId(et.getId());

    et.setNextFocusUpId(et.getId());

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

    谢谢


    在父布局中编写此行…

    1
     android:focusableInTouchMode="true"

    对我来说,所有设备的工作原理是:

    1
    2
    3
    4
    5
    6
    7
        <!-- 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" />

    把它作为一个视图放在有问题的焦点视图之前,就是这样。


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

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


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

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

    这停止了软键盘的出现,编辑文本中没有光标闪烁。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <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"/>

    在不想打开键盘的Activity中的Manifest文件中编写此代码。

    1
    android:windowSoftInputMode="stateHidden"

    清单文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     <?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>
                   

                    <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>


    在活动的EDOCX1[0]处,只需在editText元素上添加use EDOCX1[1]。例如,

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

    如果你想把注意力转移到另一个元素上,可以使用requestFocus()。例如,

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


    您可以通过创建一个布局宽度和高度设置为0dp的虚拟EditText来实现这一点,并向该视图请求焦点。在XML布局中添加以下代码段:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <EditText
        android:id="@+id/editText0"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:hint="@string/dummy"
        android:ems="10"
        >
         <requestFocus />
        </EditText>

    当您的活动打开时,键盘会自动显示,这会导致EditText聚焦。您可以通过在manifest.xml文件的活动标记中写入以下行来禁用键盘。

    1
     android:windowSoftInputMode="stateAlwaysHidden|adjustPan"

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

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

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

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

    确保从XML中的EditText标记中删除行""

    1
    2
    3
    4
    5
    6
    7
    <EditText
       android:id="@+id/input"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content">

       <requestFocus /> <!-- remove this line -->
    </EditText>

    我使用下面的代码来阻止编辑文本在按下按钮时窃取焦点。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    addButton.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            View focused = internalWrapper.getFocusedChild();
            focused.setVisibility(GONE);
            v.requestFocus();
            addPanel();
            focused.setVisibility(VISIBLE);
        }
    });

    基本上,隐藏编辑文本,然后再次显示。这对我很有用,因为EditText不在视图中,所以它是否显示并不重要。

    你可以试着连续隐藏和展示它,看看这是否有助于它失去焦点。


    1
    2
    3
    4
    View current = getCurrentFocus();

    if (current != null)
        current.clearFocus();

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    /**
     * set focus to top level window
     * disposes descendant focus
     * disposes softInput
     * */
    public static void topLevelFocus(Context context){
        if(Activity.class.isAssignableFrom(context.getClass())){
            ViewGroup tlView = (ViewGroup) ((Activity) context).getWindow().getDecorView();
            if(tlView!=null){
                tlView.setFocusable(true);
                tlView.setFocusableInTouchMode(true);
                tlView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
            }
        }
    }

    尝试

    1
    2
    3
    edit.setInputType(InputType.TYPE_NULL);

    edit.setEnabled(false);

    ListView内的EditText不能正常工作。在使用EditText时,最好将TableLayout与自动生成的行一起使用。


    最简单的方法是在manifest.xml文件的activity标签中添加android:windowSoftInputMode="stateAlwaysHidden"


    Disable it in onCreate()

    1
    2
    3
    final KeyListener edtTxtMessageKeyListener = edtTxtMessage.getKeyListener();
    edtTxtMessage.setCursorVisible(false);
    edtTxtMessage.setKeyListener(null);

    And finally enable it in onClick() of EditText

    1
    2
    edtTxtMessage.setCursorVisible(true);
    edtTxtMessage.setKeyListener(edtTxtMessageKeyListener);

    但问题是,我们必须点击twise,第一次把屏幕键盘带上。

    @解决办法

    1
    2
    InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

    也可以在onclick()中尝试此操作:()


    我遇到了这样的问题,这是由于我的选择。第一个状态是焦点,即使我的视图被禁用了,它也采用焦点状态,因为它是第一个匹配并使用它的状态。您可以将第一个状态设置为禁用,如下所示:

    1
    2
    3
    4
    5
    6
    <selector xmlns:android="http://schemas.android.com/apk/res/android">


    <item android:drawable="@drawable/text_field_disabled" android:state_enabled="false"/>
    <item android:drawable="@drawable/text_field_focused" android:state_focused="true"/>
    <item android:drawable="@drawable/text_field_normal"/>

    从XML文件中的编辑文本中删除ve

    1
    2
    3
    4
    5
    6
    7
    8
    <EditText
       android:id="@+id/emailField"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:inputType="textEmailAddress">

       //`<requestFocus />` /* <-- remove this tags */
    </EditText>`


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <EditText
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:id="@+id/etComments"
        android:hint="Comments.."
        android:textSize="14dp"

        android:focusable="false"

        android:textStyle="italic"/>

    做这件事,完成你的工作!

    1
    2
    android:focusable="true"
    android:focusableInTouchMode="true"


    您有编辑文本和列表。在OnStart/OnCreate中,您应该将焦点设置在列表视图:Listview.requestfocus()上。


    通过使用请求焦点和键盘隐藏代码,可以将焦点指定给其他小部件。


    它可以通过继承EditText和超越onTouchEvent来实现。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class NonFocusableEditText: EditText {

        constructor(context: Context): super(context)
        constructor(context: Context, attrs: AttributeSet?): super(context, attrs)
        constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int): super(context, attrs, defStyleAttr)

        override fun onTouchEvent(event: MotionEvent?): Boolean {
            return if (isFocusable) super.onTouchEvent(event) else false
        }
    }

    然后您可以在布局中使用它,如Normal EditText

    1
    2
    3
    4
    5
    6
    7
    <com.yourpackage.NonFocusableEditText
            android:id="@+id/editText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"    
            android:hint="@string/your_hint"
            android:imeOptions="actionDone"
            android:inputType="textNoSuggestions" />

    在清单文件的下面一行添加您提到的活动

    1
    android:windowSoftInputMode="stateAlwaysHidden"