Как сохранить выделение выделенного элемента в gridview при изменении numColumns?

У меня есть ActionBarActivity с GridView .

GridView имеет 2 столбца в портрете и 3 столбца в ландшафте.

Когда я выбираю элементы в портрете (начиная с моего ActionMode ), а затем поворачиваю устройство, выделенный элемент выделяет один элемент влево. Например, если я выберу второй элемент и повернусь, будет выделен первый элемент. Если я выберу первый элемент и повернусь, элементы не будут выделены.

Фактический выбор в коде правильный, просто подсветка неправильная.

Я замечаю, что это не делает, если я сохраню numColumns одинаково для портретной и альбомной ориентации.

Я считаю, что эта проблема возникла после того, как я изменил свою деятельность на ActionBarActivity так что это может быть ошибка.

Кто-нибудь знает, почему и как его исправить?

У меня был аналогичный сценарий, и я решил, что проблема заключается в создании настраиваемого элемента сетки с boolean полем, чтобы отслеживать, выбран ли элемент или нет, а затем соответствующим образом выделять элемент через пользовательский адаптер. Ниже приводится краткое описание того, что я сделал:

(1) Я создал пользовательский элемент сетки с boolean полем, которое мы будем называть selectedStatus для простоты. Я также добавил соответствующие методы в класс элемента grid, чтобы получить выбранный статус:

 public boolean getSelectedStatus () { return selectedStatus; } public void setSelectedStatus (boolean paramSelectedStatus) { this.selectedStatus = paramSelectedStatus; } 

(2) Затем я создал специальный Adapter который extends BaseAdapter для обработки настраиваемого объекта сетки, который я создал. В этом Adapter я проверяю, является ли выбранный статус объекта сетки true или false и соответствующим образом выделите элемент, как показано ниже:

 @Override public View getView (final int position, View convertView, ViewGroup parent) { // rest of getView() code... if (!yourGridObject.getSelectedStatus()) { convertView.setBackgroundColor(Color.TRANSPARENT); } else { convertView.setBackgroundColor(Color.LTGRAY); } // rest of getView() code... return convertView; } 

(3) Наконец, вы добавляете onItemClickListener для установки выбранного состояния и цвета фона элементов сетки при их onItemClickListener ):

 yourGridView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { YourGridObject yourGridObject = (YourGridObject) parent.getItemAtPosition(position); if (!yourGridObject.getSelected()) { view.setBackgroundColor(Color.LTGRAY); yourGridObject.setSelected(true); } else { view.setBackgroundColor(Color.TRANSPARENT); yourGridObject.setSelected(false); } } }); 

Реализация выбора таким образом гарантирует, что выделение (выбор) элементов сетки не изменится, когда число столбцов и строк будет меняться, поскольку статус выбора содержится внутри самих объектов сетки.

Вам не нужно вручную обрабатывать выбор предметов, как это предлагает Уиллис. Android полностью поддерживает то, что вы просите. Предположим, вы используете ArrayAdapter но этот ответ применим ко всем адаптерам. Обратите внимание, что некоторые адаптеры (например, CursorAdapter ) не пострадают от вашей размещенной проблемы и не требуют следующего решения, потому что оно уже делает это внутри.

Проблема решена в двух частях. Во-первых, адаптер должен включать стабильные идентификаторы. Два, ваш адаптер должен фактически вернуть стабильные идентификаторы. Вам нужно будет расширить ArrayAdapter или какой-либо адаптер, который вы используете. Затем убедитесь, что вы определили следующие методы, как показано ниже.

 private class MyAdapter extends ArrayAdapter<YourObjects> { @Override public boolean hasStableIds() { return true; } @Override public long getItemId(int position) { //Return a unique and stable id for the given position //While unique, Returning the position number does not count as stable. //For example: return getItem(position).methodThatReturnsUniqueValue(); } } 

Большинство адаптеров не поддерживают hasStableIds . В основном это используется только при включении метода выбора. Что я предполагаю, что вы здесь делаете. Вернувшись, вы, по сути, говорите, что Android отслеживает активированные (выделенные) элементы на основе их идентификационного значения вместо своего номера позиции.

Даже при стабильных идентификаторах вы должны фактически вернуть идентификатор, который является уникальным и стабильным в позиционных изменениях. Поскольку большинство адаптеров НЕ разрешают стабильные идентификаторы, они обычно возвращают только номер позиции в качестве стабильного идентификатора. Технически, если позиция позиции никогда не изменяется со временем, тогда номер позиции «может» использоваться как стабильный идентификатор. Тем не менее, самый безопасный способ вернуть стабильный / уникальный идентификатор – это присвоить объект класса, хранящийся в адаптере, и извлечь из него.