• Android -- RecyclerView实现顶部吸附效果


    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

  • 相关阅读:
    33 函数参数的传递方式
    33 函数递归调用
    32 头文件
    31 函数
    30 枚举
    centos6.5升级默认的Mysql到5.5方法
    Centos6.5命令行快捷键
    redhat 安装lamp
    CentOS6.5中的vsftpd安装配置
    添加一个用户并且让用户获得root权限
  • 原文地址:https://www.cnblogs.com/wjtaigwh/p/6498109.html
Copyright © 2020-2023  润新知