PinnedSectionItemDecoration

repository·master·Indexed 24 days ago

https://github.com/oubowu/pinnedsectionitemdecoration

An Android library for adding pinned section headers to RecyclerView. It supports large headers (separate items) and small headers (embedded in items) across LinearLayout, GridLayout, and StaggeredGridLayout. The library includes PinnedHeaderItemDecoration and SmallPinnedHeaderItemDecoration builders for configuration, and FullSpanUtil to ensure headers occupy the full width in grid layouts.

Tokens
4K
Snippets
8
Records
8
Agent score
35%

What's inside PinnedSectionItemDecoration

  1. Handle Full Span for Grid and Staggered Layouts

    master

    When using GridLayoutManager or StaggeredGridLayoutManager, your Adapter must handle making the header occupy a full row. It is recommended to use the FullSpanUtil tool class within your Adapter's lifecycle methods.

    Note: For vertical StaggeredGridLayoutManager, item heights must be fixed to prevent position switching during scrolling.

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        FullSpanUtil.onAttachedToRecyclerView(recyclerView, this, StockEntity.StockInfo.TYPE_HEADER);
    }
    
    @Override
    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
        super.onViewAttachedToWindow(holder);
        FullSpanUtil.onViewAttachedToWindow(holder, this, StockEntity.StockInfo.TYPE_HEADER);
    }
  2. Install PinnedSectionItemDecoration via Gradle

    master

    Add the dependency to your build.gradle file. Choose the version based on whether you are using AndroidX or not.

    If using androidx
        compile 'com.oushangfeng:PinnedSectionItemDecoration:1.3.2-androidx'
    otherwise
        compile 'com.oushangfeng:PinnedSectionItemDecoration:1.3.2'
  3. Configure Adapter with FullSpanUtil

    master

    To ensure headers occupy the full width (span count) of the RecyclerView, your adapter must process the span count using FullSpanUtil. Override onAttachedToRecyclerView and onViewAttachedToWindow in your adapter to call FullSpanUtil.onAttachedToRecyclerView and FullSpanUtil.onViewAttachedToWindow respectively, passing the RecyclerView, the adapter instance, and the specific header type constant.

        @Override
        public void onAttachedToRecyclerView(RecyclerView recyclerView) {
            super.onAttachedToRecyclerView(recyclerView);
            FullSpanUtil.onAttachedToRecyclerView(recyclerView, this, StockEntity.StockInfo.TYPE_HEADER);
        }
    
        @Override
        public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
            super.onViewAttachedToWindow(holder);
            FullSpanUtil.onViewAttachedToWindow(holder, this, StockEntity.StockInfo.TYPE_HEADER);
        }
  4. Install PinnedSectionItemDecoration

    master

    Add the dependency to your build.gradle file. Choose the version based on whether you are using AndroidX.

    For AndroidX:

    compile 'com.oushangfeng:PinnedSectionItemDecoration:1.3.2-androidx'

    For non-AndroidX projects:

    compile 'com.oushangfeng:PinnedSectionItemDecoration:1.3.2'
    compile 'com.oushangfeng:PinnedSectionItemDecoration:1.3.2-androidx'
  5. Implement Large Pinned Section Headers

    master

    Large pinned headers are used when the header is a separate item in the adapter. Use PinnedHeaderItemDecoration.Builder to configure the decoration.

    Key configuration options:

    • new PinnedHeaderItemDecoration.Builder(headerType): Constructor requires the header type constant.
    • .setDividerId(resId): Sets the drawable resource for the separator line.
    • .enableDivider(true): Enables drawing the separator line (disabled by default).
    • .setClickIds(resId): Specifies which child view IDs within the header should trigger click events.
    • .disableHeaderClick(boolean): Enables or disables the header click event (defaults to false, meaning enabled).
    • .setHeaderClickListener(OnHeaderClickAdapter): Sets the listener for header click events.

    Note: The top layer of the header cannot have a marginTop set in its layout.

    ```java
          OnHeaderClickAdapter clickAdapter = new OnHeaderClickAdapter() {
    
              @Override
              public void onHeaderClick(View view, int id, int position) {
                  switch (id) {
                      case R.id.fl:
                           // case OnItemTouchListener.HEADER_ID:
                           Toast.makeText(StockActivity.this, "click, tag: " + mAdapter.getData().get(position).pinnedHeaderName, Toast.LENGTH_SHORT).show();
                           break;
                       case R.id.iv_more:
                           Toast.makeText(StockActivity.this, "click " + mAdapter.getData().get(position).pinnedHeaderName + "'s more button", Toast.LENGTH_SHORT)
                                 .show();
                           break;
                       case R.id.checkbox:
                           final CheckBox checkBox = (CheckBox) view;
                           checkBox.setChecked(!checkBox.isChecked());
                           // invalidate ItemDecorations to draw the header
                           mRecyclerView.invalidateItemDecorations();
    
                           mAdapter.getData().get(position).check = checkBox.isChecked();
                           mAdapter.notifyItemChanged(position + mHeaderItemDecoration.getDataPositionOffset());
    
                           break;
                   }
               }
    
           };
    
        mRecyclerView.addItemDecoration(
                 // Set the type of pinned header
                 new PinnedHeaderItemDecoration.Builder(StockEntity.StockInfo.TYPE_HEADER)
                 // Set separator line resources id.
                 .setDividerId(R.drawable.divider)
                 // Enable draw the separator line, by default it's disable.
                 .enableDivider(true)
                 // Set click event for the header and its internal child view.
                 .setClickIds(R.id.iv_more)
                 // Disable header click event, by default it's enable.
                 .disableHeaderClick(false)
                 // Set the listener. If the listener is not null but disable the header click event(eg. disableHeaderClick(true)), then the callback don't return.
                 .setHeaderClickListener(clickAdapter)
                 .create());
        ```
  6. Implement Small Pinned Headers using SmallPinnedHeaderItemDecoration.Builder

    master

    Small pinned headers are implemented by overlaying a small header view onto an existing item layout. To use this, your item layout (Layout B) should contain an additional view (e.g., an ImageView) that serves as the small header.

    Implementation Steps:

    1. Design your item layout to include the small header view (e.g., R.id.iv_small_pinned_header).
    2. Use SmallPinnedHeaderItemDecoration.Builder to register the header view ID and the header item type.
    3. Important: The small header view must not have a marginTop.

    Key Builder Methods:

    • SmallPinnedHeaderItemDecoration.Builder(int headerViewId, int headerType): Constructor specifying the ID of the small header view within the item and the item type.
    • .enableDivider(boolean): Enables/disables dividers.
    • .setDividerId(int resId): Sets the divider drawable.
    • .setClickIds(int... ids): Specifies which sub-view IDs respond to clicks.
    • .disableHeaderClick(boolean): Disables header click events.
    • .setHeaderClickListener(OnHeaderClickAdapter listener): Sets the click listener.
    • .create(): Finalizes the builder.
    mRecyclerView.addItemDecoration(
        new SmallPinnedHeaderItemDecoration.Builder(R.id.iv_small_pinned_header, BaseHeaderAdapter.TYPE_HEADER)
        .enableDivider(true)
        .setDividerId(R.drawable.divider)
        .setClickIds(R.id.iv_small_pinned_header)
        .disableHeaderClick(true)
        .setHeaderClickListener(clickAdapter)
        .create());
  7. Implement Small Pinned Section Headers

    master

    Small pinned headers are used when the header is a child view embedded within a regular item layout (e.g., a small overlay).

    To implement this:

    1. Design your item layout (Layout B) to include the view that will act as the header (e.g., an ImageView with ID R.id.iv_small_pinned_header).
    2. Use SmallPinnedHeaderItemDecoration.Builder to configure the decoration.

    Key configuration options:

    • new SmallPinnedHeaderItemDecoration.Builder(headerViewId, headerType): Constructor requires the ID of the view within the item that acts as the header and the header type constant.
    • .enableDivider(true): Enables the separator line.
    • .setDividerId(resId): Sets the divider drawable.
    • .setClickIds(resId): Specifies the ID of the view within the item that should trigger click events.
    • .disableHeaderClick(boolean): Enables or disables the header click event.
    • .setHeaderClickListener(OnHeaderClickAdapter): Sets the listener for header click events.

    Note: Like large headers, the top layer of the header cannot have marginTop set in its layout.

    ```java
         OnHeaderClickAdapter headerClickAdapter = new OnHeaderClickAdapter() {
    
              @Override
              public void onHeaderClick(View view, int id, int position) {
                  if (id == R.id.iv_small_pinned_header) {
                      Toast.makeText(SecondActivity.this, "click tag: " + mAdapter.getData().get(position).getPinnedHeaderName(), Toast.LENGTH_SHORT).show();
                  }
              }
         };
         mRecyclerView.addItemDecoration(
                 // Constructor need to set the id and type of the header 
                 new SmallPinnedHeaderItemDecoration.Builder(R.id.tv_small_pinned_header,BaseHeaderAdapter.TYPE_HEADER)
                 // Enable draw the separator line, by default it's disable.
                 .enableDivider(true)
                 // Set separator line resources id.
                 .setDividerId(R.drawable.divider)
                 // Set click event for the header and its internal child view.
                 .setClickIds(R.id.tv_small_pinned_header)
                 // Disable header click event, by default it's enable.
                 .disableHeaderClick(false)
                 // Set the listener. If the listener is not null but disable the header click event(eg. disableHeaderClick(true)), then the callback don't return.
                 .setHeaderClickListener(clickAdapter)
                 .create());
        ```
  8. Implement Big Pinned Headers using PinnedHeaderItemDecoration.Builder

    master

    Big pinned headers (headers that act as distinct sections) are implemented using PinnedHeaderItemDecoration.Builder. This requires a builder pattern to configure parameters like the header type, divider settings, and click listeners.

    Important: The outermost layout containing the header must not have a marginTop, otherwise, the header may not properly cover the content when scrolling up.

    Key Builder Methods:

    • PinnedHeaderItemDecoration.Builder(int headerType): Constructor specifying the item type that represents a header.
    • .setDividerId(int resId): Sets the drawable resource for the divider.
    • .enableDivider(boolean): Enables or disables divider drawing (default is false).
    • .setClickIds(int... ids): Specifies the IDs of the header or its sub-views that should trigger click events.
    • .disableHeaderClick(boolean): Disables click events for the header (default is false).
    • .setHeaderClickListener(OnHeaderClickAdapter listener): Sets the listener for click, double-click, and long-press events.
    • .create(): Finalizes the builder.
    mRecyclerView.addItemDecoration(
        new PinnedHeaderItemDecoration.Builder(StockEntity.StockInfo.TYPE_HEADER)
        .setDividerId(R.drawable.divider)
        .enableDivider(true)
        .setClickIds(R.id.iv_more)
        .disableHeaderClick(false)
        .setHeaderClickListener(clickAdapter)
        .create());