Як відмовити EditText від отримання фокусу при запуску діяльності в Android


2871

У мене є ActivityAndroid з двома елементами:

  1. EditText
  2. ListView

Коли мій Activityзапуск, EditTextодразу має фокус на вході (миготливий курсор). Я не хочу, щоб будь-який елемент керування вводом фокусувався при запуску. Я намагався:

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

Не вдалося. Як я можу переконати EditTextне вибирати себе під час Activityстарту?

Відповіді:


2591

Відмінні відповіді Люка та Марка, проте хороший зразок коду відсутній. Додавання тегу android:focusableInTouchMode="true"та android:focusable="true"батьківського макета (наприклад, LinearLayoutабо ConstraintLayout), як у наведеному нижче прикладі, вирішить проблему.

<!-- 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"/>

711
Як щодо встановлення батьківського макета android:focusableInTouchMode="true"!
Мухаммед Бабар

28
Ідеально! Дякую ... Одне, що слід зазначити, це те, що фіктивний предмет повинен бути розміщений праворуч перед тим, як фокусується елемент !!! У мене був TextView між монетом і EditText, і метод не працював!
maddob

25
налаштування android: focusableInTouchMode = "вірно" для батьківської верстки був хорошим підходом завдяки @Muhammad Babar
sujith

7
Чудовий код, мені дуже допомогли :) Щоб спробувати покращити його, android:focusableInTouchMode="true"охоплює android:focusable="true"+ ще трохи, тому в цьому випадку android:focusable="true"це зайве, і його можна видалити. Крім того, фіктивним видом може бути Вид, а не LinearLayout. Це економить потужність обробки + позбавляє вас від деяких попереджень. Таким чином, моя рекомендація замінює вид манекена на<View android:focusableInTouchMode="true" android:layout_width="0px" android:layout_height="0px"/>
Jacob R

20
@PietroRea Android має дратівливу поведінку з автоматичним фокусуванням, яка вбудована в основну поведінку його програми. Якщо ви скажете йому, що текст редагування виділяє або втрачає фокус, він автоматично приймає рішення про те, куди йде фокус. Без нового об'єкта, на який слід перенести фокус, він вибирає перший фокусується елемент у макеті, навіть коли саме цей елемент очистив фокус! Це свого роду горіхи і розчарування, але, можливо, є поважна причина такого типу поведінки.
Вестонське весілля

1675

Чи є актуальною проблемою, що ви просто не хочете, щоб вона взагалі зосереджувалася? Або ви не хочете, щоб вона відображала віртуальну клавіатуру в результаті фокусування EditText? Я насправді не бачу проблеми з EditTextфокусом на старті, але, безумовно, проблемою є відкриття вікна softInput, коли користувач явно не просив зосередитись на EditText(і в результаті відкрити клавіатуру).

Якщо це проблема віртуальної клавіатури, перегляньте документацію AndroidManifest.xml <елемент активності> .

android:windowSoftInputMode="stateHidden" - завжди приховуйте це при вступі в діяльність.

або android:windowSoftInputMode="stateUnchanged"- не змінюйте його (наприклад, не показуйте його, якщо він уже не відображався, але якщо він був відкритим під час входу в діяльність, залиште його відкритим).


24
все ще курсор знаходиться в першому EditText в макеті - хоча клавіатура не показана
martyglaubitz

39
@Anderson: Ніщо про відповідь не означало, що це заважатиме EditTextотримати фокус. Насправді чітко зазначено, що саме так ви не даєте автоматичній відкриттю програмної клавіатури IME на фокус; тому що більш імовірно, що більша стурбованість викликає несподівана спливаюча м'яка клавіатура, а не сам фокус. Якщо у вашій проблемі EditTextвзагалі є фокус, тоді використовуйте чужу відповідь.
Джо

1
встановити це програмно: stackoverflow.com/questions/6138330/…
Nick Franceschina

3
Не робіть цього за допомогою камери - це порушує час спалаху (не питайте мене чому)
Даніель Вілсон

1
@Joe це питання не стосується приховування клавіатури при запуску. Таке питання було поставлене тут stackoverflow.com/questions/18977187 / ...
user924

1140

Існує більш просте рішення. Встановіть ці атрибути у батьківському макеті:

<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();

Хороший коментар від Гійом Перро :

android:descendantFocusability="beforeDescendants"здається, за замовчуванням (ціле значення дорівнює 0). Він працює лише додаванням android:focusableInTouchMode="true".

Дійсно, ми можемо бачити, що beforeDescendantsв ViewGroup.initViewGroup()методі встановлено за замовчуванням (Android 2.2.2). Але не дорівнює 0.ViewGroup.FOCUS_BEFORE_DESCENDANTS = 0x20000;

Завдяки Гійом.


1
Важливо встановити ці атрибути прямому батьківському погляду, який зосереджується на створенні діяльності, інакше це не буде працювати.
tomrozb

4
Просто ідеальне рішення. Працює для обох: 1. Відключення автофокусування та 2. Вимкнення автоматичного відкриття м'якої клавіатури
Зустріч

Приємно. Це не потрібно бути прямим батьком. Я встановив його на рівні кореневого макета, і, здається, він працює добре.
Куроцукі

@DanielWilson, коли ви хочете переглянути прокрутку як прямий батьків редакційного тексту?
Марк Буйкема

Ви повинні працювати з програмним входом для вікон, як Readyandroid.wordpress.com/…
готовий Android

426

Єдине знайдене нами рішення:

  • Створіть LinearLayout (я не знаю, якщо будуть працювати інші види макета)
  • Встановіть атрибути android:focusable="true"таandroid:focusableInTouchMode="true"

І EditTextпісля запуску заняття фокус не отримає


Просто !! Я спочатку додав ці властивості до батьківського подання, який не вдався, потім встановив їх на інший макет і працював чудово. Дякую!!
Ріно

Він також працює з ConstraintLayout.
Яструб

85

Здається, проблема виникає з властивості, яку я бачу лише в 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>

77

використовуючи інформацію, надану іншими плакатами, я використав таке рішення:

в макеті 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();
}

73

Спробуйте clearFocus () замість setSelected(false). Кожен погляд в Android має як фокусируемость, так і вибірковість, і я думаю, що ви хочете просто очистити фокус.


Це звучить багатообіцяюче, але в який момент життєвого циклу діяльності його слід називати? Якщо я називаю це в onCreate (), редактор редагування все ще має фокус. Чи слід викликати його в onResume () або в якомусь іншому місці? Дякую!
Марк

8
Я поєднав прийняту відповідь з цією відповіддю. Я зателефонував myEditText.clearFocus(); myDummyLinearLayout.requestFocus();до onResumeпрограми. Це гарантувало, що EditText не утримував фокус під час обертання телефону.
teedyay

71

Наведене нижче буде зупиняти редагування тексту, коли воно не створюватиме фокус, але захоплюйте його, коли ви торкаєтесь їх.

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

Таким чином, ви встановлюєте фокусируемое значення false в xml, але ключ знаходиться в Java, до якого ви додаєте наступного слухача:

etBonus.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        v.setFocusable(true);
        v.setFocusableInTouchMode(true);
        return false;
    }
});

Оскільки ви повертаєте помилкову, тобто не споживаєте подію, поведінка фокусування буде протікати як нормально.


6
Але це ніколи не набуде уваги в майбутньому, як просто зупинити фокус лише для початкового (початок діяльності) ??
Jayesh

1
OnTouchListener викликається перед іншими сенсорними діями. Таким чином, включивши фокусируемость на дотик, стандартний фокус відбувається при першому дотику. Клавіатура підійде і все.
MinceMan

1
Я думаю, що це найкращий спосіб зробити це. Крім того, вищевказаний код мамбі-джамбо-xml-манекена НЕ працює для складного набору текстів для редагування ... Якщо це спрацює, я буду визначено голосувати.
Раду

Але якщо у вас є декілька текстів для редагування, то буде зосереджено увагу на наступному редагуванні тексту та відкритті клавіатури, тож краще додати android: windowSoftInputMode = "stateAlwaysHidden" у маніфест для конкретної діяльності.
Каран-шарма

Примітка: на Android P система більше не захоплюватиме фокус за замовчуванням. Це означає, що цей злом не потрібно починати з P.
MinceMan

65

Я спробував декілька відповідей окремо, але фокус все ще залишається на EditText. Мені вдалося вирішити це лише за допомогою двох із наведених нижче рішень разом.

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

(Довідка зі срібла https://stackoverflow.com/a/8639921/15695 )

і видалити

 <requestFocus />

на EditText

(Довідка з floydaddict https://stackoverflow.com/a/9681809 )


1
Мені довелося додати edittext.clearFocus () на додаток до вищезазначеного, щоб він працював :)
Nav

57

Пізня, але найпростіша відповідь, просто додайте це в батьківський макет XML.

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

Оновіть, якщо це допомогло вам! Щасливе кодування :)


2
прекрасно працював для мене. ще одне, що слід зазначити, не додайте ці рядки до подання прокрутки. Це не буде працювати у вигляді прокрутки. Але відмінно справлявся з лінійним компонуванням.
Картик Шрінівасан

46

Жодне з цих рішень не працювало для мене. Спосіб фіксації автофокусування:

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

2
android: windowSoftInputMode = "коригуватиPan" щодо будь-якої активності в Android Manifest
rallat

43

Просте рішення: In AndroidManifestу Activityвикористанні тегів

android:windowSoftInputMode="stateAlwaysHidden"

6
Строго кажучи, це не вирішує питання. ОП заявила: "Я не хочу, щоб будь-який елемент керування вводом фокусувався при запуску". У вашому рішенні ховається лише клавіатура, є різниця в sublte.
katzenhut

@katzenhut так, саме це питання з цією відповіддю. Якщо зосередитись на моєму редакційному тексті, відкривається активність PlaceAutoComplete, тому ця відповідь є неповною
Зак

Ця відповідь була б повною, якби питання: Як я завжди переконуюсь, що моя діяльність ніколи не показує клавіатуру. Що ні.
Мартін Маркончіні

37

Ви можете просто встановити "фокусируемый" і "фокусируемый в сенсорному режимі", щоб значення було істинним на першому TextViewз layout. Таким чином, коли діяльність починається TextView, фокус буде зосередженим, але, завдяки своїй природі, ви не побачите нічого, зосередженого на екрані, і, звичайно, клавіатура не відображатиметься ...


прекрасно працює для мене, лише я встановлюю значення для найвищого макета в моїй діяльності, а не для першого перегляду тексту
Maverick1st

36

Наступне працювало для мене в Manifest. Пишіть,

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

1
Це не фокусує текстове поле: воно просто приховує клавіатуру. Ви все одно отримаєте підказку, яку виштовхнули з поля, і будь-які селектори кольорів відобразять стан "фокус = справжній".
А. Рагер

31

Мені потрібно було чітко зосередити увагу на всіх полях. Щойно я додав наступні два твердження до свого основного визначення макета.

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

Це воно. Виправили свою проблему миттєво. Дякую, Сілвер, що ти вказав мені в правильному напрямку.


28

Додайте android:windowSoftInputMode="stateAlwaysHidden"в тег активності Manifest.xmlфайлу.

Джерело


1
Це не фокусує текстове поле: воно просто приховує клавіатуру. Ви все одно отримаєте підказку, яку виштовхнули з поля, і будь-які селектори кольорів відобразять стан "фокус = справжній".
А. Рагер

25

Якщо у вас є інший погляд на вашу діяльність, як-от ListView, ви також можете зробити:

ListView.requestFocus(); 

у вашому, onResume()щоб захопити фокус від editText.

Я знаю, що на це питання відповіли, але просто пропонували альтернативне рішення, яке працювало для мене :)


22

Спробуйте це перед першим редагованим полем:

<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();

21

Додайте наступне у onCreateспособі:

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

1
Це не фокусує текстове поле: воно просто приховує клавіатуру. Ви все одно отримаєте підказку, яку виштовхнули з поля, і будь-які селектори кольорів відобразять стан "фокус = справжній".
А. Рагер

17

Оскільки я не люблю забруднювати 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;
}

15

Пізно, але може бути корисно. Створення фіктивної EditText у верхній частині макета , то дзвонити myDummyEditText.requestFocus()вonCreate()

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

Це, здається, веде себе так, як я очікував. Не потрібно обробляти зміни конфігурації тощо. Мені це потрібно для діяльності із тривалим TextView (інструкціями).


Чому б просто не зробити це з самим видом кореня?
CJBS


13

Так, я зробив те ж саме - створив "фіктивний" лінійний макет, який отримує початковий фокус. Крім того, я встановлюю "наступний" ідентифікатор фокусування, щоб користувач не міг більше фокусувати його після прокрутки один раз:

<LinearLayout 'dummy'>
<EditText et>

dummy.setNextFocusDownId(et.getId());

dummy.setNextFocusUpId(et.getId());

et.setNextFocusUpId(et.getId());

багато роботи, щоб позбутися зосередженості на погляді ..

Дякую


12

Для мене те, що працювало на всіх пристроях:

    <!-- 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" />

Просто поставте це як погляд перед проблемним зосередженим поглядом, і все.


10

Найпростіше, що я зробив - це зосередити увагу на іншому погляді в onCreate:

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

Це зупинило появу м'якої клавіатури, і в редакторі EditText не блимав курсор.


10

Це ідеальне і найпростіше рішення. Я завжди використовую це у своєму додатку.

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

Це не фокусує текстове поле: воно просто приховує клавіатуру. Ви все одно отримаєте підказку, яку виштовхнули з поля, і будь-які селектори кольорів відобразять стан "фокус = справжній".
А. Рагер

9
<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"/>

8

Запишіть цей код всередину Manifestфайлу там, Activityде ви не хочете відкривати клавіатуру.

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>

2
Це не фокусує текстове поле: воно просто приховує клавіатуру. Ви все одно отримаєте підказку, яку виштовхнули з поля, і будь-які селектори кольорів відобразять стан "фокус = справжній".
А. Рагер

7

На onCreateвашій активності просто додайте користування clearFocus()елементом EditText. Наприклад,

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

А якщо ви хочете перенаправити фокус на інший елемент, скористайтеся requestFocus()цим. Наприклад,

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

6

Я використовую наступний код, щоб запобігти крадіжці фокуса EditText при натисканні кнопки.

addButton.setOnClickListener(new OnClickListener() {
    public void onClick(View v) {
        View focused = internalWrapper.getFocusedChild();
        focused.setVisibility(GONE);
        v.requestFocus();
        addPanel();
        focused.setVisibility(VISIBLE);
    }
});

В основному прихойте текст редагування, а потім покажіть його ще раз. Це працює для мене, оскільки EditText не розглядається, тому не має значення, чи він відображається.

Ви можете спробувати сховатися і показувати це послідовно, щоб побачити, чи допомагає це втратити фокус.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.