#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. Спасибо, я всегда рад учиться 😉 Это была моя первая мысль, прежде чем я увидел ваш код.