Android画布(Canvas)之--- 圆环,利用Path切除一个扇形,形成一段圆弧效果

dxpfigo 2014-03-29 11:54:21
话不多说,情况是这样:ApiDemo大家都熟吧,其中Sweep这个demo大家一定也都看过,即利用SweepGradient这个Shader使圆随着弧度的变换有个渐进色的效果。
现在我有个想法,即想实现类似于下图中的效果



描述一下我的效果吧:
1. 缺口的圆环;
2. 圆环颜色渐进(颜色配比在下面代码中还未给出,不影响代码分析);
3. 圆环的刻度(即虚线)稳定;

首先需要强调的是,大家的答案里面千万别给canvas.drawArc()这个答案,这个答案不符合我的需求,因为不同的弧度画出的圆环,其刻度是会随意移动的;

再说说我的思路:即在从圆环的圆心利用画布类的canvas方法ClipPath方法截取我想要去掉的这段弧度所在的画布
然后再在剩余的画布上画圆形,那么自然截取的图为我上图中想要达到的效果了。

值得大家注意的是:下面这段代码中,当不给画笔设置SweepGradient属性时,是能够达到圆弧效果,但是这样的话,颜色又不符合上述要求了。



public class MainActivity extends Activity {

private ImageView mScanImage;
private ImageView mSecondImage;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}

private static class SampleView extends View {
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private float mRotate;
private Matrix mMatrix = new Matrix();
private Shader mShader;
private boolean mDoTiming;

public SampleView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);

float x = 160;
float y = 100;
mShader = new SweepGradient(x, y, new int[] { Color.GREEN,
Color.RED,
Color.BLUE,
Color.GREEN }, null);
mPaint.setShader(mShader);
mPaint.setStyle(Style.STROKE);
PathEffect effect = new DashPathEffect(new float[] { 5, 8, 5, 8}, 1);
mPaint.setPathEffect(effect);
mPaint.setStrokeWidth(10);[/color]
}

@Override protected void onDraw(Canvas canvas) {
Paint paint = mPaint;
float x = 160;
float y = 100;

canvas.drawColor(Color.WHITE);

mMatrix.setRotate(mRotate, x, y);
mShader.setLocalMatrix(mMatrix);
mRotate += 3;
if (mRotate >= 360) {
mRotate = 0;
}
invalidate();

if (mDoTiming) {
long now = System.currentTimeMillis();
for (int i = 0; i < 20; i++) {
canvas.drawCircle(x, y, 80, paint);
}
now = System.currentTimeMillis() - now;
android.util.Log.d("skia", "sweep ms = " + (now/20.));
}
else {
RectF rect = new RectF(x - 80, y - 80, x + 80, y + 80);
Paint paintRect = new Paint();
paintRect.setColor(Color.RED);
paintRect.setStyle(Style.STROKE);
canvas.drawRect(rect, paintRect);
Path path = new Path();
path.addArc(rect, 60, 60);
canvas.clipPath(path);
//canvas.clipPath(path,Op.XOR);
canvas.drawCircle(x, y, 80, paint);
}
}
}
}


这是我的代码,感觉思路是没错的,因为单独画带刻度圆弧或者单画带颜色渐进的圆都是能实现的。可是加上渐进效果,同时clipPath的时候出现了问题;

代码中31-34行以及61-69行为我自己在apidemo中sweep这个例子上新增的代码,可是最后实现的效果却是下面这样:

或者这样:


急求各路大神大仙帮忙解答;或者有更好的方案也望不吝赐教...

高分相送!
...全文
26632 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
农民工刘小二 2016-09-20
  • 打赏
  • 举报
回复
for (int i = 0; i < 100; i++) { paint.setARGB(100, (int)(255 - 2.5 * i), (int)(2.5 * i), 0); canvas.rotate(3, x, y); canvas.drawRect(580, 295, 600, 305, paint); }
gloryhero 2016-01-29
  • 打赏
  • 举报
回复
canvas.clipPath(path, Region.Op.UNION);
  • 打赏
  • 举报
回复
~\(≧▽≦)/~赞赞赞!!!!!!
nowave1024 2015-09-15
  • 打赏
  • 举报
回复
package com.example.abcd;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.os.Bundle;
import android.view.View;

public class MyActivity extends Activity{
	    @Override
	    protected void onCreate(Bundle savedInstanceState) {
	        super.onCreate(savedInstanceState);
	        setContentView(new SampleView(this));
	    }

	    @SuppressLint("DrawAllocation")
		private static class SampleView extends View {
	        private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
	        private float mRotate;
	        private Matrix mMatrix = new Matrix();
	        private Shader mShader;

	        public SampleView(Context context) {
	            super(context);
	            setFocusable(true);
	            setFocusableInTouchMode(true);
	            float x = 160;
	            float y = 100;
	            mShader = new SweepGradient(x, y, new int[] {0xFF09F68C,
	                                                  0xFFB0F44B,
	                                                  0xFFE8DD30,
	                                                  0xFFF1CA2E,
	                                                  0xFFFF902F,
	                                                  0xFFFF6433}, null);
	            mPaint.setShader(mShader);
	            mPaint.setStyle(Style.STROKE);
	            PathEffect effect = new DashPathEffect(new float[] { 2, 3, 2,3}, 1);
	            mPaint.setPathEffect(effect);
	            mPaint.setStrokeWidth(40);
	        }
	        public void getArc(Canvas canvas,float o_x,float o_y,float r,
	        		float startangel,float endangel,Paint paint){
	        	RectF rect = new RectF(o_x - r, o_y - r, o_x + r, o_y + r);
	        	Path path = new Path();
                path.moveTo(o_x,o_y);
                path.lineTo((float)(o_x+r*Math.cos(startangel*Math.PI/180))
                		  , (float)(o_y+r*Math.sin(startangel*Math.PI/180)));
                path.lineTo((float)(o_x+r*Math.cos(endangel*Math.PI/180))
                		  , (float)(o_y+r*Math.sin(endangel*Math.PI/180)));
                path.addArc(rect, startangel, endangel-startangel);
                canvas.clipPath(path);
                canvas.drawCircle(o_x, o_y, r, paint);
	        }
	        @Override 
	        protected void onDraw(Canvas canvas) {
	            Paint paint = mPaint;
	            float x = 160;
	            float y = 100;

	            canvas.drawColor(Color.WHITE);

	            mMatrix.setRotate(mRotate, x, y);
	            mShader.setLocalMatrix(mMatrix);
	            mRotate += 3;
	            if (mRotate >= 360) {
	                mRotate = 0;
	            }
	            invalidate();
	            getArc(canvas,x,y,80,135,405,paint);
	        }
	    }
}
nowave1024 2015-09-15
  • 打赏
  • 举报
回复
package com.example.abcd;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;

public class MyActivity extends Activity{
private ImageView mScanImage;
private ImageView mSecondImage;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}

@SuppressLint("DrawAllocation")
private static class SampleView extends View {
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private float mRotate;
private Matrix mMatrix = new Matrix();
private Shader mShader;
private boolean mDoTiming;

public SampleView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
mDoTiming = false;
float x = 160;
float y = 100;
mShader = new SweepGradient(x, y, new int[] {0xFF09F68C,
0xFFB0F44B,
0xFFE8DD30,
0xFFF1CA2E,
0xFFFF902F,
0xFFFF6433}, null);
mPaint.setShader(mShader);
mPaint.setStyle(Style.STROKE);
PathEffect effect = new DashPathEffect(new float[] { 2, 3, 2,3}, 1);
mPaint.setPathEffect(effect);
mPaint.setStrokeWidth(40);
}
public void getArc(Canvas canvas,float o_x,float o_y,float r,
float startangel,float endangel,Paint paint){
RectF rect = new RectF(o_x - r, o_y - r, o_x + r, o_y + r);
Path path = new Path();
path.moveTo(o_x,o_y);
path.lineTo((float)(o_x+r*Math.cos(startangel*Math.PI/180))
, (float)(o_y+r*Math.sin(startangel*Math.PI/180)));
path.lineTo((float)(o_x+r*Math.cos(endangel*Math.PI/180))
, (float)(o_y+r*Math.sin(endangel*Math.PI/180)));
path.addArc(rect, startangel, endangel-startangel);
canvas.clipPath(path);
canvas.drawCircle(o_x, o_y, 80, paint);
}
@Override
protected void onDraw(Canvas canvas) {
Paint paint = mPaint;
float x = 160;
float y = 100;

canvas.drawColor(Color.WHITE);

mMatrix.setRotate(mRotate, x, y);
mShader.setLocalMatrix(mMatrix);
mRotate += 3;
if (mRotate >= 360) {
mRotate = 0;
}
invalidate();
getArc(canvas,x,y,80,135,405,paint);
}
}
}

一只大黄鱼 2015-08-26
  • 打赏
  • 举报
回复
大神搞定了没?我也在写类似这个的,求分享
米土木木 2015-05-14
  • 打赏
  • 举报
回复
兄弟,这个问题解决了没,我也遇到了楼主一样的问题,解决了可否告知下,谢谢
dxpfigo 2014-03-30
  • 打赏
  • 举报
回复
自己顶...

80,471

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧