RecyclerView 分組 和吸頂效果
主要利用ItemDecoration 中的三個(gè)方法,不了解的可以參考;
分組
分組效果

image
思路
- 數(shù)據(jù)部分可以通過內(nèi)容或者標(biāo)志位來區(qū)分是不是第一個(gè),例子中通過標(biāo)志位區(qū)分
- ItemDecoration 定義一個(gè)接口來實(shí)現(xiàn)數(shù)據(jù)傳遞
- ItemDecoration 中g(shù)etItemOffsets方法給山西省 、河南省這部分留出空間
- ItemDecoration 中onDrawOver 方法繪制矩形和文字
其他方式實(shí)現(xiàn)參考--RecyclerView 分組實(shí)現(xiàn)(一)
實(shí)現(xiàn)
Activity中
- initData() 初始化數(shù)據(jù),給標(biāo)志位來區(qū)分?jǐn)?shù)據(jù)
- 調(diào)用SectionItemDecoration中定義的接口實(shí)現(xiàn)數(shù)據(jù)傳遞
package com.example.tuionf.recyclerviewlearn;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class SectionActivity extends AppCompatActivity {
private RecyclerView sectionRv;
private List<SectionBean> mList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_section);
initData();
sectionRv = (RecyclerView) findViewById(R.id.section_rv);
sectionRv.setLayoutManager(new LinearLayoutManager(this));
SectionAdapter sectionAdapter = new SectionAdapter(this,mList);
sectionRv.addItemDecoration(new SectionItemDecoration(this, new SectionItemDecoration.DecorationCallback() {
@Override
public boolean isGroupFirst(int position) {
return mList.get(position).isFirst();
}
@Override
public String getGroupFirstLine(int position) {
return mList.get(position).getTag();
}
}));
sectionRv.setAdapter(sectionAdapter);
}
private void initData() {
for (int i = 0; i < 10; i++) {
SectionBean sectionBean = new SectionBean();
sectionBean.setText("--" + i);
sectionBean.setTag("山西省");
if (i == 0){
sectionBean.setFirst(true);
}else {
sectionBean.setFirst(false);
}
mList.add(sectionBean);
}
for (int i = 0; i < 20; i++) {
SectionBean sectionBean = new SectionBean();
sectionBean.setText("--" + i);
sectionBean.setTag("遼寧省");
if (i == 0){
sectionBean.setFirst(true);
}else {
sectionBean.setFirst(false);
}
mList.add(sectionBean);
}
for (int i = 0; i < 25; i++) {
SectionBean sectionBean = new SectionBean();
sectionBean.setText("--" + i);
sectionBean.setTag("河南省");
if (i == 0){
sectionBean.setFirst(true);
}else {
sectionBean.setFirst(false);
}
mList.add(sectionBean);
}
for (int i = 0; i < 29; i++) {
SectionBean sectionBean = new SectionBean();
sectionBean.setText("--" + i);
sectionBean.setTag("廣東省");
if (i == 0){
sectionBean.setFirst(true);
}else {
sectionBean.setFirst(false);
}
mList.add(sectionBean);
}
for (int i = 0; i < 20; i++) {
SectionBean sectionBean = new SectionBean();
sectionBean.setText("--" + i);
sectionBean.setTag("北京市");
if (i == 0){
sectionBean.setFirst(true);
}else {
sectionBean.setFirst(false);
}
mList.add(sectionBean);
}
for (int i = 0; i < 20; i++) {
SectionBean sectionBean = new SectionBean();
sectionBean.setText("--" + i);
sectionBean.setTag("天津市");
if (i == 0){
sectionBean.setFirst(true);
}else {
sectionBean.setFirst(false);
}
mList.add(sectionBean);
}
for (int i = 0; i < 20; i++) {
SectionBean sectionBean = new SectionBean();
sectionBean.setText("--" + i);
sectionBean.setTag("重慶市");
if (i == 0){
sectionBean.setFirst(true);
}else {
sectionBean.setFirst(false);
}
mList.add(sectionBean);
}
for (int i = 0; i < 19; i++) {
SectionBean sectionBean = new SectionBean();
sectionBean.setText("--" + i);
sectionBean.setTag("山東省");
if (i == 0){
sectionBean.setFirst(true);
}else {
sectionBean.setFirst(false);
}
mList.add(sectionBean);
}
}
}
SectionItemDecoration中
- 定義接口
- 實(shí)現(xiàn)三個(gè)方法
package com.example.tuionf.recyclerviewlearn;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.support.v7.widget.RecyclerView;
import android.text.TextPaint;
import android.util.Log;
import android.view.View;
/**
* Created by tuion on 2017/9/7.
*/
public class SectionItemDecoration extends RecyclerView.ItemDecoration {
private TextPaint textPaint;
private Paint paint;
private int topGap = 43;
private Paint.FontMetrics fontMetrics;
private DecorationCallback callback;
private static final String TAG = "SectionItemDecoration";
public SectionItemDecoration(Context context,DecorationCallback decorationCallback) {
Resources res = context.getResources();
this.callback = decorationCallback;
paint = new Paint();
paint.setColor(res.getColor(R.color.colorAccent));
textPaint = new TextPaint();
textPaint.setTypeface(Typeface.DEFAULT_BOLD);
textPaint.setAntiAlias(true);
textPaint.setTextSize(80);
textPaint.setColor(Color.BLACK);
textPaint.getFontMetrics(fontMetrics);
textPaint.setTextAlign(Paint.Align.LEFT);
fontMetrics = new Paint.FontMetrics();
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
Log.e(TAG, "onDraw: " );
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
Log.e(TAG, "onDrawOver: " );
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View view = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(view);
String textLine = "~~~"+callback.getGroupFirstLine(position)+"~~~";
if (position == 0 || callback.isGroupFirst(position)) {
float top = view.getTop() - topGap;
float bottom = view.getTop();
c.drawRect(left, top, right, bottom, paint);//繪制紅色矩形
c.drawText(textLine, left, bottom, textPaint);//繪制文本
}
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int pos = parent.getChildAdapterPosition(view);
Log.e(TAG, "getItemOffsets: ---"+pos );
if (pos == 0 || callback.isGroupFirst(pos)) {//同組的第一個(gè)才添加padding
outRect.top = topGap;
} else {
outRect.top = 0;
}
}
public interface DecorationCallback {
boolean isGroupFirst(int position);
String getGroupFirstLine(int position);
}
}
吸頂效果
效果

image

image
懶得做GIF了,百度一下吸頂效果應(yīng)該可以理解
思路
- onDrawOver()方法,可以繪制在內(nèi)容的上面,覆蓋內(nèi)容—主要就是利用這個(gè)特點(diǎn)實(shí)現(xiàn)的
實(shí)現(xiàn)
- 和上面基本一樣,區(qū)別就在于 onDrawOver() 方法
//這個(gè)可以實(shí)現(xiàn)吸頂效果
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
Log.e(TAG, "onDrawOver: " );
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
int childCount = parent.getChildCount();
String preGroupName; //標(biāo)記上一個(gè)item對(duì)應(yīng)的Group
String currentGroupName = null; //當(dāng)前item對(duì)應(yīng)的Group
for (int i = 0; i < childCount; i++) {
View view = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(view);
preGroupName = currentGroupName;
currentGroupName = callback.getGroupFirstLine(position);
if (currentGroupName == null || TextUtils.equals(currentGroupName, preGroupName))
continue;
int viewBottom = view.getBottom();
float top = Math.max(topGap, view.getTop());//top 決定當(dāng)前頂部第一個(gè)懸浮Group的位置
if (position + 1 < childCount) {
//獲取下個(gè)GroupName
String nextGroupName = callback.getGroupFirstLine(position + 1);
if (!currentGroupName.equals(nextGroupName) && viewBottom < top) {
top = viewBottom;
}
}
//根據(jù)top繪制group
c.drawRect(left, top - topGap, right, top, paint);
Paint.FontMetrics fm = textPaint.getFontMetrics();
//文字豎直居中顯示
float baseLine = top - (topGap - (fm.bottom - fm.top)) / 2 - fm.bottom;
c.drawText(currentGroupName, left, baseLine, textPaint);
}
}