Adrian Patterson
Adrian Patterson

Reputation: 105

How to display multiple recycler views on Android Studio?

very new to Android App development here. I'm not sure if I'm asking the right question, but here's my situation. I have a simple gradebook app that looks like the following:

enter image description here

My goal is to display multiple courses on the app. I am using the RecyclerView to implement this, using the following onCreate function in my activity to pass the course information to the adapter:

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_grade);

        getSupportActionBar().setDisplayShowHomeEnabled(true);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowTitleEnabled(false);

        for(int i = 0; i<2; i++)
        {
            Course course = Course.generateRandomCourse();

            recyclerView = (RecyclerView) findViewById(R.id.togglegrades);
            layoutManager = new LinearLayoutManager(this);
            recyclerView.setLayoutManager(layoutManager);

            mAdapter = new RecyclerViewAdapter(course);
            recyclerView.setAdapter(mAdapter);
        }

My goal for the for loop was to have two courses show up, but this is not the case. I'm not sure whether I need to rework my Recycling Adapter to take a list of courses, or if there is a simple way to display multiple courses.

Any help is much appreciated! Thank you for your time :)

EDIT: After adding 2 recyclers in XML and trying to invoke both, this is the code I used:

        Course course = Course.generateRandomCourse();
        Course course1 = Course.generateRandomCourse();

        recyclerView = (RecyclerView) findViewById(R.id.togglegrades);
        recyclerView1 = (RecyclerView) findViewById(R.id.togglegrades1);

        layoutManager = new LinearLayoutManager(this);
        layoutManager1 = new LinearLayoutManager(this);


        recyclerView.setLayoutManager(layoutManager);
        recyclerView1.setLayoutManager(layoutManager1);

        mAdapter = new RecyclerViewAdapter(course);
        mAdapter1 = new RecyclerViewAdapter(course1);

        recyclerView.setAdapter(mAdapter);
        recyclerView1.setAdapter(mAdapter1);

Now the output is just overlapped.

enter image description here

EDIT 2: Including full adapter code below.

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
{
    private static final int TYPE_HEADER = 0;
    private static final int TYPE_ITEM = 1;

    private List<Course> courses = new ArrayList<>();
    private ArrayList<Assignment> assignments;
    private String course;
    private String average;


    public RecyclerViewAdapter(List<Course> courses)
    {
        for(Course c : courses)
        {
            course = c.getCourseTitle();
            assignments = c.getAssignments();
            if(assignments.size()==0)
            {
                average = "0";
            }
            else
            {
                Integer grade_total = new Integer(0);
                Integer assignment_total = new Integer(0);
                for (Assignment i : assignments)
                {
                    grade_total += i.getAssignmentGrade();
                    assignment_total++;
                }
                average = Integer.toString(grade_total /assignment_total);
            }
        }
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType)
    {

        if(viewType == TYPE_HEADER)
        {
            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.header_course,parent,false);
            return new ViewHolderHeader(v);
        }
        else if(viewType == TYPE_ITEM)
        {
            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_course, parent, false);
            return new ViewHolderItem(v);
        }
        else return null;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
    {
        if(holder instanceof ViewHolderHeader)
        {
            ViewHolderHeader VHHeader = (ViewHolderHeader)holder;
            VHHeader.title.setText(course);
            VHHeader.average.setText("Average: " + average + "%");
        }
        else if(holder instanceof ViewHolderItem)
        {
            String assignemnt_name = assignments.get(position-1).getAssignmentTitle();
            String assignment_grade = Integer.toString(assignments.get(position-1).getAssignmentGrade());
            ViewHolderItem VHItem = (ViewHolderItem)holder;
            VHItem.name.setText(assignemnt_name);
            VHItem.grade.setText(assignment_grade + "%");
        }

    }

    @Override
    public int getItemCount()
    {
        return assignments.size() + 1;
    }

    private boolean isPositionHeader(int position)
    {
        if(position == 0)
            return true;
        else
            return false;
    }

    @Override
    public int getItemViewType(int position)
    {
        if(isPositionHeader(position))
            return TYPE_HEADER;
        return TYPE_ITEM;
    }

    public class ViewHolderHeader extends RecyclerView.ViewHolder
    {
        TextView title;
        TextView average;
        public ViewHolderHeader(View view)
        {
            super(view);
            this.title = (TextView)itemView.findViewById(R.id.course);
            this.average = (TextView)itemView.findViewById(R.id.average);
        }
    }

    public class ViewHolderItem extends RecyclerView.ViewHolder
    {
        TextView name;
        TextView grade;
        public ViewHolderItem(View view)
        {
            super(view);
            this.name = (TextView)itemView.findViewById(R.id.assignment);
            this.grade = (TextView)itemView.findViewById(R.id.grade);
        }
    }

}

Upvotes: 1

Views: 1059

Answers (4)

Keyur Nimavat
Keyur Nimavat

Reputation: 3635

You do not need to use multiple RecyclerView.

Just look at your code and you will find the answer why your code is not working.

RecyclerView is similar like listview where you have to pass a list. But in your code you are passing just 1 object of course.

You must not add recyclerview inside for loop, as recyclerview purpose is to store list,not 1 object.

So you should pass List to the recyclerview.

 @Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_grade);

    getSupportActionBar().setDisplayShowHomeEnabled(true);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setDisplayShowTitleEnabled(false);

    recyclerView = (RecyclerView) findViewById(R.id.togglegrades);
    layoutManager = new LinearLayoutManager(this);
    recyclerView.setLayoutManager(layoutManager);

    List<Course> listCourse=new ArrayList();

    for(int i = 0; i<2; i++)
    {
        listCourse.add(Course.generateRandomCourse());
    }

    mAdapter = new RecyclerViewAdapter(listCourse);
    recyclerView.setAdapter(mAdapter);
}

And inside the adapter you can use this list of course.

For more reference you can check this link, on how to use RecyclerView with Adapter

EDIT: In your adapter look at this code:

 private boolean isPositionHeader(int position)
{
    if(position == 0)
        return true;
    else
        return false;
}

Here position == 0 is static code, which will not work for dynamic code.If your list contains 1 Header and 1 Item, than you can change simply position%2 == 0 condition. else you have to create other recyclerview inside adapter.

Check out below code and comments I have added , at the end of onBindViewHolder you can add new recyclerview, for that you have to add recyclerview in your layout also.

Checkout how you can use List<Course> courses in your constructor and onBindViewHolder.

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;

private List<Course> courses = new ArrayList<>();



public RecyclerViewAdapter(List<Course> courses)
{
   this.courses = courses;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType)
{

      View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.header_course,parent,false);
        return new ViewHolderHeader(v);
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
        Course c=courses.get(position);
        String course = c.getCourseTitle();
        String assignments = c.getAssignments();
        if(assignments.size()==0)
        {
            average = "0";
        }
        else
        {
            Integer grade_total = new Integer(0);
            Integer assignment_total = new Integer(0);
            for (Assignment i : assignments)
            {
                grade_total += i.getAssignmentGrade();
                assignment_total++;
            }
            average = Integer.toString(grade_total /assignment_total);
        }
     ViewHolderHeader VHHeader = (ViewHolderHeader)holder;
        VHHeader.title.setText(course);
        VHHeader.average.setText("Average: " + average + "%");

        //Here you can set new recyclerview in your adapter for assignments

}

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

/*private boolean isPositionHeader(int position)
{
    //Change logic here as per your list, because you have list not single object. 
    //if(position == 0)
    //    return true;
    //else
    //    return false;
}*/
//Remove this code as you have not different views in your list
/*@Override
public int getItemViewType(int position)
{

    if(isPositionHeader(position))
        return TYPE_HEADER;
    return TYPE_ITEM;
}*/

public class ViewHolderHeader extends RecyclerView.ViewHolder
{
     View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.header_course,parent,false);
        return new ViewHolderHeader(v);
}


}

Upvotes: 1

GHH
GHH

Reputation: 2029

Why do you use two RecyclerView?

Your Layout looks simple, just use one recyclerView with two viewType.

This is a sample

Upvotes: 1

Gk Mohammad Emon
Gk Mohammad Emon

Reputation: 6966

You can do it in a very optimal way. Please see the tutorial titled Recyclerview multiple view type. Here you don't need to create multiple recycler views and you can use a single recycler view for multiple types of data.

Upvotes: 1

Omar Hezi
Omar Hezi

Reputation: 165

You need to have 2 RecycleViews in your activity_grade xml layout, and do what you're doing inside the for loops for each. What your for loop is currently doing, is creating a random course, and then setting that course to the RecyclerView called togglegrades, then on the second iteration, it does the same thing again, on the same RecyclerView

So what I would do after adding a second RecyclerView in the xml layout, is replace the for loop with something like this:

recyclerView1 = (RecyclerView) findViewById(R.id.togglegrades);
recyclerView2 = (RecyclerView) findViewById(R.id.togglegrades2);

layoutManager = new LinearLayoutManager(this);

recyclerView1.setLayoutManager(layoutManager);
recyclerView2.setLayoutManager(layoutManager);
    
mAdapter = new RecyclerViewAdapter(course);
// Maybe create a different course here and set it to a new adapter variable
recyclerView.setAdapter(mAdapter);
recyclerView2.setAdapter(mAdapter);

Upvotes: 1

Related Questions