Android高仿马蜂窝Tabbar波浪线

    科技2022-07-15  103

    文章目录

    简介效果思路关键代码先画完整的弧线,图中红色曲线再画指示器部分的弧线,图中深蓝色弧线 不足源码[github](https://github.com/Super-Bin/HornetNestView.git)

    简介

    Android高仿马蜂窝Tabbar波浪线,tabbar的部分直接使用FlycoTabLayout这个库,很早以前用过,重点也不在这tabbar功能,主要是如何绘制tabbar下方的波浪线。

    效果

    可以直接看github

    思路

    波浪线的实现,可以借助二阶贝塞尔曲线。先画出一整条波浪线,然后再截取其中蓝色的线段,监听ViewPager的滑动,来改变截取的起始点,看起来就像会动的波浪线。

    关键代码

    其中

    黄色框,表示一个tab的宽度深蓝色的弧线,表示指示器indicator的宽度浅蓝色线,表示指示器indicator与tab的间距

    先画完整的弧线,图中红色曲线

    int distance, lastDistance = 0; int indicatorTop = getHeight() - indicatorHeight; int indicatorBottom = getHeight(); // 先计算开始坐标 int startY = (indicatorBottom - indicatorTop) / 2 + indicatorTop; for (int i = 0; i < this.mTabCount; i++) { View currentTabView = mTitleContainer.getChildAt(i); float left = currentTabView.getLeft(); float right = currentTabView.getRight(); // 表示当前指示器与tab的偏移量 distance = (int) ((right - left - indicatorWidth) / 2); Log.i(TAG, "left = " + left); Log.i(TAG, "right = " + right); if (i == 0) { mPath.moveTo(left + distance, startY); // 开始画指示器下半部分弧线 mPath.rQuadTo(indicatorWidth / 2, indicatorHeight / 2, indicatorWidth, 0); // 获取一个指示器的长度 mArcMeasure.setPath(mPath, false); mArcPathLength = mArcMeasure.getLength(); Log.i(TAG, "一段圆弧的长度 mArcPathLength = " + mArcPathLength); } else { int nextX = (distance + lastDistance) / 2; // 这里画上半部分弧线,因为这个弧线被拉的比较长,所以没有除以2 mPath.rQuadTo(nextX, -indicatorHeight, distance + lastDistance, 0); // 再继续画指示器下半部分弧线 mPath.rQuadTo(indicatorWidth / 2, indicatorHeight / 2, indicatorWidth, 0); } lastDistance = distance; } mPaint.setColor(Color.RED); // 完整的正弦曲线,背景底色 canvas.drawPath(mPath, mPaint);

    再画指示器部分的弧线,图中深蓝色弧线

    灰色框表示一个完整的周期,红色线相当于有三个完整的周期+最后一个下划线的曲线长度

    mMeasure.setPath(mPath, false); mPathLength = mMeasure.getLength(); ...//中间省略 float startD = 0; // 这种计算方式,是在保证每一个tab的宽度相等、而且每一个指示器长度也相等的情况下 float cycleLength = (mPathLength - mArcPathLength )/ (this.mTabCount - 1); // 一个周期长度 Log.i(TAG, "cycleLength = " + cycleLength); // 计算起始点 startD = this.mCurrentTab * cycleLength + cycleLength * this.mCurrentPositionOffset; if(startD < 0) { startD = 0; } Log.i(TAG, "startD = " + startD); mMeasure.getSegment(startD, startD + mArcPathLength, mDstPath, true); mPaint.setColor(Color.BLUE); // 绘制弧线段 canvas.drawPath(mDstPath, mPaint);

    不足

    目前的情况只适用,是在保证每一个tab的宽度相等、而且每一个指示器长度indicator也相等的情况下。不同Tab宽度、不同指示器indicato长度还没做,不过可以根据以上的思路进行修改就能达到目的。

    源码github

    Processed: 0.013, SQL: 8