Как убрать фокус, не установив фокус на другой элемент управления?


96

Мне нравится интуитивно понятный интерфейс; каждый экран должен естественно и ненавязчиво вести пользователя к следующему шагу в приложении. За исключением этого, я стараюсь сделать вещи как можно более запутанными и запутанными.

Просто шучу :-)

У меня есть три TableRows, каждый из которых содержит элемент управления EditText, доступный только для чтения и не фокусируемый, а затем кнопку справа от него. Каждая кнопка запускает одно и то же действие, но с другим аргументом. Пользователь делает выбор там, и подзадача завершается, заполняя соответствующие EditTextвыборы пользователя.

Это классический механизм каскадных значений; каждый выбор сужает доступные параметры для следующего выбора и т. д. Таким образом, я отключаю оба элемента управления в каждой из следующих строк, пока EditText в текущей строке не будет содержать значение.

Мне нужно сделать одно из двух в следующем порядке:

  1. При нажатии кнопки сразу же убирать фокус, не устанавливая фокус на другую кнопку.
  2. Установите фокус на первую кнопку при запуске действия

Проблема проявляется после возвращения подактивности; нажатая кнопка сохраняет фокус.

Re: # 1 выше - похоже, нет removeFocus()метода или чего-то подобного

Re: # 2 выше - я могу использовать requestFocus()для установки фокуса на кнопку в следующей строке, и это работает после возврата под-активности, но по какой-то причине это не работает в родительской активности onCreate().

Мне нужна согласованность пользовательского интерфейса в любом направлении - либо кнопки не имеют фокуса после завершения субдействия, либо каждая кнопка получает фокус в зависимости от своего места в логическом потоке, включая самую первую (и единственную) активную кнопку до любого выбора.

Ответы:


174

Использование clearFocus (), похоже, тоже не сработало для меня, как вы обнаружили (видели в комментариях к другому ответу), но в итоге у меня сработало добавление:

<LinearLayout 
    android:id="@+id/my_layout" 
    android:focusable="true" 
    android:focusableInTouchMode="true" ...>

на мой самый верхний уровень Layout View (линейный макет). Чтобы удалить фокус со всех кнопок / EditTexts и т. Д., Вы можете просто сделать

LinearLayout myLayout = (LinearLayout) activity.findViewById(R.id.my_layout);
myLayout.requestFocus();

Запрос фокуса ничего не сделал, если я не установил фокусируемое представление.


На мгновение я подумал, что это может сработать. «Как красиво в своей простоте!» Я сказал себе. Увы, этого не произошло. Даже когда я удаляю requestFocus (), кнопка следующей строки получает фокус. Это было бы нормально в качестве второго предпочтения, но только если я могу каким-то образом установить фокус на первой кнопке в onCreate ().
InteXX

@InteXX: Сегодня я снова столкнулся с этой проблемой и нашел решение. Я знаю, что вы сейчас выбрали другой маршрут, но попробуйте его, если снова окажетесь в той же лодке!
actionshrimp

«Я знаю, что ты выбрал другой путь». Еще не поздно сделать резервную копию :-) Я попробую и дам тебе знать, спасибо.
InteXX

Штопать. Почти, но не совсем. Да, он снимает фокус с последней нажатой кнопки, но также предотвращает фокусировку ЛЮБОЙ кнопки. Это означало бы, что мои пользователи без сенсорного экрана не смогут нажать кнопку. Это делает то же самое для вас?
InteXX 02

6
Это не будет работать с ScrollView. Если ваш вид сверху - ScrollView, используйте его для его дочернего элемента.
Урош Подкрижник

79

Старый вопрос, но я столкнулся с ним, когда у меня была аналогичная проблема, и подумал, что поделюсь тем, чем я закончил.

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

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

12
Элегантный способ сделать это. Перед вызовом clearFocus () можно проверить на null значение из getCurrentFocus ()
Веринг

4
+1 Да, вам придется бросить этот нулевой чек! - Почему Java не может просто реализовать оператор безопасного обхода? Это было бы так просто getCurrentFocus()?.clearFocus();, так красиво и элегантно: - /
Левит

1
@willlma: Да, я имел в виду именно это.
Веринг

5
@Levit Очень быстрый. :-) Но даже если бы в Java был реализован такой оператор, Android все равно потребовалось бы 4 года, чтобы наверстать упущенное.
Грег Браун,

2
@Levit, ты, наверное, уже его нашел, но Котлин.
prodaea

9
  1. Вы можете использовать View.clearFocus().

  2. Использование View.requestFocus()вызвано из onResume().


@siliconeagle: Это ОЧЕНЬ странно. (Спасибо за указатель на clearFocus (), кстати - я не знал об этом.) Когда я нажимаю первую кнопку, делаю выбор и затем возвращаюсь, первая кнопка больше не может получать фокус. Я не устанавливаю фокусировку для этой кнопки где-либо в моем коде. Я хотел бы показать вам свой код, но в этом окне редактирования недостаточно символов, и я новичок в этом. Поэтому я не уверен, следует ли мне вводить другой ответ, чтобы иметь возможность опубликовать код.
InteXX

@siliconeagle: К сожалению, clearFocus () не работает - кнопки сохраняют фокус при возвращении подактивности.
InteXX

@siliconeagle: Хорошо, не обращайте внимания на этот первый комментарий. Я использовал setFocusable (false) в событии нажатия кнопки и забыл включить его после возврата подактивности. clearFocus () по-прежнему не действует - интересно, почему? Я вызываю его для всех кнопок из onActivityResult (), но нажатая кнопка по-прежнему сохраняет фокус. Странный.
InteXX

@siliconeagle: @actionshrimp: Я решил отказаться от всех команд и настроек, связанных с фокусом. Моим первоначальным намерением было предотвратить фокусировку на отключенных кнопках, но если это того стоит, это того не стоит. Без requestFocus (), clearFocus () или setFocusable () ни одна кнопка не сохраняет фокус после возврата под-активности. Это меньший из двух долгоносиков - я думаю, мне придется жить с возможностью установить фокус на отключенную кнопку.
InteXX

инвалидов элементы не фокусируемый AFAIK ... использование setEnabled (ложь)
siliconeagle

8

android:descendantFocusability="beforeDescendants"

использование следующего в упражнении с некоторыми вариантами макета, приведенными ниже, похоже, работает должным образом.

 getWindow().getDecorView().findViewById(android.R.id.content).clearFocus();

в связи со следующими параметрами в корневом представлении.

<?xml
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:descendantFocusability="beforeDescendants" />

https://developer.android.com/reference/android/view/ViewGroup#attr_android:descendantFocusability

Ответ спасибо: https://forums.xamarin.com/discussion/1856/how-to-disable-auto-focus-on-edit-text

О windowSoftInputMode

Есть еще один аргумент, о котором следует знать. По умолчанию Android автоматически назначает начальный фокус первому EditText или фокусируемому элементу управления в вашей деятельности. Естественно, следует, что InputMethod (обычно программная клавиатура) будет реагировать на событие фокуса, показывая себя. Атрибут windowSoftInputMode в AndroidManifest.xml, если ему задано значение stateAlwaysHidden, указывает клавиатуре игнорировать этот автоматически назначаемый начальный фокус.

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

отличная ссылка


6
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto"
          android:id="@+id/ll_root_view"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical">

LinearLayout llRootView = findViewBindId(R.id.ll_root_view);
llRootView.clearFocus();

Я использую это, когда уже закончил обновление информации профиля и убираю весь фокус с EditText в моем макете

====> Обновление: в содержимом родительского макета моя строка добавления EditText:

android:focusableInTouchMode="true"


2

Во-первых, будет 100% работать ........

  1. Создать onResume()метод.
  2. Внутри onResume()найдите вид, который фокусируется снова и снова findViewById().
  3. Внутри этого onResume()набора requestFocus()для этого представления.
  4. Внутри этого onResume()набора clearFocusдля этого представления.
  5. Зайдите в xml того же макета и найдите тот вид сверху, который вы хотите сфокусировать, и установите focusabletrue и focusableInTuchtrue.
  6. Внутри onResume()найдите вид сверху, сделанныйfindViewById
  7. Внутри этого, наконец, onResume()установлен requestFocus()этот вид.
  8. А теперь наслаждайтесь ......

2

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

focusedView.setFocusable(false);
focusedView.setFocusableInTouchMode(false);
focusedView.setFocusable(true);
focusedView.setFocusableInTouchMode(true);

1

Вы можете попробовать отключить возможность основного Activity сохранять свое состояние (таким образом, заставляя его забыть, какой элемент управления имеет текст, а какой - фокус). Вам понадобится другой способ запомнить, что есть у вашего EditText, и повторно заполнить их onResume (). Запустите свои дочерние действия с помощью startActivityForResult () и создайте обработчик onActivityResult () в своем основном действии, который будет правильно обновлять EditText. Таким образом, вы можете установить правильную кнопку, на которой вы хотите сфокусироваться наResume (), в то же время, когда вы повторно заполняете EditText, используя myButton.post (new Runnable () {run () {myButton.requestFocus ();}});

Метод View.post () полезен для первоначальной установки фокуса, потому что этот runnable будет выполнен после того, как окно будет создано и все успокоится, позволяя механизму фокуса нормально функционировать к этому времени. Я обнаружил, что при попытке установить фокус во время onCreate / Start / Resume () обычно возникают проблемы.

Обратите внимание, что это псевдокод и не проверено, но это возможное направление, которое вы можете попробовать.


С другой стороны ... попробуйте сначала просто использовать материал View.post () вместо отключения сохраненного состояния Activity. Это могло бы помочь вам всем само по себе.
Uncle Code Monkey

Увы, у меня больше нет простого способа проверить это для нас. С тех пор я решил отказаться от модели нативного кода и перейти на HTML5 / CSS3 для мобильных приложений и, таким образом, соответствующим образом перестроил свою систему. Но спасибо за подробный ответ. Я проголосовал за.
InteXX

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

Добавьте их в свою ViewGroup, которая включает ваш EditTextView. Он правильно работает с моим макетом ограничений. Надеюсь на эту помощь


0

Попробуйте следующее (звонок clearAllEditTextFocuses();)

private final boolean clearAllEditTextFocuses() {
    View v = getCurrentFocus();
    if(v instanceof EditText) {
        final FocusedEditTextItems list = new FocusedEditTextItems();
        list.addAndClearFocus((EditText) v);

        //Focus von allen EditTexten entfernen
        boolean repeat = true;
        do {
            v = getCurrentFocus();
            if(v instanceof EditText) {
                if(list.containsView(v))
                    repeat = false;
                else list.addAndClearFocus((EditText) v);
            } else repeat = false;
        } while(repeat);

        final boolean result = !(v instanceof EditText);
        //Focus wieder setzen
        list.reset();
        return result;
    } else return false;
}

private final static class FocusedEditTextItem {

    private final boolean focusable;

    private final boolean focusableInTouchMode;

    @NonNull
    private final EditText editText;

    private FocusedEditTextItem(final @NonNull EditText v) {
        editText = v;
        focusable = v.isFocusable();
        focusableInTouchMode = v.isFocusableInTouchMode();
    }

    private final void clearFocus() {
        if(focusable)
            editText.setFocusable(false);
        if(focusableInTouchMode)
            editText.setFocusableInTouchMode(false);
        editText.clearFocus();
    }

    private final void reset() {
        if(focusable)
            editText.setFocusable(true);
        if(focusableInTouchMode)
            editText.setFocusableInTouchMode(true);
    }

}

private final static class FocusedEditTextItems extends ArrayList<FocusedEditTextItem> {

    private final void addAndClearFocus(final @NonNull EditText v) {
        final FocusedEditTextItem item = new FocusedEditTextItem(v);
        add(item);
        item.clearFocus();
    }

    private final boolean containsView(final @NonNull View v) {
        boolean result = false;
        for(FocusedEditTextItem item: this) {
            if(item.editText == v) {
                result = true;
                break;
            }
        }
        return result;
    }

    private final void reset() {
        for(FocusedEditTextItem item: this)
            item.reset();
    }

}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.