Expandable Item In RecyclerView in Android

In my last articles we have learned about the basic of recyclerView. If you have not seen my last article please check those article that really helps you. Here are the link details.
Multiple view type recyclerView and Section recyclerView.

Now in this article I am focusing about core feature of recyclerView and major used in the current building apps that is Expandable Item in recyclerView. You can expand and collapse the item of recyclerView to see the subitems of particular item. In the old API android provides the ListViewExpandable class the provides the feature to expand and collapse item of group. But in RecyclerView there is no specific Control to handle this.

While implementing this feature I found best library that make my work very simple. But if you want any specific expand feature you can feel free to choose any one as per your requirement.
Here is uploaded video by me that helps you to understand, please check this video.


Lets create the android project to implements the expandable and collapsable item in RecyclerView.
Here are the details of Code that required to achieve this feature.


build.gradle app level

apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.0"
    defaultConfig {
        applicationId "com.sunil.expandablerecyclerview"
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.0.0'
    testCompile 'junit:junit:4.12'

    compile 'com.thoughtbot:expandablerecyclerview:1.0'
    compile 'com.android.support:recyclerview-v7:25.0.0'
    compile 'com.android.support:cardview-v7:25.0.0'
    compile 'com.android.support:design:25.0.0'

    compile 'com.jakewharton:butterknife:8.4.0'
    apt 'com.jakewharton:butterknife-compiler:8.4.0'

    compile 'com.github.bumptech.glide:glide:3.7.0'
    compile 'de.hdodenhof:circleimageview:2.0.0'
}


MainActivity.java

public class MainActivity extends AppCompatActivity {

    String imageUrl[] = Constant.image;
    String names[] = Constant.name;
    String subNames[] = Constant.subName;

    @BindView(R.id.recyclerView)
    RecyclerView recyclerView;


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

        List list = getList();
        RecyclerAdapter adapter = new RecyclerAdapter(this, list);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(adapter);
        recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
        recyclerView.setAdapter(adapter);

    }

    private List getList() {
        List list = new ArrayList<>();
        for (int i = 0; i < imageUrl.length; i++) {
            List subTitles = new ArrayList<>();
            for (int j = 0; j< subNames.length; j++){
                SubTitle subTitle = new SubTitle(subNames[j]);
                subTitles.add(subTitle);
            }
            Title model = new Title(names[i],subTitles, imageUrl[i]);
            list.add(model);
        }
        return list;
    }
}

RecyclerAdapter.java

public class RecyclerAdapter extends ExpandableRecyclerViewAdapter {

    private Context context;
    public RecyclerAdapter(Context context, List groups) {
        super(groups);
        this.context = context;
    }

    @Override
    public TitleViewHolder onCreateGroupViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_item_title, parent, false);
        return new TitleViewHolder(view);
    }

    @Override
    public SubTitleViewHolder onCreateChildViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_item_subtitle, parent, false);
        return new SubTitleViewHolder(view);
    }

    @Override
    public void onBindChildViewHolder(SubTitleViewHolder holder, int flatPosition,
                                      ExpandableGroup group, int childIndex) {

        final SubTitle subTitle = ((Title) group).getItems().get(childIndex);
        holder.setSubTitletName(subTitle.getName());
    }

    @Override
    public void onBindGroupViewHolder(TitleViewHolder holder, int flatPosition, ExpandableGroup group) {
        holder.setGenreTitle(context, group);
    }
}

TitleViewHolder.java

public class TitleViewHolder extends GroupViewHolder {

    private TextView titleName;
    private ImageView arrow;
    private ImageView icon;

    public TitleViewHolder(View itemView) {
        super(itemView);
        titleName = (TextView) itemView.findViewById(R.id.list_item_genre_name);
        arrow = (ImageView) itemView.findViewById(R.id.list_item_genre_arrow);
        icon = (ImageView) itemView.findViewById(R.id.list_item_genre_icon);
    }

    public void setGenreTitle(Context context, ExpandableGroup title) {
        if (title instanceof Title) {
            titleName.setText(title.getTitle());
            if (((Title) title).getImageUrl()!= null && !((Title) title).getImageUrl().isEmpty()){
                Glide.with(context)
                        .load(((Title) title).getImageUrl())
                        .into(icon);

            }
        }
    }

    @Override
    public void expand() {
        animateExpand();
    }

    @Override
    public void collapse() {
        animateCollapse();
    }

    private void animateExpand() {
        RotateAnimation rotate =
                new RotateAnimation(360, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        rotate.setDuration(300);
        rotate.setFillAfter(true);
        arrow.setAnimation(rotate);
    }

    private void animateCollapse() {
        RotateAnimation rotate =
                new RotateAnimation(180, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        rotate.setDuration(300);
        rotate.setFillAfter(true);
        arrow.setAnimation(rotate);
    }
}

SubTitleViewHolder.java

public class SubTitleViewHolder extends ChildViewHolder {

    private TextView subTitleTextView;

    public SubTitleViewHolder(View itemView) {
        super(itemView);
        subTitleTextView = (TextView) itemView.findViewById(R.id.subtitle);
    }

    public void setSubTitletName(String name) {
        subTitleTextView.setText(name);
    }
}


Thanks for reading this post. I hope it will helps you to understand.

9 comments:

  1. Replies
    1. You cab download here
      https://github.com/sunil676/ExpandableRecyclerView

      Delete
  2. I need your help. Can you contact me? reprobats@gmail.com

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. giving error in builed.gradle in app module while syn project after adding dependecies

    ReplyDelete
  5. Replies
    1. https://github.com/sunil676/ExpandableRecyclerView

      Delete
  6. 1)How to change different sub items names for different Items ?
    2)How to create clickable activities for different sub items ?
    Thank you

    ReplyDelete

Debug Database in Android

In my last tutorial, we have learned how we can use persistence database in android. We also understood which database wrapper we can use...

Contact Me

Name

Email *

Message *