引言
??不知道大家有沒有仔細觀察過支付寶的賬單頁面吴趴,月份為組頭漆诽,賬單為組的內(nèi)容。賬單按月份進行分組锣枝,當連續(xù)往下滑動RecyclerView厢拭,當月月份仍顯示,下滑至前一月賬單時撇叁,由前一月的組頭頂替當前月組頭供鸠,如此循環(huán)往復(fù)。
??這一功能陨闹,又成為“吸頂”效果楞捂,原因無它,皆因內(nèi)容變化趋厉,導致組頭交替覆蓋寨闹,但最頂上的組頭位置不會發(fā)生任何改變,故稱吸頂君账。
效果預(yù)覽
用法
步驟一繁堡、添加第三方依賴庫
依賴:app下的build.gradle文件中添加:
implementation 'com.github.donkingliang:GroupedRecyclerViewAdapter:2.3.0'
步驟二、創(chuàng)建實體類
實體類1:GroupEntity
/**
* 組數(shù)據(jù)的實體類
*/
public class GroupEntity {
private String header;
private String footer;
private ArrayList<ChildEntity> children;
public GroupEntity(String header, String footer, ArrayList<ChildEntity> children) {
this.header = header;
this.footer = footer;
this.children = children;
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public String getFooter() {
return footer;
}
public void setFooter(String footer) {
this.footer = footer;
}
public ArrayList<ChildEntity> getChildren() {
return children;
}
public void setChildren(ArrayList<ChildEntity> children) {
this.children = children;
}
}
實體類2:ChildEntity
/**
* 子項數(shù)據(jù)的實體類
*/
public class ChildEntity {
private String child;
public ChildEntity(String child) {
this.child = child;
}
public String getChild() {
return child;
}
public void setChild(String child) {
this.child = child;
}
}
實體類3:GroupModel
/**
* @data on 12/1/20 4:11 PM
* @auther armStrong
* @describe 用來處理和獲辱境瘛:頭+體+尾數(shù)據(jù)
*/
public class GroupModel {
/**
* 獲取組列表數(shù)據(jù)
*
* @param groupCount 組數(shù)量
* @param childrenCount 每個組里的子項數(shù)量
* @return
*/
public static ArrayList<GroupEntity> getGroups(int groupCount, int childrenCount) {
ArrayList<GroupEntity> groups = new ArrayList<>();
for (int i = 0; i < groupCount; i++) {
ArrayList<ChildEntity> children = new ArrayList<>();
for (int j = 0; j < childrenCount; j++) {
children.add(new ChildEntity("第" + (i + 1) + "組第" + (j + 1) + "項"));
}
groups.add(new GroupEntity("第" + (i + 1) + "組頭部",
"第" + (i + 1) + "組尾部", children));
}
return groups;
}
}
步驟三帖蔓、布局文件
布局文件1:主布局R.layout.activity_case66
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".blog2.Case66"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/blue"
android:gravity="center"
android:text="RecyclerView吸頂效果"
android:textColor="@color/white"
android:textSize="20sp" />
<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>
</LinearLayout>
布局文件2:頭布局R.layout.adapter_header
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/red"
android:orientation="vertical">
<TextView
android:id="@+id/tv_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:textColor="@android:color/white"
android:textSize="20sp" />
</LinearLayout>
布局文件3:內(nèi)容布局R.layout.adapter_child
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:layout_marginBottom="1px"
android:orientation="vertical">
<TextView
android:id="@+id/tv_child"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:padding="8dp"
android:textSize="16sp" />
</LinearLayout>
布局文件4:尾布局R.layout.adapter_footer
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/green"
android:orientation="vertical">
<TextView
android:id="@+id/tv_footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:textColor="@android:color/white"
android:textSize="20sp" />
</LinearLayout>
步驟四矮瘟、為RecyclerView書寫Adapter
Adapter1:GroupedListAdapter
/**
* @data on 11/25/20 2:13 PM
* @auther armStrong
* @describe 這是普通的分組Adapter 每一個組都有頭部瞳脓、尾部和子項。
*/
public class GroupedListAdapter extends GroupedRecyclerViewAdapter {
protected ArrayList<GroupEntity> mGroups;
public GroupedListAdapter(Context context, ArrayList<GroupEntity> groups) {
super(context);
mGroups = groups;
}
@Override
public int getGroupCount() {
return mGroups == null ? 0 : mGroups.size();
}
@Override
public int getChildrenCount(int groupPosition) {
ArrayList<ChildEntity> children = mGroups.get(groupPosition).getChildren();
return children == null ? 0 : children.size();
}
public void clear(){
mGroups.clear();
notifyDataChanged();
}
public void setGroups(ArrayList<GroupEntity> groups){
mGroups = groups;
notifyDataChanged();
}
@Override
public boolean hasHeader(int groupPosition) {
return true;
}
@Override
public boolean hasFooter(int groupPosition) {
return true;
}
@Override
public int getHeaderLayout(int viewType) {
return R.layout.adapter_header;
}
@Override
public int getFooterLayout(int viewType) {
return R.layout.adapter_footer;
}
@Override
public int getChildLayout(int viewType) {
return R.layout.adapter_child;
}
@Override
public void onBindHeaderViewHolder(BaseViewHolder holder, int groupPosition) {
GroupEntity entity = mGroups.get(groupPosition);
holder.setText(R.id.tv_header, entity.getHeader());
}
@Override
public void onBindFooterViewHolder(BaseViewHolder holder, int groupPosition) {
GroupEntity entity = mGroups.get(groupPosition);
holder.setText(R.id.tv_footer, entity.getFooter());
}
@Override
public void onBindChildViewHolder(BaseViewHolder holder, int groupPosition, int childPosition) {
ChildEntity entity = mGroups.get(groupPosition).getChildren().get(childPosition);
holder.setText(R.id.tv_child, entity.getChild());
}
}
Adaprer2:NoFooterAdapter
/**
* @data on 12/1/20 4:38 PM
* @auther armStrong
* @describe 沒有尾部的Adapter(用來做吸頂效果)
*/
public class NoFooterAdapter extends GroupedListAdapter {
public NoFooterAdapter(Context context, ArrayList<GroupEntity> groups) {
super(context, groups);
}
/**
* 返回false表示沒有組尾
*
* @param groupPosition
* @return
*/
@Override
public boolean hasFooter(int groupPosition) {
return false;
}
/**
* 當hasFooter返回false時澈侠,這個方法不會被調(diào)用劫侧。
*
* @return
*/
@Override
public int getFooterLayout(int viewType) {
return 0;
}
/**
* 當hasFooter返回false時,這個方法不會被調(diào)用。
*
* @param holder
* @param groupPosition
*/
@Override
public void onBindFooterViewHolder(BaseViewHolder holder, int groupPosition) {
}
}
步驟五烧栋、在Activity中書寫業(yè)務(wù)邏輯
public class Case66 extends AppCompatActivity {
private RecyclerView recycler;
private StickyHeaderLayout stickyLayout;
private LinearLayoutManager layoutManager;
private NoFooterAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_case66);
initView();
initAdatper();
//設(shè)置是否吸頂写妥。
stickyLayout.setSticky(true);
}
private void initAdatper() {
layoutManager = new LinearLayoutManager(this);
recycler.setLayoutManager(layoutManager);
adapter = new NoFooterAdapter(this, GroupModel.getGroups(10, 5));
adapter.setOnHeaderClickListener(new GroupedRecyclerViewAdapter.OnHeaderClickListener() {
@Override
public void onHeaderClick(GroupedRecyclerViewAdapter adapter, BaseViewHolder holder,
int groupPosition) {
Toast.makeText(Case66.this, "組頭:groupPosition = " + groupPosition,
Toast.LENGTH_LONG).show();
Log.e("eee", adapter.toString() + " " + holder.toString());
}
});
adapter.setOnChildClickListener(new GroupedRecyclerViewAdapter.OnChildClickListener() {
@Override
public void onChildClick(GroupedRecyclerViewAdapter adapter, BaseViewHolder holder,
int groupPosition, int childPosition) {
Toast.makeText(Case66.this, "子項:groupPosition = " + groupPosition
+ ", childPosition = " + childPosition,
Toast.LENGTH_LONG).show();
}
});
recycler.setAdapter(adapter);
}
private void initView(){
recycler = (RecyclerView) findViewById(R.id.rv_list);
stickyLayout = (StickyHeaderLayout) findViewById(R.id.sticky_layout);
}
}