Android S1E18 : Sectioned RecyclerView with StickyHeaders

Android S1E18 : Sectioned RecyclerView with StickyHeaders



Language :
Platform :
Rating : 5/5 (1)




Android Sectioned RecyclerView with Sticky Headers

Introduction

You can easily show headers in your recyclerview and have a sectioned recyclerview Headers can help you categorize your lists of data into groups. This is very important especially if you have grouped data. Say you have a list of players and their teams. You can organize the players per team. Or say, like we did in this example, alist of galaxies. The galaxies belong to different categories like irregular, elliptical and spiral. So first we have to apply a custom sort to our list of data so that wgroup the galaxies according to category or type. We will use java. In this class we see how to show grouped items in a recyclerview with sticky headers. We have a list of galaxy objects. These galaxy objects we will have name, description, image and category objects. We use the categories to apply a custom sort to our recyclerview list of data. We will be using the SimpleRecyclerView library available at github.

Screenshot

  • Here's the screenshot of the project.

Android Sectioned RecyclerView with StickyHeaders.
Android Sectioned RecyclerView

Android Sectioned RecyclerView example. : Project Structure.

Android Sectioned RecyclerViewProject Structure

Common Questions this example explores

  • Android Sectioned Recycleview with StickyHeaders.
  • Android RecyclerView with Headers.
  • Android SimpleRecyclerView library.
  • Android ReccylerView with images and text.
  • Android custom sorting and grouping according to categories.

Tools Used

This example was written with the following tools:

  • Windows 8
  • AndroidStudio IDE
  • Genymotion Emulator
  • Language : Java
  • Topic : RecyclerView Events, Android SimpleRecyclerView

Libaries Used

  • We use Android SimpleRecyclerView library.

Source Code

Lets jump directly to the source code.

Build.Gradle Project LevelBuild.Gradle App LevelCategory.javaGalaxy.javaGalaxyCell.javaMainActivity.javaActivityMain.xmlheader.xmlmodel.xmlVideo/PreviewDownload
  • Our project level build.gradle.
  • We add repositories for fetching our dependencies here.
  • The dafult,jccenter() is already specified.
  • However, we add the maven and specify the url we'll use to fetch our third part library here.
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
//Specify maven jitpack.io as a repository.
allprojects {
    repositories {
        jcenter()
        maven { url "https://jitpack.io" }
        maven { url "https://maven.google.com" }
    }
}
task clean(type: Delete) {
    delete rootProject.buildDir
}

 

  • Our app level build.gradle file.
  • We specify compilesdk,minimum sdk,target sdk and dependencies.
  • Note that the minimum sdk for this project isn't that strict,it is much lower than that specified below.
  • We also add dependencies using 'compile' statement.
  • Our activity shall derive from the appCompatActivity to make it target earlier android versions.
  • We also specify design support library as well as CardView.
  • Add dependencies including com.github.jaychang0917:SimpleRecyclerView.
  • This is the recyclerview we will use in our project.
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
//Specify maven jitpack.io as a repository.
allprojects {
    repositories {
        jcenter()
        maven { url "https://jitpack.io" }
        maven { url "https://maven.google.com" }
    }
}
task clean(type: Delete) {
    delete rootProject.buildDir
}

 

  • Our Category class.
  • A category object
  • A category has an id and name.
  • We will sort our RecyclerView using this category class.
package com.tutorials.hp.recyclerstickyheaders;
public class Category {
    int id;
    String name;
    public Category(int id, String name) {
        this.id = id;
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public String getName() {
        return name;
    }
}

 

  • Our data object
  • We pass it data via constructor.
  • We retrieve its data via getters.
package com.tutorials.hp.recyclerstickyheaders;
public class Galaxy {
    private String name,description;
    private int image;
    private Category category;
    public Galaxy(String name, String description, int image,Category category) {
        this.name = name;
        this.description = description;
        this.image = image;
        this.category = category;
    }
    public String getName() {
        return name;
    }
    public String getDescription() {
        return description;
    }
    public int getImage() {
        return image;
    }
    public int getCategoryId() {
        return category.getId();
    }
    public String getCategoryName() {
        return category.getName();
    }
}

 

  • Our galaxy cell object.
  • Derives from SimpleCell.
  • ViewItem layout is inflated here.
  • Data is also bound to views here.
  • Represents a single viewitem that will get inflated from our model layout.
  • Will comprise an inner static ViewHolder class.
  • Think of this class as the equivalence of our RecyclerView.Adapter class.
package com.tutorials.hp.recyclerstickyheaders;
import android.content.Context;
import android.support.annotation.NonNull;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.jaychang.srv.SimpleCell;
import com.jaychang.srv.SimpleViewHolder;
/*
- Our galaxy cell object.
- Derives from SimpleCell
- Represents a single viewitem that will get inflated from our model layout.
 */
public class GalaxyCell extends SimpleCell<Galaxy,GalaxyCell.ViewHolder>  {
    public GalaxyCell(@NonNull Galaxy item) {
        super(item);
    }
    @Override
    protected int getLayoutRes() {
        return R.layout.model;
    }
    /*
    - Return a ViewHolder instance
     */
    @NonNull
    @Override
    protected ViewHolder onCreateViewHolder(ViewGroup parent, View cellView) {
        return new ViewHolder(cellView);
    }
    /*
    - Bind data to widgets in our viewholder.
     */
    @Override
    protected void onBindViewHolder(@NonNull ViewHolder viewHolder, int i, @NonNull Context context, Object o) {
        viewHolder.titleTxt.setText(getItem().getName());
        viewHolder.descTxt.setText(getItem().getDescription());
        viewHolder.img.setImageResource(getItem().getImage());
    }
    /**
     - Our ViewHolder class.
     - Inner static class.
     * Define your view holder, which must extend SimpleViewHolder.
     * */
    static class ViewHolder extends SimpleViewHolder {
        TextView titleTxt,descTxt;
        ImageView img;
        ViewHolder(View itemView) {
            super(itemView);
            titleTxt=itemView.findViewById(R.id.nameTxt);
            descTxt=itemView.findViewById(R.id.descTxt);
            img=itemView.findViewById(R.id.galaxyImageview);
        }
    }
}

 

  • Our MainActivity class.
  • Derives from AppCompatActivity which is a Base class for activities that use the support library action bar features.
  • Methods: onCreate(),addRecyclerHeaders(),bindData(),getData().
  • Inflated From activity_main.xml using the setContentView() method.
  • The views we use are SimpleRecyclerView.
  • Reference RecyclerView from our layout specification using findViewById().
  • Call addRecyclerHeaders() to add RecyclerView sticky headers.
  • Call bindData() to bind data to RecyclerView.
  • getData() will be our data source.
  • We will also implement a custom sort using Collections.sort(), we sort our recyclerview using categories.
package com.tutorials.hp.recyclerstickyheaders;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.jaychang.srv.SimpleCell;
import com.jaychang.srv.SimpleRecyclerView;
import com.jaychang.srv.decoration.SectionHeaderProvider;
import com.jaychang.srv.decoration.SimpleSectionHeaderProvider;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class MainActivity extends AppCompatActivity {
    SimpleRecyclerView simpleRecyclerView;
    /*
    - When activity is created.
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        simpleRecyclerView=findViewById(R.id.recyclerView);
        this.addRecyclerHeaders();
        this.bindData();
    }
    /*
    - Create RecyclerViewHeaders
     */
    private void addRecyclerHeaders()
    {
        SectionHeaderProvider<Galaxy> sh=new SimpleSectionHeaderProvider<Galaxy>() {
            @NonNull
            @Override
            public View getSectionHeaderView(@NonNull Galaxy Galaxy, int i) {
                View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.header, null, false);
                TextView textView =  view.findViewById(R.id.headerTxt);
                textView.setText(Galaxy.getCategoryName());
                return view;
            }
            @Override
            public boolean isSameSection(@NonNull Galaxy Galaxy, @NonNull Galaxy nextGalaxy) {
                return Galaxy.getCategoryId() == nextGalaxy.getCategoryId();
            }
            // Optional, whether the header is sticky, default false
            @Override
            public boolean isSticky() {
                return true;
            }
        };
        simpleRecyclerView.setSectionHeader(sh);
    }
    /*
    - Bind data to our RecyclerView
     */
    private void bindData()
    {
        List<Galaxy> Galaxys = getData();
        //CUSTOM SORT ACCORDING TO CATEGORIES
        Collections.sort(Galaxys, new Comparator<Galaxy>(){
            public int compare(Galaxy Galaxy, Galaxy nextGalaxy) {
                return Galaxy.getCategoryId() - nextGalaxy.getCategoryId();
            }
        });
        List<GalaxyCell> cells = new ArrayList<>();
        //LOOP THROUGH GALAXIES INSTANTIATING THEIR CELLS AND ADDING TO CELLS COLLECTION
        for (Galaxy galaxy : Galaxys) {
            GalaxyCell cell = new GalaxyCell(galaxy);
            // There are two default cell listeners: OnCellClickListener<CELL, VH, T> and OnCellLongClickListener<CELL, VH, T>
            cell.setOnCellClickListener2(new SimpleCell.OnCellClickListener2<GalaxyCell, GalaxyCell.ViewHolder, Galaxy>() {
                @Override
                public void onCellClicked(GalaxyCell GalaxyCell, GalaxyCell.ViewHolder viewHolder, Galaxy item) {
                    Toast.makeText(MainActivity.this, item.getName(), Toast.LENGTH_SHORT).show();
                }
            });
            cell.setOnCellLongClickListener2(new SimpleCell.OnCellLongClickListener2<GalaxyCell, GalaxyCell.ViewHolder, Galaxy>() {
                @Override
                public void onCellLongClicked(GalaxyCell GalaxyCell, GalaxyCell.ViewHolder viewHolder, Galaxy item) {
                    Toast.makeText(MainActivity.this, item.getDescription(), Toast.LENGTH_SHORT).show();
                }
            });
            cells.add(cell);
        }
        simpleRecyclerView.addCells(cells);
    }
    /*
    - Data Source
    - Returns an arraylist of galaxies.
     */
    private ArrayList<Galaxy> getData()
    {
        ArrayList<Galaxy> galaxies=new ArrayList<>();
        //CREATE CATEGORIES
        Category elliptical=new Category(0,"Elliptical");
        Category irregular=new Category(1,"Irregular");
        Category spiral=new Category(2,"Spiral");
        //INSTANTIATE GALAXY OBJECTS AND ADD THEM TO GALAXY LIST
        Galaxy g=new Galaxy("Whirlpool",
                "The Whirlpool Galaxy, also known as Messier 51a, M51a, and NGC 5194, is an interacting grand-design spiral Galaxy with a Seyfert 2 active galactic nucleus in the constellation Canes Venatici.",
                R.drawable.whirlpool,spiral);
        galaxies.add(g);
        g=new Galaxy("Ring Nebular",
                "The Ring Nebula is a planetary nebula in the northern constellation of Lyra. Such objects are formed when a shell of ionized gas is expelled into the surrounding interstellar medium by a red giant star.",
                R.drawable.ringnebular,elliptical);
        galaxies.add(g);
        g=new Galaxy("IC 1011",
                "C 1011 is a compact elliptical galaxy with apparent magnitude of 14.7, and with a redshift of z=0.02564 or 0.025703, yielding a distance of 100 to 120 Megaparsecs. Its light has taken 349.5 million years to travel to Earth.",
                R.drawable.ic1011,elliptical);
        galaxies.add(g);
        g=new Galaxy("Cartwheel",
                "The Cartwheel Galaxy is a lenticular galaxy and ring galaxy about 500 million light-years away in the constellation Sculptor. It is an estimated 150,000 light-years diameter, and a mass of about 2.9–4.8 × 10⁹ solar masses; it rotates at 217 km/s.",
                R.drawable.cartwheel,irregular);
        galaxies.add(g);
        g=new Galaxy("Triangulumn",
                "The Triangulum Galaxy is a spiral Galaxy approximately 3 million light-years from Earth in the constellation Triangulum",
                R.drawable.triangulum,spiral);
        galaxies.add(g);
        g=new Galaxy("Small Magellonic Cloud",
                "The Small Magellanic Cloud, or Nubecula Minor, is a dwarf galaxy near the Milky Way. It is classified as a dwarf irregular galaxy.",
                R.drawable.smallamgellonic,irregular);
        galaxies.add(g);
        g=new Galaxy("Centaurus A",
                " Centaurus A or NGC 5128 is a galaxy in the constellation of Centaurus. It was discovered in 1826 by Scottish astronomer James Dunlop from his home in Parramatta, in New South Wales, Australia.",
                R.drawable.centaurusa,elliptical);
        galaxies.add(g);
        g=new Galaxy("Ursa Minor",
                "The Milky Way is the Galaxy that contains our Solar System." +
                        " The descriptive milky is derived from the appearance from Earth of the Galaxy – a band of light seen in the night sky formed from stars",
                R.drawable.ursaminor,irregular);
        galaxies.add(g);
        g=new Galaxy("Large Magellonic Cloud",
                " The Large Magellanic Cloud is a satellite galaxy of the Milky Way. At a distance of 50 kiloparsecs, the LMC is the third-closest galaxy to the Milky Way, after the Sagittarius Dwarf Spheroidal and the.",
                R.drawable.largemagellonic,irregular);
        galaxies.add(g);
        g=new Galaxy("Milky Way",
                "The Milky Way is the Galaxy that contains our Solar System." +
                        " The descriptive milky is derived from the appearance from Earth of the Galaxy – a band of light seen in the night sky formed from stars",
                R.drawable.milkyway,spiral);
        galaxies.add(g);
        g=new Galaxy("Andromeda",
                "The Andromeda Galaxy, also known as Messier 31, M31, or NGC 224, is a spiral Galaxy approximately 780 kiloparsecs from Earth. It is the nearest major Galaxy to the Milky Way and was often referred to as the Great Andromeda Nebula in older texts.",
                R.drawable.andromeda,irregular);
        galaxies.add(g);
        g=new Galaxy("Messier 81",
                "Messier 81 is a spiral Galaxy about 12 million light-years away in the constellation Ursa Major. Due to its proximity to Earth, large size and active galactic nucleus, Messier 81 has been studied extensively by professional astronomers.",
                R.drawable.messier81,elliptical);
        galaxies.add(g);
        g=new Galaxy("Own Nebular",
                " The Owl Nebula is a planetary nebula located approximately 2,030 light years away in the constellation Ursa Major. It was discovered by French astronomer Pierre Méchain on February 16, 1781",
                R.drawable.ownnebular,elliptical);
        galaxies.add(g);
        g=new Galaxy("Messier 87",
                "Messier 87 is a supergiant elliptical galaxy in the constellation Virgo. One of the most massive galaxies in the local universe, it is notable for its large population of globular clusters—M87 contains",
                R.drawable.messier87,elliptical);
        galaxies.add(g);
        g=new Galaxy("Cosmos Redshift",
                "Cosmos Redshift 7 is a high-redshift Lyman-alpha emitter Galaxy, in the constellation Sextans, about 12.9 billion light travel distance years from Earth, reported to contain the first stars —formed ",
                R.drawable.cosmosredshift,irregular);
        galaxies.add(g);
        g=new Galaxy("StarBust",
                "A starburst Galaxy is a Galaxy undergoing an exceptionally high rate of star formation, as compared to the long-term average rate of star formation in the Galaxy or the star formation rate observed in most other galaxies. ",
                R.drawable.starbust,irregular);
        galaxies.add(g);
        g=new Galaxy("Sombrero",
                "Sombrero Galaxy is an unbarred spiral galaxy in the constellation Virgo located 31 million light-years from Earth. The galaxy has a diameter of approximately 50,000 light-years, 30% the size of the Milky Way.",
                R.drawable.sombrero,spiral);
        galaxies.add(g);
        g=new Galaxy("Pinwheel",
                "The Pinwheel Galaxy is a face-on spiral galaxy distanced 21 million light-years away from earth in the constellation Ursa Major. ",
                R.drawable.pinwheel,spiral);
        galaxies.add(g);
        g=new Galaxy("Canis Majos Overdensity",
                "The Canis Major Dwarf Galaxy or Canis Major Overdensity is a disputed dwarf irregular galaxy in the Local Group, located in the same part of the sky as the constellation Canis Major. ",
                R.drawable.canismajoroverdensity,irregular);
        galaxies.add(g);
        g=new Galaxy("Virgo Stella Stream",
                " Group, located in the same part of the sky as the constellation Canis Major. ",
                R.drawable.virgostellarstream,spiral);
        galaxies.add(g);
        return galaxies;
    }
}

 

  • Our activitymain.xml.
  • Contains a SimpleRecyclerView.
  • Will get inflated to MainActivity.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.tutorials.hp.recyclerstickyheaders.MainActivity">
    <com.jaychang.srv.SimpleRecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:srv_layoutMode="linearVertical"
        app:srv_showDivider="true"
        app:srv_showLastDivider="true"
        app:srv_dividerOrientation="both"
        app:srv_dividerColor="@color/colorAccent"
        app:srv_dividerPaddingLeft="5dp"
        app:srv_dividerPaddingRight="5dp"
        app:srv_dividerPaddingTop="5dp"
        app:srv_dividerPaddingBottom="5dp" />
</android.support.constraint.ConstraintLayout>

 

  • Our header.xml file.
  • Defines the layout specification for our RecyclerView headers.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
  android:background="#009968"
    android:layout_height="match_parent">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textSize="30dp"
            android:textStyle="bold|italic"
            android:text="Header"
            android:id="@+id/headerTxt"
            android:gravity="center"
            android:padding="10dp"
            android:layout_gravity="center"
            android:layout_alignParentTop="true"/>
</LinearLayout>

 

  • As the name suggests, this layout models our viewitem.
  • We define how each Card shall appear in our List.
  • So at the root level we have a CardView widget.
  • We can also customize our CardView by specifying cardCornerRadius,cardElevation,width,height etc.
  • Each Card shall comprise textviews and images.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_margin="5dp"
    card_view:cardCornerRadius="15dp"
    card_view:cardElevation="10dp"
    android:layout_height="200dp">
    <LinearLayout
       android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text="Galaxy"
            android:id="@+id/nameTxt"
            android:padding="10dp"
      android:textColor="@color/abc_btn_colored_borderless_text_material"
            android:layout_alignParentTop="true"/>
        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <ImageView
                android:id="@+id/galaxyImageview"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentTop="true"
                android:layout_marginLeft="24dp"
                android:src="@drawable/andromeda" />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:text="Description"
                android:id="@+id/descTxt"
                android:padding="10dp"/>
        </LinearLayout>
    </LinearLayout>
</android.support.v7.widget.CardView>

 

  • We have a YouTube channel with almost a thousand tutorials, this one below being one of them.

Android S1E18 : Sectioned RecyclerView with StickyHeaders

  • You can Download the full Project below. Source code is well commented.
Download

How To Run

  1. Download the project above.
  2. You'll get a zipped file,extract it.
  3. Open the Android Studio.
  4. Now close, already open project.
  5. From the Menu bar click on File >New> Import Project.
  6. Now Choose a Destination Folder, from where you want to import project.
  7. Choose an Android Project.
  8. Now Click on “OK“.
  9. Done, your done importing the project,now edit it.

More

YouTube

  • Visit our channel for more examples like these.

Facebook

Oclemy,Cheers.



Rating :

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    eighteen − twelve =

    COMMENTS