原文出处: 李诗雨

开始逐渐领略到ItemDecoration的美~

今天让我 使用 ItemDecoration 来完成 可推动的悬浮导航栏的效果,最终实现的效果如下图:

具体实现步骤如下:

根据我前面的文章所讲的RecyclerView的基本使用,我们先来完成基本的recyclerView

第一步:布局里写一个RecyclerView

第二步:实例化

Java
1
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);

第三步:获取所需的数据 (这里我们来个真实点的情景,去联网请求数据)

Java
1
2
3
4

/**
    * 联网请求所需的url
    */  
   public String url="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";

Java
1
2

//联网获取数据  
       getDataFromNet();

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

/**
     * 使用okhttpUtils进行联网请求数据
     */  
    private void getDataFromNet() {  
        OkHttpUtils.  
                get()  
                .url(url)  
                .build()  
                .execute(new StringCallback() {  
                    @Override  
                    public void onError(okhttp3.Call call, Exception e, int id) {  
                        Log.e("TAG", "联网失败" + e.getMessage());  
                    }  
  
                    @Override  
                    public void onResponse(String response, int id) {  
                        Log.e("TAG", "联网成功==" + response);  
  
                        //联网成功后使用fastjson解析  
                        processData(response);  
                    }  
                });  
    }

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

/**
     * 使用fastjson进行解析
     *
     * @param json
     */  
    private void processData(String json) {  
        //这里使用GsonFormat生成对应的bean类  
       JSONObject jsonObject = parseObject(json);  
  
        String data = jsonObject.getString("data");  
        JSONObject dataObj = JSON.parseObject(data);  
  
        String coming = dataObj.getString("coming");  
        List<WaitMVBean.DataBean.ComingBean> comingslist = parseArray(coming, WaitMVBean.DataBean.ComingBean.class);  
  
        //测试是否解析数据成功  
//        String strTest = comingslist.get(0).getCat();  
//        Log.e("TAG", strTest + "222");  
  
         //解析数据成功,设置适配器-->  
        
        }  
  
    }

第四步:解析数据成功后,创建并设置适配器,并传递相关数据

Java
1
2
3

//解析数据成功,设置适配器  
           MyRecyclerAdapter adapter = new MyRecyclerAdapter( mContext,comingslist);  
           recyclerView.setAdapter(adapter);

适配器:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

public class MyRecyclerAdapter extends RecyclerView.Adapter {  
  
    private final List<WaitMVBean.DataBean.ComingBean> comingslist;  
    private final Context mContext;  
    private final LayoutInflater mLayoutInflater;  
  
  
    public MyRecyclerAdapter(Context mContext, List<WaitMVBean.DataBean.ComingBean> comingslist) {  
        this.mContext = mContext;  
        this.comingslist = comingslist;  
        mLayoutInflater = LayoutInflater.from(mContext);  
    }  
  
    @Override  
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {  
        return new MyViewHolder(mLayoutInflater.inflate(R.layout.date_item, null));  
    }  
  
    @Override  
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {  
        MyViewHolder myholder = (MyViewHolder) holder;  
        myholder.setData(position);  
    }  
  
    @Override  
    public int getItemCount() {  
        return comingslist.size();  
    }  
  
    class MyViewHolder extends RecyclerView.ViewHolder {  
        private TextView mv_name;  
        private TextView mv_dec;  
        private TextView mv_date;  
        private ImageView imageView;  
  
        public MyViewHolder(View itemView) {  
            super(itemView);  
            mv_name = (TextView) itemView.findViewById(R.id.mv_name);  
            mv_dec = (TextView) itemView.findViewById(R.id.mv_dec);  
            mv_date = (TextView) itemView.findViewById(R.id.mv_date);  
            imageView = (ImageView) itemView.findViewById(R.id.image);  
        }  
  
        public void setData(int position) {  
            WaitMVBean.DataBean.ComingBean coming = comingslist.get(position);  
  
            String name = coming.getNm();  
            mv_name.setText(name);  
  
            String date = coming.getShowInfo();  
            mv_date.setText(date);  
  
            String dec = coming.getScm();  
            mv_dec.setText(dec);  
  
            //注:当你发下图片无法打开是,做个字符串替换即可  
            String imagUrl = coming.getImg();  
            String newImagUrl = imagUrl.replaceAll("w.h", "50.80");  
  
            //使用Glide加载图片  
            Glide.with(mContext)  
                    .load(newImagUrl)  
                    .into(imageView);  
        }  
    }  
}

item的布局:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="wrap_content"  
    android:layout_height="wrap_content"  
    android:background="#ffffff"  
    android:gravity="center_vertical"  
    android:orientation="horizontal">  
  
    <ImageView  
        android:id="@+id/image"  
        android:layout_width="70dp"  
        android:layout_height="110dp"  
        android:layout_marginBottom="5dp"  
        android:layout_marginLeft="10dp"  
        android:layout_marginRight="8dp"  
        android:layout_marginTop="5dp" />  
  
    <LinearLayout  
        android:layout_width="0dp"  
        android:layout_height="wrap_content"  
        android:layout_marginLeft="6dp"  
        android:layout_weight="1"  
        android:orientation="vertical">  
  
        <TextView  
            android:id="@+id/mv_name"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:text="神奇動物在哪裏"  
            android:textColor="#000000"  
            android:textSize="15sp" />  
  
        <LinearLayout  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:orientation="horizontal">  
  
            <TextView  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"  
                android:text="观众"  
                android:textColor="#55000000"  
                android:textSize="14sp" />  
  
            <TextView  
                android:id="@+id/tv_people"  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"  
                android:text="9.0 "  
                android:textColor="#FFCE42"  
                android:textSize="18sp" />  
  
            <TextView  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"  
                android:text=" | 专业"  
                android:textColor="#55000000"  
                android:textSize="14sp" />  
  
            <TextView  
                android:id="@+id/tv_professional"  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"  
                android:text="6.7"  
                android:textColor="#FFCE42"  
                android:textSize="18sp" />  
        </LinearLayout>  
          
        <TextView  
            android:id="@+id/mv_dec"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:layout_marginTop="8dp"  
            android:text="神奇動物城,法師顯超能"  
            android:textColor="#99000000"  
            android:textSize="11sp" />  
  
        <TextView  
            android:id="@+id/mv_date"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:layout_marginTop="10dp"  
            android:text="今天165家影院放映2088场"  
            android:textColor="#99000000"  
            android:textSize="11sp" />  
    </LinearLayout>  
  
</LinearLayout>

第五步:一定不能忘!!!

recycleView不仅要设置适配器还要设置布局管理者,否则图片不显示

Java
1
2

GridLayoutManager manager = new GridLayoutManager(this, 1);  
            recyclerView.setLayoutManager(manager);

此时RecyclerView简单的完成效果如下:

下面开始做 可推动的 悬浮导航栏:

第一步:首先我们来写一个类,它起标记的作用,来放每一个item的对应的悬浮栏的字符串

Java
1
2
3
4
5
6
7
8
9
10
11

public class NameBean {  
    String name;  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
}

第二步:自定义一个SectionDecoration 类 继承 RecyclerView的ItemDecoration

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

public class SectionDecoration extends RecyclerView.ItemDecoration {  
    private static final String TAG = "SectionDecoration";  
  
    private List<NameBean> dataList;  
  
    private DecorationCallback callback;  
    private TextPaint textPaint;  
    private Paint paint;  
    private int topGap;  
    private int alignBottom;  
    private Paint.FontMetrics fontMetrics;  
  
  
    public SectionDecoration(List<NameBean> dataList, Context context, DecorationCallback decorationCallback) {  
        Resources res = context.getResources();  
        this.dataList = dataList;  
        this.callback = decorationCallback;  
        //设置悬浮栏的画笔---paint  
        paint = new Paint();  
        paint.setColor(res.getColor(R.color.colorGray));  
  
        //设置悬浮栏中文本的画笔  
        textPaint = new TextPaint();  
        textPaint.setAntiAlias(true);  
        textPaint.setTextSize(DensityUtil.dip2px(context, 14));  
        textPaint.setColor(Color.DKGRAY);  
        textPaint.setTextAlign(Paint.Align.LEFT);  
        fontMetrics = new Paint.FontMetrics();  
        //决定悬浮栏的高度等  
        topGap = res.getDimensionPixelSize(R.dimen.sectioned_top);  
        //决定文本的显示位置等  
        alignBottom = res.getDimensionPixelSize(R.dimen.sectioned_alignBottom);  
    }  
  
    @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.i(TAG, "getItemOffsets:" + pos);  
        String groupId = callback.getGroupId(pos);  
        if (groupId.equals("-1")) return;  
        //只有是同一组的第一个才显示悬浮栏  
        if (pos == 0 || isFirstInGroup(pos)) {  
            outRect.top = topGap;  
            if (dataList.get(pos).getName() == "") {  
                outRect.top = 0;  
            }  
        } else {  
            outRect.top = 0;  
        }  
    }  
  
    @Override  
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {  
        super.onDraw(c, parent, state);  
        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 groupId = callback.getGroupId(position);  
            if (groupId.equals("-1")) return;  
            String textLine = callback.getGroupFirstLine(position).toUpperCase();  
            if (textLine == "") {  
                float top = view.getTop();  
                float bottom = view.getTop();  
                c.drawRect(left, top, right, bottom, paint);  
                return;  
            } else {  
                if (position == 0 || isFirstInGroup(position)) {  
                    float top = view.getTop() - topGap;  
                    float bottom = view.getTop();  
                    //绘制悬浮栏  
                    c.drawRect(left, top - topGap, right, bottom, paint);  
                    //绘制文本  
                    c.drawText(textLine, left, bottom, textPaint);  
                }  
            }  
        }  
    }  
  
    @Override  
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {  
        super.onDrawOver(c, parent, state);  
        int itemCount = state.getItemCount();  
        int childCount = parent.getChildCount();  
        int left = parent.getPaddingLeft();  
        int right = parent.getWidth() - parent.getPaddingRight();  
        float lineHeight = textPaint.getTextSize() + fontMetrics.descent;  
  
        String preGroupId = "";  
        String groupId = "-1";  
        for (int i = 0; i < childCount; i++) {  
            View view = parent.getChildAt(i);  
            int position = parent.getChildAdapterPosition(view);  
  
            preGroupId = groupId;  
            groupId = callback.getGroupId(position);  
            if (groupId.equals("-1") || groupId.equals(preGroupId)) continue;  
  
            String textLine = callback.getGroupFirstLine(position).toUpperCase();  
            if (TextUtils.isEmpty(textLine)) continue;  
  
            int viewBottom = view.getBottom();  
            float textY = Math.max(topGap, view.getTop());  
            //下一个和当前不一样移动当前  
            if (position + 1 < itemCount) {  
                String nextGroupId = callback.getGroupId(position + 1);  
                //组内最后一个view进入了header  
                if (nextGroupId != groupId && viewBottom < textY) {  
                    textY = viewBottom;  
                }  
            }  
            //textY - topGap决定了悬浮栏绘制的高度和位置  
            c.drawRect(left, textY - topGap, right, textY, paint);  
            //left+2*alignBottom 决定了文本往左偏移的多少(加-->向左移)  
            //textY-alignBottom  决定了文本往右偏移的多少  (减-->向上移)  
            c.drawText(textLine, left + 2 * alignBottom, textY - alignBottom, textPaint);  
        }  
    }  
  
  
    /**
     * 判断是不是组中的第一个位置
     *
     * @param pos
     * @return
     */  
    private boolean isFirstInGroup(int pos) {  
        if (pos == 0) {  
            return true;  
        } else {  
            // 因为是根据 字符串内容的相同与否 来判断是不是同意组的,所以此处的标记id 要是String类型  
            // 如果你只是做联系人列表,悬浮框里显示的只是一个字母,则标记id直接用 int 类型就行了  
            String prevGroupId = callback.getGroupId(pos - 1);  
            String groupId = callback.getGroupId(pos);  
            //判断前一个字符串 与 当前字符串 是否相同  
            if (prevGroupId.equals(groupId)) {  
                return false;  
            } else {  
                return true;  
            }  
        }  
    }  
  
    //定义一个借口方便外界的调用  
    interface DecorationCallback {  
        String getGroupId(int position);  
  
        String getGroupFirstLine(int position);  
    }  
}

第三步:在向list集合中先把每一个item的 起“标记”作用的字符串都加进去

Java
1
setPullAction(comingslist);

Java
1
2
3
4
5
6
7
8
9
10

private void setPullAction(List<WaitMVBean.DataBean.ComingBean> comingslist) {  
        dataList = new ArrayList<>();  
  
        for (int i = 0; i < comingslist.size(); i++) {  
            NameBean nameBean = new NameBean();  
            String name0 = comingslist.get(i).getComingTitle();  
            nameBean.setName(name0);  
            dataList.add(nameBean);  
        }  
    }

第四步:在setAdapter() 前,为RecyclerView添加ItemDecoration:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

recyclerView.addItemDecoration(new SectionDecoration(dataList,mContext, new SectionDecoration.DecorationCallback() {  
               //返回标记id (即每一项对应的标志性的字符串)  
                @Override  
                public String getGroupId(int position) {  
                    if(dataList.get(position).getName()!=null) {  
                        return dataList.get(position).getName();  
                    }  
                    return "-1";  
                }  
  
                //获取同组中的第一个内容  
                @Override  
                public String getGroupFirstLine(int position) {  
                    if(dataList.get(position).getName()!=null) {  
                        return dataList.get(position).getName();  
                    }  
                    return "";  
                }  
            }));

这样就完成了~

再看一眼最终效果感受一下:

转载于:https://www.cnblogs.com/henkun010/p/6645616.html

安卓当下最流行的吸顶效果的实现(转)相关推荐

  1. android滑动自动吸顶效果,安卓当下最流行的吸顶效果的实现(上)

    原标题:安卓当下最流行的吸顶效果的实现(上) 开始逐渐领略到ItemDecoration的美~ 今天让我 使用 ItemDecoration 来完成 可推动的悬浮导航栏的效果,最终实现的效果如下图: ...

  2. 自定义tab吸顶效果一

    PS:问题:什么是吸顶,吸顶有什么作用,吸顶怎么使用? 在很多app商城中,介绍软件的时候就会使用吸顶效果, 吸顶有很多作用,一个最简单粗暴的作用就是,让用户知道此刻在浏览哪个模块,并可以选择另外的模 ...

  3. 30秒实现Vue吸顶效果

    酱酱,好久不见鸭! 前言:吸顶效果图: 1.滚动前: image.png 2.滚动中: image.png 3.滚动超过后: image.png 直观效果可参pc端微博左侧的信息栏 第一步:html ...

  4. vue音乐项目歌手页面滚动、吸顶效果

    总结singer页面: 1.api中去获取 ['热',A-Z] 以及根据['热',A-Z]获取的所有歌手的数据 2.渲染数据 2.1 渲染左边 字母title ['热',A-Z] + 该字母开头的歌手 ...

  5. 微信小程序中实现吸顶效果(流畅、不卡顿)

    欢迎访问我的 个人博客 最开始的时候,在小程序中实现吸顶效果,开发工具看起来还挺好的,但是在真机上就会有问题了. 原因是我不停的去 setData 会导致操作反馈延迟严重,无法及时将操作处理结果及时传 ...

  6. 最贴近京东首页体验的嵌套滑动吸顶效果

    吸顶效果是各家 App 或多或少都会用的一个交互,这种交互也常见于 PC.H5,可以说是一种通用性很强的前端交互体验,相比较来说京东首页的嵌套滑动吸顶效果是各个类似效果中体验比较好的一个,因为在嵌套布 ...

  7. vue中怎么实现吸顶效果

    在 web 应用中,我们经常需要让页面中的一个或多个元素在页面滚动时保持固定位置.这种效果通常被称为吸顶效果,因为它使元素像粘在页面顶部一样固定不动. 在 Vue 中,实现吸顶效果有不同的方法.本文将 ...

  8. Android - 吸顶效果 布局篇

    调研了一下微博和豆瓣等大体量的APP,发现内容详情页的评论吸顶效果非常常见. 以截图自豆瓣的效果为例,当上划至内容部分消失时,滑动中的回复条会置顶,并保持在位置不动. 笔者通过实践,记录下目前发现的最 ...

  9. Flutter吸顶效果

    前言: 关于吸顶效果,在Flutter当中,已经提供了这么一个控件,但是由于太复杂,所以网上的资料有些少,本文章主要利用Flutter自带的这种吸顶动画控件,配合着动画完成的一个用户中心的页面. im ...

最新文章

  1. 网编编程必看书籍:unix网络编程
  2. 网页怎么在图片上添加文字_抖音一天可见怎么添加文字-抖音一天可见添加文字文案方法介绍...
  3. 计算机不能进入桌面,电脑开机无法进入桌面,请高手解决。
  4. JQUERY方法给TABLE动态增加行
  5. 数据结构之基于Java的链接队列实现
  6. linux shell 流程控制(条件if,循环【for,while】,选择【case】语句实例
  7. mysql实验视图及索引_MySQL视图及索引
  8. Maven错误:“No goals have been specified for this build...”问题解决
  9. FISCO BCOS (六)———ubantu安装mysql5.7
  10. Mac Sublime Text 3插件安装
  11. 「POJ2826」An Easy Problem?!【计算几何】
  12. 调用百度地图或是高德地图直接导航
  13. PYRIT 强大的密码分析工具(可使用GPU分析)-学习笔记
  14. 运营管理体系有何价值?
  15. python已知两边求第三边_已知两边求第三边公式
  16. AJ-Report项目分析(7)
  17. 时间轮(TimeWheel)的设计与实现
  18. iOS音频播放 (三):AudioFileStream
  19. hhvm v3.30_HHVM 3.1.0发布
  20. uniapp 微信小程序版本更新提示

热门文章

  1. C++核心编程(三)
  2. 运动是性价比最高的投资
  3. 难忘的一天——装操作系统(四)
  4. 【Sql Server】DateBase-视频总结
  5. cuda安装教cudnn安装显卡问题
  6. nn.moduleList 和Sequential由来、用法和实例 —— 写网络模型
  7. VAE变分自编码器实现
  8. Python:Resquest/Response
  9. HTTP/HTTPS的请求和响应
  10. [JavaScript] 日期时间戳的使用与计算