GroupedRecyclerViewAdapter
GroupedRecyclerViewAdapter可以很方便的实现RecyclerView的分组显示,并且每个组都可以包含组头、组尾和子项;可以方便实现多种Type类型的列表, 可以实现如QQ联系人的列表一样的列表展开收起功能,还可以实现头部悬浮吸顶功能等。
Top Related Projects
BRVAH:Powerful and flexible RecyclerAdapter
The bullet proof, fast and easy to use adapter library, which minimizes developing time to a fraction...
"Favor composition over inheritance" for RecyclerView Adapters
Flexible multiple types for Android RecyclerView.
Fast and versatile Adapter for RecyclerView which regroups several features into one library to considerably improve the user experience :-)
[UNMAINTAINED] Sticky Headers decorator for Android's RecyclerView
Quick Overview
GroupedRecyclerViewAdapter is an Android library that simplifies the creation of grouped lists in RecyclerView. It provides a flexible and efficient way to display hierarchical data structures, such as expandable lists or sectioned content, within a single RecyclerView.
Pros
- Easy implementation of grouped lists without nested RecyclerViews
- Supports various group types and layouts, including headers, footers, and child items
- Efficient performance through view recycling and minimal adapter calls
- Customizable group expansion and collapse functionality
Cons
- Limited documentation and examples available
- May require additional setup compared to standard RecyclerView adapters
- Potential learning curve for developers unfamiliar with grouped list concepts
- Might not be suitable for very complex nested structures
Code Examples
- Creating a basic grouped adapter:
public class MyGroupedAdapter extends GroupedRecyclerViewAdapter {
public MyGroupedAdapter(Context context) {
super(context);
}
@Override
public int getGroupCount() {
return 3; // Number of groups
}
@Override
public int getChildrenCount(int groupPosition) {
return 5; // Number of children in each group
}
// Implement other required methods...
}
- Binding data to a group header:
@Override
public void onBindHeaderViewHolder(BaseViewHolder holder, int groupPosition) {
TextView textView = holder.get(R.id.tv_header);
textView.setText("Group " + groupPosition);
}
- Handling child item clicks:
@Override
public void onBindChildViewHolder(BaseViewHolder holder, int groupPosition, int childPosition) {
TextView textView = holder.get(R.id.tv_child);
textView.setText("Child " + childPosition);
holder.itemView.setOnClickListener(v -> {
// Handle child item click
});
}
Getting Started
- Add the dependency to your app's
build.gradle
:
dependencies {
implementation 'com.github.donkingliang:GroupedRecyclerViewAdapter:2.4.0'
}
- Create a custom adapter extending
GroupedRecyclerViewAdapter
:
public class MyAdapter extends GroupedRecyclerViewAdapter {
// Implement required methods
}
- Set up the RecyclerView in your activity or fragment:
RecyclerView recyclerView = findViewById(R.id.recycler_view);
MyAdapter adapter = new MyAdapter(this);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
Competitor Comparisons
BRVAH:Powerful and flexible RecyclerAdapter
Pros of BaseRecyclerViewAdapterHelper
- More comprehensive feature set, including animations, drag & drop, and swipe actions
- Larger community and more frequent updates
- Extensive documentation and examples
Cons of BaseRecyclerViewAdapterHelper
- Steeper learning curve due to its extensive features
- Potentially higher memory footprint for simpler use cases
- May introduce unnecessary complexity for basic list implementations
Code Comparison
BaseRecyclerViewAdapterHelper:
class MyAdapter : BaseQuickAdapter<String, BaseViewHolder>(R.layout.item_layout) {
override fun convert(holder: BaseViewHolder, item: String) {
holder.setText(R.id.textView, item)
}
}
GroupedRecyclerViewAdapter:
class MyAdapter(context: Context) : GroupedRecyclerViewAdapter(context) {
override fun getGroupCount(): Int = // group count
override fun getChildrenCount(groupPosition: Int): Int = // children count
override fun onBindChildViewHolder(holder: RecyclerView.ViewHolder, groupPosition: Int, childPosition: Int) {
// Bind child view
}
}
BaseRecyclerViewAdapterHelper offers a more concise implementation for simple lists, while GroupedRecyclerViewAdapter provides a structured approach for grouped data. The former is more versatile but may require additional setup for grouped layouts, whereas the latter is specifically designed for hierarchical data presentation.
The bullet proof, fast and easy to use adapter library, which minimizes developing time to a fraction...
Pros of FastAdapter
- More comprehensive and feature-rich, offering a wide range of functionalities beyond just grouping
- Actively maintained with frequent updates and a larger community
- Supports multiple item types and complex layouts out of the box
Cons of FastAdapter
- Steeper learning curve due to its extensive feature set
- May be overkill for simpler projects that only require basic grouping functionality
- Larger library size, which could impact app size and performance
Code Comparison
GroupedRecyclerViewAdapter:
GroupedRecyclerViewAdapter adapter = new GroupedRecyclerViewAdapter(this, list);
adapter.setOnHeaderClickListener(new GroupedRecyclerViewAdapter.OnHeaderClickListener() {
@Override
public void onHeaderClick(GroupedRecyclerViewAdapter adapter, BaseViewHolder holder, int groupPosition) {
// Handle header click
}
});
FastAdapter:
val fastAdapter = FastAdapter.with(itemAdapter)
fastAdapter.onClickListener = { view, adapter, item, position ->
// Handle item click
false
}
recyclerView.adapter = fastAdapter
Both libraries provide solutions for working with RecyclerView, but FastAdapter offers a more comprehensive set of features at the cost of increased complexity. GroupedRecyclerViewAdapter focuses specifically on grouping functionality, making it simpler for projects with basic grouping needs.
"Favor composition over inheritance" for RecyclerView Adapters
Pros of AdapterDelegates
- Promotes better separation of concerns by delegating view type handling to separate classes
- Easier to maintain and scale for complex RecyclerViews with multiple view types
- Supports composition over inheritance, allowing for more flexible adapter structures
Cons of AdapterDelegates
- May require more initial setup and boilerplate code for simple use cases
- Learning curve for developers unfamiliar with the delegation pattern
- Potentially higher memory usage due to multiple delegate objects
Code Comparison
AdapterDelegates:
class CatAdapterDelegate : AdapterDelegate<List<DisplayableItem>>() {
override fun isForViewType(items: List<DisplayableItem>, position: Int): Boolean {
return items[position] is Cat
}
// ... onCreateViewHolder and onBindViewHolder methods
}
GroupedRecyclerViewAdapter:
public class MyAdapter extends GroupedRecyclerViewAdapter {
@Override
public int getGroupCount() {
return groups.size();
}
// ... other group and child methods
}
AdapterDelegates focuses on delegating view type handling to separate classes, promoting modularity and easier maintenance for complex RecyclerViews. GroupedRecyclerViewAdapter, on the other hand, specializes in creating grouped layouts within a RecyclerView, which can be beneficial for specific use cases but may be less flexible for general-purpose adapters with multiple view types.
Flexible multiple types for Android RecyclerView.
Pros of MultiType
- More flexible and extensible architecture for handling multiple view types
- Simpler API with less boilerplate code required
- Better support for composition and delegation patterns
Cons of MultiType
- Less built-in support for grouped or sectioned data
- May require more custom implementation for complex hierarchical structures
- Steeper learning curve for developers new to the concept of item delegates
Code Comparison
MultiType:
class TextItemViewBinder : ItemViewBinder<String, 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: String) {
holder.textView.text = item
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val textView: TextView = itemView.findViewById(R.id.text)
}
}
GroupedRecyclerViewAdapter:
class MyAdapter(context: Context) : GroupedRecyclerViewAdapter(context) {
override fun getGroupCount(): Int = // Return group count
override fun getChildrenCount(groupPosition: Int): Int = // Return children count for group
override fun onBindHeaderViewHolder(holder: RecyclerView.ViewHolder, groupPosition: Int) {
// Bind header view
}
override fun onBindChildViewHolder(holder: RecyclerView.ViewHolder, groupPosition: Int, childPosition: Int) {
// Bind child view
}
}
Fast and versatile Adapter for RecyclerView which regroups several features into one library to considerably improve the user experience :-)
Pros of FlexibleAdapter
- More feature-rich, offering advanced functionalities like expandable items, multi-level sections, and drag & drop
- Extensive documentation and examples, making it easier for developers to implement complex list structures
- Active community and regular updates, ensuring ongoing support and improvements
Cons of FlexibleAdapter
- Steeper learning curve due to its extensive feature set and more complex implementation
- Potentially higher memory footprint and performance overhead for simpler list structures
- May require more boilerplate code for basic use cases
Code Comparison
GroupedRecyclerViewAdapter:
GroupedRecyclerViewAdapter adapter = new GroupedRecyclerViewAdapter(this, list);
adapter.setOnHeaderClickListener(this);
adapter.setOnFooterClickListener(this);
adapter.setOnChildClickListener(this);
FlexibleAdapter:
FlexibleAdapter<IFlexible> adapter = new FlexibleAdapter<>(items);
adapter.addListener(this);
adapter.setDisplayHeadersAtStartUp(true);
adapter.setStickyHeaders(true);
Both adapters offer group/section functionality for RecyclerView, but FlexibleAdapter provides a more comprehensive solution with additional features. GroupedRecyclerViewAdapter is simpler and may be easier to implement for basic grouped lists. FlexibleAdapter is better suited for complex list structures and advanced requirements, albeit with a steeper learning curve.
[UNMAINTAINED] Sticky Headers decorator for Android's RecyclerView
Pros of sticky-headers-recyclerview
- Specialized focus on sticky headers, providing a smooth and efficient implementation
- Lightweight library with minimal dependencies
- Easy integration with existing RecyclerView implementations
Cons of sticky-headers-recyclerview
- Limited to sticky header functionality, lacking support for grouped data structures
- Less active maintenance and updates compared to GroupedRecyclerViewAdapter
- May require additional customization for complex grouping scenarios
Code Comparison
GroupedRecyclerViewAdapter:
GroupedRecyclerViewAdapter adapter = new GroupedRecyclerViewAdapter(this, list);
adapter.setOnHeaderClickListener(new GroupedRecyclerViewAdapter.OnHeaderClickListener() {
@Override
public void onHeaderClick(GroupedRecyclerViewAdapter adapter, BaseViewHolder holder, int groupPosition) {
// Handle header click
}
});
sticky-headers-recyclerview:
StickyRecyclerHeadersAdapter adapter = new 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
}
@Override
public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder, int position) {
// Bind header view holder
}
};
Both libraries offer solutions for handling grouped or sectioned data in RecyclerViews, but they differ in their approach and feature set. GroupedRecyclerViewAdapter provides a more comprehensive solution for grouped data structures, while sticky-headers-recyclerview focuses specifically on implementing sticky headers efficiently.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
GroupedRecyclerViewAdapter
GroupedRecyclerViewAdapterå¯ä»¥å¾æ¹ä¾¿çå®ç°RecyclerViewçåç»æ¾ç¤ºï¼å¹¶ä¸æ¯ä¸ªç»é½å¯ä»¥å å«ç»å¤´ãç»å°¾åå项ï¼å¯ä»¥æ¹ä¾¿å®ç°å¤ç§Typeç±»åçå表ï¼å¯ä»¥å®ç°å¦QQè系人çå表ä¸æ ·çå表å±å¼æ¶èµ·åè½ï¼è¿å¯ä»¥å®ç°å¤´é¨æ¬æµ®å¸é¡¶åè½çãä¸é¢å 让æ们çä¸ä¸å®æè½å¤å®ç°çä¸äºææï¼
ææå¾
è¿å¯ä»¥å¾å®¹æçå®æ¶å表çå±å¼æ¶èµ·ææï¼
è¿å¯ä»¥è½»æ¾å®ç°å¤´é¨æ¬æµ®å¸é¡¶çææï¼
以ä¸å±ç¤ºçåªæ¯GroupedRecyclerViewAdapterè½å®ç°çä¸äºå¸¸ç¨ææï¼å ¶å®ä½¿ç¨GroupedRecyclerViewAdapterè¿å¯ä»¥å¾å®¹æçå®ç°ä¸äºæ´å å¤æçå表ææãå¨æçGroupedRecyclerViewAdapter项ç®çDemoä¸ç»åºäºä¸é¢å ç§ææçå®ç°ä¾åï¼å¹¶ä¸æ详ç»ç注é说æï¼æå ´è¶£çåå¦å¯ä»¥å°æçGitHubä¸è½½æºç ãä¸é¢ç´æ¥è®²è§£GroupedRecyclerViewAdapterç使ç¨ã
å¼å ¥ä¾èµ
å¨Projectçbuild.gradleå¨æ·»å 以ä¸ä»£ç
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
å¨Moduleçbuild.gradleå¨æ·»å 以ä¸ä»£ç
implementation 'com.github.donkingliang:GroupedRecyclerViewAdapter:2.4.3'
åºæ¬ä½¿ç¨
1ã继æ¿GroupedRecyclerViewAdapter
public class GroupedListAdapter extends GroupedRecyclerViewAdapter {
}
2ãå®ç°GroupedRecyclerViewAdapteréçæ¹æ³
GroupedRecyclerViewAdapteræ¯ä¸ä¸ªæ½è±¡ç±»ï¼å®æä¾äºä¸ç³»åéè¦åç±»å»å®ç°çæ¹æ³ã
//è¿åç»çæ°é
public abstract int getGroupCount();
//è¿åå½åç»çå项æ°é
public abstract int getChildrenCount(int groupPosition);
//å½åç»æ¯å¦æ头é¨
public abstract boolean hasHeader(int groupPosition);
//å½åç»æ¯å¦æå°¾é¨
public abstract boolean hasFooter(int groupPosition);
//è¿å头é¨çå¸å±idã(å¦æhasHeaderè¿åfalseï¼è¿ä¸ªæ¹æ³ä¸ä¼æ§è¡)
public abstract int getHeaderLayout(int viewType);
//è¿åå°¾é¨çå¸å±idã(å¦æhasFooterè¿åfalseï¼è¿ä¸ªæ¹æ³ä¸ä¼æ§è¡)
public abstract int getFooterLayout(int viewType);
//è¿åå项çå¸å±idã
public abstract int getChildLayout(int viewType);
//ç»å®å¤´é¨å¸å±æ°æ®ã(å¦æhasHeaderè¿åfalseï¼è¿ä¸ªæ¹æ³ä¸ä¼æ§è¡)
public abstract void onBindHeaderViewHolder(BaseViewHolder holder, int groupPosition);
//ç»å®å°¾é¨å¸å±æ°æ®ã(å¦æhasFooterè¿åfalseï¼è¿ä¸ªæ¹æ³ä¸ä¼æ§è¡)
public abstract void onBindFooterViewHolder(BaseViewHolder holder, int groupPosition);
//ç»å®å项å¸å±æ°æ®ã
public abstract void onBindChildViewHolder(BaseViewHolder holder,
int groupPosition, int childPosition);
è¿å¯æ¯éåGroupedRecyclerViewAdapteræ¹æ³å®ç°å¤´ãå°¾åå项çå¤ç§ç±»åitemãææå°±åä¸é¢ç第6å¼ å¾ä¸æ ·ã
//è¿å头é¨çviewTypeã
public int getHeaderViewType(int groupPosition);
//è¿åå°¾é¨çviewTypeã
public int getFooterViewType(int groupPosition) ;
//è¿åå项çviewTypeã
public int getChildViewType(int groupPosition, int childPosition) ;
3ã设置ç¹å»äºä»¶ççå¬
GroupedRecyclerViewAdapteræä¾äºå¯¹å表çç¹å»äºä»¶ççå¬æ¹æ³ã
//设置ç»å¤´ç¹å»äºä»¶
public void setOnHeaderClickListener(OnHeaderClickListener listener) {
mOnHeaderClickListener = listener;
}
//设置ç»å°¾ç¹å»äºä»¶
public void setOnFooterClickListener(OnFooterClickListener listener) {
mOnFooterClickListener = listener;
}
// 设置å项ç¹å»äºä»¶
public void setOnChildClickListener(OnChildClickListener listener) {
mOnChildClickListener = listener;
}
4ã设置空å¸å±
GroupedRecyclerViewAdapteræä¾è®¾ç½®ç©ºå¸å±çåè½ï¼å¦æå表没ææ°æ®çæ åµä¸å¯ä»¥æ¾ç¤ºä¸ä¸ªç©ºå¸å±ã
// æ¾ç¤ºç©ºå¸å±ãé»è®¤ä¸æ¾ç¤º
adapter.showEmptyView(true);
æ¡æ¶æä¾çé»è®¤ç©ºå¸å±æ¯è¾ç®åï¼å¯ä»¥éè¿å¤ågetEmptyViewèªå®ä¹ç©ºå¸å±
@Override
public View getEmptyView(ViewGroup parent) {
// è¿åèªå®ä¹ç©ºå¸å±
View view = LayoutInflater.from(mContext).inflate(R.layout.adapter_empty_view, parent, false);
return view;
}
æ¡æ¶åªæä¾ç©ºå¸å±ç设置æ¹æ³ï¼ä¸ä¼ç®¡ç空å¸å±ãæ以å¦æä½ ç空å¸å±æç¹å»äºä»¶çå ¶ä»çä¸å¡é»è¾ï¼ä¹éè¦èªå·±å¨è¿ä¸ªæ¹æ³å®ç°ã
5ã使ç¨ItemDecoration
ä»2.4.0çæ¬å¼å§ï¼æ¯æ使ç¨ItemDecorationãä¹åä¸ç´æ²¡æ对GroupedRecyclerViewAdapteræä¾ItemDecorationçæ¯æï¼æ¯å 为对äºåç»çå表ï¼æ¯ä¸ªåç»çItemDecorationåç»å¤´ãç»å°¾çItemDecorationé½åºè¯¥æ¯å¯ä»¥åç¬è®¾ç½®æ ·å¼çãè¿å¯¹äºèªå®ä¹ItemDecorationçå®ç°æ¯è¾éº»ç¦ï¼èä¸é¾ä»¥å®ç°ç»ä¸ç设置åæ©å±æ¹å¼ãåæ¥æå®ç°äºä¸ä¸ªèªå®ä¹ItemDecorationçåºï¼VariedItemDecorationã使ç¨VariedItemDecorationå¯ä»¥å®ç°å¨ä¸ä¸ªå表éæ¾ç¤ºå¤ç§ä¸åæ ·å¼çItemDecorationï¼å¹¶ä¸å¯ä»¥é常ç®åçå®ç°èªå®ä¹ItemDecorationãåºäºVariedItemDecorationçå®ç°åºç¡ï¼æå®ç°äºå¤æ ·å¼ItemDecorationçåç»ç®¡çï¼ä½¿ItemDecorationå¯ä»¥ä½¿ç¨äºGroupedRecyclerViewAdapterå表ãæå¨åºéæä¾äºå¯ç´æ¥ä½¿ç¨çGroupedLinearItemDecoration/GroupedGridItemDecorationåç¨äºèªå®ä¹ItemDecorationçåºç±»AbsGroupedLinearItemDecoration/AbsGroupedGridItemDecorationã
ä¸é¢æ以线æ§å表为ä¾ï¼è¯´æItemDecoration使ç¨ã
// 空ç½åå²çº¿ï¼åªéè¦è®¾ç½®åå²çº¿å¤§å°ï¼ä¸éè¦è®¾ç½®æ ·å¼ï¼divider为空ååªæ·»å é´éï¼ä¸ç»å¶æ ·å¼
GroupedLinearItemDecoration itemDecoration = new GroupedLinearItemDecoration(adapter,20, null,20,null,20,null);
// æ®éåå²çº¿ï¼è®¾ç½®åå²çº¿å¤§å°å头ãå°¾ãå项çåå²çº¿æ ·å¼
GroupedLinearItemDecoration itemDecoration = new GroupedLinearItemDecoration(adapter,20, mHeaderDivider,20,mFooterDivider,20,mChildDivider);
// èªå®ä¹åå²çº¿ï¼å¯ä»¥æ ¹æ®éè¦è®¾ç½®æ¯ä¸ªitemçåå²çº¿å¤§å°åæ ·å¼
CustomLinearItemDecoration itemDecoration = new CustomLinearItemDecoration(this,adapter);
// æ·»å åå²çº¿
recyclerView.addItemDecoration(itemDecoration);
// èªå®ä¹åå²çº¿
public class CustomLinearItemDecoration extends AbsGroupedLinearItemDecoration {
private Drawable headerDivider;
private Drawable footerDivider;
private Drawable childDivider1;
private Drawable childDivider2;
public CustomLinearItemDecoration(Context context,GroupedRecyclerViewAdapter adapter) {
super(adapter);
headerDivider = context.getResources().getDrawable(R.drawable.green_divider);
footerDivider = context.getResources().getDrawable(R.drawable.purple_divider);
childDivider1 = context.getResources().getDrawable(R.drawable.pink_divider);
childDivider2 = context.getResources().getDrawable(R.drawable.orange_divider);
}
@Override
public int getChildDividerSize(int groupPosition, int ChildPosition) {
// æ ¹æ®positionè¿ååå²çº¿ç大å°
return 20;
}
@Override
public Drawable getChildDivider(int groupPosition, int ChildPosition) {
// æ ¹æ®positionè¿åDrawable å¯ä»¥ä¸ºnull
if(groupPosition % 2 == 0){
return childDivider1;
} else {
return childDivider2;
}
}
@Override
public int getHeaderDividerSize(int groupPosition) {
// æ ¹æ®positionè¿ååå²çº¿ç大å°
return 30;
}
@Override
public Drawable getHeaderDivider(int groupPosition) {
// æ ¹æ®positionè¿åDrawable å¯ä»¥ä¸ºnull
return headerDivider;
}
@Override
public int getFooterDividerSize(int groupPosition) {
// æ ¹æ®positionè¿ååå²çº¿ç大å°
return 30;
}
@Override
public Drawable getFooterDivider(int groupPosition) {
// æ ¹æ®positionè¿åDrawable å¯ä»¥ä¸ºnull
return footerDivider;
}
}
对äºç½æ ¼å表çItemDecorationï¼ä½¿ç¨ä¹æ¯ä¸æ ·çï¼å¤§å®¶å¯ä»¥çædemoä¸çä¾åã
å¦æä½ æ³å¨æ®éçRecyclerViewä¸ä½¿ç¨è¿ç§å¤æ ·å¼çItemDecorationï¼è¯·ä½¿ç¨VariedItemDecorationã
注æäºé¡¹
1ã对æ¹æ³éåç注æã
å¦ææ们ç´æ¥ç»§æ¿RecyclerView.Adapterå»å®ç°èªå·±çAdapteræ¶ï¼ä¸è¬ä¼éåAdapterä¸ç以ä¸å 个æ¹æ³ï¼
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType);
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position);
public int getItemCount();
public int getItemViewType(int position);
ä½å¦ææ¯ä½¿ç¨GroupedRecyclerViewAdapterï¼å°±ä¸å®ä¸è½å»éåè¿å 个æ¹æ³ï¼å 为å¨GroupedRecyclerViewAdapterä¸å·²ç»å¯¹è¿å 个æ¹æ³åäºå®ç°ï¼èä¸æ¯å¯¹å®ç°å表åç»è³å ³éè¦çï¼å¦æåç±»éåäºè¿å 个æ¹æ³ï¼å¯è½ä¼ç ´åGroupedRecyclerViewAdapterçåè½ã ä»åé¢ç»åºçGroupedRecyclerViewAdapterçæ¹æ³æ们å¯ä»¥çå°ï¼è¿äºæ¹æ³å ¶å®å°±æ¯å¯¹åºRecyclerView.Adapterçè¿4个æ¹æ³çï¼æ以æ们ç´æ¥ä½¿ç¨GroupedRecyclerViewAdapteræä¾çæ¹æ³å³å¯ã RecyclerView.Adapterä¸ç
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType);
对åºGroupedRecyclerViewAdapterä¸ç
//è¿å头é¨çå¸å±idã(å¦æhasHeaderè¿åfalseï¼è¿ä¸ªæ¹æ³ä¸ä¼æ§è¡)
public abstract int getHeaderLayout(int viewType);
//è¿åå°¾é¨çå¸å±idã(å¦æhasFooterè¿åfalseï¼è¿ä¸ªæ¹æ³ä¸ä¼æ§è¡)
public abstract int getFooterLayout(int viewType);
//è¿åå项çå¸å±idã
public abstract int getChildLayout(int viewType);
è¿éä¹æ以è¿åçæ¯å¸å±idèä¸æ¯ViewHolder ï¼æ¯å 为å¨GroupedRecyclerViewAdapter项ç®ä¸å·²ç»æä¾äºä¸ä¸ªéç¨çViewHolderï¼BaseViewHolderãæ以使ç¨è åªéè¦æä¾å¸å±çidå³å¯ï¼ä¸éè¦èªå·±å»å®ç°ViewHolderã
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(getLayoutId(mTempPosition, viewType), parent, false);
return new BaseViewHolder(view);
}
private int getLayoutId(int position, int viewType) {
int type = judgeType(position);
if (type == TYPE_HEADER) {
return getHeaderLayout(viewType);
} else if (type == TYPE_FOOTER) {
return getFooterLayout(viewType);
} else if (type == TYPE_CHILD) {
return getChildLayout(viewType);
}
return 0;
}
RecyclerView.Adapterä¸ç
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position);
对åºGroupedRecyclerViewAdapterä¸ç
//ç»å®å¤´é¨å¸å±æ°æ®ã(å¦æhasHeaderè¿åfalseï¼è¿ä¸ªæ¹æ³ä¸ä¼æ§è¡)
public abstract void onBindHeaderViewHolder(BaseViewHolder holder, int groupPosition);
//ç»å®å°¾é¨å¸å±æ°æ®ã(å¦æhasFooterè¿åfalseï¼è¿ä¸ªæ¹æ³ä¸ä¼æ§è¡)
public abstract void onBindFooterViewHolder(BaseViewHolder holder, int groupPosition);
//ç»å®å项å¸å±æ°æ®ã
public abstract void onBindChildViewHolder(BaseViewHolder holder,
int groupPosition, int childPosition);
RecyclerView.Adapterä¸ç
public int getItemCount();
对åºGroupedRecyclerViewAdapterä¸ç
//è¿åç»çæ°é
public abstract int getGroupCount();
//è¿åå½åç»çå项æ°é
public abstract int getChildrenCount(int groupPosition);
RecyclerView.Adapterä¸ç
public int getItemViewType(int position);
对åºGroupedRecyclerViewAdapterä¸ç
//è¿å头é¨çviewTypeã
public int getHeaderViewType(int groupPosition);
//è¿åå°¾é¨çviewTypeã
public int getFooterViewType(int groupPosition) ;
//è¿åå项çviewTypeã
public int getChildViewType(int groupPosition, int childPosition) ;
2ã对å表æä½ç注æ
RecyclerView.Adapteræä¾äºä¸ç³»å对å表è¿è¡æä½çæ¹æ³ãå¦ï¼
//æ´æ°æä½
public final void notifyDataSetChanged();
public final void notifyItemChanged(int position);
public final void notifyItemChanged(int position, Object payload);
public final void notifyItemRangeChanged(int positionStart, int itemCount);
public final void notifyItemRangeChanged(int positionStart, int itemCount, Object payload);
//æå
¥æä½
public final void notifyItemInserted(int position);
public final void notifyItemRangeInserted(int positionStart, int itemCount);
//å é¤æä½
public final void notifyItemRemoved(int position)
public final void notifyItemRangeRemoved(int positionStart, int itemCount);
å¨GroupedRecyclerViewAdapterä¸å»ºè®®ä½¿ç¨RecyclerView.Adapterçä»»ä½å¯¹å表çæä½æ¹æ³ï¼å 为è¿äºæ¹æ³é½æ¯åºäºå表çæä½ï¼å®çpositionæ¯ç¸å¯¹äºæ´ä¸ªå表èè¨çï¼èGroupedRecyclerViewAdapteræ¯åç»çå表ï¼å®å¯¹å表çæä½åºè¯¥æ¯åºäºç»çãåæ¶GroupedRecyclerViewAdapter使ç¨äºç»ç»ææ¥ç»´æ¤æ´ä¸ªå表çç»æï¼ä½¿æ们å¯ä»¥å¯¹å表è¿è¡ç»çæä½ï¼å¨å表åçååæ¶GroupedRecyclerViewAdapteréè¦åæ¶å¯¹ç»ç»æè¿è¡è°æ´ï¼å¦æ使ç¨äºRecyclerView.Adapterä¸çæ¹æ³å¯¹å表è¿è¡æ´æ°ï¼GroupedRecyclerViewAdapterå¯è½å 为æ æ³åæ¶è°æ´ç»ç»æèåçå¼å¸¸ãæ以å¨ä½¿ç¨ä¸åºè¯¥é¿å 使ç¨è¿äºæ¹æ³ãGroupedRecyclerViewAdapteråæ ·æä¾äºä¸ç³»å对å表è¿è¡æä½çæ¹æ³ï¼æ们åºè¯¥ä½¿ç¨GroupedRecyclerViewAdapterææä¾çæ¹æ³ã
//****** å·æ°æä½ *****//
//éç¥æ°æ®å表å·æ°ãå¯¹åº notifyDataSetChanged();
public void notifyDataChanged();
//éç¥ä¸ç»æ°æ®å·æ°ï¼å
æ¬ç»å¤´,ç»å°¾åå项
public void notifyGroupChanged(int groupPosition);
//éç¥å¤ç»æ°æ®å·æ°ï¼å
æ¬ç»å¤´,ç»å°¾åå项
public void notifyGroupRangeChanged(int groupPosition, int count);
// éç¥ç»å¤´å·æ°
public void notifyHeaderChanged(int groupPosition);
// éç¥ç»å°¾å·æ°
public void notifyFooterChanged(int groupPosition);
// éç¥ä¸ç»éçæ个å项å·æ°
public void notifyChildChanged(int groupPosition, int childPosition);
// éç¥ä¸ç»éçå¤ä¸ªå项å·æ°
public void notifyChildRangeChanged(int groupPosition, int childPosition, int count);
// éç¥ä¸ç»éçææå项å·æ°
public void notifyChildrenChanged(int groupPosition);
//****** å é¤æä½ *****//
// éç¥æææ°æ®å é¤
public void notifyDataRemoved();
// éç¥ä¸ç»æ°æ®å é¤ï¼å
æ¬ç»å¤´,ç»å°¾åå项
public void notifyGroupRemoved(int groupPosition);
// éç¥å¤ç»æ°æ®å é¤ï¼å
æ¬ç»å¤´,ç»å°¾åå项
public void notifyGroupRangeRemoved(int groupPosition, int count);
// éç¥ç»å¤´å é¤
public void notifyHeaderRemoved(int groupPosition);
// éç¥ç»å°¾å é¤
public void notifyFooterRemoved(int groupPosition);
// éç¥ä¸ç»éçæ个å项å é¤
public void notifyChildRemoved(int groupPosition, int childPosition);
// éç¥ä¸ç»éçå¤ä¸ªå项å é¤
public void notifyChildRangeRemoved(int groupPosition, int childPosition, int count);
// éç¥ä¸ç»éçææå项å é¤
public void notifyChildrenRemoved(int groupPosition);
//****** æå
¥æä½ *****//
// éç¥ä¸ç»æ°æ®æå
¥
public void notifyGroupInserted(int groupPosition);
// éç¥å¤ç»æ°æ®æå
¥
public void notifyGroupRangeInserted(int groupPosition, int count);
// éç¥ç»å¤´æå
¥
public void notifyHeaderInserted(int groupPosition);
// éç¥ç»å°¾æå
¥
public void notifyFooterInserted(int groupPosition);
// éç¥ä¸ä¸ªå项å°ç»éæå
¥
public void notifyChildInserted(int groupPosition, int childPosition);
// éç¥ä¸ç»éçå¤ä¸ªå项æå
¥
public void notifyChildRangeInserted(int groupPosition, int childPosition, int count);
// éç¥ä¸ç»éçææå项æå
¥
public void notifyChildrenInserted(int groupPosition);
注æï¼ GroupedRecyclerViewAdapterä¸ç®¡çå表æ°æ®æºï¼å¨è°ç¨notifyxxxRemovedæè notifyxxxInsertedçæ¹æ³å·æ°å表åï¼è¯·ç¸åºçå·æ°æ°æ®æºãä¹å°±æ¯è¯´ï¼å¯¹æ°æ®çæä½åºè¯¥åå¨å¯¹å表çå·æ°åã
3ã使ç¨GridLayoutManagerç注æ
å¦æè¦ä½¿ç¨GridLayoutManagerï¼ä¸å®è¦ä½¿ç¨é¡¹ç®ä¸ææä¾çGroupedGridLayoutManagerãå 为åç»å表å¦æè¦ä½¿ç¨GridLayoutManagerå®ç°ç½æ ¼å¸å±ï¼å°±è¦ä¿è¯ç»ç头é¨åå°¾é¨æ¯è¦åç¬å ç¨ä¸è¡çãå¦åç»ç头ãå°¾å¯è½ä¼è·å项混çä¸èµ·ï¼é æå¸å±æ··ä¹±ãåæ¶GroupedGridLayoutManageræä¾äºå¯¹å项çSpanSizeçä¿®æ¹æ¹æ³ï¼ä½¿ç¨GroupedGridLayoutManagerå¯ä»¥å®ç°æ´å¤çå¤æå表å¸å±ã
//ç´æ¥ä½¿ç¨GroupedGridLayoutManagerå®ç°å项çGridææ
GroupedGridLayoutManager gridLayoutManager = new GroupedGridLayoutManager(this, 2, adapter);
rvList.setLayoutManager(gridLayoutManager);
GroupedGridLayoutManager gridLayoutManager = new GroupedGridLayoutManager(this, 4, adapter){
//éåè¿ä¸ªæ¹æ³ æ¹åå项çSpanSizeã
//è¿ä¸ªè·éåSpanSizeLookupçgetSpanSizeæ¹æ³ç使ç¨æ¯ä¸æ ·çã
@Override
public int getChildSpanSize(int groupPosition, int childPosition) {
if(groupPosition % 2 == 1){
return 2;
}
return super.getChildSpanSize(groupPosition, childPosition);
}
};
rvList.setLayoutManager(gridLayoutManager);
4ãBaseViewHolderç使ç¨
项ç®ä¸æä¾äºä¸ä¸ªéç¨çViewHolderï¼BaseViewHolderãæä¾äºæ ¹æ®viewIdè·åViewçæ¹æ³å对ViewãTextViewãImageViewç常ç¨è®¾ç½®æ¹æ³ã
//æ ¹æ®idè·åView
TextView textView = holder.get(R.id.tv_header);
//ViewãTextViewãImageViewç常ç¨è®¾ç½®æ¹æ³ã并ä¸æ¯ææ¹æ³è¿ç¼è°ç¨
holder.setText(R.id.tv_header, "å
容")
.setImageResource(R.id.iv_image, èµæºid)
.setBackgroundRes(R.id.view,èµæºid);
BaseViewHolderæ¯å¯ä»¥éç¨çï¼å¨æ®éçAdapterä¸ä¹å¯ä»¥ä½¿ç¨ï¼å¯ä»¥çå»æ¯æ¬¡é½è¦å建ViewHolderç麻ç¦ã
5ã头é¨æ¬æµ®å¸é¡¶åè½
åºä¸äºæåçåé¦ï¼æå¨1.2.0çæ¬ä¸æ°å äºå表ç头é¨æ¬æµ®å¸é¡¶åè½ã使ç¨èµ·æ¥é常çç®åï¼åªéè¦ç¨æ¡æ¶éæä¾çStickyHeaderLayoutå 裹ä¸ä¸ä½ çRecyclerViewå°±å¯ä»¥äºãå½ç¶ï¼ä½ éè¦ä½¿ç¨GroupedRecyclerViewAdapteræè½çå°ææã
<!-- ç¨StickyHeaderLayoutå
裹RecyclerView -->
<com.donkingliang.groupedadapter.widget.StickyHeaderLayout
android:id="@+id/sticky_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.donkingliang.groupedadapter.widget.StickyHeaderLayout>
StickyHeaderLayoutæä¾äºä¸ä¸ªè®¾ç½®æ¯å¦æ¾ç¤ºæ¬æµ®å¸é¡¶çæ¹æ³ã
//æ¯å¦å¸é¡¶ï¼é»è®¤ä¸ºtrueã
stickyLayout.setSticky(true);
6ã使ç¨DataBinding
GroupedRecyclerViewAdapterå¨1.3.0çæ¬å å ¥äºå¯¹DataBindingçæ¯æãè¦æ³å¨Adapterä¸ä½¿ç¨DataBindingï¼åªéè¦å¨GroupedRecyclerViewAdapterçæé å½æ°çuseBindingåæ°ä¼ trueå³å¯ã
public class BindingAdapter extends GroupedRecyclerViewAdapter {
public BindingAdapter(Context context) {
//åªè¦å¨è¿éä¼ trueï¼Adapterå°±ä¼ç¨DataBindingçæ¹å¼å è½½å表çitemå¸å±ãé»è®¤ä¸ºfalseã
super(context, true);
}
}
ç¶ååè¿BaseViewHolderçgetBinding()å°±å¯ä»¥è·åå°item对åºçViewDataBinding对象ã
@Override
public void onBindHeaderViewHolder(BaseViewHolder holder, int groupPosition) {
//è·åViewDataBinding对象ã
AdapterBindingHeaderBinding binding = holder.getBinding();
}
@Override
public void onBindFooterViewHolder(BaseViewHolder holder, int groupPosition) {
//è·åViewDataBinding对象ã
AdapterBindingFooterBinding binding = holder.getBinding();
}
@Override
public void onBindChildViewHolder(BaseViewHolder holder, int groupPosition, int childPosition) {
//è·åViewDataBinding对象ã
AdapterBindingChildBinding binding = holder.getBinding();
}
Top Related Projects
BRVAH:Powerful and flexible RecyclerAdapter
The bullet proof, fast and easy to use adapter library, which minimizes developing time to a fraction...
"Favor composition over inheritance" for RecyclerView Adapters
Flexible multiple types for Android RecyclerView.
Fast and versatile Adapter for RecyclerView which regroups several features into one library to considerably improve the user experience :-)
[UNMAINTAINED] Sticky Headers decorator for Android's RecyclerView
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot