Другой макет для элементов в listview

#android #listview #cursor #adapter

#Android #listview #курсор #адаптер

Вопрос:

У меня есть какой-то расширенный адаптер курсора, в witch я вызываю super с контекстом и макетом ресурсов для элемента в списке, что-то вроде этого.

вызов super в моем адаптере:

 super(activity, viewResource, c, false);
  

создание моего адаптера:

 new MyCursorAdapter(this, null, R.layout.my_list_item, null);
  

Чего я хочу добиться, так это чего-то вроде моего глупого макета, сделанного в paint.
Проще говоря, я хочу иметь разные виды расположения элементов, например, я хочу, чтобы все четные элементы имели layout1, а все нечетные — layout2. Пока я могу предоставить только один макет в этом случае R.layout.my_list_item. Возможно ли динамически изменять макет?
Возможно ли сконструировать адаптер так, чтобы в нем были элементы с другим расположением? Моя цель — динамически выбирать макет элемента. Я не хочу иметь только один макет для всех элементов, которые я хочу иметь в примере два…

Спасибо

введите описание изображения здесь

Ответ №1:

Да, вам все же придется сделать две вещи. Во-первых, переопределите getItemViewType() метод в вашем адаптере, чтобы вы могли быть уверены, что ваши bindView() единственные представления get соответствуют определенной позиции в списке, например:

 public int getItemViewType(int position){
  if(correspondsToViewType1(position)){
    return VIEW_TYPE_1;
  }
  else(correspondsToViewType2(position)){
    return VIEW_TYPE_2;
  }
  //and so on and so forth.
}
  

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

 public void bindView(View view, Context context, Cursor cursor){
  if(correspondsToViewType1(cursor)){
    //Now we know view is of a particular type and we can do the 
    //setup for it
  }
  else if(correspondsToViewType2(cursor){
    //Now we know view is of a different type and we can do the 
    //setup for it
  }
}
  

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

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

Ответ №2:

Я предполагаю, что вы расширяете SimpleCursorAdapter по имени вашего пользовательского адаптера. Вы захотите переопределить функцию getView в своем адаптере и в зависимости от объекта в списке создать другой макет и вернуть это представление.

ПРИМЕР:

      @Override
     public View getView (int position, View convertView, ViewGroup parent)
     {
            Object myObject = myList.get(position);

            if(convertView == null)
            {
                  if( something to determine layout )
                        convertView = inflater.inflate(Layout File);
                  else
                        convertView = inflater.inflate(Some Other Layout File);
            }

            //Set up the view here, such as setting textview text and such

            return convertView;
     }
  

Это всего лишь пример и в некоторой степени код sudo, поэтому для вашей конкретной ситуации потребуются некоторые корректировки.

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

1. Это не сработает. Он расширяет CursorAdapter, в котором уже переопределен метод getView. Вы не хотите связываться с этим методом, потому что он выполняет специальные действия, связанные с получением соответствующего курсора. Кроме того, переработанный convertView, который он получает, может быть неправильного типа, поэтому он никогда не сможет его использовать, и его приложение сильно пострадает в производительности.

Ответ №3:

Просто переопределите метод NewView:

 public class MyCursorAdapter extends CursorAdapter {

private final LayoutInflater inflater;
    private ContentType type;

public MyCursorAdapter (Context context, Cursor c) {
    super(context, c);
    inflater = LayoutInflater.from(context);
}

@Override
public void bindView(View view, Context context, Cursor cursor) {
    if( cursor.getString(cursor.getColumnIndex("type")).equals("type1") ) {
                // get elements for type1
    } else {
                // get elements for type1
            }

}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {

    if( cursor.getString(cursor.getColumnIndex("type")).equals("type1") ) {
        final View view = inflater.inflate(R.layout.item_type1, parent, false);
    } else {
        final View view = inflater.inflate(R.layout.item_type2, parent, false);
    }
    return view;
}
  

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

1. Метод @Kurtis Nusbaum выглядит более солидно. Я рекомендую использовать его.

2. Это бесполезно, потому что это не позволяет ему использовать параметр View, переданный в BindView, который потенциально мог быть переработан. Ему придется каждый раз создавать новое представление, поэтому его приложение получит гигантский удар по производительности.

3. Извините, марк, просто ваш комментарий после того, как я добавил свой. Спасибо. Я собираюсь оставить свой комментарий там, хотя в качестве объяснения.

4. Спасибо, я всегда рад учиться 😉 Это была моя первая мысль, прежде чем я увидел ваш код.