提供接口 提供接口(提供设置数据的接口)
操作类型 | 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比较难以理解和使用,故封装了一些常用的方法。 |
通过设置数据名字和数据值自动生成对应的扇形分析图。
主要绘制算法:
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
此定义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
新闻热点
疑难解答