Pertanyaan Cara membuat tata letak yang rumit di android dengan banyak tampilan daftar


Kami sedang mengerjakan aplikasi dengan beberapa komponen yang ingin kami integrasikan ke dalam tampilan detail dari sebuah posting (lihat mockup.) Setiap bagian dapat diperluas (biasanya dengan panggilan ajax) dan seluruh layar dapat digulir untuk melihat semua konten .

listview mockup

Kami tidak yakin tentang cara terbaik untuk mengatasi masalah ini karena, menurut Google, tampilan daftar tidak boleh dimasukkan ke dalam tampilan gulir. Sepertinya ada orang yang melakukan ini seperti di Bagaimana saya bisa menempatkan ListView ke dalam ScrollView tanpa itu runtuh?.

Secara umum, jumlah konten yang ada di pos cukup kecil sehingga semuanya dapat ditingkatkan sekaligus, tetapi Anda dapat memperoleh pos dengan 100+ foto atau 300+ komentar di mana memori mungkin menjadi perhatian.

Pertanyaan saya adalah apa yang terbaik, jika tidak resmi, cara membangun tata letak seperti itu. Saya tertarik untuk mendengar rekomendasi untuk seluruh struktur tata letak sehingga saya memahami bagaimana konten yang lebih statis seperti judul bermain dengan foto atau komentar.

Saya ingin mengoptimalkan kinerja / kemudahan implementasi untuk posting kecil (beberapa foto, 20-50 komentar) - tetapi kita harus dapat menangani posting besar tanpa menabrak aplikasi.


7
2017-11-19 12:08


asal


Jawaban:


Pada awalnya saya pikir itu adalah tata letak yang rumit untuk tablet, tetapi jika itu hanya 1 daftar, itu dapat diimplementasikan dengan menggunakan adaptor daftar kustom.

Bayangkan tata letak ini sebagai daftar tunggal dengan tampilan berbeda. Jadi judul posting adalah item daftar tipe 1, tampilan foto adalah tipe 3, tombol adalah tipe 4. Berikut adalah tata letak Anda dengan posisi item ditandai dengan angka merah dan jenis tampilan ditandai dengan teks biru.

OP layout with marked item positions

Anda harus membuat kelas model untuk setiap item dengan viewType properti, jadi untuk 11 jenis tampilan akan ada 11 kelas (atau kelas dasar dan beberapa kelas turunan). Kemudian tambahkan model ini dalam urutan yang tepat ke adaptor Anda seperti ini:

    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

Kemudian Anda dapat memperbarui / menambah / menghapus item daftar dengan mengubah model. Misalnya, jika Anda mengklik tombol "Lihat lebih banyak teks", panggil fungsi berikut:

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

Jika Anda mengklik tombol "Lihat lebih banyak foto", panggil fungsi ini:

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

Saya pikir idenya jelas.

Berikut ini contoh lengkap untuk 4 jenis tampilan:

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

7
2017-12-08 12:43



Melihat persyaratan yang Anda miliki, saya dapat memikirkan 3 kemungkinan solusi ini di atas kepala saya:

  1. Gunakan Tampilan Daftar yang Dapat Diperluas - Saya pikir ini akan membantu Anda melihat gambar di atas, lihat di sini - http://www.androidhive.info/2013/07/android-expandable-list-view-tutorial/

  2. Tulis tata letak dinamis melalui kode, buat tata letak baru di klik.

  3. Gunakan item baris yang berbeda dalam tampilan daftar menggunakan metode getViewTypeCount (). Lebih lanjut tentang ini di sini - http://android.amberfog.com/?p=296  Android ListView dengan tata letak berbeda untuk setiap baris          dan http://www.jiahaoliuliu.com/2012/08/android-list-view-with-different-views.html

Saya pribadi melihat Anda menggunakan kombinasi 1 & 3 untuk memecahkan masalah Anda saat ini

Saya akan sangat menyarankan untuk tidak menggunakan listview dalam listview atau listview dalam scrollview. Mereka akan menjadi banyak masalah kinerja dan hal-hal lain yang benar-benar tidak Anda inginkan. Semoga ini membantu.


3
2017-12-08 08:47



Tata letak grafis dapat melakukan trik dengan mudah. layout vertikal kemudian relatif pertama dengan widget milik item yang digulir.


0
2017-11-19 14:40



tampilan daftar kustom dengan adaptor yang berbeda akan memecahkan masalah Anda


0
2017-11-20 13:12