Как помешать EditText получить фокус при запуске Activity в Android

2874

У меня есть Activityв Android, с двумя элементами:

  1. EditText
  2. ListView

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

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

Не повезло. Как я могу убедить EditTextне выбирать себя, когда Activityначинается?

отметка
источник

Ответы:

2593

Отличные ответы от Люка и Марка, однако хороший пример кода отсутствует. Добавление тега 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, и метод не работал!
Мэддоб
25
установка android: focusableInTouchMode = "true" для родительского макета была хорошим подходом, спасибо @Muhammad Babar
sujith s
7
Отличный код, мне очень помог :) Чтобы попытаться улучшить его, android:focusableInTouchMode="true"охватывает android:focusable="true"+ еще немного, так что в этом случае нет android:focusable="true"необходимости, и его можно удалить. Кроме того, фиктивное представление может быть View вместо LinearLayout. Это экономит вычислительную мощность + спасает вас от некоторых предупреждений. Таким образом, я рекомендую заменить фиктивный вид на<View android:focusableInTouchMode="true" android:layout_width="0px" android:layout_height="0px"/>
Jacob R
20
@PietroRea Android имеет раздражающее поведение автофокуса, которое встроено в основное поведение его структуры приложения. Если вы скажете ему, что редактируемый текст освобождает или теряет фокус, он автоматически принимает решение о том, куда направлен фокус. Без нового объекта для переноса фокуса он выбирает первый фокусируемый элемент в макете, даже если этот элемент только что очистил фокус! Это немного офигительно и неприятно, но, возможно, есть веская причина для такого поведения.
Уэстон Свадьба
1676

Действительно ли проблема в том, что вы просто не хотите, чтобы она вообще имела фокус? Или вы не хотите, чтобы он отображал виртуальную клавиатуру в результате фокусировки EditText? На самом деле я не вижу проблемы с EditTextфокусировкой на старте, но определенно проблема заключается в том, чтобы открывать окно softInput, когда пользователь явно не запрашивал фокусировку на EditText(и в результате открывал клавиатуру).

Если это проблема виртуальной клавиатуры, обратитесь к документации по AndroidManifest.xml элементу <activity> .

android:windowSoftInputMode="stateHidden" - всегда скрывать это при входе в активность.

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

Джо
источник
24
все же курсор все еще находится в первом EditText в макете - даже если клавиатура не показана
martyglaubitz
39
@ Андерсон: Ничто в ответе не подразумевает, что это помешало бы EditTextполучению фокуса. На самом деле в нем четко говорится, что именно так вы предотвращаете автоматическое открытие IME программной клавиатуры в фокусе; потому что более вероятно, что большее беспокойство вызывает неожиданно всплывающая программная клавиатура, а не сам фокус. Если ваша проблема связана с тем, что вы EditTextдействительно сосредоточены, используйте ответ другого человека.
Джо,
1
установите его программно: stackoverflow.com/questions/6138330/…
Ник Франческина
3
Не делайте этого на мероприятии с камерой - это нарушает синхронизацию вспышки (не спрашивайте меня, почему)
Даниэль Уилсон
1
@ Джо, этот вопрос не о том, чтобы скрыть клавиатуру при запуске. Такой вопрос был задан здесь stackoverflow.com/questions/18977187/…
user924
1141

Существует более простое решение. Установите эти атрибуты в родительском макете:

<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
Важно установить эти атрибуты в качестве прямого родителя представления, которое фокусируется на создании действий, иначе это не будет работать.
Томрозб
4
Просто идеальное решение. Работает для обоих: 1. Отключение автофокуса и 2. Отключение автоматического открытия программной клавиатуры
встреча
Ницца. Это не должно быть прямым родителем. Я установил его на корневой уровень макета, и, кажется, работает нормально.
Куроцуки
@DanielWilson, когда вы хотите, чтобы представление прокрутки было прямым родителем текста редактирования?
Марк Буйкема
Вы должны работать с окном ввода мягкой , как readyandroid.wordpress.com/...
Ready Android
427

Единственное решение, которое я нашел, это:

  • Создать LinearLayout (я не знаю, будут ли работать другие виды Layout)
  • Установите атрибуты android:focusable="true"иandroid:focusableInTouchMode="true"

И EditTextне получит фокус после начала деятельности

Люк
источник
Просто!! Сначала я добавил эти свойства в родительское представление, что не удалось, затем я установил их в другой макет и работал нормально. Спасибо!!
Рино
Это работает с ConstraintLayout тоже.
Ястреб
86

Кажется, проблема связана со свойством, которое я вижу только в 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>
floydaddict
источник
78

используя информацию, предоставленную другими авторами, я использовал следующее решение:

в макете 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();
}
Кто-то где-то
источник
74

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

Эрик Милл
источник
Это звучит многообещающе, но в какой момент в жизненном цикле деятельности его следует назвать? Если я вызываю его в onCreate (), EditText все еще имеет фокус. Должен ли он вызываться в onResume () или в другом месте? Спасибо!
Mark
8
Я совместил принятый ответ с этим ответом. Я позвонил myEditText.clearFocus(); myDummyLinearLayout.requestFocus();в onResumeактивность. Это гарантировало, что EditText не удерживал фокус при повороте телефона.
teedyay
71

Следующее действие остановит редактирование текста при создании фокуса, но захватите его при прикосновении к ним.

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

Таким образом, вы устанавливаете focusable в false в XML, но ключ находится в Java, который вы добавляете следующий слушатель:

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

Поскольку вы возвращаете false, т.е. не используете событие, поведение фокусировки будет продолжаться как обычно.

MinceMan
источник
6
Но это никогда не получит фокус в будущем, как просто остановить фокус только для начальной (начало деятельности) ??
Джаеш
1
OnTouchListener вызывается перед другими действиями касания. Таким образом, при включении фокусировки при прикосновении стандартная фокусировка происходит при первом касании. Клавиатура подойдет и все.
MinceMan
1
Я думаю, что это лучший способ сделать это. Кроме того, вышеприведенный магический фиктивный код mumbo-jumbo 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" >

(Ссылка от Silver 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"

Upvote, если это помогло вам! Удачного кодирования :)

Ришабх Саксена
источник
2
работал отлично для меня. еще одна вещь, на которую следует обратить внимание, не добавляйте эти строки в представление прокрутки. Это не будет работать в режиме прокрутки. Но отлично работал с линейной версткой.
Картич Сринивасан
46

Ни одно из этих решений не помогло мне. Способ, которым я исправляю автофокус, был:

<activity android:name=".android.InviteFriendsActivity" android:windowSoftInputMode="adjustPan">
    <intent-filter >
    </intent-filter>
</activity>
rallat
источник
2
android: windowSoftInputMode = "AdjustPan" для любого действия в манифесте Android
ралли
43

Простое решение: В AndroidManifestв Activityиспользовании тегов

android:windowSoftInputMode="stateAlwaysHidden"
Сергей Шелег
источник
6
Строго говоря, это не решает проблему. ОП сказал: «Я не хочу, чтобы какой-либо элемент управления имел фокус ввода при запуске». Ваше решение скрывает только клавиатуру, есть небольшая разница.
Каценхут
@katzenhut Да, это моя проблема с этим ответом точно. Сосредоточение внимания на моем тексте редактирования открывает действие PlaceAutoComplete, так что этот ответ неполон
Зак
Этот ответ был бы полным, если бы вопрос был: Как я всегда гарантирую, что моя деятельность никогда не показывает клавиатуру. Который не.
Мартин Маркончини
37

Вы можете просто установить «фокусируемый» и «фокусируемый в сенсорном режиме» на значение true в первом TextViewиз layout. Таким образом , когда активность Запускает TextViewбудет сфокусировано , но, в силу своей природы, вы будете видеть ничего не будет сфокусировано на экране и, конечно же , будет не клавиатура не отображается ...

Зевс
источник
отлично работает для меня, только я устанавливаю значение для внешнего макета в моей деятельности, а не для первого текстового просмотра
Maverick1st
36

Следующее работало для меня в Manifest. Написать ,

<activity
android:name=".MyActivity"
android:windowSoftInputMode="stateAlwaysHidden"/>
Бабар Сана
источник
1
Это не расфокусирует текстовое поле: оно просто скрывает клавиатуру. Вы по-прежнему получите подсказку, которая выдвигается за пределы поля, и любые селекторы состояния цвета будут отображать состояние «focus = true».
А. Рейгер
31

Мне нужно было очистить фокус со всех полей программно. Я просто добавил следующие два утверждения в мое основное определение макета.

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

Вот и все. Исправил мою проблему мгновенно. Спасибо, Сильвер, за то, что указал мне правильное направление.

jakeneff
источник
28

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

Источник

prgmrDev
источник
1
Это не расфокусирует текстовое поле: оно просто скрывает клавиатуру. Вы по-прежнему получите подсказку, которая выдвигается за пределы поля, и любые селекторы состояния цвета будут отображать состояние «focus = true».
А. Рейгер
25

Если у вас есть другой взгляд на вашу деятельность, например ListView, вы также можете сделать:

ListView.requestFocus(); 

в вашем, onResume()чтобы захватить фокус с editText.

Я знаю, что на этот вопрос ответили, но просто предоставили альтернативное решение, которое сработало для меня :)

Sid
источник
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
Это не расфокусирует текстовое поле: оно просто скрывает клавиатуру. Вы по-прежнему получите подсказку, которая выдвигается за пределы поля, и любые селекторы состояния цвета будут отображать состояние «focus = true».
А. Рейгер
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;
}
Takhion
источник
15

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

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

Это, кажется, ведет себя как я ожидаю. Не нужно обрабатывать изменения конфигурации и т. Д. Мне это нужно для Activity с длинным TextView (инструкции).

Джим
источник
Почему бы просто не сделать это с самим корневым представлением?
CJBS
14

Напишите эту строку в вашем макете для родителей ...

 android:focusableInTouchMode="true"
Вишал Вайшнав
источник
Дублированный ответ
Рикардо А.
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" />

Просто поместите это как представление перед проблемным сфокусированным представлением, и все.

разработчик Android
источник
10

Самое простое, что я сделал, это установил фокус на другое представление в onCreate:

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

Это остановило всплывающую программную клавиатуру, и в EditText не мигало курсор.

Lumis
источник
10

Это идеальное и самое простое решение. Я всегда использую это в своем приложении.

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

источник
Это не расфокусирует текстовое поле: оно просто скрывает клавиатуру. Вы по-прежнему получите подсказку, которая выдвигается за пределы поля, и любые селекторы состояния цвета будут отображать состояние «focus = true».
А. Рейгер
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
Это не расфокусирует текстовое поле: оно просто скрывает клавиатуру. Вы по-прежнему получите подсказку, которая выдвигается за пределы поля, и любые селекторы состояния цвета будут отображать состояние «focus = true».
А.Рагер
7

В onCreateвашей деятельности, просто добавьте использование clearFocus()в свой элемент EditText. Например,

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

И если вы хотите перевести фокус на другой элемент, используйте его requestFocus(). Например,

button = (Button) findViewById(R.id.button);
button.requestFocus();
Compaq LE2202x
источник
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 не отображается, поэтому не имеет значения, показывает ли он.

Вы можете попытаться скрыть и показать его последовательно, чтобы увидеть, поможет ли это потерять фокус.

drei01
источник