Convert Figma logo to code with AI

timehop logosticky-headers-recyclerview

[UNMAINTAINED] Sticky Headers decorator for Android's RecyclerView

3,742
755
3,742
83

Top Related Projects

BRVAH:Powerful and flexible RecyclerAdapter

"Favor composition over inheritance" for RecyclerView Adapters

The bullet proof, fast and easy to use adapter library, which minimizes developing time to a fraction...

8,494

Epoxy is an Android library for building complex screens in a RecyclerView

A SnapHelper that snaps a RecyclerView to an edge.

Flexible multiple types for Android RecyclerView.

Quick Overview

Sticky-headers-recyclerview is an Android library that provides a simple way to add sticky headers to RecyclerView. It allows headers to stick to the top of the list as the user scrolls, improving navigation and readability in long lists of data.

Pros

  • Easy integration with existing RecyclerView implementations
  • Supports both vertical and horizontal orientations
  • Customizable header appearance and behavior
  • Lightweight and efficient, with minimal impact on performance

Cons

  • Limited documentation and examples
  • Not actively maintained (last update was several years ago)
  • May not be fully compatible with the latest Android versions or RecyclerView updates
  • Lacks some advanced features found in newer alternatives

Code Examples

  1. Basic setup with a RecyclerView:
val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
val adapter = YourAdapter()
val layoutManager = LinearLayoutManager(this)

recyclerView.layoutManager = layoutManager
recyclerView.adapter = adapter

// Add the StickyRecyclerHeadersDecoration
val headerDecor = StickyRecyclerHeadersDecoration(adapter)
recyclerView.addItemDecoration(headerDecor)
  1. Implementing the StickyRecyclerHeadersAdapter interface:
class YourAdapter : RecyclerView.Adapter<YourViewHolder>(), StickyRecyclerHeadersAdapter<HeaderViewHolder> {
    override fun getHeaderId(position: Int): Long {
        // Return a unique ID for each header
        return items[position].headerId
    }

    override fun onCreateHeaderViewHolder(parent: ViewGroup): HeaderViewHolder {
        // Create and return your header view holder
        val view = LayoutInflater.from(parent.context).inflate(R.layout.header_item, parent, false)
        return HeaderViewHolder(view)
    }

    override fun onBindHeaderViewHolder(holder: HeaderViewHolder, position: Int) {
        // Bind data to your header view holder
        holder.bind(items[position].headerData)
    }
}
  1. Adding click listeners to headers:
val headerClickListener = StickyRecyclerHeadersTouchListener(recyclerView, headerDecor)
headerClickListener.setOnHeaderClickListener { view, position, headerId ->
    // Handle header click
    Toast.makeText(this, "Header $headerId clicked", Toast.LENGTH_SHORT).show()
}
recyclerView.addOnItemTouchListener(headerClickListener)

Getting Started

  1. Add the dependency to your build.gradle file:
dependencies {
    implementation 'com.timehop.stickyheadersrecyclerview:library:0.4.3@aar'
}
  1. Implement the StickyRecyclerHeadersAdapter interface in your RecyclerView adapter.
  2. Create and add the StickyRecyclerHeadersDecoration to your RecyclerView.
  3. (Optional) Add header click listeners using StickyRecyclerHeadersTouchListener.

For more detailed instructions and advanced usage, refer to the project's GitHub repository.

Competitor Comparisons

BRVAH:Powerful and flexible RecyclerAdapter

Pros of BaseRecyclerViewAdapterHelper

  • More comprehensive feature set, including drag & drop, animations, and multi-item types
  • Actively maintained with frequent updates and a large community
  • Extensive documentation and examples for easier implementation

Cons of BaseRecyclerViewAdapterHelper

  • Steeper learning curve due to its extensive feature set
  • May include unnecessary features for simpler projects, potentially increasing app size
  • Less focused on sticky headers specifically, as it's a more general-purpose library

Code Comparison

sticky-headers-recyclerview:

mRecyclerView.addItemDecoration(new StickyRecyclerHeadersDecoration(mAdapter));

BaseRecyclerViewAdapterHelper:

public class MyAdapter extends BaseQuickAdapter<MyItem, BaseViewHolder> {
    @Override
    protected void convert(BaseViewHolder helper, MyItem item) {
        // Bind data to views
    }
}

BaseRecyclerViewAdapterHelper provides a more comprehensive approach to RecyclerView adapters, while sticky-headers-recyclerview focuses specifically on implementing sticky headers. The former offers a wider range of features but may require more setup, while the latter is simpler to implement for its specific use case.

Both libraries aim to enhance RecyclerView functionality, but BaseRecyclerViewAdapterHelper is more versatile and actively maintained, making it a better choice for projects requiring multiple advanced RecyclerView features beyond just sticky headers.

"Favor composition over inheritance" for RecyclerView Adapters

Pros of AdapterDelegates

  • Promotes a more modular and flexible approach to RecyclerView adapters
  • Easier to maintain and extend complex list structures
  • Supports multiple view types with less boilerplate code

Cons of AdapterDelegates

  • Requires additional setup and understanding of the delegation pattern
  • May introduce slight performance overhead for simple list structures
  • Less focused on specific features like sticky headers

Code Comparison

sticky-headers-recyclerview:

public class MyStickyHeaderAdapter extends StickyRecyclerHeadersAdapter<RecyclerView.ViewHolder> {
    @Override
    public long getHeaderId(int position) {
        // Return header ID for position
    }

    @Override
    public RecyclerView.ViewHolder onCreateHeaderViewHolder(ViewGroup parent) {
        // Create header view holder
    }
}

AdapterDelegates:

public class MyAdapterDelegate extends AdapterDelegate<List<Object>> {
    @Override
    public boolean isForViewType(@NonNull List<Object> items, int position) {
        // Determine if this delegate handles the view type
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
        // Create view holder
    }
}

The sticky-headers-recyclerview focuses on implementing sticky headers, while AdapterDelegates provides a more general-purpose solution for handling multiple view types in a RecyclerView. AdapterDelegates offers greater flexibility but requires more setup, whereas sticky-headers-recyclerview is more specialized for its specific use case.

The bullet proof, fast and easy to use adapter library, which minimizes developing time to a fraction...

Pros of FastAdapter

  • More comprehensive feature set, including drag & drop, swipe-to-dismiss, and multi-select
  • Actively maintained with frequent updates and a larger community
  • Supports a wider range of item types and layouts

Cons of FastAdapter

  • Steeper learning curve due to its extensive functionality
  • May be overkill for simpler projects that only need basic RecyclerView functionality
  • Larger library size compared to sticky-headers-recyclerview

Code Comparison

FastAdapter:

val fastAdapter = FastAdapter.with(itemAdapter)
recyclerView.adapter = fastAdapter

itemAdapter.add(Item("Example"))

sticky-headers-recyclerview:

val adapter = StickyRecyclerHeadersAdapter(YourAdapter())
recyclerView.adapter = adapter

recyclerView.addItemDecoration(StickyRecyclerHeadersDecoration(adapter))

Summary

FastAdapter offers a more feature-rich solution for RecyclerView implementations, with active maintenance and a larger community. However, it may be more complex for simple use cases. sticky-headers-recyclerview provides a more focused solution for implementing sticky headers in RecyclerViews, with a simpler API but fewer additional features. The choice between the two depends on the specific requirements of your project and the level of functionality needed.

8,494

Epoxy is an Android library for building complex screens in a RecyclerView

Pros of Epoxy

  • More comprehensive solution for building complex RecyclerViews
  • Supports data binding and view binding out of the box
  • Offers automatic diffing and efficient updates

Cons of Epoxy

  • Steeper learning curve due to its extensive feature set
  • Requires more setup and configuration
  • May be overkill for simpler RecyclerView implementations

Code Comparison

Sticky-headers-recyclerview:

mRecyclerView.addItemDecoration(new StickyRecyclerHeadersDecoration(mAdapter));

Epoxy:

EpoxyRecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setController(new MyEpoxyController());

Key Differences

  • Sticky-headers-recyclerview focuses specifically on implementing sticky headers in RecyclerViews
  • Epoxy provides a more holistic approach to building complex RecyclerViews with various features
  • Sticky-headers-recyclerview is simpler to implement for its specific use case
  • Epoxy offers more flexibility and power for handling diverse RecyclerView scenarios

Use Cases

  • Choose Sticky-headers-recyclerview for quick implementation of sticky headers in a RecyclerView
  • Opt for Epoxy when building complex, data-driven RecyclerViews with multiple view types and dynamic content

Community and Maintenance

  • Epoxy is actively maintained by Airbnb and has a larger community
  • Sticky-headers-recyclerview has fewer recent updates but remains a solid choice for its specific functionality

A SnapHelper that snaps a RecyclerView to an edge.

Pros of GravitySnapHelper

  • Provides smooth snapping behavior for RecyclerView items
  • Supports multiple orientations (horizontal, vertical, and grid)
  • Offers customizable snap positions (start, center, end)

Cons of GravitySnapHelper

  • Focuses on snapping functionality rather than sticky headers
  • May require additional implementation for header-specific features
  • Limited to snapping behavior, lacking advanced header management

Code Comparison

GravitySnapHelper:

val snapHelper = GravitySnapHelper(Gravity.START)
snapHelper.attachToRecyclerView(recyclerView)

sticky-headers-recyclerview:

StickyRecyclerHeadersDecoration headersDecor = new StickyRecyclerHeadersDecoration(mAdapter);
recyclerView.addItemDecoration(headersDecor);

Summary

GravitySnapHelper excels in providing smooth snapping behavior for RecyclerView items, supporting multiple orientations and customizable snap positions. However, it lacks specific functionality for sticky headers, which is the primary focus of sticky-headers-recyclerview. The latter offers more advanced header management features but may not provide the same level of snapping capabilities. Developers should choose based on their specific requirements for item snapping versus header management in their RecyclerView implementations.

Flexible multiple types for Android RecyclerView.

Pros of MultiType

  • Supports multiple view types in a single RecyclerView adapter
  • Easier to add new item types without modifying existing code
  • More flexible and extensible architecture

Cons of MultiType

  • Doesn't provide built-in sticky header functionality
  • May require more initial setup for simple use cases
  • Learning curve for understanding the concept of ItemViewBinders

Code Comparison

MultiType:

class TextItemViewBinder : ItemViewBinder<TextItem, TextItemViewBinder.ViewHolder>() {
    override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): ViewHolder {
        return ViewHolder(inflater.inflate(R.layout.item_text, parent, false))
    }
    override fun onBindViewHolder(holder: ViewHolder, item: TextItem) {
        holder.textView.text = item.text
    }
    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val textView: TextView = itemView.findViewById(R.id.text)
    }
}

sticky-headers-recyclerview:

public class MyStickyHeaderAdapter extends StickyRecyclerHeadersAdapter<RecyclerView.ViewHolder> {
    @Override
    public long getHeaderId(int position) {
        // Return ID for header based on position
    }
    @Override
    public RecyclerView.ViewHolder onCreateHeaderViewHolder(ViewGroup parent) {
        // Create header view holder
    }
    @Override
    public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder, int position) {
        // Bind header view holder
    }
}

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

This project is no longer being maintained

sticky-headers-recyclerview

This decorator allows you to easily create section headers for RecyclerViews using a LinearLayoutManager in either vertical or horizontal orientation.

Credit to Emil Sjölander for creating StickyListHeaders, a library that many of us relied on for sticky headers in our listviews.

Here is a quick video of it in action (click to see the full video):

animated gif demo

animated gif demo

Download

Current version: Maven Central

compile 'com.timehop.stickyheadersrecyclerview:library:[latest.version.number]@aar'

Usage

There are three main classes, StickyRecyclerHeadersAdapter, StickyRecyclerHeadersDecoration, and StickyRecyclerHeadersTouchListener.

StickyRecyclerHeadersAdapter has a very similar interface to the RecyclerView.Adapter, and it is recommended that you make your RecyclerView.Adapter implement StickyRecyclerHeadersAdapter.

There interface looks like this:

public interface StickyRecyclerHeadersAdapter<VH extends RecyclerView.ViewHolder> {
  public long getHeaderId(int position);

  public VH onCreateHeaderViewHolder(ViewGroup parent);

  public void onBindHeaderViewHolder(VH holder, int position);

  public int getItemCount();
}

The second class, StickyRecyclerHeadersDecoration, is where most of the magic happens, and does not require any configuration on your end. Here's an example from onCreate() in an activity:

mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
mAdapter = new MyStickyRecyclerHeadersAdapter();
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(context));
mRecyclerView.addItemDecoration(new StickyRecyclerHeadersDecoration(mAdapter));

StickyRecyclerHeadersTouchListener allows you to listen for clicks on header views. Simply create an instance of StickyRecyclerHeadersTouchListener, set the OnHeaderClickListener, and add the StickyRecyclerHeadersTouchListener as a touch listener to your RecyclerView.

StickyRecyclerHeadersTouchListener touchListener =
    new StickyRecyclerHeadersTouchListener(recyclerView, headersDecor);
touchListener.setOnHeaderClickListener(
    new StickyRecyclerHeadersTouchListener.OnHeaderClickListener() {
      @Override
      public void onHeaderClick(View header, int position, long headerId) {
        Toast.makeText(MainActivity.this, "Header position: " + position + ", id: " + headerId,
            Toast.LENGTH_SHORT).show();
      }
    });
mRecyclerView.addOnItemTouchListener(touchListener);

The StickyHeaders aren't aware of your adapter so if you must notify them when your data set changes.

    mAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
      @Override public void onChanged() {
        headersDecor.invalidateHeaders();
      }
    });

If the Recyclerview's layout manager implements getExtraLayoutSpace (to preload more content then is visible for performance reasons), you must implement ItemVisibilityAdapter and pass an instance as a second argument to StickyRecyclerHeadersDecoration's constructor.

    @Override
    public boolean isPositionVisible(final int position) {
        return layoutManager.findFirstVisibleItemPosition() <= position
            && layoutManager.findLastVisibleItemPosition() >= position;
    }

Item animators don't play nicely with RecyclerView decorations, so your mileage with that may vary.

Compatibility

API 11+

Known Issues

  • The header views aren't recycled at this time. Contributions are most welcome.

  • I haven't tested this with ItemAnimators yet.

  • The header views are drawn to a canvas, and are not actually a part of the view hierarchy. As such, they can't have touch states, and you may run into issues if you try to load images into them asynchronously.

Version History

0.4.3 (12/24/2015) - Change minSDK to 11, fix issue with header bounds caching

0.4.2 (8/21/2015) - Add support for reverse ReverseLayout in LinearLayoutManager by AntonPukhonin

0.4.1 (6/24/2015) - Fix "dancing headers" by DarkJaguar91

0.4.0 (4/16/2015) - Code reorganization by danoz73, fixes for different sized headers, performance improvements

0.3.6 (1/30/2015) - Prevent header clicks from passing on the touch event

0.3.5 (12/12/2014) - Add StickyRecyclerHeadersDecoration.invalidateHeaders() method

0.3.4 (12/3/2014) - Fix issues with rendering of header views with header ID = 0

0.3.3 (11/13/2014) - Fixes for padding, support views without headers

0.3.2 (11/1/2014) - Bug fixes for list items with margins and deleting items

0.2 (10/3/2014) - Add StickyRecyclerHeadersTouchListener

0.1 (10/2/2014) - Initial Release