Android 自定义漏斗图FunnelView(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qingfeng812/article/details/52211110

  1. 这个版本为固定设置漏斗数据;后面提供动态设置数据;
  2. 具有动画效果;
  3. 主要麻烦的地方是算坐标点;


效果截图:


代码 FunnelView:




import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;

import java.util.ArrayList;
import java.util.List;

/**
 * 漏斗图 v1.0
 */
@SuppressLint("NewApi")
public class FunnelView extends View implements ValueAnimator.AnimatorUpdateListener {
    public static final float ANGLE_SCALE = 3.0f;
    private List<Integer> mMoneys = new ArrayList<>();
    private int maxMoney;

    private float phaseX = 1f;
    private int textAlpha = 255;

    private Paint mPaint1;
    private Paint mPaint2;
    private Paint mPaint3;
    private Paint mPaint4;
    private Paint mPaint5;
    private Paint mPaint6;
    private Paint mPaint7;
    private Paint mPaint8;
    private Paint mPaint9;
    private Paint mPaint10;

    private Paint mPaintLine;
    private Paint mPaintText;


    private Path mPath1;
    private Path mPath2;
    private Path mPath3;
    private Path mPath4;
    private Path mPath5;
    private Path mPath6;
    private Path mPath7;
    private Path mPath8;
    private Path mPath9;
    private Path mPath10;


    private float mTotalHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 250, getResources().getDisplayMetrics());

    private float mPath1Height;
    private float mPath2Height;
    private float mPath3Height;
    private float mPath4Height;
    private float mPath5Height;
    private float mPath6Height;
    private float mPath7Height;
    private float mPath8Height;
    private float mPath9Height;
    private float mPath10Height;

    private float mPath1AngleWidth;
    private float mPath2AngleWidth;
    private float mPath3AngleWidth;
    private float mPath4AngleWidth;
    private float mPath5AngleWidth;
    private float mPath6AngleWidth;
    private float mPath7AngleWidth;
    private float mPath8AngleWidth;
    private float mPath9AngleWidth;
    private float mPath10AngleWidth;


    private float mPath3LineStartX;
    private float mPath3LineStartY;

    private float mPath4LineStartX;
    private float mPath4LineStartY;

    private float mPath5LineStartX;
    private float mPath5LineStartY;

    private float maxWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 330, getResources().getDisplayMetrics());
    private float maxLineH = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 90, getResources().getDisplayMetrics());
    private float minLineH = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics());

    private float startOffsetX = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics());
    private float startOffsetY = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics());

    private float lineStartOffsetX = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, getResources().getDisplayMetrics());
    private float textStartOffsetX = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 7, getResources().getDisplayMetrics());

    private float mLastX;
    private float mLastY;
    private float mLastWidth;

    public FunnelView(Context context) {
        this(context, null);
    }

    public FunnelView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    /**
     * @desc:设置数据
     * @author:Arison on 2016/8/15
     */
    public void setData(List<Integer> moneys, int maxMoney) {
        this.mMoneys = moneys;
        this.maxMoney = maxMoney;
        calculate();
        //int averageHeight = (int) (mTotalHeight / 5);
        invalidate();
    }

    private void calculate() {
        for (int i = 0; i < mMoneys.size(); i++) {
            int money = mMoneys.get(i);
            float scale = (float) money / maxMoney;
            switch (i) {
                case 0:
                    mPath1Height = mTotalHeight * scale * phaseX;
                    if (mPath1Height < minLineH * phaseX) {
                        mPath1Height = minLineH * phaseX;
                    } else if (mPath1Height > maxLineH * phaseX) {
                        mPath1Height = maxLineH * phaseX;
                    }
                    mPath1AngleWidth = mPath1Height / ANGLE_SCALE;
                    //System.out.println("mPath1Height=" + mPath1Height + " ,phaseX=" + phaseX);
                    break;
                case 1:
                    mPath2Height = mTotalHeight * scale * phaseX;
                    if (mPath2Height < minLineH * phaseX) {
                        mPath2Height = minLineH * phaseX;
                    } else if (mPath2Height > maxLineH * phaseX) {
                        mPath2Height = maxLineH * phaseX;
                    }

                    mPath2AngleWidth = mPath2Height / ANGLE_SCALE;

                    //System.out.println("mPath2Height=" + mPath2Height);
                    break;
                case 2:
                    mPath3Height = mTotalHeight * scale * phaseX;
                    if (mPath3Height < minLineH * phaseX) {
                        mPath3Height = minLineH * phaseX;
                    } else if (mPath3Height > maxLineH * phaseX) {
                        mPath3Height = maxLineH * phaseX;
                    }

                    mPath3AngleWidth = mPath3Height / ANGLE_SCALE;

                    //System.out.println("mPath3Height=" + mPath3Height);
                    break;
                case 3:
                    mPath4Height = mTotalHeight * scale * phaseX;
                    if (mPath4Height < minLineH * phaseX) {
                        mPath4Height = minLineH * phaseX;
                    } else if (mPath4Height > maxLineH * phaseX) {
                        mPath4Height = maxLineH * phaseX;
                    }

                    mPath4AngleWidth = mPath4Height / ANGLE_SCALE;

                    //System.out.println("mPath4Height=" + mPath4Height);
                    break;
                case 4:
                    mPath5Height = mTotalHeight * scale * phaseX;
                    if (mPath5Height < minLineH * phaseX) {
                        mPath5Height = minLineH * phaseX;
                    } else if (mPath5Height > maxLineH * phaseX) {
                        mPath5Height = maxLineH * phaseX;
                    }

                    mPath5AngleWidth = mPath5Height / ANGLE_SCALE;

                    //System.out.println("mPath5Height=" + mPath5Height);
                    break;
                case 5:
                    mPath6Height = mTotalHeight * scale * phaseX;
                    if (mPath6Height < minLineH * phaseX) {
                        mPath6Height = minLineH * phaseX;
                    } else if (mPath6Height > maxLineH * phaseX) {
                        mPath6Height = maxLineH * phaseX;
                    }

                    mPath6AngleWidth = mPath6Height / ANGLE_SCALE;
                    break;
                case 6:
                    mPath7Height = mTotalHeight * scale * phaseX;
                    if (mPath7Height < minLineH * phaseX) {
                        mPath7Height = minLineH * phaseX;
                    } else if (mPath7Height > maxLineH * phaseX) {
                        mPath7Height = maxLineH * phaseX;
                    }

                    mPath7AngleWidth = mPath7Height / ANGLE_SCALE;
                    break;
                case 7:
                    mPath8Height = mTotalHeight * scale * phaseX;
                    if (mPath8Height < minLineH * phaseX) {
                        mPath8Height = minLineH * phaseX;
                    } else if (mPath8Height > maxLineH * phaseX) {
                        mPath8Height = maxLineH * phaseX;
                    }

                    mPath8AngleWidth = mPath8Height / ANGLE_SCALE;
                    break;
                case 8:
                    mPath9Height = mTotalHeight * scale * phaseX;
                    if (mPath9Height < minLineH * phaseX) {
                        mPath9Height = minLineH * phaseX;
                    } else if (mPath9Height > maxLineH * phaseX) {
                        mPath9Height = maxLineH * phaseX;
                    }

                    mPath9AngleWidth = mPath9Height / ANGLE_SCALE;
                    break;
                case 9:
                    mPath10Height = mTotalHeight * scale * phaseX;
                    if (mPath10Height < minLineH * phaseX) {
                        mPath10Height = minLineH * phaseX;
                    } else if (mPath10Height > maxLineH * phaseX) {
                        mPath10Height = maxLineH * phaseX;
                    }

                    mPath10AngleWidth = mPath10Height / ANGLE_SCALE;
                    break;
            }

        }
    }

    private void init() {
        mPaint1 = new Paint();
        mPaint2 = new Paint();
        mPaint3 = new Paint();
        mPaint4 = new Paint();
        mPaint5 = new Paint();
        mPaint6 = new Paint();
        mPaint7 = new Paint();
        mPaint8 = new Paint();
        mPaint9 = new Paint();
        mPaint10 = new Paint();
        //FF0000   00CCFF   FFFF00  00FF00    FF00FF   FF9900  993366  C0C0C0  FFCC99
        mPaint1.setColor(Color.parseColor("#FF0000"));
        mPaint1.setStyle(Paint.Style.FILL);
        mPaint1.setDither(true);
        mPaint1.setAntiAlias(true);

        mPaint2.setColor(Color.parseColor("#00CCFF"));
        mPaint2.setStyle(Paint.Style.FILL);
        mPaint2.setDither(true);
        mPaint2.setAntiAlias(true);

        mPaint3.setColor(Color.parseColor("#FFFF00"));
        mPaint3.setStyle(Paint.Style.FILL);
        mPaint3.setDither(true);
        mPaint3.setAntiAlias(true);

        mPaint4.setColor(Color.parseColor("#00FF00"));
        mPaint4.setStyle(Paint.Style.FILL);
        mPaint4.setDither(true);
        mPaint4.setAntiAlias(true);

        mPaint5.setColor(Color.parseColor("#FF00FF"));
        mPaint5.setStyle(Paint.Style.FILL);
        mPaint5.setDither(true);
        mPaint5.setAntiAlias(true);


        mPaint6.setColor(Color.parseColor("#FF9900"));
        mPaint6.setStyle(Paint.Style.FILL);
        mPaint6.setDither(true);
        mPaint6.setAntiAlias(true);


        mPaint7.setColor(Color.parseColor("#993366"));
        mPaint7.setStyle(Paint.Style.FILL);
        mPaint7.setDither(true);
        mPaint7.setAntiAlias(true);


        mPaint8.setColor(Color.parseColor("#C0C0C0"));
        mPaint8.setStyle(Paint.Style.FILL);
        mPaint8.setDither(true);
        mPaint8.setAntiAlias(true);


        mPaint9.setColor(Color.parseColor("#FFCC99"));
        mPaint9.setStyle(Paint.Style.FILL);
        mPaint9.setDither(true);
        mPaint9.setAntiAlias(true);


        mPaint10.setColor(Color.parseColor("#FFCC99"));
        mPaint10.setStyle(Paint.Style.FILL);
        mPaint10.setDither(true);
        mPaint10.setAntiAlias(true);

        mPaintLine = new Paint();
        mPaintText = new Paint();
        mPaintLine.setColor(Color.parseColor("#A8ADB2"));
        mPaintLine.setStyle(Paint.Style.FILL);
        mPaintLine.setStrokeWidth(2);

        mPaintText.setColor(Color.parseColor("#A8ADB2"));
        mPaintText.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 14, getResources().getDisplayMetrics()));
        mPaintText.setAntiAlias(true);
        mPaintText.setTextAlign(Paint.Align.LEFT);
    }

    private void draw1(Canvas canvas) {
        mLastX = startOffsetX;
        mLastY = startOffsetY;
        mLastWidth = maxWidth - startOffsetX;

        mPath1 = new Path();
        mPath1.moveTo(mLastX, startOffsetY);
        mPath1.lineTo(mLastX + mLastWidth, startOffsetY);
        mPath1.lineTo(mLastX + mLastWidth - mPath1AngleWidth, mLastY + mPath1Height);
        mPath1.lineTo(mLastX + mPath1AngleWidth, mLastY + mPath1Height);

        mPath1.close();
        canvas.drawPath(mPath1, mPaint1);
        mLastWidth = mLastWidth - 2 * mPath1AngleWidth;
        mLastX = mLastX + mPath1AngleWidth;
        mLastY = mLastY + mPath1Height;
    }


    private void draw2(Canvas canvas) {

        mPath2 = new Path();

        mPath2.moveTo(mLastX, mLastY);
        mPath2.lineTo(mLastX + mLastWidth, mLastY);
        mPath2.lineTo(mLastX + mLastWidth - mPath2AngleWidth, mLastY + mPath2Height);
        mPath2.lineTo(mLastX + mPath2AngleWidth, mLastY + mPath2Height);
        mPath2.close();
        canvas.drawPath(mPath2, mPaint2);

        mLastWidth = mLastWidth - mPath2AngleWidth - mPath2AngleWidth;
        mLastX = mLastX + mPath2AngleWidth;
        mLastY = mLastY + mPath2Height;
    }


    private void draw3(Canvas canvas) {

        mPath3 = new Path();

        mPath3.moveTo(mLastX, mLastY);
        mPath3.lineTo(mLastX + mLastWidth, mLastY);
        mPath3.lineTo(mLastX + mLastWidth - mPath3AngleWidth, mLastY + mPath3Height);
        mPath3.lineTo(mLastX + mPath3AngleWidth, mLastY + mPath3Height);
        mPath3.close();
        canvas.drawPath(mPath3, mPaint3);

        mLastWidth = mLastWidth - mPath3AngleWidth - mPath3AngleWidth;
        mLastX = mLastX + mPath3AngleWidth;
        mLastY = mLastY + mPath3Height;
        mPath3LineStartX = mLastX + mLastWidth + mPath3AngleWidth / 2;
        mPath3LineStartY = mLastY - mPath3Height / 2;
    }

    private void draw4(Canvas canvas) {

        mPath4 = new Path();

        mPath4.moveTo(mLastX, mLastY);
        mPath4.lineTo(mLastX + mLastWidth, mLastY);
        mPath4.lineTo(mLastX + mLastWidth - mPath4AngleWidth, mLastY + mPath4Height);
        mPath4.lineTo(mLastX + mPath4AngleWidth, mLastY + mPath4Height);
        mPath4.close();
        canvas.drawPath(mPath4, mPaint4);

        mLastWidth = mLastWidth - 2 * mPath4AngleWidth;//最新长度
        mLastX = mLastX + mPath4AngleWidth;//第四个点的x坐标
        mLastY = mLastY + mPath4Height;//第四个点的y坐标
        mPath4LineStartX = mLastX + mLastWidth + mPath4AngleWidth / 2;
        mPath4LineStartY = mLastY - mPath4Height / 2;
    }

    private void draw5(Canvas canvas) {
        mPath5 = new Path();

        mPath5.moveTo(mLastX, mLastY);
        mPath5.lineTo(mLastX + mLastWidth, mLastY);
        mPath5.lineTo(mLastX + mLastWidth - mPath5AngleWidth, mLastY + mPath5Height);
        mPath5.lineTo(mLastX + mPath5AngleWidth, mLastY + mPath5Height);
        mPath5.close();
        canvas.drawPath(mPath5, mPaint5);


        //mLastWidth = maxWidth - startOffsetX;
        //mLastX = mLastX;
//        mLastY = mLastY + mPath5Height;
//        mPath5LineStartX = mLastX + mLastWidth;
//        mPath5LineStartY = mLastY - mPath5Height / 2;

        mLastWidth = mLastWidth - 2 * mPath5AngleWidth;//最新长度
        mLastX = mLastX + mPath5AngleWidth;//第四个点的x坐标
        mLastY = mLastY + mPath5Height;//第四个点的y坐标
    }


    private void draw6(Canvas canvas) {
        mPath6 = new Path();
        mPath6.moveTo(mLastX, mLastY);
        mPath6.lineTo(mLastX + mLastWidth, mLastY);
        mPath6.lineTo(mLastX + mLastWidth - mPath6AngleWidth, mLastY + mPath6Height);
        mPath6.lineTo(mLastX + mPath6AngleWidth, mLastY + mPath6Height);
        mPath6.close();
        canvas.drawPath(mPath6, mPaint6);
        mLastWidth = mLastWidth - 2 * mPath6AngleWidth;//最新长度
        mLastX = mLastX + mPath6AngleWidth;//第四个点的x坐标
        mLastY = mLastY + mPath6Height;//第四个点的y坐标
    }


    private void draw7(Canvas canvas) {
        mPath7 = new Path();
        mPath7.moveTo(mLastX, mLastY);
        mPath7.lineTo(mLastX + mLastWidth, mLastY);
        mPath7.lineTo(mLastX + mLastWidth - mPath7AngleWidth, mLastY + mPath7Height);
        mPath7.lineTo(mLastX + mPath7AngleWidth, mLastY + mPath7Height);
        mPath7.close();
        canvas.drawPath(mPath7, mPaint7);
        mLastWidth = mLastWidth - 2 * mPath7AngleWidth;//最新长度
        mLastX = mLastX + mPath7AngleWidth;//第四个点的x坐标
        mLastY = mLastY + mPath7Height;//第四个点的y坐标
    }


    private void draw8(Canvas canvas) {
        mPath8 = new Path();
        mPath8.moveTo(mLastX, mLastY);
        mPath8.lineTo(mLastX + mLastWidth, mLastY);
        mPath8.lineTo(mLastX + mLastWidth - mPath8AngleWidth, mLastY + mPath8Height);
        mPath8.lineTo(mLastX + mPath8AngleWidth, mLastY + mPath8Height);
        mPath8.close();
        canvas.drawPath(mPath8, mPaint8);
        mLastWidth = mLastWidth - 2 * mPath8AngleWidth;//最新长度
        mLastX = mLastX + mPath8AngleWidth;//第四个点的x坐标
        mLastY = mLastY + mPath8Height;//第四个点的y坐标
    }


    private void draw9(Canvas canvas) {
        mPath9 = new Path();
        mPath9.moveTo(mLastX, mLastY);
        mPath9.lineTo(mLastX + mLastWidth, mLastY);
        mPath9.lineTo(mLastX + mLastWidth - mPath9AngleWidth, mLastY + mPath9Height);
        mPath9.lineTo(mLastX + mPath9AngleWidth, mLastY + mPath9Height);
        mPath9.close();
        canvas.drawPath(mPath9, mPaint9);
//        mLastWidth = mLastWidth - 2 * mPath9AngleWidth;//最新长度
//        mLastX = mLastX + mPath9AngleWidth;//第四个点的x坐标
        mLastY = mLastY + mPath9Height;//第四个点的y坐标
    }


    private void draw10(Canvas canvas) {
        mPath10 = new Path();
        mPath10.moveTo(mLastX, mLastY);
        mPath10.lineTo(mLastX + mLastWidth, mLastY);
        mPath10.lineTo(mLastX + mLastWidth - mPath10AngleWidth, mLastY + mPath10Height);
        mPath10.lineTo(mLastX + mPath10AngleWidth, mLastY + mPath10Height);
        mPath10.close();
        canvas.drawPath(mPath10, mPaint10);
        mLastWidth = mLastWidth - 2 * mPath10AngleWidth;//最新长度
        mLastX = mLastX + mPath10AngleWidth;//第四个点的x坐标
        mLastY = mLastY + mPath10Height;//第四个点的y坐标
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        draw1(canvas);
        draw2(canvas);
        draw3(canvas);
        draw4(canvas);
        draw5(canvas);
        draw6(canvas);
        draw7(canvas);
        draw8(canvas);
        draw9(canvas);
        drawText9(canvas);
    }

    public void animateY() {
        ObjectAnimator xAnimator = ObjectAnimator.ofFloat(this, "phaseX", 0, 1);
        xAnimator.setDuration(2000);
        xAnimator.addUpdateListener(this);
        xAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        xAnimator.start();

        ObjectAnimator alphaAnimator = ObjectAnimator.ofInt(this, "textAlpha", 0, 255);
        alphaAnimator.setDuration(2000);
        //alphaAnimator.addUpdateListener(this);
        alphaAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        alphaAnimator.start();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        /*int specMode = MeasureSpec.getMode(heightMeasureSpec);
        int specSize = MeasureSpec.getSize(heightMeasureSpec);

        int height = 0;
        if (specMode == MeasureSpec.EXACTLY) {
            height = specSize;
        } else {
            height = (int) mLastY;
        }
        System.out.println("onMeasure mLastY=" + mLastY);

        setMeasuredDimension(MeasureSpec.getMode(widthMeasureSpec), height);*/
    }

    public float getPhaseX() {
        return phaseX;
    }

    public void setPhaseX(float phaseX) {
        this.phaseX = phaseX;
    }

    public int getTextAlpha() {
        return textAlpha;
    }

    public void setTextAlpha(int textAlpha) {
        this.textAlpha = textAlpha;
    }

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        calculate();
        postInvalidate();
    }


    private void drawText1(Canvas canvas) {
        Paint.FontMetrics fontMetrics = mPaintText.getFontMetrics();

        float fontTotalHeight = fontMetrics.bottom - fontMetrics.top;

        float offY = fontTotalHeight / 2 - fontMetrics.bottom;
        //System.out.println("offY=" +offY);
        //float newY = baseY + offY;

        mPaintText.setAlpha(textAlpha);
        canvas.drawText("初期沟通(10%)", maxWidth + textStartOffsetX, mLastY - mPath1Height / 2 + offY, mPaintText);
    }

    private void drawText2(Canvas canvas) {
        Paint.FontMetrics fontMetrics = mPaintText.getFontMetrics();

        float fontTotalHeight = fontMetrics.bottom - fontMetrics.top;

        float offY = fontTotalHeight / 2 - fontMetrics.bottom;
        //float newY = baseY + offY;

        canvas.drawText("立项跟踪(10%)", maxWidth + textStartOffsetX, mLastY - mPath2Height / 2 + offY, mPaintText);
    }

    private void drawLine3(Canvas canvas) {
        canvas.drawLine(mPath3LineStartX + lineStartOffsetX, mPath3LineStartY, maxWidth, mPath3LineStartY, mPaintLine);
    }

    private void drawText3(Canvas canvas) {
        Paint.FontMetrics fontMetrics = mPaintText.getFontMetrics();

        float fontTotalHeight = fontMetrics.bottom - fontMetrics.top;

        float offY = fontTotalHeight / 2 - fontMetrics.bottom;
        //float newY = baseY + offY;

        canvas.drawText("呈报方案(10%)", maxWidth + textStartOffsetX, mLastY - mPath3Height / 2 + offY, mPaintText);
    }

    private void drawLine4(Canvas canvas) {
        canvas.drawLine(mPath4LineStartX + lineStartOffsetX, mPath4LineStartY, maxWidth, mPath4LineStartY, mPaintLine);
    }

    private void drawText4(Canvas canvas) {
        Paint.FontMetrics fontMetrics = mPaintText.getFontMetrics();

        float fontTotalHeight = fontMetrics.bottom - fontMetrics.top;

        float offY = fontTotalHeight / 2 - fontMetrics.bottom;
        //float newY = baseY + offY;

        canvas.drawText("商务谈判(10%)", maxWidth + textStartOffsetX, mLastY - mPath4Height / 2 + offY, mPaintText);
    }


    private void drawText9(Canvas canvas) {
        Paint.FontMetrics fontMetrics = mPaintText.getFontMetrics();

        float fontTotalHeight = fontMetrics.bottom - fontMetrics.top;

        float offY = fontTotalHeight / 2 - fontMetrics.bottom;
        //float newY = baseY + offY;

        canvas.drawText("销售漏斗", mLastX + mLastWidth - mPath9AngleWidth + 3 * textStartOffsetX, mLastY - mPath9Height / 2 + offY, mPaintText);
    }


    private void drawLine5(Canvas canvas) {
        canvas.drawLine(mPath5LineStartX + lineStartOffsetX, mPath5LineStartY, maxWidth, mPath5LineStartY, mPaintLine);
    }

    private void drawText5(Canvas canvas) {
        Paint.FontMetrics fontMetrics = mPaintText.getFontMetrics();

        float fontTotalHeight = fontMetrics.bottom - fontMetrics.top;

        float offY = fontTotalHeight / 2 - fontMetrics.bottom;
        //float newY = baseY + offY;

        canvas.drawText("赢单(10%)", maxWidth + textStartOffsetX, mLastY - mPath5Height / 2 + offY, mPaintText);
    }

}

优秀的个人博客,低调大师

微信关注我们

原文链接:https://yq.aliyun.com/articles/685560

转载内容版权归作者及来源网站所有!

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

相关文章

发表评论

资源下载

更多资源
优质分享Android(本站安卓app)

优质分享Android(本站安卓app)

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Mario,低调大师唯一一个Java游戏作品

Mario,低调大师唯一一个Java游戏作品

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Java Development Kit(Java开发工具)

Java Development Kit(Java开发工具)

JDK是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心,它包含了JAVA的运行环境(JVM+Java系统类库)和JAVA工具。

Sublime Text 一个代码编辑器

Sublime Text 一个代码编辑器

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。