Навигация на клавиатуре с Android GridView не прокручивает сетку

Я пытаюсь использовать клавиатуру для навигации по GridView элементов.

В короткой демонстрации, в которой содержится только GridView (содержащий представления элементов с android:focusable="true"), вы можете видеть, что ни один из элементов не фокусируется - сетка - это вещь, которая прокручивает (элементы не становятся оранжевыми).

scrolling short demo

Добавление android:descendantFocusability="afterDescendants" позволяет сначала сфокусировать каждый элемент, но при этом не продолжать прокручивать GridView, чтобы вы могли перемещаться вниз:

with descendent focusability set

Щелчок по элементу (с помощью мыши или нажатием кнопки "Возврат", если объект был сфокусирован, после исправления фокусности потомства), элемент "синий" указывает на его нажатие.

clicking grid items

@макет/activity_my.xml:

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/listview"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:numColumns="2" />

@макет/dummy_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/dummy_item_parent"
  android:layout_width="match_parent"
  android:layout_height="150dp"
  android:gravity="center"
  android:focusable="true"
  android:clickable="true"
  android:background="@drawable/item_background" />

@вытяжке/item_background.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_pressed="true" android:drawable="@android:color/holo_blue_light" />
  <item android:state_focused="true" android:drawable="@android:color/holo_orange_light" />
  <item android:drawable="@android:color/holo_red_light" />
</selector>

MyActivity.java(со списком):

public class MyActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);

        AbsListView listview = (AbsListView) findViewById(R.id.listview);
        listview.setAdapter(new DummyAdapter(getLayoutInflater()));
    }

    private static class DummyAdapter extends BaseAdapter {

        private static final int COUNT = 25;

        private final LayoutInflater layoutInflater;

        DummyAdapter(LayoutInflater layoutInflater) {
            this.layoutInflater = layoutInflater;
        }

        @Override
        public int getCount() {
            return COUNT;
        }

        @Override
        public String getItem(int position) {
            return "Item " + position;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = convertView;
            if (view == null) {
                view = layoutInflater.inflate(R.layout.dummy_item, parent, false);
            }
            ((TextView) view).setText(getItem(position));
            return view;
        }

    }

}

Переключение GridView для ListView без изменения адаптера или атрибутов представления/элементов представления элементов будет вести себя так, как ожидалось, - элементы могут быть сфокусированы, а ListView будет прокручиваться в нижнюю часть, чтобы все элементы можно сфокусировать, используя просто ввод клавиатуры. Кроме того, использование RecyclerView с LinearLayoutManager/GridLayoutManager также будет работать правильно.

Я пробовал это на API 16 и 22 с теми же результатами. Я попытался настроить атрибут android:descendantFocusability в GridView на afterDescendents с тем же результатом.

Ответы

Ответ 1

Я попробовал ваш код, и он не работает с GridView, как вы сказали, но у меня есть проблема с ListView. ListView прокручивается правильно, но выделяется только первый элемент каждой страницы.

С помощью этих небольших модификаций вы можете добиться желаемого эффекта как для GridView, так и для ListView.

Удалите android:descendantFocusability в activity_my.xml:

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/listview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:numColumns="2" />

Удалите android:focusable в dummy_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dummy_item_parent"
    android:layout_width="match_parent"
    android:layout_height="150dp"
    android:gravity="center"
    android:clickable="true"
    android:background="@drawable/item_background" />

Измените с android:state_focused на android:state_selected в item_background.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@android:color/holo_blue_light" />
    <item android:state_selected="true" android:drawable="@android:color/holo_orange_light" />
    <item android:drawable="@android:color/holo_red_light" />
</selector>