Непредсказуемое поведение Android GridView

#android #android-gridview

#Android #android-gridview

Вопрос:

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

Вот что я хочу получить. Должен быть GridView с элементами (8×10). Каждый элемент имеет изначально сгенерированный случайный цвет из 5 поддерживаемых наборов цветов. (Я использовал тип представления Android для элемента и просто установил цвет фона).

Каждый раз, когда пользователь нажимает на элемент, он должен быть «удален», а все элементы над ним должны быть перемещены вниз, чтобы заполнить свободное пространство. (Я беру идентификатор цвета из элемента выше и устанавливаю его на текущий элемент и делаю это до достижения самого верхнего элемента, затем случайным образом генерирую новый цвет для верхнего элемента столбца).

После всего этого я просто вызываю функцию notifyDataSetChanged () на моем адаптере, которая использовалась для просмотра сетки.

Проблема в том, что поведение непредсказуемо. На некоторых устройствах это работает, на некоторых устройствах он обновляет все элементы, и все элементы изменены. Иногда я вижу, что не было набора цветов, который, по-видимому, был связан с оптимизацией, и, кажется, я нашел решение…

Итак, кто-нибудь сталкивался с какими-то проблемами? Как вы достигли стабильного (ожидаемого) поведения? Может быть, вы можете предложить какое-то другое (более простое) решение или некоторые связанные с ним документы / примеры / уроки, которые я уже прочитал почти все, что Google предлагает в отношении GridLayouts.

Я любезно признателен за время, которое вы потратили на мой вопрос! Спасибо, Арсен

Обновлено:

Вот часть кодов, которые я использую: извините, что не публикую некоторые подробности.

в layout.xml

  <GridView
    class="<name>" 
android:id="@ id/gridView1"
android:listSelector="@null"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="0dp"
android:layout_alignParentBottom="true"
android:horizontalSpacing="0dp"
android:numColumns="8"
android:padding="0dp"
android:stretchMode="columnWidth"
android:cacheColorHint="@android:color/transparent"
android:verticalSpacing="0dp" >
 </GridView>
  

в layout.simple_grid_view_element:

 <View xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@ id/box"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
/>
  

в ImageAdapder, который расширяет BaseAdapter:

  ...
 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (convertView == null) {  // for the first time initialize each element.
      LayoutInflater Inf = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      convertView = Inf.inflate(R.layout.simple_grid_view_element, parent, false);
      v = (ImageView) convertView.findViewById(R.id.box);
      WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
      Display display = wm.getDefaultDisplay();
      int width = display.getWidth();
      int height = display.getHeight() - 40;
      v.setLayoutParams(new GridView.LayoutParams(((int)(width)/(mEngine.ColumnNumber)), ((int)((height)/mEngine.RowNumber) - 5)));
          v.setBackgroundResource( mEngine.generate_color_based_on_box_color(mEngine.TABLE.get(position)));
    }
    return v;
 }
  

в MainActivity:

 ....
GridView gridview = (GridView) findViewById(R.id.gridView1);
gridview.setAdapter(mEngine.getAdapter());
gridview.setVerticalScrollBarEnabled(false);
gridview.setOnItemClickListener(this);

....
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
        long id) {
mEngine.RespondOnClick(parent, position);
}
  

в классе Engine я просто меняю цвет фона элемента с заданной позицией, используя функцию onItemClick:
Эта функция использует таблицу вспомогательного массива, которая на самом деле предназначена для сохранения индексов цвета, потому что функция View.getBackground() возвращает огромное значение, которое работает некорректно, потому что JAVA не имеет неподписанных типов… (но это уже решено). Я отладил приложение, и все изменения в массиве таблиц выполняются правильно.

 ...
private ImageAdapter mAdapter;
...
Engine(Context mContext) {
    Columns = new ArrayList<ArrayList<Integer>>(ColumnNumber);
for (int i = 0; i < ColumnNumber;   i) {
    Columns.add(new ArrayList<Integer>());
}

TABLE = new ArrayList<Integer>(ColumnNumber * RowNumber);
for (int i = 0; i < ColumnNumber * RowNumber;   i) {
    TABLE.add(i, generateRandomColor());
}

    mAdapter = new ImageAdapter(mContext, this);
}

public void RespondOnClick(AdapterView<?> parent, final int position) {
CollectBoxesMarkedToRemoveByLine();
for (int i = 0; i < Columns.size();   i) {
    while (0 != Columns.get(i).size()) {
        int TopDeletedBoxPosition = Columns.get(i).get(0);
        int CurrentRowValue = (TopDeletedBoxPosition / ColumnNumber);
        while (0 < CurrentRowValue) {
            int PrevBoxColor = TABLE.get(TopDeletedBoxPosition - ColumnNumber);
            TABLE.set(TopDeletedBoxPosition, PrevBoxColor);
            this.getBox(TopDeletedBoxPosition).setBackgroundResource(generate_color_based_on_box_color(PrevBoxColor));
            --CurrentRowValue;
            TopDeletedBoxPosition -= ColumnNumber;
        }
        if (0 == CurrentRowValue) {
            int newColor = generateRandomColor();
            TABLE.set(TopDeletedBoxPosition, newColor);
            this.getBox(TopDeletedBoxPosition).setBackgroundResource(generate_color_based_on_box_color(TABLE.get(TopDeletedBoxPosition)));
        }
        Columns.get(i).remove(0);
    }
}
...
mAdapter.notifyDataSetChanged();  // called after RespondOnClick() has done all the replacements.
  

Комментарии:

1. На самом деле не уверен, стоит ли добавлять мир кодов в мою реализацию?

2. Пожалуйста, добавьте некоторый код к вашему вопросу. Не уверен, о чем вы спрашиваете.

3. Уже добавлено с обновлением вопроса.

Ответ №1:

Я только что исправил эту проблему и хотел бы поделиться опытом.

Причина проблемы возникла из функции getView(). Неправильно установлен фоновый ресурс. Это должно быть для обоих случаев, когда функция вызывается в первый раз, а convertview имеет значение null, а также для дальнейших вызовов во время обновления gridview.

Итак, единственное, что я сделал, это просто переместил эту строку из инструкции if-then:

ДО:

 @Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if (convertView == null) {  // for the first time initialize each element.
        ...
        v.setBackgroundResource( mEngine.generate_color_based_on_box_color(mEngine.TABLE.get(position)));
    }
    return v;
}
  

ПОСЛЕ:

 @Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if (convertView == null) {  // for the first time initialize each element.
        ...
    }
    v.setBackgroundResource( mEngine.generate_color_based_on_box_color(mEngine.TABLE.get(position)));
    return v;
}
  

Надеюсь, это будет кому-то полезно 🙂

Приветствую, Арсен