在RecyclerView进阶(一)之分割线、添加Header和Footer展示过一个类似微信通讯录的粘性头部效果。
这篇文章就来实现一下这个效果。
像上面这种分组栏,它是通过ItemDecoration实现的;也就是说继承ItemDecoration并重写它的方法绘制出来的,注意一下:分组栏本身不是itemView,它本质上是在itemView撑开的区域上画出来的图案。
普通的分组栏
我们首先复习一下RecyclerView的背景,ondraw()
绘制的内容,itemView
,onDrawOver()
绘制的内容的层级关系,这样对后面分组栏的绘制有一个较好的理解;它们刚好是按顺序从最底层到最顶层。观察这个粘性头部的效果,发现给itemView分组后,始终有一个分组栏在最顶部,而且不能被itemView遮盖。说明它是onDrawOver()
方法绘制出来。而且要使每组第一个itemView上有一个分组栏,就要判断出每组第一个itemView,然后将它的顶部撑开一定的区域来绘制分组栏。所以这种效果的思路就出来:判断每组的第一个itemView,然后将它的顶部撑开一定的区域来绘制分组栏
既然要进行分组,那么我们首先定义一个组的类,这里就以省份来分组。
public class Province {
private int provinceId;
private String provinceName;
//recyclerView中每个itemview的位置,也就是城市的位置序号
private int cityPosition;
private Bitmap provinceBitmap;
private String provinceBackground;
public Province(int provinceId, String provinceName) {
this.provinceId = provinceId;
this.provinceName = provinceName;
}
public Bitmap getProvinceBitmap() {
return provinceBitmap;
}
public void setProvinceBitmap(Bitmap provinceBitmap) {
this.provinceBitmap = provinceBitmap;
}
public String getProvinceBackground() {
return provinceBackground;
}
public void setProvinceBackground(String provinceBackground) {
this.provinceBackground = provinceBackground;
}
public boolean isFirstCityInProvince(){
if(cityPosition == 0){
return true;
}
return false;
}
public int getProvinceId() {
return provinceId;
}
public void setProvinceId(int provinceId) {
this.provinceId = provinceId;
}
public String getProvinceName() {
return provinceName;
}
public void setProvinceName(String provinceName) {
this.provinceName = provinceName;
}
public int getCityPosition() {
return cityPosition;
}
public void setCityPosition(int position) {
this.cityPosition = position;
}
}
我们定义了省份的id和名字,还有城市的位置序号,城市就是在itemView中展示的内容。其中有一个重要方法,
public boolean isFirstCityInProvince(){
if(cityPosition == 0){
return true;
}
return false;
}
来判断当前itemView是不是该分组的第一项。有了分组的类,我们新建一个接口,里面提供一个方法来返回Province类的对象。
public interface OnProvinceListener{
public Province getProvince(int position);
}
通过接口返回的Province对象,我们就可以知道分组的信息,方便我们绘制分组栏使用。
接下来我们开始继承ItemDecoration类重写它的方法,前面说过,分组栏要在最顶层,不能被itemView遮挡,所以在onDrawOver()
方法中进行分组栏的绘制。
public class