버그 잡이

중첩리사이클러뷰 recyclerView 안에 recyclerView 넣기 #야놀자 앱 레이아웃 #nested recycelerview 본문

안드로이드

중첩리사이클러뷰 recyclerView 안에 recyclerView 넣기 #야놀자 앱 레이아웃 #nested recycelerview

버그잡이 2020. 4. 3. 16:40

야놀자 앱을 보면 다음과 같이 recyclerView 안에 recyclerView가 들어간 구조로 되어있다.

 

 

원리는 간단한다.

 

1. recyclerViewA를 만든다

 

2. recyclerViewA 어답터에서 ViewHolder에 recyclerViewB를 정의해준다.

 

3. (recyclerViewA의 나오는 항목을 수평, 그리드 등 다양하게 적용하고 싶다면)

 -> ViewType을 활용하여 recyclerViewA에 각기 다른 뷰 타입을 적용하면 된다.

 

이렇게 만들어보자

 

 

파일 구조

 

1. DataModel

 

Chapter.class

public class Chapter {
    public int id;
    public String chapterName;
    public String imageUrl;
}

 

SubJect.class

public class Subject {
    public int id;
    public String subjectName;
    public ArrayList<Chapter> chapters;
}

 

* 여기서 point는 Subject의 "ArrayList<Chapter> chapters"이다. 

recyclerViewA에 리스트를 넘겨줄때 리스트(Subject) 안에 세부 항목에 대한 리스트(Chapter)가 있어야한다.

 

 

 

 

2. ViewHolder

 

*GridViewHolder.class

public class GridViewHolder extends RecyclerView.ViewHolder {
    public RecyclerView recyclerView;
    public TextView tvSubjectName;

    public GridViewHolder(View itemView) {
        super(itemView);
        recyclerView = itemView.findViewById(R.id.rvChapters);
        tvSubjectName = itemView.findViewById(R.id.tvSubjectName);
    }
}

 

*HorizonViewHolder.class

public class HorizonViewHolder extends RecyclerView.ViewHolder {
    public RecyclerView recyclerView;
    public TextView tvSubjectName;

    public HorizonViewHolder(View itemView) {
        super(itemView);
        recyclerView = itemView.findViewById(R.id.rvChapters);
        tvSubjectName = itemView.findViewById(R.id.tvSubjectName);
    }
}

 

*지금은 새로 레이아웃 만들기 귀찮아서 내용을 같게 했는데 필요한 경우 레이아웃을 새로 만들고 세부 항목을 바꾸면 된다.

 

 

 

3. Adapter

 

*ChapterAdapter.class

public class ChapterAdapter extends RecyclerView.Adapter<ChapterAdapter.CustomViewHolder> {

    private Context context;
    private ArrayList<Chapter> chapters;
    private LayoutInflater inflater;

    public ChapterAdapter(Context context, ArrayList<Chapter> chapters) {
        this.context = context;
        this.chapters = chapters;
        this.inflater = LayoutInflater.from(context);
    }

    @NonNull
    @Override
    public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view;
        view = inflater.inflate(R.layout.single_chapter, parent, false);

        return new CustomViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) {
        Chapter chapter = chapters.get(position);
        holder.tvChapterName.setText(chapter.chapterName);
        Picasso.get().load(chapter.imageUrl).into(holder.ivChapter);
    }

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

    public class CustomViewHolder extends RecyclerView.ViewHolder {
        public ImageView ivChapter;
        public TextView tvChapterName;

        public CustomViewHolder(View itemView) {
            super(itemView);
            tvChapterName = (TextView) itemView.findViewById(R.id.tvChapterName);
            ivChapter = (ImageView) itemView.findViewById(R.id.ivChapter);
        }
    }
}

- customViewHolder를 따로 빼지 않고 내부에 만들었다.

 

 

*SubjectAdapter.class

public class SubjectAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private Context context;
    private ArrayList<Subject> subjects;
    private LayoutInflater inflater;

    public SubjectAdapter(Context context, ArrayList<Subject> subjects) {
        this.context = context;
        this.subjects = subjects;
        this.inflater = LayoutInflater.from(context);
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view;

        if (viewType == Constant.CHAPTER_VIEW) {
            view = inflater.inflate(R.layout.single_subject, parent, false);
            return new HorizonViewHolder(view);
        } else {
            view = inflater.inflate(R.layout.single_subject, parent, false);
            return new GridViewHolder(view);
        }

    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        if (holder instanceof HorizonViewHolder)
        {
            ((HorizonViewHolder) holder).recyclerView.setAdapter(new ChapterAdapter(context, subjects.get(position).chapters));
            ((HorizonViewHolder) holder).recyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
            ((HorizonViewHolder) holder).recyclerView.setHasFixedSize(true);
            ((HorizonViewHolder) holder).tvSubjectName.setText(subjects.get(position).subjectName);
        }
        else
        {
            ((GridViewHolder) holder).recyclerView.setAdapter(new ChapterAdapter(context, subjects.get(position).chapters));
            ((GridViewHolder) holder).recyclerView.setLayoutManager(new GridLayoutManager(context, 2));
            ((GridViewHolder) holder).recyclerView.setHasFixedSize(true);
            ((GridViewHolder) holder).tvSubjectName.setText(subjects.get(position).subjectName);
        }

    }

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

    @Override
    public int getItemViewType(int position) {
        return subjects.get(position).id;
    }
}

- onCreateViewHolder : viewType에 따라 ViewHolder를 다르게 반환한다

- onBindViewHolder : ViewHolder별로 원하는 리사이클러뷰의 형태를 출력한다.

 

 

 

4. Activity & Constant

 

* MainActivity.class

public class MainActivity extends AppCompatActivity {

    private RecyclerView rvSubject;
    private SubjectAdapter subjectAdapter;
    private ArrayList<Subject> subjects;

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

        subjects = prepareData();

        rvSubject = findViewById(R.id.rvSubject);

        subjectAdapter = new SubjectAdapter(MainActivity.this, subjects);
        LinearLayoutManager manager = new LinearLayoutManager(MainActivity.this);
        rvSubject.setLayoutManager(manager);
        rvSubject.setAdapter(subjectAdapter);

    }

    private ArrayList<Subject> prepareData() {
        ArrayList<Subject> subjects = new ArrayList<Subject>();

        //첫번째 subject 추가
        Subject physics = new Subject();
        physics.id = 1;
        physics.subjectName = "Physics";
        physics.chapters = new ArrayList<Chapter>();

        Chapter chapter1 = new Chapter();
        chapter1.id = 1;
        chapter1.chapterName = "Atomic power";
        chapter1.imageUrl = "http://ashishkudale.com/images/phy/atoms.png";

        Chapter chapter2 = new Chapter();
        chapter2.id = 2;
        chapter2.chapterName = "Theory of relativity";
        chapter2.imageUrl = "http://ashishkudale.com/images/phy/sigma.png";

        Chapter chapter3 = new Chapter();
        chapter3.id = 3;
        chapter3.chapterName = "Theory of relativity";
        chapter3.imageUrl = "http://ashishkudale.com/images/phy/sigma.png";

        Chapter chapter4 = new Chapter();
        chapter4.id = 4;
        chapter4.chapterName = "Theory of relativity";
        chapter4.imageUrl = "http://ashishkudale.com/images/phy/sigma.png";

        physics.chapters.add(chapter1);
        physics.chapters.add(chapter2);
        physics.chapters.add(chapter3);
        physics.chapters.add(chapter4);

        subjects.add(physics);

        //두번째 subject 추가
        Subject physics2 = new Subject();
        physics2.id = 2;
        physics2.subjectName = "Physics";
        physics2.chapters = new ArrayList<Chapter>();

        physics2.chapters.add(chapter1);
        physics2.chapters.add(chapter2);
        physics2.chapters.add(chapter3);
        physics2.chapters.add(chapter4);

        subjects.add(physics2);

        //세번째 subject 추가
        Subject physics3 = new Subject();
        physics3.id = 2;
        physics3.subjectName = "Physics";
        physics3.chapters = new ArrayList<Chapter>();

        physics3.chapters.add(chapter1);
        physics3.chapters.add(chapter2);
        physics3.chapters.add(chapter3);
        physics3.chapters.add(chapter4);

        subjects.add(physics3);

        //네번째 subject 추가
        Subject physics4 = new Subject();
        physics4.id = 1;
        physics4.subjectName = "Physics";
        physics4.chapters = new ArrayList<Chapter>();

        physics4.chapters.add(chapter1);
        physics4.chapters.add(chapter2);
        physics4.chapters.add(chapter3);
        physics4.chapters.add(chapter4);

        subjects.add(physics4);

        return subjects;
    }
}

- 자료는 좀 무식하게 넣었다...

 

 

*Constant

public class Constant {

    public static final int CHAPTER_VIEW = 1;
    public static final int GRID_VIEW = 2;

}

 

 

 

참고자료

https://medium.com/@ashishkudale/android-list-inside-list-using-recyclerview-73cff2c4ea95

반응형
Comments