Nikolay Kolomiytsev
Nikolay Kolomiytsev

Reputation: 525

How to create a ListView with multiple views

my problem is - how to create custom list view with not just repeating one custom view, but like in Instagram or other app where list include other views in it, which it looks like scroll view with list view android other views in it, but Roman Guy says "List View in a Scroll view is a very poor way", and I'm agreed with it, don't believe which is Google use this way...

What are the best way to achieve this thing with ListView or Recycler View

enter image description here

enter image description here

Upvotes: 3

Views: 2586

Answers (3)

You are looking for different View types. It's possible with using these

GetViewTypeCount() this is an overridable method which returns how many view type you have in your listview-recycleview.

getItemViewType(int pos) get which item view type should return at the given position

For example if you want to add a different view in every 10 item, and there is only 2 type of views, you should use a code like this:

@Override
public int getItemViewType(int position){
    if (position % 10 == 0)
        return SECOND_ITEM;
    return FIRST_ITEM;
}
@Override
public int getViewTypeCount() {
    return 2;
}

And at the getView() function you can handle it with a switch-case or if-else structure like this:

switch (getItemViewType(cursor.getPosition())) {
            case SECOND_ITEM:
                //something to do
                break;

            default:

                //something to do
}

You might want to use 2 different layout file to inflate in the switch-case statement above. However, if the layouts of both items are not different that much, I recommend to create just 1 layout, and make views inside it visible and gone according to item you want to get.

Oh and in case you don't know where to use them, you use them at your adapter class. The functions may vary as which kind of adapter you use however, they all work with the same logic.

And finally, I recommend you to use recyclerview. It is just a bit harder to implement than listview but it is a great substitution of listview which is more powerful and flexible. You can do a research for it.

Here is how you can achieve this like instagram, facebook etc. : You inflate a scrollable view at the given positions.

I hope the answer helps.

As always, Have a nice day.

Upvotes: 2

Adam Adli
Adam Adli

Reputation: 96

To achieve that UI, you must define multiple view types for your Listview or Recyclerview; a very similar question has been answered here.

In your example, you will have two view types:

There are many tutorials on this concept. I would recommend you to use Recyclerview in your implementation due to its advantages over Listview.

Upvotes: 3

LeoNeo
LeoNeo

Reputation: 739

Hey this is how your main fragment will look like :

package com.leoneo.stackoverflow;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.soulpatch.stackoverflow.R;

import java.util.ArrayList;

public class RecyclerViewExample extends Fragment {
    private ArrayList<Object> mValues = new ArrayList<>();
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        final RecyclerView recyclerView = inflater.inflate(R.layout.recycler_view_example, container, false);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        final MultpleItemAdapter adapter = new MultpleItemAdapter(mValues);
        recyclerView.setAdapter(adapter);
        return recyclerView;
    }
}

And here's your adapter code.

package com.leoneo.stackoverflow;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

import com.soulpatch.stackoverflow.R;

import java.util.ArrayList;

public class MultpleItemAdapter extends RecyclerView.Adapter<MultpleItemAdapter.ViewHolder> {
    private ArrayList<Object> mValues = new ArrayList<>();

    public MultpleItemAdapter(ArrayList<Object> values) {
        mValues = values;
    }

    enum ItemType {
        TYPE_A,
        TYPE_B;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch (viewType) {
            case 1:
                //Inflate Type A layout
                final LinearLayout linearLayoutA = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_a, parent, false);
                //And pass the view to the ViewHolder
                return new ViewHolder(linearLayoutA);
            break;
            case 2:
                //Inflate Type B layout
                final LinearLayout linearLayoutB = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_b, parent, false)
                //And pass the view to the ViewHolder
                return new ViewHolder(linearLayoutB);
            break;
        }
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        switch (getItemViewType(position)) {
            case 1:
                final TypeA typeA = (TypeA) mValues.get(position);
                //Deal with the views that you defined for LinearLayout A
                break;
            case 2:
                final TypeB typeB = (TypeB) mValues.get(position);
                //Deal with the views that you defined for LinearLayout B
                break;
        }
    }

    @Override
    public int getItemCount() {
        return mValues.size();
    }

    @Override
    public int getItemViewType(int position) {
        final Object obj = mValues.get(position);
        if (obj instanceof TypeA) {
            return ItemType.TYPE_A.ordinal();
        } else if (obj instanceof TypeB) {
            return ItemType.TYPE_B.ordinal();
        }
        return super.getItemViewType(position);
    }

    static class ViewHolder extends RecyclerView.ViewHolder {

        public ViewHolder(View itemView) {
            super(itemView);
        }
    }

    //Class that I want to be displayed in a CardView
    private class TypeA {
    }

    //Class that I want to be displayed in a a LinearLayout
    private class TypeB {
    }
}

You can have as many classes as you want like TypeA and TypeB and add types to ItemType class as well accordingly. Rest should be pretty self explanatory assuming you've worked with RecyclerViews before.

Upvotes: 2

Related Questions