如何在Android中使用多个列表视图构build复杂的布局

我们正在开发一个包含多个组件的应用程序,我们希望将其整合到一个post的详细视图中(参见模拟)。每个组件都是可扩展的(通常使用ajax调用),整个屏幕可滚动以查看所有内容。

listview样机

我们不确定解决这个问题的最好方法,因为根据Google的说法,不应该将列表视图放入滚动视图中。 似乎有人在做这个反正我如何将ListView放入ScrollView而不会崩溃? 。

一般而言,post中的内容数量足够小,可以一次充满,但是可能会获得超过100张照片或超过300条评论,这些内容可能会成为问题。

我的问题是什么是最好的,如果不是官方的方式来build立这样的布局。 我很有兴趣听到整个版面结构的build议,所以我了解标题等静态内容如何与照片或评论一起播放。

我想优化性能/易于实现的小post(less数照片,20-50评论) – 但我们必须能够处理大的职位,而不会崩溃的应用程序。

起初我以为这是一个复杂的平板电脑布局,但如果它只有一个列表,它可以通过使用自定义列表适配器实现。

把这个布局想象成一个具有不同视图的单个列表。 因此,post标题是types1的列表项目,照片视图types3,buttontypes4.这是您的布局,项目位置标记为红色数字和视图types标记为蓝色文本。

具有标记物品位置的OP布局

你应该使用viewType属性为每个项目创build模型类,所以对于11个视图types,将会有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 

然后,您可以通过更改模型来更新/添加/删除列表项目。 例如,如果您单击“查看更多文本”button,请调用以下函数:

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

如果您点击“查看更多照片”button,请调用此function:

 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); } 

我认为这个想法很清楚。

以下是4种视图types的完整示例:

 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种可能的解决scheme:

  1. 使用可扩展列表视图 – 我认为这将帮助您查看上面的图像,看看这里 – http://www.androidhive.info/2013/07/android-expandable-list-view-tutorial/

  2. 通过代码编写dynamic布局,点击创build一个新的布局。

  3. 使用getViewTypeCount()方法在列表视图中使用不同的行项目。 更多关于这里 – http://android.amberfog.com/?p=296 Android ListView与每行不同的布局和http://www.jiahaoliuliu.com/2012/08/android-list-view-with-不同-views.html

我个人看到你使用1和3的组合来解决你目前的问题

我强烈build议不要在列表视图中使用listview或滚动视图内的列表视图。 他们将是大量的性能问题和其他你真的不想进入的东西。 希望这可以帮助。

graphics化布局可以轻松实现。 首先是垂直滚动项目的widget属性的相对布局。

自定义列表视图与不同的适配器将解决您的问题