【问题标题】:How to invert Curved Bottom Navigation?如何反转弯曲底部导航?
【发布时间】:2019-05-08 12:55:11
【问题描述】:

我找到了一个库https://github.com/androidtutorialonline/CurvedBottomNavigationView,它用画布绘制了一条曲线。 我想反转曲线,使曲线不会从顶部开始。 曲线应该从底部到顶部。但我现在真的不知道如何反转这一点。我尝试了 2 个小时,我不知道如何绘制立方体。

看起来像这样:

但我希望它看起来像这样, 它应该只改变这张图片中的曲线。 不要像我所做的那样旋转整个事情以使您清楚。 只有曲线应该像这个截图一样绘制:

有密码

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.util.AttributeSet;

public class Test extends BottomNavigationView {
    private Path mPath;
    private Paint mPaint;


    /** the CURVE_CIRCLE_RADIUS represent the radius of the fab button */
    public final int CURVE_CIRCLE_RADIUS = 256 / 3;
    // the coordinates of the first curve
    public Point mFirstCurveStartPoint = new Point();
    public Point mFirstCurveEndPoint = new Point();
    public Point mFirstCurveControlPoint2 = new Point();
    public Point mFirstCurveControlPoint1 = new Point();

    //the coordinates of the second curve
    @SuppressWarnings("FieldCanBeLocal")
    public Point mSecondCurveStartPoint = new Point();
    public Point mSecondCurveEndPoint = new Point();
    public Point mSecondCurveControlPoint1 = new Point();
    public Point mSecondCurveControlPoint2 = new Point();
    public int mNavigationBarWidth;
    public int mNavigationBarHeight;

    public Test(Context context) {
        super(context);
        init();
    }

    public Test(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public Test(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mPath = new Path();
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mPaint.setColor(Color.WHITE);
        setBackgroundColor(Color.TRANSPARENT);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // get width and height of navigation bar
        // Navigation bar bounds (width & height)
         mNavigationBarWidth = getWidth();
         mNavigationBarHeight = getHeight();
        // the coordinates (x,y) of the start point before curve
        mFirstCurveStartPoint.set((mNavigationBarWidth / 2) - (CURVE_CIRCLE_RADIUS * 2) - (CURVE_CIRCLE_RADIUS / 3), 0);
        // the coordinates (x,y) of the end point after curve
        mFirstCurveEndPoint.set(mNavigationBarWidth / 2, CURVE_CIRCLE_RADIUS + (CURVE_CIRCLE_RADIUS / 4));
        // same thing for the second curve
        mSecondCurveStartPoint = mFirstCurveEndPoint;
        mSecondCurveEndPoint.set((mNavigationBarWidth / 2) + (CURVE_CIRCLE_RADIUS * 2) + (CURVE_CIRCLE_RADIUS / 3), 0);

        // the coordinates (x,y)  of the 1st control point on a cubic curve
        mFirstCurveControlPoint1.set(mFirstCurveStartPoint.x + CURVE_CIRCLE_RADIUS + (CURVE_CIRCLE_RADIUS / 4), mFirstCurveStartPoint.y);
        // the coordinates (x,y)  of the 2nd control point on a cubic curve
        mFirstCurveControlPoint2.set(mFirstCurveEndPoint.x - (CURVE_CIRCLE_RADIUS * 2) + CURVE_CIRCLE_RADIUS, mFirstCurveEndPoint.y);

        mSecondCurveControlPoint1.set(mSecondCurveStartPoint.x + (CURVE_CIRCLE_RADIUS * 2) - CURVE_CIRCLE_RADIUS, mSecondCurveStartPoint.y);
        mSecondCurveControlPoint2.set(mSecondCurveEndPoint.x - (CURVE_CIRCLE_RADIUS + (CURVE_CIRCLE_RADIUS / 4)), mSecondCurveEndPoint.y);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPath.reset();
        mPath.moveTo(0, 0);
        mPath.lineTo(mFirstCurveStartPoint.x, mFirstCurveStartPoint.y);

        mPath.cubicTo(mFirstCurveControlPoint1.x, mFirstCurveControlPoint1.y,
                mFirstCurveControlPoint2.x, mFirstCurveControlPoint2.y,
                mFirstCurveEndPoint.x, mFirstCurveEndPoint.y);

        mPath.cubicTo(mSecondCurveControlPoint1.x, mSecondCurveControlPoint1.y,
                mSecondCurveControlPoint2.x, mSecondCurveControlPoint2.y,
                mSecondCurveEndPoint.x, mSecondCurveEndPoint.y);

        mPath.lineTo(mNavigationBarWidth, 0);
        mPath.lineTo(mNavigationBarWidth, mNavigationBarHeight);
        mPath.lineTo(0, mNavigationBarHeight);
        mPath.close();

        canvas.drawPath(mPath, mPaint);
    }
}

【问题讨论】:

    标签: android canvas path


    【解决方案1】:

    由于您要在 x 轴上镜像给定曲线,因此您必须更改所有点的 y 坐标。例子:

    • 0 变为 navigationbarHeight
    • navigationbarHeight 变为 0
    • RADIUS 变为 navigationbarHeight - RADIUS

    我引入了额外的变量,以便能够在同一个View 中绘制两条曲线:

    private Path mOtherPath;
    private Paint mOtherPaint;
    
    
    // the coordinates of the first "inverted" curve
    public Point mFirstOtherCurveStartPoint = new Point();
    public Point mFirstOtherCurveEndPoint = new Point();
    public Point mFirstOtherCurveControlPoint2 = new Point();
    public Point mFirstOtherCurveControlPoint1 = new Point();
    
    //the coordinates of the second "inverted" curve
    @SuppressWarnings("FieldCanBeLocal")
    public Point mSecondOtherCurveStartPoint = new Point();
    public Point mSecondOtherCurveEndPoint = new Point();
    public Point mSecondOtherCurveControlPoint1 = new Point();
    public Point mSecondOtherCurveControlPoint2 = new Point();
    

    init()中初始化PathPaint

    private void init() {
        mPath = new Path();
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mPaint.setColor(Color.LTGRAY);
    
        mOtherPath = new Path();
        mOtherPaint = new Paint();
        mOtherPaint.setStyle(Paint.Style.STROKE);
        mOtherPaint.setStrokeWidth(8f);
        mOtherPaint.setColor(Color.RED);
    
        setBackgroundColor(Color.TRANSPARENT);
    }
    

    onSizeChanged()中的新变量设置值

    // ... last lines of the given curve ...
    mSecondCurveControlPoint1.set(mSecondCurveStartPoint.x + (CURVE_CIRCLE_RADIUS * 2) - CURVE_CIRCLE_RADIUS, mSecondCurveStartPoint.y);
    mSecondCurveControlPoint2.set(mSecondCurveEndPoint.x - (CURVE_CIRCLE_RADIUS + (CURVE_CIRCLE_RADIUS / 4)), mSecondCurveEndPoint.y);
    
    // and now once more for the "inverted" curve...
    //
    
    // the coordinates (x,y) of the start point before curve
    mFirstOtherCurveStartPoint.set((mNavigationBarWidth / 2) - (CURVE_CIRCLE_RADIUS * 2) - (CURVE_CIRCLE_RADIUS / 3), mNavigationBarHeight);
    // the coordinates (x,y) of the end point after curve
    mFirstOtherCurveEndPoint.set(mNavigationBarWidth / 2, mNavigationBarHeight - (CURVE_CIRCLE_RADIUS + (CURVE_CIRCLE_RADIUS / 4) ) );
    // same thing for the second curve
    mSecondOtherCurveStartPoint = mFirstOtherCurveEndPoint;
    mSecondOtherCurveEndPoint.set((mNavigationBarWidth / 2) + (CURVE_CIRCLE_RADIUS * 2) + (CURVE_CIRCLE_RADIUS / 3), mNavigationBarHeight);
    
    // the coordinates (x,y)  of the 1st control point on a cubic curve
    mFirstOtherCurveControlPoint1.set(mFirstOtherCurveStartPoint.x + CURVE_CIRCLE_RADIUS + (CURVE_CIRCLE_RADIUS / 4), mFirstOtherCurveStartPoint.y);
    // the coordinates (x,y)  of the 2nd control point on a cubic curve
    mFirstOtherCurveControlPoint2.set(mFirstOtherCurveEndPoint.x - (CURVE_CIRCLE_RADIUS * 2) + CURVE_CIRCLE_RADIUS, mFirstOtherCurveEndPoint.y);
    
    mSecondOtherCurveControlPoint1.set(mSecondOtherCurveStartPoint.x + (CURVE_CIRCLE_RADIUS * 2) - CURVE_CIRCLE_RADIUS, mSecondOtherCurveStartPoint.y);
    mSecondOtherCurveControlPoint2.set(mSecondOtherCurveEndPoint.x - (CURVE_CIRCLE_RADIUS + (CURVE_CIRCLE_RADIUS / 4)), mSecondOtherCurveEndPoint.y);
    

    最后,将 onDraw() 中的所有内容拼凑在一起

    // ... last line of drawing the "normal" curve ...
    canvas.drawPath(mPath, mPaint);
    
    // now we draw the mirrored curve:
    mOtherPath.reset();
    mOtherPath.moveTo(0, mNavigationBarHeight);
    mOtherPath.lineTo(mFirstOtherCurveStartPoint.x, mFirstOtherCurveStartPoint.y);
    mOtherPath.cubicTo(mFirstOtherCurveControlPoint1.x, mFirstOtherCurveControlPoint1.y,
            mFirstOtherCurveControlPoint2.x, mFirstOtherCurveControlPoint2.y,
            mFirstOtherCurveEndPoint.x, mFirstOtherCurveEndPoint.y);
    
    mOtherPath.cubicTo(mSecondOtherCurveControlPoint1.x, mSecondOtherCurveControlPoint1.y,
            mSecondOtherCurveControlPoint2.x, mSecondOtherCurveControlPoint2.y,
            mSecondOtherCurveEndPoint.x, mSecondOtherCurveEndPoint.y);
    mOtherPath.lineTo(mNavigationBarWidth, mNavigationBarHeight);
    mOtherPath.lineTo(mNavigationBarWidth, 0);
    mOtherPath.lineTo(0, 0);
    mOtherPath.close();
    canvas.drawPath(mOtherPath, mOtherPaint);
    

    结果:

    【讨论】:

    • 谢谢,为我节省了很多时间。我试图将 0 更改为 navigationbarHeight 等,但我不知道为什么它不起作用。去理解它!
    猜你喜欢
    • 2020-02-15
    • 2022-01-16
    • 2021-11-29
    • 1970-01-01
    • 2020-10-21
    • 2016-09-26
    • 1970-01-01
    • 2021-05-14
    • 1970-01-01
    相关资源
    最近更新 更多