Как построить сложный макет в андроиде с несколькими списками просмотров

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

Макет списка

Мы не уверены в наилучшем способе решения этой проблемы, потому что, согласно Google, списки просмотров не следует размещать в scrollviews. Кажется, есть люди, которые это делают так или иначе, как в том, как я могу поместить ListView в ScrollView без его свертывания? ,

В общем, количество контента, которое находится в сообщении, достаточно мало, чтобы все его можно было надуть сразу, но можно получить сообщения со 100 + фотографиями или более 300 комментариями, в которых может возникнуть проблема с памятью.

Мой вопрос – это лучший, если не официальный способ создания такого макета. Мне интересно услышать рекомендации по всей структуре макета, поэтому я понимаю, как более статический контент, такой как название, воспроизводится с фотографиями или комментариями.

Я хотел бы оптимизировать производительность / простоту реализации для небольших сообщений (несколько фотографий, 20-50 комментариев), но мы должны иметь возможность обрабатывать большие сообщения без сбоев приложения.

Solutions Collecting From Web of "Как построить сложный макет в андроиде с несколькими списками просмотров"

Сначала я думал, что это сложный макет для планшетов, но если это всего лишь 1 список, его можно реализовать с помощью адаптера пользовательского списка.

Представьте себе этот макет как единый список с разными представлениями. Таким образом, заголовок сообщения представляет собой элемент списка типа 1, вид фотографии имеет тип 3, кнопка имеет тип 4. Вот ваш макет с позициями позиций, отмеченными красными цифрами и видами, отмеченными синим текстом.

Схема OP с отмеченными позициями позиции

Вы должны создать классы моделей для каждого элемента с свойством viewType , поэтому для 11 типов видят 11 классов (или базовый класс и несколько производных классов). Затем добавьте эти модели в правильном порядке к вашему адаптеру следующим образом:

  this.add(new ListItemModelBase(ListItemViewTypes.POST_TITLE)); this.add(new PhotoViewItemModel("image1.jpg", "Image 1")); this.add(new PhotoViewItemModel("image2.jpg", "Image 2")); this.add(new PhotoViewItemModel("image3.jpg", "Image 3")); this.add(new ListItemModelBase(ListItemViewTypes.SEE_MORE_PHOTOS_BUTTON)); // other models 

Затем вы можете обновлять / добавлять / удалять элементы списка, меняя модели. Например, если вы нажмете кнопку «Просмотреть больше текста», вызовите следующую функцию:

 private void onSeeMoreTextButtonClicked(ListItemModelBase item){ item.setViewType(ListItemViewTypes.POST_TITLE_EXPANDED); this.notifyDataSetChanged(); } 

Если вы нажмете кнопку «Просмотреть больше фотографий», вызовите эту функцию:

 private void onSeeMorePhotosButtonClicked(ListItemModelBase item){ int index = this.getPosition(item); this.remove(item); this.insert(new PhotoViewItemModel("image4.jpg", "Image 4"), index); this.insert(new PhotoViewItemModel("image5.jpg", "Image 5"), index + 1); this.insert(new PhotoViewItemModel("image6.jpg", "Image 6"), index + 2); } 

Я думаю, что идея понятна.

Вот полный пример для четырех типов вида:

 public class ListItemViewTypes { public static final int VIEW_TYPES_COUNT = 4; // Must start from 0 public static final int POST_TITLE = 0; public static final int POST_TITLE_EXPANDED = 1; public static final int PHOTO_VIEW = 2; public static final int SEE_MORE_PHOTOS_BUTTON = 3; } public class ListItemModelBase { private int mViewType; public ListItemModelBase(int viewType){ mViewType = viewType; } public int getViewType() { return mViewType; } public void setViewType(int viewType) { mViewType = viewType; } } public class PhotoViewItemModel extends ListItemModelBase { private final String mUrl; private final String mDescription; public PhotoViewItemModel(String url, String description) { super(ListItemViewTypes.PHOTO_VIEW); mUrl = url; mDescription = description; } public String getUrl() { return mUrl; } public String getDescription() { return mDescription; } } public class TestListAdapter extends ArrayAdapter<ListItemModelBase> { private final LayoutInflater mInflater; public TestListAdapter(Context context) { super(context, -1); mInflater = LayoutInflater.from(context); this.add(new ListItemModelBase(ListItemViewTypes.POST_TITLE)); this.add(new PhotoViewItemModel("image1.jpg", "Image 1")); this.add(new PhotoViewItemModel("image2.jpg", "Image 2")); this.add(new PhotoViewItemModel("image3.jpg", "Image 3")); this.add(new ListItemModelBase(ListItemViewTypes.SEE_MORE_PHOTOS_BUTTON)); } @Override public int getViewTypeCount() { return ListItemViewTypes.VIEW_TYPES_COUNT; } @Override public int getItemViewType(int position) { // important method so that convertView has a correct type return this.getItem(position).getViewType(); } @Override public boolean isEnabled(int position) { // enable context menu for photo views, comments and related posts // or always return false if context menu is not needed at all if (this.getItem(position).getViewType() == ListItemViewTypes.PHOTO_VIEW) { return true; } return false; } @Override public View getView(int position, View convertView, ViewGroup parent) { final ListItemModelBase item = this.getItem(position); int viewType = item.getViewType(); if (convertView == null) { // different layouts for different `viewType` int layoutId = -1; if (viewType == ListItemViewTypes.POST_TITLE) { layoutId = R.layout.post_title; } else if (viewType == ListItemViewTypes.POST_TITLE_EXPANDED) { layoutId = R.layout.post_title_expanded; } else if (viewType == ListItemViewTypes.PHOTO_VIEW) { layoutId = R.layout.photo_view; } else if (viewType == ListItemViewTypes.SEE_MORE_PHOTOS_BUTTON) { layoutId = R.layout.more_photos_button; } convertView = this.mInflater.inflate(layoutId, null); } // update the current view based on data from the current model if (viewType == ListItemViewTypes.POST_TITLE) { Button seeMoreTextButton = (Button)convertView.findViewById(R.id.button_see_more_text); seeMoreTextButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onSeeMoreTextButtonClicked(item); } }); } else if (viewType == ListItemViewTypes.SEE_MORE_PHOTOS_BUTTON) { Button seeMorePhotosButton = (Button)convertView.findViewById(R.id.button_see_more_photos); seeMorePhotosButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onSeeMorePhotosButtonClicked(item); } }); } else if (viewType == ListItemViewTypes.PHOTO_VIEW){ PhotoViewItemModel photoViewItem = (PhotoViewItemModel)item; TextView photoDescriptionText = (TextView)convertView.findViewById(R.id.photo_view_text); photoDescriptionText.setText(photoViewItem.getDescription()); } return convertView; } private void onSeeMoreTextButtonClicked(ListItemModelBase item){ item.setViewType(ListItemViewTypes.POST_TITLE_EXPANDED); this.notifyDataSetChanged(); } private void onSeeMorePhotosButtonClicked(ListItemModelBase item){ int index = this.getPosition(item); this.remove(item); this.insert(new PhotoViewItemModel("image4.jpg", "Image 4"), index); this.insert(new PhotoViewItemModel("image5.jpg", "Image 5"), index + 1); this.insert(new PhotoViewItemModel("image6.jpg", "Image 6"), index + 2); } } public class MainActivity extends ListActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main); this.getListView().setChoiceMode(ListView.CHOICE_MODE_NONE); this.getListView().setDivider(null); TestListAdapter adapter = new TestListAdapter(this.getApplicationContext()); this.getListView().setAdapter(adapter); } } 

Глядя на требование, которое у вас есть, я могу думать об этих 3 возможных решениях на моей голове:

  1. Используйте расширенный просмотр списка. Я думаю, что это поможет вам взглянуть на изображения выше, посмотрите здесь – http://www.androidhive.info/2013/07/android-expandable-list-view-tutorial/

  2. Напишите динамические макеты с помощью кода, создайте новый макет при щелчке.

  3. Используйте разные элементы строки в представлении списка с помощью метода getViewTypeCount (). Подробнее об этом здесь – http://android.amberfog.com/?p=296 Android ListView с различными макетами для каждой строки и http://www.jiahaoliuliu.com/2012/08/android-list-view-with- различного views.html

Я лично вижу, что вы используете комбинацию 1 и 3 для решения текущей проблемы

Я настоятельно рекомендую использовать listview в listview или listview в прокрутке. У них будет множество проблем с производительностью и другие вещи, которые вы действительно не хотите вникать. Надеюсь это поможет.

Графический макет может легко сделать трюк. Сначала вертикальная, затем относительная компоновка с свойством виджета прокрутки.

Пользовательский список с различными адаптерами решит вашу проблему