自定义View

自定义View步骤

  1. 构造函数 初始化(初始化画笔Paint)
  2. onMeasure 测量View的大小(暂时不用关心)
  3. onSizeChanged 确定View大小(记录当前View的宽高)
  4. onLayout 确定子View布局(无子View,不关心)
  5. onDraw 实际绘制内容(绘制饼状图)
  6. 提供接口 提供接口(提供设置数据的接口)

    操作类型API备注
    绘制颜色drawColor, drawRGB, drawARGB使用单一颜色填充整个画布
    绘制基本形状drawPoint, drawPoints, drawLine, drawLines, drawRect, drawRoundRect, drawOval, drawCircle, drawArc依次为 点、线、矩形、圆角矩形、椭圆、圆、圆弧
    绘制图片drawBitmap, drawPicture绘制位图和图片
    绘制文本drawText, drawPosText, drawTextOnPath依次为 绘制文字、绘制文字时指定每个文字位置、根据路径绘制文字
    绘制路径drawPath绘制路径,绘制贝塞尔曲线时也需要用到该函数
    顶点操作drawVertices, drawBitmapMesh通过对顶点操作可以使图像形变,drawVertices直接对画布作用、 drawBitmapMesh只对绘制的Bitmap作用
    画布剪裁clipPath, clipRect设置画布的显示区域
    画布快照save, restore, saveLayerXxx, restoreToCount, getSaveCount依次为 保存当前状态、 回滚到上一次保存的状态、 保存图层状态、 回滚到指定状态、 获取保存次数
    画布变换translate, scale, rotate, skew依次为 位移、缩放、 旋转、错切
    Matrix(矩阵)getMatrix, setMatrix, concat实际上画布的位移,缩放等操作的都是图像矩阵Matrix, 只不过Matrix比较难以理解和使用,故封装了一些常用的方法。

示例:

1.自定义扇形图:

通过设置数据名字和数据值自动生成对应的扇形分析图。

cv_01
主要绘制算法:

   if (null == mData)
            return;
        float currentStartAngle = mStartAngle;
        canvas.translate(mWidth/2, mHeight/2);
        float r = (float) (Math.min(mHeight,mWidth)/2*0.8);
        RectF rect = new RectF(-r,-r,r,r);

        for (int i = 0; i< mData.size(); i++){
            CircleData data = mData.get(i);
            mPaint.setColor(data.getColor());
            canvas.drawArc(rect,currentStartAngle,data.getAngle(),true,mPaint);
            currentStartAngle += data.getAngle();
            // 平移画布
            mCenterX = (float) ((float)0.5 * r * Math.cos(Math.toRadians(currentStartAngle - 0.5 * data.getAngle())));
            mCenterY = (float) ((float)0.5 * r * Math.sin(Math.toRadians(currentStartAngle - 0.5 * data.getAngle())));
            canvas.translate(mCenterX,mCenterY); // 文字中心坐标
            // 设置字体颜色
            mPaint.setColor(Color.BLACK);
            mPaint.setTextSize(30f);
            mPaint.setTextAlign(Paint.Align.CENTER);
            canvas.drawText(decimalFormat.format(data.getPercentage()*100)+" %",0,0,mPaint);
            canvas.translate(-mCenterX,-mCenterY);//绘制文字完成回到原点
        }

这里需要特别注意扇形图中文字的绘制,通过获取每一个扇形的夹角以及半径,不断的移动画布,从而来获取文字的绘制位置。
github地址:https://github.com/zoky2017/CustomViewDemo

2.示例2 自定义载入条

cv_02
此定义View是通过网上的自定义载入条改编而来
从效果上看,我们需要考虑以下几个问题:

1.叶子的随机产生;

2.叶子随着一条正余弦曲线移动;

3.叶子在移动的时候旋转,旋转方向随机,正时针或逆时针;

4.叶子遇到进度条,似乎是融合进入;

5.叶子不能超出最左边的弧角;

7.叶子飘出时的角度不是一致,走的曲线的振幅也有差别,否则太有规律性,缺乏美感;

难点在于载入条的椭圆形的填充及叶子对象飘落轨迹的绘制。

private void drawProgressAndLeafs(Canvas canvas) {

        if (mProgress >= TOTAL_PROGRESS) {
            mProgress = 0;
        }
        // mProgressWidth为进度条的宽度,根据当前进度算出进度条的位置
        mCurrentProgressPosition = mProgressWidth * mProgress / TOTAL_PROGRESS;
        // 即当前位置在图中所示1范围内
        if (mCurrentProgressPosition < mArcRadius) {
            Log.i(TAG, "mProgress = " + mProgress + "---mCurrentProgressPosition = "
                    + mCurrentProgressPosition
                    + "--mArcProgressWidth" + mArcRadius);
            // 1.绘制白色ARC,绘制orange ARC
            // 2.绘制白色矩形

            // 1.绘制白色ARC
            canvas.drawArc(mArcRectF, 90, 180, false, mWhitePaint);

            // 2.绘制白色矩形
            mWhiteRectF.left = mArcRightLocation;
            canvas.drawRect(mWhiteRectF, mWhitePaint);

            // 绘制叶子
            drawLeafs(canvas);

            // 3.绘制棕色 ARC
            // 单边角度
            int angle = (int) Math.toDegrees(Math.acos((mArcRadius - mCurrentProgressPosition)
                    / (float) mArcRadius));
            // 起始的位置
            int startAngle = 180 - angle;
            // 扫过的角度
            int sweepAngle = 2 * angle;
            Log.i(TAG, "startAngle = " + startAngle);
            canvas.drawArc(mArcRectF, startAngle, sweepAngle, false, mOrangePaint);
        } else {
            Log.i(TAG, "mProgress = " + mProgress + "---transfer-----mCurrentProgressPosition = "
                    + mCurrentProgressPosition
                    + "--mArcProgressWidth" + mArcRadius);
            // 1.绘制white RECT
            // 2.绘制Orange ARC
            // 3.绘制orange RECT
            // 这个层级进行绘制能让叶子感觉是融入棕色进度条中

            // 1.绘制white RECT
            mWhiteRectF.left = mCurrentProgressPosition;
            canvas.drawRect(mWhiteRectF, mWhitePaint);
            // 绘制叶子
            drawLeafs(canvas);
            // 2.绘制Orange ARC
            canvas.drawArc(mArcRectF, 90, 180, false, mOrangePaint);
            // 3.绘制orange RECT
            mOrangeRectF.left = mArcRightLocation;
            mOrangeRectF.right = mCurrentProgressPosition;
            canvas.drawRect(mOrangeRectF, mOrangePaint);

        }

    }

    /**
     * 绘制叶子
     *
     * @param canvas
     */
    private void drawLeafs(Canvas canvas) {
        mLeafRotateTime = mLeafRotateTime <= 0 ? LEAF_ROTATE_TIME : mLeafRotateTime;
        long currentTime = System.currentTimeMillis();
        for (int i = 0; i < mLeafInfos.size(); i++) {
            Leaf leaf = mLeafInfos.get(i);
            if (currentTime > leaf.startTime && leaf.startTime != 0) {
                // 绘制叶子--根据叶子的类型和当前时间得出叶子的(x,y)
                getLeafLocation(leaf, currentTime);
                // 根据时间计算旋转角度
                canvas.save();
                // 通过Matrix控制叶子旋转
                Matrix matrix = new Matrix();
                float transX = mLeftMargin + leaf.x;
                float transY = mLeftMargin + leaf.y;
                Log.i(TAG, "left.x = " + leaf.x + "--leaf.y=" + leaf.y);
                matrix.postTranslate(transX, transY);
                // 通过时间关联旋转角度,则可以直接通过修改LEAF_ROTATE_TIME调节叶子旋转快慢
                float rotateFraction = ((currentTime - leaf.startTime) % mLeafRotateTime)
                        / (float) mLeafRotateTime;
                int angle = (int) (rotateFraction * 360);
                // 根据叶子旋转方向确定叶子旋转角度
                int rotate = leaf.rotateDirection == 0 ? angle + leaf.rotateAngle : -angle
                        + leaf.rotateAngle;
                matrix.postRotate(rotate, transX
                        + mLeafWidth / 2, transY + mLeafHeight / 2);
                canvas.drawBitmap(mLeafBitmap, matrix, mBitmapPaint);
                canvas.restore();
            } else {
                continue;
            }
        }
    }

github地址: https://github.com/zoky2017/CustomViewDemo2

3.挖个坑,后面补上~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值