看网上也有些例子,看着挺有意思。本人之前面试的时候也遇到面试官询问这样的问题,那时候我其实没有清晰的思路,就大体说了下图形绘制过程,需要画笔、画布,设置下各自属性,可以画圆、画弧、画图、画线等。闲话不多说了,直接看看怎么实现的。
效果图:
1.自定义TurnTableView,继承自View.
初始化的地方,主要是设置了下画笔的属性等。
// 初始化数据
private void init(Context context) {
this.context = context;
paint = new Paint();
paint.setColor(Color.RED);// 设置颜色
paint.setAntiAlias(true);// 去除锯齿效果,会消耗较大资源,绘制图形速度会变慢
paint.setDither(true);// 防抖动
paint.setStyle(Paint.Style.STROKE);// 空心
paint.setStrokeWidth(strokeWidth);// 设置空心边框的宽度
paint.setAlpha(100);// 透明度
paint.setARGB(100, 0, 255, 255);// 设置绘制的颜色,a代表透明度,r,g,b代表颜色值。
textPaint = new Paint();
textPaint.setColor(Color.RED);// 设置颜色
textPaint.setTextSize(20);
// 设置下,对于viewgroup能调用onDraw
setWillNotDraw(false);
setKeepScreenOn(true);
}
2.onMeasure()里拿到测量后的控件的宽高值,取最小值为直径radius,并初始化rangeRectF类对象,这就是个包围圆的一个矩形,用于画弧型和文字。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
radius = Math.min(getMeasuredWidth(), getMeasuredHeight());
setMeasuredDimension(radius, radius);
rangeRectF = new RectF(0, 0, radius, radius);
}
3.onDraw(Canvas canvas)里绘制圆弧以及文字
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
rotate(canvas);
}
float mSpeed = 0;//初始旋转速度(其实也是角度)
/**
* 进行旋转
*/
private void rotate(Canvas canvas) {
startAngle += mSpeed;
// 先画几个弧形
float sweepAngle = 360 / rewards.length;// 每个的弧度
paint.setStyle(Paint.Style.FILL);
for (int i = 0; i < rewards.length; i++) {// 子控件
paint.setColor(colors[i]);
canvas.drawArc(rangeRectF, startAngle, sweepAngle, true, paint);// 绘制弧形
float textWidth = textPaint.measureText(rewards[i]); // 获取文字的宽度
// FontMetrics fontMetrics = textPaint.getFontMetrics();
// float textHeight = (float) (Math
// .ceil((fontMetrics.descent - fontMetrics.top)) + 2);
//水平偏移量: 计算下周长2πr,然后(周长-textWidth)/2
float hOffset = (float) ((radius * Math.PI / rewards.length - textWidth) / 2);
//垂直偏移量:半径的1/3
float vOffset = radius / 2 / 3;
Path path = new Path();
path.addArc(rangeRectF, startAngle, sweepAngle);
canvas.drawTextOnPath(rewards[i], path, hOffset, vOffset, textPaint);// 画文字
startAngle += sweepAngle;
}
if (mSpeed <= 0) {// 要结束了
isEnd = true;
}
}
4.外部调用,旋转操作:
/**
* 旋转,其实就是不断重绘,重绘过程中,设置下偏转角度mSpeed,这样就能看出像是转盘在旋转了
*/
public void start() {
isEnd = false;
mSpeed = 5;// 每次旋转的角度
new Thread(new Runnable() {
@Override
public void run() {
while (!isEnd) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
((MainActivity) context).handler.post(new Runnable() {
@Override
public void run() {
invalidate();
}
});
}
}
}).start();
/*
* 随机数3-6秒之间停止旋转
*/
double radom = Math.random();
long time = (long) (radom * 3000 + 3000);
((MainActivity) context).handler.postDelayed(new Runnable() {
@Override
public void run() {
end();
}
}, time);
}
/**
* 停止旋转
*/
public void end() {
isEnd = true;
// 做一个缓冲效果
mSpeed = 0;
}
5.布局文件如下:
"http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context=".MainActivity" >
<com.example.turntabledemo.TurnTableView
android:id="@+id/turn"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerHorizontal="true"
android:layout_margin="10dp" >
com.example.turntabledemo.TurnTableView>
"wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="90dp"
android:background="@null"
android:onClick="aaa"
android:src="@drawable/start" />
demo下载:
http://yun.baidu.com/s/1slozw2x