如何在具有多个列表视图的android中构建复杂的布局

Yeh*_*sef 7 android listview android-layout

我们正在与我们想融入后的详细视图多个组件的应用程序工作(见样机.)每件的可扩展(通常使用Ajax调用)和整个屏幕滚动查看全部内容.

listview样机

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

一般来说,帖子中的内容量足够小,可以一次性全部膨胀,但有可能获得100多张照片或300多条评论的帖子,其中内存可能是一个问题.

我的问题是建立这样一个布局的最好的方法是什么,如果不是正式的话.我有兴趣听听整个布局结构的建议,所以我理解像标题这样的静态内容如何与照片或评论一起播放.

我想优化小帖子的性能/易于实现(几张照片,20-50条评论) - 但我们必须能够处理大型帖子而不会崩溃应用程序.

vor*_*olf 7

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

将此布局想象为具有不同视图的单个列表.因此,帖子标题是类型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
Run Code Online (Sandbox Code Playgroud)

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

private void onSeeMoreTextButtonClicked(ListItemModelBase item){
    item.setViewType(ListItemViewTypes.POST_TITLE_EXPANDED);
    this.notifyDataSetChanged();
}
Run Code Online (Sandbox Code Playgroud)

如果单击"查看更多照片"按钮,请调用此功能:

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);
}
Run Code Online (Sandbox Code Playgroud)

我认为这个想法很清楚.

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)