1,先来看一下今天实现的效果:
2,这次的效果是使用ItemDecoration来实践的,来看一看我们的实现吧
第一步:首先添加依赖,由于我们这些数据是请求网络的,所以一下我们添加网络框架依赖、RecyclerView、Glide依赖
apply plugin: 'com.android.application' apply plugin: 'com.neenbedankt.android-apt' android { compileSdkVersion 25 buildToolsVersion "25.0.2" defaultConfig { applicationId "com.qianmo.stickyitemdecoration" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.1.1' //添加reccycleview compile 'com.android.support:recyclerview-v7:25.1.1' //添加glide,需要依赖V4包 compile 'com.github.bumptech.glide:glide:3.7.0' compile 'com.android.support:support-v4:25.1.1' //添加水波纹效果 compile 'com.balysv:material-ripple:1.0.2' //添加butter注解 compile 'com.jakewharton:butterknife:8.2.1' apt 'com.jakewharton:butterknife-compiler:8.2.1' //添加网络框架 compile 'io.reactivex:rxjava:1.1.0' compile 'io.reactivex:rxandroid:1.1.0' compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4' compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4' compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4' compile 'com.google.code.gson:gson:2.6.2' testCompile 'junit:junit:4.12' }
第二步:主界面的xml文件就只是一个简单的RecyclerView控件,首先来实例化我们的RecyclerView
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
第三步:获取网络请求数据,首先我们要创建MovieServiceApi接口,并使用GET请求访问目标接口
请求地址
http://api.meituan.com/mmdb/movie/v2/list/rt/order/coming.json?ci=1&limit=12&token=&__vhost=api.maoyan.com&utm_campaign=AmovieBmovieCD-1&movieBundleVersion=6801&utm_source=xiaomi&utm_medium=android&utm_term=6.8.0&utm_content=868030022327462&net=255&dModel=MI%205&uuid=0894DE03C76F6045D55977B6D4E32B7F3C6AAB02F9CEA042987B380EC5687C43&lat=40.100673&lng=116.378619&__skck=6a375bce8c66a0dc293860dfa83833ef&__skts=1463704714271&__skua=7e01cf8dd30a179800a7a93979b430b2&__skno=1a0b4a9b-44ec-42fc-b110-ead68bcc2824&__skcy=sXcDKbGi20CGXQPPZvhCU3%2FkzdE%3D
MovieServiceApi.java
package com.qianmo.stickyitemdecoration.api; import com.qianmo.stickyitemdecoration.base.BaseResponse; import com.qianmo.stickyitemdecoration.bean.MovieBean; import retrofit2.http.GET; import rx.Observable; /** * Created by wangjitao on 2017/3/3 0003. * E-Mail:543441727@qq.com * 电影网API */ public interface MovieApiService { @GET("v2/list/rt/order/coming.json?ci=1&limit=12&token=&__vhost=api.maoyan.com&utm_campaign=AmovieBmovieCD-1&movieBundleVersion=6801&utm_source=xiaomi&utm_medium=android&utm_term=6.8.0&utm_content=868030022327462&net=255&dModel=MI%205&uuid=0894DE03C76F6045D55977B6D4E32B7F3C6AAB02F9CEA042987B380EC5687C43&lat=40.100673&lng=116.378619&__skck=6a375bce8c66a0dc293860dfa83833ef&__skts=1463704714271&__skua=7e01cf8dd30a179800a7a93979b430b2&__skno=1a0b4a9b-44ec-42fc-b110-ead68bcc2824&__skcy=sXcDKbGi20CGXQPPZvhCU3%2FkzdE%3D") Observable<BaseResponse<MovieBean>> getMovieDatas(); }
创建数据接口响应的Bean
BaseResponse.java
package com.qianmo.stickyitemdecoration.base; /** * Created by wangjitao on 2017/3/3 0003. * E-Mail:543441727@qq.com * 数据返回体的基本接收类,由于本次接口没有code和message */ public class BaseResponse<T> { // private int code; // private String message; private T data; // public String getMessage() { // return message; // } // // public void setMessage(String message) { // this.message = message; // } // // public int getCode() { // return code; // } // // public void setCode(int code) { // this.code = code; // } public T getData() { return data; } public void setData(T data) { this.data = data; } }
MovieBean.java
package com.qianmo.stickyitemdecoration.bean; import java.util.List; /** * Created by wangjitao on 2017/3/3 0003. * E-Mail:543441727@qq.com * 用于数据接收实体类 */ public class MovieBean { private List<ComingBean> coming ; public List<ComingBean> getComing() { return coming; } public void setComing(List<ComingBean> coming) { this.coming = coming; } }
ComingBean.java
package com.qianmo.stickyitemdecoration.bean; import java.util.List; /** * Created by Administrator on 2017/3/3 0003. * E-Mail:543441727@qq.com */ public class ComingBean { /** * boxInfo : 喵,即将上映 * cat : 动作,科幻 * civilPubSt : 0 * comingTitle : 3月10日 周五 * desc : 主演:亚伦·保尔,肖恩·宾,琳娜·海蒂 * dir : 野末武志 * dur : 116 * effectShowNum : 0 * fra : 日本 * frt : 2016-08-19 * globalReleased : false * headLineShow : false * headLinesVO : [] * id : 346383 * img : http://p0.meituan.net/w.h/movie/5be09f397d474988afaf930ac5346243715496.png * late : false * localPubSt : 0 * mk : 0 * nm : 最终幻想15:王者之剑 * pn : 98 * preShow : false * proScore : 0 * proScoreNum : 0 * pubDate : 1489075200000 * pubDesc : 2017-03-10大陆上映 * pubShowNum : 0 * recentShowDate : 0 * recentShowNum : 0 * rt : 2017-03-10 * sc : 0 * scm : 法力渐微弱,勇士卫祖国 * showCinemaNum : 0 * showInfo : 2017-03-10 下周五上映 * showNum : 0 * showst : 4 * snum : 903 * star : 亚伦·保尔,肖恩·宾,琳娜·海蒂 * ver : 2D * videoId : 83711 * videoName : 魔法机械版预告片 * videourl : http://maoyan.meituan.net/movie/videos/854x480df7f69dd367b4dd5829c98d1a5a07dfa.mp4 * vnum : 9 * weight : 1 * wish : 22799 * wishst : 0 */ private String boxInfo; private String cat; private int civilPubSt; private String comingTitle; private String desc; private String dir; private int dur; private int effectShowNum; private String fra; private String frt; private boolean globalReleased; private boolean headLineShow; private int id; private String img; private boolean late; private int localPubSt; private int mk; private String nm; private int pn; private boolean preShow; private int proScore; private int proScoreNum; private long pubDate; private String pubDesc; private int pubShowNum; private int recentShowDate; private int recentShowNum; private String rt; private int sc; private String scm; private int showCinemaNum; private String showInfo; private int showNum; private int showst; private int snum; private String star; private String ver; private int videoId; private String videoName; private String videourl; private int vnum; private int weight; private int wish; private int wishst; private List<?> headLinesVO; public String getBoxInfo() { return boxInfo; } public void setBoxInfo(String boxInfo) { this.boxInfo = boxInfo; } public String getCat() { return cat; } public void setCat(String cat) { this.cat = cat; } public int getCivilPubSt() { return civilPubSt; } public void setCivilPubSt(int civilPubSt) { this.civilPubSt = civilPubSt; } public String getComingTitle() { return comingTitle; } public void setComingTitle(String comingTitle) { this.comingTitle = comingTitle; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getDir() { return dir; } public void setDir(String dir) { this.dir = dir; } public int getDur() { return dur; } public void setDur(int dur) { this.dur = dur; } public int getEffectShowNum() { return effectShowNum; } public void setEffectShowNum(int effectShowNum) { this.effectShowNum = effectShowNum; } public String getFra() { return fra; } public void setFra(String fra) { this.fra = fra; } public String getFrt() { return frt; } public void setFrt(String frt) { this.frt = frt; } public boolean isGlobalReleased() { return globalReleased; } public void setGlobalReleased(boolean globalReleased) { this.globalReleased = globalReleased; } public boolean isHeadLineShow() { return headLineShow; } public void setHeadLineShow(boolean headLineShow) { this.headLineShow = headLineShow; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getImg() { return img; } public void setImg(String img) { this.img = img; } public boolean isLate() { return late; } public void setLate(boolean late) { this.late = late; } public int getLocalPubSt() { return localPubSt; } public void setLocalPubSt(int localPubSt) { this.localPubSt = localPubSt; } public int getMk() { return mk; } public void setMk(int mk) { this.mk = mk; } public String getNm() { return nm; } public void setNm(String nm) { this.nm = nm; } public int getPn() { return pn; } public void setPn(int pn) { this.pn = pn; } public boolean isPreShow() { return preShow; } public void setPreShow(boolean preShow) { this.preShow = preShow; } public int getProScore() { return proScore; } public void setProScore(int proScore) { this.proScore = proScore; } public int getProScoreNum() { return proScoreNum; } public void setProScoreNum(int proScoreNum) { this.proScoreNum = proScoreNum; } public long getPubDate() { return pubDate; } public void setPubDate(long pubDate) { this.pubDate = pubDate; } public String getPubDesc() { return pubDesc; } public void setPubDesc(String pubDesc) { this.pubDesc = pubDesc; } public int getPubShowNum() { return pubShowNum; } public void setPubShowNum(int pubShowNum) { this.pubShowNum = pubShowNum; } public int getRecentShowDate() { return recentShowDate; } public void setRecentShowDate(int recentShowDate) { this.recentShowDate = recentShowDate; } public int getRecentShowNum() { return recentShowNum; } public void setRecentShowNum(int recentShowNum) { this.recentShowNum = recentShowNum; } public String getRt() { return rt; } public void setRt(String rt) { this.rt = rt; } public int getSc() { return sc; } public void setSc(int sc) { this.sc = sc; } public String getScm() { return scm; } public void setScm(String scm) { this.scm = scm; } public int getShowCinemaNum() { return showCinemaNum; } public void setShowCinemaNum(int showCinemaNum) { this.showCinemaNum = showCinemaNum; } public String getShowInfo() { return showInfo; } public void setShowInfo(String showInfo) { this.showInfo = showInfo; } public int getShowNum() { return showNum; } public void setShowNum(int showNum) { this.showNum = showNum; } public int getShowst() { return showst; } public void setShowst(int showst) { this.showst = showst; } public int getSnum() { return snum; } public void setSnum(int snum) { this.snum = snum; } public String getStar() { return star; } public void setStar(String star) { this.star = star; } public String getVer() { return ver; } public void setVer(String ver) { this.ver = ver; } public int getVideoId() { return videoId; } public void setVideoId(int videoId) { this.videoId = videoId; } public String getVideoName() { return videoName; } public void setVideoName(String videoName) { this.videoName = videoName; } public String getVideourl() { return videourl; } public void setVideourl(String videourl) { this.videourl = videourl; } public int getVnum() { return vnum; } public void setVnum(int vnum) { this.vnum = vnum; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } public int getWish() { return wish; } public void setWish(int wish) { this.wish = wish; } public int getWishst() { return wishst; } public void setWishst(int wishst) { this.wishst = wishst; } public List<?> getHeadLinesVO() { return headLinesVO; } public void setHeadLinesVO(List<?> headLinesVO) { this.headLinesVO = headLinesVO; } }
第四部:创建适配器
MyAdapter.java
package com.qianmo.stickyitemdecoration.adapter; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.bumptech.glide.Glide; import com.qianmo.stickyitemdecoration.R; import com.qianmo.stickyitemdecoration.bean.ComingBean; import java.util.List; import static java.lang.System.load; /** * Created by Administrator on 2017/3/3 0003. * E-Mail:543441727@qq.com */ public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { private Context context; private List<ComingBean> datas; public MyAdapter(Context context, List<ComingBean> datas) { this.context = context; this.datas = datas; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(context).inflate(R.layout.item_recyclerview, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(final ViewHolder holder, int position) { String imagUrl = datas.get(position).getImg(); String newImagUrl = imagUrl.replaceAll("w.h", "50.80"); Glide .with(context) .load(newImagUrl) .error(R.mipmap.ic_launcher) .into(holder.img); holder.tv_time.setText(datas.get(position).getPubDesc()); holder.tv_title.setText(datas.get(position).getNm()); holder.tv_introduce.setText(datas.get(position).getDesc()); holder.tv_score_major_real.setText(datas.get(position).getDur()+""); holder.tv_score_people_real.setText(datas.get(position).getPn()+""); } @Override public int getItemCount() { return datas == null ? 0 : datas.size(); } class ViewHolder extends RecyclerView.ViewHolder { ImageView img; TextView tv_title; TextView tv_introduce; TextView tv_score_major_real; TextView tv_score_people_real; TextView tv_time; public ViewHolder(View view) { super(view); img = (ImageView) view.findViewById(R.id.img); tv_title = (TextView) view.findViewById(R.id.tv_title); tv_introduce = (TextView) view.findViewById(R.id.tv_introduce); tv_score_major_real = (TextView) view.findViewById(R.id.tv_score_major_real); tv_score_people_real = (TextView) view.findViewById(R.id.tv_score_people_real); tv_time = (TextView) view.findViewById(R.id.tv_time); } } }
第五步:自定义ItemDecoration,使头部悬浮,具体思路代码中有了,就不在分析了
FloatingItemDecoration.java
package com.qianmo.stickyitemdecoration.view; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.support.annotation.ColorInt; import android.support.annotation.Dimension; import android.support.annotation.DrawableRes; import android.support.v4.content.ContextCompat; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.util.TypedValue; import android.view.View; import java.util.HashMap; import java.util.Map; /** * Created by Administrator on 2017/3/3 0003. * E-Mail:543441727@qq.com */ public class FloatingItemDecoration extends RecyclerView.ItemDecoration { private static final String TAG = "FloatingItemDecoration"; private static final int[] ATTRS = new int[]{android.R.attr.listDivider}; private Drawable mDivider; private int dividerHeight; private int dividerWidth; private Map<Integer, String> keys = new HashMap<>(); private int mTitleHeight; private Paint mTextPaint; private Paint mBackgroundPaint; private float mTextHeight; private float mTextBaselineOffset; private Context mContext; /** * 滚动列表的时候是否一直显示悬浮头部 */ private boolean showFloatingHeaderOnScrolling = true; public FloatingItemDecoration(Context context) { final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); a.recycle(); this.dividerHeight = mDivider.getIntrinsicHeight(); this.dividerWidth = mDivider.getIntrinsicWidth(); init(context); } /** * 自定义分割线 * * @param context * @param drawableId 分割线图片 */ public FloatingItemDecoration(Context context, @DrawableRes int drawableId) { mDivider = ContextCompat.getDrawable(context, drawableId); this.dividerHeight = mDivider.getIntrinsicHeight(); this.dividerWidth = mDivider.getIntrinsicWidth(); init(context); } /** * 自定义分割线 * 也可以使用{@link Canvas#drawRect(float, float, float, float, Paint)}或者{@link Canvas#drawText(String, float, float, Paint)}等等 * 结合{@link Paint}去绘制各式各样的分割线 * * @param context * @param color 整型颜色值,非资源id * @param dividerWidth 单位为dp * @param dividerHeight 单位为dp */ public FloatingItemDecoration(Context context, @ColorInt int color, @Dimension float dividerWidth, @Dimension float dividerHeight) { mDivider = new ColorDrawable(color); this.dividerWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dividerWidth, context.getResources().getDisplayMetrics()); this.dividerHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dividerHeight, context.getResources().getDisplayMetrics()); init(context); } private void init(Context mContext) { this.mContext = mContext; mTextPaint = new Paint(); mTextPaint.setAntiAlias(true); mTextPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, mContext.getResources().getDisplayMetrics())); mTextPaint.setColor(Color.WHITE); Paint.FontMetrics fm = mTextPaint.getFontMetrics(); mTextHeight = fm.bottom - fm.top;//计算文字高度 mTextBaselineOffset = fm.bottom; mBackgroundPaint = new Paint(); mBackgroundPaint.setAntiAlias(true); mBackgroundPaint.setColor(Color.MAGENTA); } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); drawVertical(c, parent); } @Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDrawOver(c, parent, state); if (!showFloatingHeaderOnScrolling) { return; } int firstVisiblePos = ((LinearLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition(); if (firstVisiblePos == RecyclerView.NO_POSITION) { return; } String title = getTitle(firstVisiblePos); if (TextUtils.isEmpty(title)) { return; } boolean flag = false; if (getTitle(firstVisiblePos + 1) != null && !title.equals(getTitle(firstVisiblePos + 1))) { //说明是当前组最后一个元素,但不一定碰撞了 // Log.e(TAG, "onDrawOver: "+"==============" +firstVisiblePos); View child = parent.findViewHolderForAdapterPosition(firstVisiblePos).itemView; if (child.getTop() + child.getMeasuredHeight() < mTitleHeight) { //进一步检测碰撞 // Log.e(TAG, "onDrawOver: "+child.getTop()+"$"+firstVisiblePos ); c.save();//保存画布当前的状态 flag = true; c.translate(0, child.getTop() + child.getMeasuredHeight() - mTitleHeight);//负的代表向上 } } int left = parent.getPaddingLeft(); int right = parent.getWidth() - parent.getPaddingRight(); int top = parent.getPaddingTop(); int bottom = top + mTitleHeight; c.drawRect(left, top, right, bottom, mBackgroundPaint); float x = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, mContext.getResources().getDisplayMetrics()); float y = bottom - (mTitleHeight - mTextHeight) / 2 - mTextBaselineOffset;//计算文字baseLine c.drawText(title, x, y, mTextPaint); if (flag) { //还原画布为初始状态 c.restore(); } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); int pos = parent.getChildViewHolder(view).getAdapterPosition(); if (keys.containsKey(pos)) {//留出头部偏移 outRect.set(0, mTitleHeight, 0, 0); } else { outRect.set(0, dividerHeight, 0, 0); } } /** * *如果该位置没有,则往前循环去查找标题,找到说明该位置属于该分组 * * @param position * @return */ private String getTitle(int position) { while (position >= 0) { if (keys.containsKey(position)) { return keys.get(position); } position--; } return null; } private void drawVertical(Canvas c, RecyclerView parent) { int left = parent.getPaddingLeft(); int right = parent.getWidth() - parent.getPaddingRight(); int top = 0; int bottom = 0; for (int i = 0; i < parent.getChildCount(); i++) { View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); if (!keys.containsKey(params.getViewLayoutPosition())) { //画普通分割线 top = child.getTop() - params.topMargin - dividerHeight; bottom = top + dividerHeight; mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } else { //画头部 top = child.getTop() - params.topMargin - mTitleHeight; bottom = top + mTitleHeight; c.drawRect(left, top, right, bottom, mBackgroundPaint); // float x=child.getPaddingLeft()+params.leftMargin; float x = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, mContext.getResources().getDisplayMetrics()); float y = bottom - (mTitleHeight - mTextHeight) / 2 - mTextBaselineOffset;//计算文字baseLine // Log.e(TAG, "drawVertical: "+bottom ); c.drawText(keys.get(params.getViewLayoutPosition()), x, y, mTextPaint); } } } public void setShowFloatingHeaderOnScrolling(boolean showFloatingHeaderOnScrolling) { this.showFloatingHeaderOnScrolling = showFloatingHeaderOnScrolling; } public void setKeys(Map<Integer, String> keys) { this.keys.clear(); this.keys.putAll(keys); } public void setmTitleHeight(int titleHeight) { this.mTitleHeight = titleHeight; } }
第六步:设置ItemDecoration,设置适配器
final FloatingItemDecoration floatingItemDecoration=new FloatingItemDecoration(this, Color.GRAY,1,1); floatingItemDecoration.setKeys(keys); floatingItemDecoration.setmTitleHeight((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,50,getResources().getDisplayMetrics())); recycleview.addItemDecoration(floatingItemDecoration); adapter = new MyAdapter(mContext, datas); recycleview.setHasFixedSize(true); recycleview.setAdapter(adapter);
完整的MainActivity代码如下:
package com.qianmo.stickyitemdecoration; import android.content.Context; import android.graphics.Color; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.TypedValue; import com.qianmo.stickyitemdecoration.adapter.MyAdapter; import com.qianmo.stickyitemdecoration.api.MovieApiService; import com.qianmo.stickyitemdecoration.base.BaseResponse; import com.qianmo.stickyitemdecoration.bean.ComingBean; import com.qianmo.stickyitemdecoration.bean.MovieBean; import com.qianmo.stickyitemdecoration.bean.NameBean; import com.qianmo.stickyitemdecoration.utils.Constant; import com.qianmo.stickyitemdecoration.view.FloatingItemDecoration; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import butterknife.BindView; import butterknife.ButterKnife; import retrofit2.Retrofit; import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; import rx.Subscriber; import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; public class MainActivity extends AppCompatActivity { @BindView(R.id.recycleview) RecyclerView recycleview; private List<ComingBean> datas; private Map<Integer,String> keys=new HashMap<>();//存放所有key的位置和内容 private MyAdapter adapter; private Context mContext = MainActivity.this; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); initData(); } /** * 请求数据 */ private void initData() { datas = new ArrayList<>(); requestNetwork(); } /** * 初始化UI */ private void initView() { GridLayoutManager manager = new GridLayoutManager(this, 1); recycleview.setLayoutManager(manager); keys.put(0,"欧美大片"); keys.put(2,"国产剧透"); keys.put(4,"印度神剧"); final FloatingItemDecoration floatingItemDecoration=new FloatingItemDecoration(this, Color.GRAY,1,1); floatingItemDecoration.setKeys(keys); floatingItemDecoration.setmTitleHeight((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,50,getResources().getDisplayMetrics())); recycleview.addItemDecoration(floatingItemDecoration); adapter = new MyAdapter(mContext, datas); recycleview.setHasFixedSize(true); recycleview.setAdapter(adapter); } /** * 请求网络 */ private void requestNetwork() { Retrofit retrofit = new Retrofit.Builder() .baseUrl(Constant.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); MovieApiService movieApiService = retrofit.create(MovieApiService.class); movieApiService.getMovieDatas() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<BaseResponse<MovieBean>>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(BaseResponse<MovieBean> movieBeanBaseResponse) { datas.addAll(movieBeanBaseResponse.getData().getComing()); initView(); // adapter.notifyDataSetChanged(); } }); } }
再上一些github下载地址:https://github.com/543441727/StickyItemDecoration.git