• 安卓实现饿了么点餐界面效果(京东类别左右列表联动)


    没有效果图的示例简直就是扯淡

    在这里插入图片描述


    通过两个RecyclerView实现左右联动,吸附的标题通过自定义分割线view实现


    源码在最下面👇

    废话不多说,直接看代码吧。

    Mainactivity.class

    package com.cc.test;
    
    import android.graphics.Color;
    import android.os.Bundle;
    import android.support.design.widget.Snackbar;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.DividerItemDecoration;
    import android.support.v7.widget.GridLayoutManager;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.util.Log;
    import android.view.View;
    import android.widget.TextView;
    
    import com.cc.test.adapter.LeftAdapter;
    import com.cc.test.adapter.RightAdapter;
    import com.cc.test.listener.RightItemCheckListener;
    import com.cc.test.model.RightBean;
    import com.cc.test.model.SortBean;
    import com.cc.test.view.ItemHeaderDecoration;
    import com.google.gson.Gson;
    import com.google.gson.reflect.TypeToken;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 主界面
     * 14点57分
     *
     * @author cc
     */
    public class MainActivity extends AppCompatActivity implements RightItemCheckListener {
    
        //左边的rv列表和适配器
        private RecyclerView mRvLeft;
        private LeftAdapter leftAdapter;
        private LinearLayoutManager mLinearLayoutManager;
    
        //右边的rv列表和适配器
        private RecyclerView mRvRight;
        private RightAdapter rightAdapter;
        private GridLayoutManager mManager;
    
        //总数据源
        private List mSortBean = new ArrayList<>();
        //右边的数据源
        private List rightBeanList = new ArrayList<>();
    
        //头部吸附自定义分割线
        private ItemHeaderDecoration mDecoration;
        private boolean move = false;
        //标量
        private int mIndex = 0;
    
        //点击左边某一个具体的item的位置
        private int targetPosition;
        //是否可移动
        private boolean isMoved;
    
        /**
         * 开始
         *
         * @param savedInstanceState
         */
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //加载默认数据
            getDefaultData();
            //初始化控件
            initLeftView();
            initRightView();
        }
    
        /**
         * 获取默认数据
         */
        private void getDefaultData() {
            //获取asset目录下的资源文件
            String assetsData = getAssetsData("data.json");
            Gson gson = new Gson();
            //mSortBean就是要使用的集合啦
            mSortBean = gson.fromJson(assetsData, new TypeToken>() {
            }.getType());
        }
    
        /**
         * 初始化左边的rv及绑定适配器
         */
        private void initLeftView() {
            mRvLeft = (RecyclerView) findViewById(R.id.rv_left);
            mLinearLayoutManager = new LinearLayoutManager(this);
            mRvLeft.setLayoutManager(mLinearLayoutManager);
            DividerItemDecoration decoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
            mRvLeft.addItemDecoration(decoration);
    
            //左边的item要填充的内容啦
            List leftTitle = new ArrayList<>();
            //初始化左侧列表数据
            for (int i = 0; i < mSortBean.size(); i++) {
                leftTitle.add(mSortBean.get(i).getName());
            }
            //左边的adapter开始实现并处理item的点击事件
            leftAdapter = new LeftAdapter(this, leftTitle, (id, position) -> {
                //可以移动啦
                isMoved = true;
                //目标的下标
                targetPosition = position;
                //去设置
                setChecked(position, true);
            });
            //绑定适配器
            mRvLeft.setAdapter(leftAdapter);
        }
    
        /**
         * 创建右边的布局
         */
        private void initRightView() {
            //获取右边的控件
            mRvRight = (RecyclerView) findViewById(R.id.rv_right);
            //监听右边的滑动事件
            mRvRight.addOnScrollListener(new RecyclerViewListener());
            //创建item布局管理器
            mManager = new GridLayoutManager(this, 3);
            //通过isTitle的标志来判断是否是头部吸附title
            mManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    return rightBeanList.get(position).isTitle() ? 3 : 1;
                }
            });
            //设置布局管理
            mRvRight.setLayoutManager(mManager);
            //点击事件
            rightAdapter = new RightAdapter(this, rightBeanList, (id, position) -> {
                String content = "";
                switch (id) {
                    case R.id.root:
                        content = "title";
                        break;
                    case R.id.content:
                        content = "content";
                        break;
    
                }
                Snackbar snackbar = Snackbar.make(mRvRight, "当前点击的是" + content + ":" + rightBeanList.get(position).getName(), Snackbar.LENGTH_SHORT);
                View mView = snackbar.getView();
                mView.setBackgroundColor(Color.BLUE);
                TextView text = mView.findViewById(android.support.design.R.id.snackbar_text);
                text.setTextColor(Color.WHITE);
                text.setTextSize(25);
                snackbar.show();
            });
            //绑定适配器
            mRvRight.setAdapter(rightAdapter);
            //创建一个自定义分割线,给右边的列表布局添加上
            mDecoration = new ItemHeaderDecoration(this, rightBeanList);
            mRvRight.addItemDecoration(mDecoration);
            //分割线点击事件
            mDecoration.setCheckListener(this);
            //循环遍历数据源
            for (int i = 0; i < mSortBean.size(); i++) {
                //将一级数据添加为头部数据(就左边的列表数据)
                RightBean head = new RightBean(mSortBean.get(i).getName());
                //头部设置为true
                head.setTitle(true);
                head.setTitleName(mSortBean.get(i).getName());
                //这里的tag不能为空,不能重复,是滑动对比用的
                head.setTag(String.valueOf(i));
                //添加到右边的数据源集合里面去
                rightBeanList.add(head);
                //开始遍历二级数据,真正在右边item加载的数据
                List categoryTwoArray = mSortBean.get(i).getCategoryTwoArray();
                //遍历
                for (int j = 0; j < categoryTwoArray.size(); j++) {
                    //遍历每一个并添加到右边的数据源里面
                    RightBean body = new RightBean(categoryTwoArray.get(j).getName());
                    body.setTag(String.valueOf(i));
                    String name = mSortBean.get(i).getName();
                    body.setTitleName(name);
                    rightBeanList.add(body);
                }
            }
            //刷新
            rightAdapter.notifyDataSetChanged();
            mDecoration.setData(rightBeanList);
        }
    
        /**
         * 右边列表的滑动事件
         */
        private class RecyclerViewListener extends RecyclerView.OnScrollListener {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (move && newState == RecyclerView.SCROLL_STATE_IDLE) {
                    move = false;
                    int n = mIndex - mManager.findFirstVisibleItemPosition();
                    if (0 <= n && n < mRvRight.getChildCount()) {
                        int top = mRvRight.getChildAt(n).getTop();
                        mRvRight.smoothScrollBy(0, top);
                    }
                }
            }
    
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                if (move) {
                    move = false;
                    int n = mIndex - mManager.findFirstVisibleItemPosition();
                    if (0 <= n && n < mRvRight.getChildCount()) {
                        int top = mRvRight.getChildAt(n).getTop();
                        mRvRight.scrollBy(0, top);
                    }
                }
            }
        }
    
        /**
         * 选中的点击事件
         *
         * @param position 当前下标
         * @param isLeft   是否是左边的
         */
        private void setChecked(int position, boolean isLeft) {
            //左边
            if (isLeft) {
                leftAdapter.setCheckedPosition(position);
                //此处的位置需要根据每个分类的集合来进行计算
                int count = 0;
                for (int i = 0; i < position; i++) {
                    count += mSortBean.get(i).getCategoryTwoArray().size();
                }
                count += position;
                mIndex = count;
                mRvRight.stopScroll();
                smoothMoveToPosition(count);
                ItemHeaderDecoration.setCurrentTag(String.valueOf(targetPosition));//凡是点击左边,将左边点击的位置作为当前的tag
            } else {
                //右边
                if (isMoved) {
                    isMoved = false;
                } else {
                    leftAdapter.setCheckedPosition(position);
                }
                ItemHeaderDecoration.setCurrentTag(String.valueOf(position));//如果是滑动右边联动左边,则按照右边传过来的位置作为tag
            }
            //移动到中间
            moveToCenter(position);
        }
    
        /**
         * 滑动到某一个位置
         *
         * @param n
         */
        private void smoothMoveToPosition(int n) {
            int firstItem = mManager.findFirstVisibleItemPosition();
            int lastItem = mManager.findLastVisibleItemPosition();
            if (n <= firstItem) {
                mRvRight.scrollToPosition(n);
            } else if (n <= lastItem) {
                int top = mRvRight.getChildAt(n - firstItem).getTop();
                mRvRight.scrollBy(0, top);
            } else {
                mRvRight.scrollToPosition(n);
                move = true;
            }
        }
    
        /**
         * 将当前左边选中的item居中
         *
         * @param position
         */
        private void moveToCenter(int position) {
            //将点击的position转换为当前屏幕上可见的item的位置以便于计算距离顶部的高度,从而进行移动居中
            View childAt = mRvLeft.getChildAt(position - mLinearLayoutManager.findFirstVisibleItemPosition());
            if (childAt != null) {
                int y = (childAt.getTop() - mRvLeft.getHeight() / 2);
                mRvLeft.smoothScrollBy(0, y);
            }
        }
    
        /**
         * 右边item事件
         *
         * @param position
         * @param isScroll
         */
        @Override
        public void check(int position, boolean isScroll) {
            setChecked(position, isScroll);
        }
    
        /**
         * 从资源文件中获取分类json
         *
         * @param path
         * @return
         */
        private String getAssetsData(String path) {
            String result = "";
            try {
                //获取输入流
                InputStream mAssets = getAssets().open(path);
                //获取文件的字节数
                int length = mAssets.available();
                //创建byte数组
                byte[] buffer = new byte[length];
                //将文件中的数据写入到字节数组中
                mAssets.read(buffer);
                mAssets.close();
                result = new String(buffer);
                return result;
            } catch (IOException e) {
                e.printStackTrace();
                Log.e("fuck", e.getMessage());
                return result;
            }
        }
    
    }
    
    • 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
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329

    LeftAdapter.class

    package com.cc.test.adapter;
    
    import android.content.Context;
    import android.graphics.Color;
    import android.view.View;
    import android.widget.TextView;
    
    import com.cc.test.R;
    import com.cc.test.listener.RvItemClickListener;
    import com.cc.test.base.BaseAdapter;
    import com.cc.test.base.BaseHolder;
    
    import java.util.List;
    
    /**
     * 左边列表的适配器
     * 14点57分
     *
     * @author cc
     */
    public class LeftAdapter extends BaseAdapter {
    
        //当前选中的item下标
        private int checkedPosition;
    
        /**
         * 获取当前选中的item下标
         *
         * @param checkedPosition
         */
        public void setCheckedPosition(int checkedPosition) {
            this.checkedPosition = checkedPosition;
            notifyDataSetChanged();
        }
    
        /**
         * 构造方法
         *
         * @param context  上下文
         * @param list     item数据集合
         * @param listener 点击事件
         */
        public LeftAdapter(Context context, List list, RvItemClickListener listener) {
            super(context, list, listener);
        }
    
        /**
         * 获取布局文件
         *
         * @param viewType
         * @return
         */
        @Override
        protected int getLayoutId(int viewType) {
            return R.layout.item_left_detail;
        }
    
        /**
         * holder
         *
         * @param view
         * @param viewType
         * @return
         */
        @Override
        protected BaseHolder getHolder(View view, int viewType) {
            return new SortHolder(view, listener);
        }
    
        /**
         * 处理数据交互
         */
        private class SortHolder extends BaseHolder {
    
            //左边的item内容
            private TextView tvName;
    
            SortHolder(View itemView, RvItemClickListener listener) {
                super(itemView, listener);
                tvName = itemView.findViewById(R.id.tv_sort);
            }
    
            @Override
            public void bindHolder(String string, int position) {
                //填充左边的item内容
                tvName.setText(string);
                //处理选中与未选中的ui状态
                tvName.setBackgroundColor(
                        position == checkedPosition
                                ? Color.parseColor("#f3f3f3")
                                : Color.parseColor("#FFFFFF")
                );
                tvName.setTextColor(
                        position == checkedPosition
                                ? Color.parseColor("#0068cf")
                                : Color.parseColor("#1e1d1d")
                );
            }
    
        }
    }
    
    
    • 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

    RightAdapter.class

    package com.cc.test.adapter;
    
    import android.content.Context;
    import android.view.View;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import com.cc.test.R;
    import com.cc.test.listener.RvItemClickListener;
    import com.cc.test.base.BaseAdapter;
    import com.cc.test.base.BaseHolder;
    import com.cc.test.model.RightBean;
    
    import java.util.List;
    
    /**
     * 右边的适配器
     * 14点58分
     *
     * @author cc
     */
    public class RightAdapter extends BaseAdapter {
    
        /**
         * 构造方法
         *
         * @param context
         * @param list
         * @param listener
         */
        public RightAdapter(Context context, List list, RvItemClickListener listener) {
            super(context, list, listener);
        }
    
        /**
         * 布局view
         *
         * @param viewType
         * @return
         */
        @Override
        protected int getLayoutId(int viewType) {
            return viewType == 0 ? R.layout.item_right_title : R.layout.item_right_detail;
        }
    
        /**
         * 根据isTitle确认是否未头部吸附布局
         *
         * @param position
         * @return
         */
        @Override
        public int getItemViewType(int position) {
            return list.get(position).isTitle() ? 0 : 1;
        }
    
        @Override
        protected BaseHolder getHolder(View view, int viewType) {
            return new ClassifyHolder(view, viewType, listener);
        }
    
        public class ClassifyHolder extends BaseHolder {
            TextView tvCity;
            ImageView avatar;
            TextView tvTitle;
    
            public ClassifyHolder(View itemView, int type, RvItemClickListener listener) {
                super(itemView, listener);
                switch (type) {
                    case 0:
                        tvTitle = itemView.findViewById(R.id.tv_title);
                        break;
                    case 1:
                        tvCity = itemView.findViewById(R.id.tvCity);
                        avatar = itemView.findViewById(R.id.ivAvatar);
                        break;
                }
    
            }
    
            @Override
            public void bindHolder(RightBean sortBean, int position) {
                int itemViewType = RightAdapter.this.getItemViewType(position);
                switch (itemViewType) {
                    case 0:
                        tvTitle.setText(sortBean.getName());
                        break;
                    case 1:
                        tvCity.setText(sortBean.getName());
                        break;
                }
    
            }
        }
    }
    
    
    • 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

    自定义分割线

    package com.cc.test.view;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.support.v7.widget.GridLayoutManager;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.text.TextUtils;
    import android.util.Log;
    import android.util.TypedValue;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    
    import com.cc.test.R;
    import com.cc.test.listener.RightItemCheckListener;
    import com.cc.test.model.RightBean;
    
    import java.util.List;
    
    /**
     * 吸附的分割布局
     * 14点57分
     *
     * @author cc
     */
    public class ItemHeaderDecoration extends RecyclerView.ItemDecoration {
    
        private int mTitleHeight;
        private List mDatas;
        private LayoutInflater mInflater;
        private RightItemCheckListener mCheckListener;
        public static String currentTag = "0";//标记当前左侧选中的position,因为有可能选中的item,右侧不能置顶,所以强制替换掉当前的tag
    
        public void setCheckListener(RightItemCheckListener checkListener) {
            mCheckListener = checkListener;
        }
    
        public ItemHeaderDecoration(Context context, List datas) {
            this.mDatas = datas;
            Paint paint = new Paint();
            mTitleHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, context.getResources().getDisplayMetrics());
            int titleFontSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, context.getResources().getDisplayMetrics());
            paint.setTextSize(titleFontSize);
            paint.setAntiAlias(true);
            mInflater = LayoutInflater.from(context);
        }
    
        public ItemHeaderDecoration setData(List mDatas) {
            this.mDatas = mDatas;
            return this;
        }
    
        public static void setCurrentTag(String currentTag) {
            ItemHeaderDecoration.currentTag = currentTag;
        }
    
        @Override
        public void onDrawOver(Canvas canvas, final RecyclerView parent, RecyclerView.State state) {
            GridLayoutManager manager = (GridLayoutManager) parent.getLayoutManager();
            GridLayoutManager.SpanSizeLookup spanSizeLookup = manager.getSpanSizeLookup();
            int pos = ((LinearLayoutManager) (parent.getLayoutManager())).findFirstVisibleItemPosition();
            int spanSize = spanSizeLookup.getSpanSize(pos);
            Log.d("pos--->", String.valueOf(pos));
            String tag = mDatas.get(pos).getTag();
            View child = parent.findViewHolderForLayoutPosition(pos).itemView;
            boolean isTranslate = false;//canvas是否平移的标志
            if (!TextUtils.equals(mDatas.get(pos).getTag(), mDatas.get(pos + 1).getTag())
                    || !TextUtils.equals(mDatas.get(pos).getTag(), mDatas.get(pos + 2).getTag())
                    || !TextUtils.equals(mDatas.get(pos).getTag(), mDatas.get(pos + 3).getTag())
            ) {
                tag = mDatas.get(pos).getTag();
                int i = child.getHeight() + child.getTop();
                Log.d("i---->", String.valueOf(i));
                if (spanSize == 1) {
                    //body 才平移
                    if (child.getHeight() + child.getTop() < mTitleHeight) {
                        canvas.save();
                        isTranslate = true;
                        int height = child.getHeight() + child.getTop() - mTitleHeight;
                        canvas.translate(0, height);
                    }
                }
            }
            drawHeader(parent, pos, canvas);
            if (isTranslate) {
                canvas.restore();
            }
            Log.d("tag--->", tag + "VS" + currentTag);
            if (!TextUtils.equals(tag, currentTag)) {
                currentTag = tag;
                Integer integer = Integer.valueOf(tag);
                mCheckListener.check(integer, false);
            }
        }
    
        /**
         * @param parent
         * @param pos
         */
        private void drawHeader(RecyclerView parent, int pos, Canvas canvas) {
            View topTitleView = mInflater.inflate(R.layout.item_right_title, parent, false);
            TextView tvTitle = (TextView) topTitleView.findViewById(R.id.tv_title);
            tvTitle.setText(mDatas.get(pos).getTitleName());
            //绘制title开始
            int toDrawWidthSpec;//用于测量的widthMeasureSpec
            int toDrawHeightSpec;//用于测量的heightMeasureSpec
            RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) topTitleView.getLayoutParams();
            if (lp == null) {
                lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);//这里是根据复杂布局layout的width height,new一个Lp
                topTitleView.setLayoutParams(lp);
            }
            topTitleView.setLayoutParams(lp);
            if (lp.width == ViewGroup.LayoutParams.MATCH_PARENT) {
                //如果是MATCH_PARENT,则用父控件能分配的最大宽度和EXACTLY构建MeasureSpec
                toDrawWidthSpec = View.MeasureSpec.makeMeasureSpec(parent.getWidth() - parent.getPaddingLeft() - parent.getPaddingRight(), View.MeasureSpec.EXACTLY);
            } else if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
                //如果是WRAP_CONTENT,则用父控件能分配的最大宽度和AT_MOST构建MeasureSpec
                toDrawWidthSpec = View.MeasureSpec.makeMeasureSpec(parent.getWidth() - parent.getPaddingLeft() - parent.getPaddingRight(), View.MeasureSpec.AT_MOST);
            } else {
                //否则则是具体的宽度数值,则用这个宽度和EXACTLY构建MeasureSpec
                toDrawWidthSpec = View.MeasureSpec.makeMeasureSpec(lp.width, View.MeasureSpec.EXACTLY);
            }
            //高度同理
            if (lp.height == ViewGroup.LayoutParams.MATCH_PARENT) {
                toDrawHeightSpec = View.MeasureSpec.makeMeasureSpec(parent.getHeight() - parent.getPaddingTop() - parent.getPaddingBottom(), View.MeasureSpec.EXACTLY);
            } else if (lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
                toDrawHeightSpec = View.MeasureSpec.makeMeasureSpec(parent.getHeight() - parent.getPaddingTop() - parent.getPaddingBottom(), View.MeasureSpec.AT_MOST);
            } else {
                toDrawHeightSpec = View.MeasureSpec.makeMeasureSpec(mTitleHeight, View.MeasureSpec.EXACTLY);
            }
            //依次调用 measure,layout,draw方法,将复杂头部显示在屏幕上
            topTitleView.measure(toDrawWidthSpec, toDrawHeightSpec);
            topTitleView.layout(parent.getPaddingLeft(), parent.getPaddingTop(), parent.getPaddingLeft() + topTitleView.getMeasuredWidth(), parent.getPaddingTop() + topTitleView.getMeasuredHeight());
            topTitleView.draw(canvas);//Canvas默认在视图顶部,无需平移,直接绘制
            //绘制title结束
        }
    
    }
    
    • 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

    还有部分代码就不一一贴出来了。


    呐,代码就这些啦,简单吧~~

    附上demo源码。

    源码:源码请点这里

    如果下不了源码,请评论带邮箱。


    phone:18588400509
    email:mr.cai_cai@foxmail.com

    如果有什么问题,欢迎大家指导。并相互联系,希望能够通过文章互相学习。

    											                               	---财财亲笔
    
    • 1
  • 相关阅读:
    王道数据结构6.2(图的应用)
    梦开始的地方 —— C语言内存函数memcpy-memmove-memset(使用+模拟实现)
    遮挡Windows电脑上烦人的微信/企业微信/钉钉消息闪烁提醒
    跳槽了...历经字节测试岗3轮面试,4个小时灵魂拷问,结局透心凉...
    极客天成RDMA分布式存储加速自动驾驶仿真建模
    jupyter notebook的安装和使用
    Linux I/O schedulers类型简介
    关于vba代码运行时错误1004 应用程序定义或对象定义错误问题
    磁盘和文件系统管理(二)
    云原生爱好者周刊:Dockershim 即将被正式废弃
  • 原文地址:https://blog.csdn.net/qq_35840038/article/details/126785422