仿马蜂窝TabLayout 波纹滑动菜单导航栏

先看一下马蜂窝的样式
在这里插入图片描述
我刚看到觉得下面的样式好神奇,自己就像动手做一做。

由于数学方面我不是很精通,我的实现方式没有复杂的公式计算,而是通过绘制+覆盖的形式。

自己写一个TabLayout过于麻烦,这里就借用了MaterialDesign 的TabLayout改动了其中的draw的代码;

这里绘制路径主要用的是贝塞尔曲线不了解的可以先去网上搜下用法
1.首先设置Paint绘制线条

int lineWidth = 8;
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(lineWidth);

2.TabLayout中又一个方法可以计算出每个tab的边界坐标

private void calculateTabViewContentBounds(
                @NonNull TabView tabView, @NonNull RectF contentBounds) {
            int tabViewContentWidth = tabView.getContentWidth();
            int minIndicatorWidth = (int) ViewUtils.dpToPx(getContext(), MIN_INDICATOR_WIDTH);

            if (tabViewContentWidth < minIndicatorWidth) {
                tabViewContentWidth = minIndicatorWidth;
            }

            int tabViewCenter = (tabView.getLeft() + tabView.getRight()) / 2;
            int contentLeftBounds = tabViewCenter - (tabViewContentWidth / 2);
            int contentRightBounds = tabViewCenter + (tabViewContentWidth / 2);

            contentBounds.set(contentLeftBounds, 0, contentRightBounds, 0);
        }

3.从起点开始绘制所有Tab的底部曲线

//设置本文的宽度默认为100,后期可以自己根据情况进行设置
int total = 100;
for (int i = 0; i < getTabCount(); i++) {
                    View tabView = getChildAt(i);
                    calculateTabViewContentBounds((TabView) tabView, tabViewContentBounds);
                    int left = (int) tabViewContentBounds.left;
                    int right = (int) tabViewContentBounds.right;
                    //底部曲线起点、终点距Tab边界的距离
                    smDim = (right - left - total) / 2;
                    //绘制第一个tab的曲线
                    if (i == 0) {
                    //移动到曲线绘制起点
                        mPath.moveTo(left + smDim, startY);
                        //开始规划路径
                        mPath.rQuadTo(total / 2, indicatorHeight / 2, total, 0);
                    } else {
                        int cx = smDim + (left - lastRight) / 2;
                        //绘制两个tab之间的曲线
                        mPath.rQuadTo(cx, -indicatorHeight + lineWidth, smDim + lastsmDim + (left - lastRight), 0);
                        //绘制tab下面的曲线
                        mPath.rQuadTo(total / 2, indicatorHeight / 2, total, 0);

                    }
                    //记录上次的边界坐标
                    lastRight = right;
                    lastsmDim = smDim;
                }
//开始绘制路径                                canvas.drawPath(mPath, paint);

这样整个tab下面的曲线就完成了,如下图所示:
在这里插入图片描述
4.开始绘制中遮罩层,覆盖曲线只留下当前位置tab的总宽度

                blockPaint.setStyle(Paint.Style.FILL);
                blockPaint.setColor(Color.parseColor("#f8f8f8"));
                int dimen = (indicatorRight - indicatorLeft - total) / 2;
                canvas.drawRect(0, indicatorTop, indicatorLeft + dimen, indicatorBottom, blockPaint);
                canvas.drawRect(indicatorRight - dimen, indicatorTop, getWidth(), indicatorBottom, blockPaint);

根据tab的移动 动态绘制遮罩层就实现了曲线移动的视觉
最终实现结果如下图所示:
在这里插入图片描述
这里有一个问题就是当两个相邻tab的宽度相差比较大的时候曲线在某一点拐点比较生硬。

当然如果数学功底比较好的,可以根据坐标计算出贝塞尔曲线在某一点的坐标值,这样可能会解决上面的问题。

如果有更好的方法还请多多指教;

Demo 地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值