MultiLevelAdapter - Android library to allow collapsing and expanding items in RecyclerView's Adapter on multiple levels

Overview

MultiLevelAdapter

Maven Central

MultiLevelAdapter is an Android library to allow collapsing and expanding items in RecyclerView's Adapter on multiple levels (no limits).

Demo Gif

This library lets you collapse and expand items in your RecyclerView by only:

  • Extending your adapter with abstract class MultiLevelAdapter
  • Implementing the interface MultiLevelItem or extending the abstract class AbstractMultiLevelItem in your RecyclerView's item's class

Dependency

dependencies {
    implementation 'io.github.automatik:multileveladapter:1.0.1'
}

Features

  • The interface MultiLevelItem<R, T> lets you define both the type of the item's id and the item itself.
  • The abstract class AbstractMultiLevelItem<R, T> lets you define both the type of the item's id and the item itself, but you don't need to implement all the interface's methods.
  • The interface MultiLevelLongItem<T> is a shortcut and defines the id's type as long and lets you define the item's class.
  • The abstract class AbstractMultiLevelLongItem<T> is a shortcut and defines the id's type as long and implements all the interface's methods, but lets you define the item's class.
  • The abstract class MultiLevelAdapter<T, VH> already implements the logic behind collapsing and expanding items. You need only to call its listener when clicking collapse/expand.
  • The adapter's method addItem adds an item to the adapter's list. If the item's parent is collapsed, the item will be added to its parent's children and will not be showed in the RecyclerView.
  • The adapter's method addItem lets you add new items immediately, running on main UI thread, or delayed by using a Handler attached to main UI thread and adding the addItemTask to the message queue. This is to avoid possible heavy-blocking execution. In case delayed is true obviously the new item won't be immediately indexable in the list.
  • The adapter's method addItem lets you avoid to add redundant items by checking the item's id.

Basic Usage

Your item's class needs to have an id to uniquely identify the item in the list and to pass the parent's instance in the constructor. If the parent is null the item is considered as a top-level item (level = 1). The parent doesn't need to have all the fields complete but only the id field. The id field is used when adding the item to the list. You don't need to manually edit or set the fields children, isCollapsed and level. They are used internally in the addItemTask.

The most straightforward way to use this library is by first extending your item's class (used in your list) with AbstractMultiLevelItem. The MyItem class has the id's type as long.

public class MyItem extends AbstractMultiLevelItem<Long, MyItem> {

    public MyItem(Long id, MyItem parent) {
        super(id, parent);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MyItem item = (MyItem) o;
        return getId().equals(item.getId());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getId());
    }
}

And then extending your adapter's class with MultiLevelAdapter

public class Adapter extends MultiLevelAdapter<MyItem, Adapter.ViewHolder> {


    public Adapter(List<MyItem> recyclerViewItems) {
        super(recyclerViewItems);
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.recyclerview_item, parent, false);
        //collapseItemListener is defined in MultiLevelAdapter class
        return new Adapter.ViewHolder(view, getCollapseItemListener());
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position, MyItem item) {
        holder.mItem = item;
        if(item.isCollapsed())
            holder.mCollapseText.setText("Expand");
        else
            holder.mCollapseText.setText("Collapse");
    }

    public static class ViewHolder extends MultiLevelViewHolder<MyItem> {

        final TextView mCollapseText;
        MyItem mItem;

        public ViewHolder(@NonNull View view, CollapseItemListener<MyItem> listener) {
            super(view, listener);
            mCollapseText = view.findViewById(R.id.item_expand_text);
            mCollapseText.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(mItem.isCollapsed()) {
                        listener.onExpand(mItem);
                        mCollapseText.setText("Collapse");
                    } else {
                        listener.onCollapse(mItem);
                        mCollapseText.setText("Expand");
                    }
                }
            });
        }
    }
}

Finally, to add items to your list you need to call addItem in your Activity/Fragment

adapter.addItem(item);

A sample app is also provided in this repository.

Advanced Usage

Instead of extending your item's class, you can implement the interface MultiLevelItem

public class MyItem implements MultiLevelItem<Long, MyItem> {

    private Long id;
    private MyItem parent;
    private List<MyItem> children = null;
    private boolean isCollapsed = false;
    private int level = 0;
    
    //The parent's instance is null so the item will be considered a top level item (level = 1).
    public MyItem(long id) {
        this.id = id;
        parent = null;
    }
    
    public MyItem(long id, MyItem parent) {
        this.id = id;
        this.parent = parent;
    }


    @Override
    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public Long getId() {
        return id;
    }

    @Override
    public void setIsCollapsed(boolean isCollapsed) {
        this.isCollapsed = isCollapsed;
    }

    @Override
    public boolean isCollapsed() {
        return isCollapsed;
    }

    @Override
    public void setLevel(int level) {
        this.level = level;
    }

    @Override
    public int getLevel() {
        return level;
    }

    @Override
    public void setParent(MyItem parent) {
        this.parent = parent;
    }

    @Override
    public MyItem getParent() {
        return parent;
    }

    @Override
    public boolean hasChildren() {
        return children != null;
    }

    @Override
    public void setChildren(List<MyItem> children) {
        this.children = children;
    }

    @Override
    public List<MyItem> getChildren() {
        return children;
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MyItem item = (MyItem) o;
        return getId().equals(item.getId());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getId());
    }
}
  • You can also define more hierarchies by implementing or extending the library's classes and interfaces and defining only one type.
  • You can implement your own TaskRunner if you want to execute the addItemTask on another thread and pass it in the adapter's constructor.
  • Yoi can implement your own AddItemTask and override the addItem method to define how you want to add your items to the adapter.

License

Copyright 2020 Emil Osterhed

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
You might also like...
Add RecyclerView, use Adapter class and ViewHolder to display data.
Add RecyclerView, use Adapter class and ViewHolder to display data.

فكرة المشروع في هذا المشروع سنقوم بعرض قائمة من البيانات للطلاب على واجهة تطبيق Android بإستخدام: مفهوم RecyclerView مفهوم Adapter مفهوم ViewModel محت

Shimo is an adapter for Moshi which randomizes the order of keys when serializing and deserializing

Shimo Shimo is a JsonAdapter.Factory for Moshi which randomizes the order of keys when serializing objects to JSON and when deserializing objects from

Don't write a RecyclerView adapter again. Not even a ViewHolder!

LastAdapter Don't write a RecyclerView adapter again. Not even a ViewHolder! Based on Android Data Binding Written in Kotlin No need to write the adap

kotlin dsl for kids to simplify RecyclerView.Adapter logic

KidAdapter RecyclerView adapter for kids. A kotlin dsl mechanism to simplify and reduce boilerplate logic of a RecyclerView.Adapter. With KidAdapter y

A RecyclerView Adapter which allows you to have an Infinite scrolling list in your apps
A RecyclerView Adapter which allows you to have an Infinite scrolling list in your apps

Infinite Recycler View A RecyclerView Adapter which allows you to have an Infinite scrolling list in your apps. This library offers you a custom adapt

Reproducible sample with Fix for Memory Leak in RecyclerView Adapter
Reproducible sample with Fix for Memory Leak in RecyclerView Adapter

Memory Leak RecyclerView Adapter Reproducible Sample with Fix Video Instructions: https://www.youtube.com/c/awesomedevnotes Code Only the relevant and

RecyclerView With No Adapter | Available For Jetpack Compose
RecyclerView With No Adapter | Available For Jetpack Compose

About This Project Available on Google Dev Library Click Here RecyclerView No Adapter (Adapter Has Been Handled) RecyclerView No Adapter Using ViewBin

Easy RecyclerView Adapter

GenericAdapter Easy RecyclerView Adapter Getting started build.gradle allprojects { repositories { // ... maven { url 'https://jit

Just another one easy-to-use adapter for RecyclerView :rocket:
Just another one easy-to-use adapter for RecyclerView :rocket:

Elementary RecyclerView Adapter Another one easy-to-use adapter for RecyclerView 🚀 Features: DSL-like methods for building adapters similar to Jetpac

Owner
Emil Osterhed
Emil Osterhed
Android library for RecyclerView to manage order of items and multiple view types.

recyclerview-binder Android Library for RecyclerView to manage order of items and multiple view types. Features Insert any items to wherever you want

Satoru Fujiwara 185 Nov 15, 2022
Beautify your RecyclerViews with a great parallax effect !

BeautifulParallax Beautify your RecyclerViews with a great parallax effect ! Without Carpaccio public class YOURAdapter extends RecyclerView.Adapter<Y

Florent CHAMPIGNY 413 Nov 2, 2022
A Common RecyclerView.Adapter implementation which supports all kind of items and has useful data operating APIs such as remove,add,etc.

##PowerfulRecyclerViewAdapter A Common RecyclerView.Adapter implementation which supports any kind of items and has useful data operating APIs such as

null 313 Nov 12, 2022
Android library defining adapter classes of RecyclerView to manage multiple view types

RecyclerView-MultipleViewTypeAdapter RecyclerView adapter classes for managing multiple view types Release Note [Release Note] (https://github.com/yqr

Yoshihito Ikeda 414 Nov 21, 2022
Handy library to integrate pagination, which allow no data layout, refresh layout, recycler view in one view and easy way to bind pagination in app.

Pagination View Handy library to integrate pagination, which allow no data layout, refresh layout, recycler view in one view and easy way to bind pagi

DhiWise 4 Dec 18, 2021
An Android Animation library which easily add itemanimator to RecyclerView items.

RecyclerView Animators RecyclerView Animators is an Android library that allows developers to easily create RecyclerView with animations. Please feel

Daichi Furiya 11.2k Jan 8, 2023
Android library providing simple way to control divider items (ItemDecoration) of RecyclerView

RecyclerView-FlexibleDivider Android library providing simple way to control divider items of RecyclerView Release Note [Release Note] (https://github

Yoshihito Ikeda 2.4k Dec 18, 2022
Elegant design and convenient to use RecyclerView adapter library based on Kotlin DSL.

xAdapter: Kotlin DSL 风格的 Adapter 封装 1、简介 该项目是 KotlinDSL 风格的 Adapter 框架封装,用来简化 Adapter 调用,思想是采用工厂和构建者方式获取 Adapter 避免代码中定义大量的 Adapter 类。该项目在 BRVAH 的 Ada

ShouHeng 17 Oct 9, 2022
Examples of custom recycler view items. Automatically detecting a dominant color of an image using Picasso and Palette libraries

custom-image-list-item Examples of custom RecyclerView items using Data Binding Features: Loading images urls with the help of a Picasso library Autom

Alina Stepanova 2 Sep 12, 2022
Yet another adapter delegate library.

Yet another adapter delegate library. repositories { ... maven { url 'https://jitpack.io' } } ... dependencies { implementation("com.git

Mike 10 Dec 26, 2022