Focusable EditText в ListView

Я провел приблизительно 6 часов на это до сих пор и был ударом только контрольно-пропускные пункты. Общая предпосылка - то, что существует некоторая строка в a ListView (сгенерировано ли это адаптером или добавлено как представление заголовка), который содержит EditText виджет и a Button. Все, что я хочу сделать, смочь использовать jogball/arrows, переместиться по селектору к отдельным объектам как нормальный, но когда я добираюсь до конкретной строки - даже если я должен явно определить строку - который имеет focusable ребенка, я хочу, чтобы тот ребенок взял фокус вместо того, чтобы указать на положение с селектором.

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

расположение:

<ListView
    android:id="@android:id/list" 
    android:layout_height="fill_parent" 
    android:layout_width="fill_parent"
    />

Представление Header:

EditText view = new EditText(this);
listView.addHeaderView(view, null, true);

Принятие там является другими объектами в адаптере, использование клавиш со стрелками переместит выбор/вниз в список, как ожидалось; но при получении до строки заголовка, это также отображено с селектором и никаким способом сфокусироваться в EditText использование jogball.Примечание: ответвление на EditText сфокусирует его в той точке, однако который полагается на сенсорный экран, который не должен быть требованием.

ListView по-видимому, имеет два режима в этом отношении:
1. setItemsCanFocus(true): селектор никогда не отображается, но EditText может получить фокус при использовании стрелок. Сфокусируйтесь алгоритм поиска трудно предсказать, и никакая визуальная обратная связь (на любых строках: наличие focusable детей или не), на котором выбран объект, оба из которых могут дать пользователю неожиданный опыт.
2. setItemsCanFocus(false): селектор всегда оттягивается в несенсорном режиме, и EditText никогда не может получать фокус - даже если Вы касаетесь на нем.

Усугублять положение, звоня editTextView.requestFocus() возвращает true, но на самом деле не дает фокус EditText.

То, что я предполагаю, является в основном гибридом 1 и 2, где, а не установка списка, если все объекты focusable или нет, я хочу установить focusability для единственного объекта в списке, так, чтобы селектор беспрепятственно перешел от выбора всей строки для non-focusable объектов и пересечения дерева фокуса для объектов, которые содержат focusable дочерние элементы.

Какие-либо берущие?

120
задан Catalina 20 April 2015 в 12:22
поделиться

1 ответ

Извините, сам ответил на свой вопрос. Возможно, это не самое правильное или элегантное решение, но оно работает для меня, и дает довольно солидный пользовательский опыт. Я заглянул в код ListView, чтобы понять, почему эти два поведения настолько различны, и наткнулся на следующее из ListView.java:

    public void setItemsCanFocus(boolean itemsCanFocus) {
        mItemsCanFocus = itemsCanFocus;
        if (!itemsCanFocus) {
            setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
        }
    }

Итак, при вызове setItemsCanFocus(false), он также устанавливает фокусируемость потомков, так что ни один ребенок не может получить фокус. Это объясняет, почему я не мог просто переключить mItemsCanFocus в OnItemSelectedListener ListView - потому что ListView тогда блокировал фокус для всех дочерних элементов.

Что у меня сейчас:

<ListView
    android:id="@android:id/list" 
    android:layout_height="match_parent" 
    android:layout_width="match_parent"
    android:descendantFocusability="beforeDescendants"
    />

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

Затем в OnItemSelectedListener, поскольку я знаю, какое представление заголовка я хочу переопределить селектор (потребовалось бы больше работы, чтобы динамически определить, содержит ли любая данная позиция фокусируемое представление), я могу изменить фокусируемость потомков и установить фокус на EditText. А когда я выйду из этого заголовка, снова изменить фокус.

public void onItemSelected(AdapterView<?> listView, View view, int position, long id)
{
    if (position == 1)
    {
        // listView.setItemsCanFocus(true);

        // Use afterDescendants, because I don't want the ListView to steal focus
        listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
        myEditText.requestFocus();
    }
    else
    {
        if (!listView.isFocused())
        {
            // listView.setItemsCanFocus(false);

            // Use beforeDescendants so that the EditText doesn't re-take focus
            listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
            listView.requestFocus();
        }
    }
}

public void onNothingSelected(AdapterView<?> listView)
{
    // This happens when you start scrolling, so we need to prevent it from staying
    // in the afterDescendants mode if the EditText was focused 
    listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
}

Обратите внимание на закомментированные вызовы setItemsCanFocus. С помощью этих вызовов я получил правильное поведение, но setItemsCanFocus(false) заставлял фокус перескакивать с EditText на другой виджет вне ListView, обратно в ListView и отображал селектор на следующем выбранном элементе, и это перескакивание фокуса отвлекало. Убрав изменение ItemsCanFocus и просто переключив фокусируемость потомков, я добился желаемого поведения. Все элементы рисуют селектор как обычно, но при переходе к строке с EditText он фокусируется на текстовом поле. Затем, при выходе из этого EditText, он снова начал рисовать селектор.

101
ответ дан 24 November 2019 в 01:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: