Как помешать 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>

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, т.е. не используете событие, поведение фокусировки будет продолжаться как обычно.


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>

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

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


28

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

Источник


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

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

15

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

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

Это, кажется, ведет себя как я ожидаю. Не нужно обрабатывать изменения конфигурации и т. Д. Мне это нужно для Activity с длинным 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);

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

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.