内容简概
一、画线、圆、扇形
二、扇形动画
具体内容
一、画线、圆、扇形、圆弧
(一)创建一个类(继承View)用于测试
在这个类中,我们放置线、圆、扇形、圆弧。
public class TestView extends View {
// 实现View的两个方法
public TestView(Context context) {
super(context);
}
public TestView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
// 画线
// 1. 准备画笔 抗锯齿
Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setTextSize(70);
mPaint.setColor(Color.BLACK); // 设置画笔颜色
mPaint.setStrokeWidth(20); // 设置画笔粗细
// 2.在画布上画线
canvas.drawLine(50,50,300,400,mPaint);
// x,y为开头文字左下角左标
canvas.drawText("↑",200,600,mPaint);
canvas.drawText("drawLine",50,700,mPaint);
//3.画圆
// 这里的top是圆心坐标,
canvas.drawArc(600,50,1000,450,0,300,true,mPaint);
canvas.drawText("↑",770,600,mPaint);
canvas.drawText("drawArc",650,700,mPaint);
// useCenter = false
canvas.drawArc(50,800,450,1200,0,300,false,mPaint);
canvas.drawText("↑",200,1300,mPaint);
canvas.drawText("drawArc",50,1400,mPaint);
canvas.drawText("useCenter=false",50,1500,mPaint);
// 画圆的另一种方法
canvas.drawCircle(800,1000,200,mPaint);
canvas.drawText("↑",770,1300,mPaint);
canvas.drawText("drawCircle",650,1400,mPaint);
}
}
这里的圆是实心的,如果想要画空心的圆或者圆弧怎么办呢?只要多加一句mPaint.setStyle(Paint.Style.STROKE);
就可以了,系统默认的style为FILL(实心)。
(二) xml(使用RelativeLayout)
<com.example.test.TestView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
(三)运行结果图
左边为实心,右边为空心。空心就是描绘外轮廓。(请忽略空心的丑陋文字)。
二、扇形动画
扇形动画是扇形的半径不变,转的角度在变。下面我用两个类分别实现两种动画,一种是点击展开的扇形,一种是自动展开的扇形。前者可以用onTouchEvent方法实现,后者可以用Timer(定时器)或属性动画实现。
(一)点击展开的扇形
规定扇形完全展开后就固定为圆形,不再变化。
public class FanAnimation extends View {
int angle; //每次增长之后的值
int speed = 20; //增长速度
public FanAnimation(Context context) {
super(context);
}
public FanAnimation(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onDraw(Canvas canvas) {
drawFanChart(canvas,Color.BLACK, (float) (angle/360.0),"点击展开的扇形");
}
// onDraw方法不能满足需求,所以自己写一个方法
private void drawFanChart(Canvas canvas,int color,float rate,String text){
//画笔
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(70);
paint.setColor(color);
//画扇形
int endAngle = (int) (360*rate);// 新绘制的扇形endAngle都在增大
canvas.drawArc(50,100,450,500, 0,endAngle, true,paint);
canvas.drawText(text,550,300,paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
// 点击屏幕 画一点 这里的angle就是上面的rate
angle += speed;
// 控制最大值
if (angle>360){
angle = 360;
}
// 刷新
invalidate();
}
return true;
}
}
(二)自动展开的扇形——Timer
public class AutoFanAnimation extends View {
int angle; //每次增长之后的值
int speed = 5; //增长速度
public AutoFanAnimation(Context context) {
super(context);
}
public AutoFanAnimation(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 创建定时器 每个0.5s 画一次
final Timer t = new Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
angle += speed;
if (angle > 360){
angle = 0; // 重新开始
// t.cancel();// 关闭定时器
}
invalidate(); // 通知系统调用ondraw
postInvalidate(); // 子进程里面
}
},0,100);
}
@Override
protected void onDraw(Canvas canvas) {
drawFanChart(canvas, Color.BLACK, (float) (angle/360.0),"自动展开的扇形");
}
// onDraw方法不能满足需求,所以自己写一个方法
private void drawFanChart(Canvas canvas,int color,float rate,String text){
//画笔
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(70);
paint.setColor(color);
//画扇形
int endAngle = (int) (360*rate);
canvas.drawArc(50,0,450,400, 0,endAngle, true,paint);
canvas.drawText(text,550,300,paint);
}
}
(三)自动展开的扇形——valueAnimator属性动画
和自动展开的扇形唯一不同的就是onSizeChanged。
public class ValueAnimator extends View {
int angle; //每次增长之后的值
int speed = 20; //增长速度
public ValueAnimator(Context context) {
super(context);
}
public ValueAnimator(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 创建ValueAnimator对象 设置范围0-360
android.animation.ValueAnimator va = android.animation.ValueAnimator.ofInt(0,360);
va.setDuration(3000); // 动画时间
va.setRepeatCount(android.animation.ValueAnimator.INFINITE);
// 设置监听器 监听值的变化
va.addUpdateListener(new android.animation.ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(android.animation.ValueAnimator valueAnimator) {
// 获取某一刻的值
angle = (int) valueAnimator.getAnimatedValue();
// 刷新
invalidate();
}
});
// 启动
va.start();
}
@Override
protected void onDraw(Canvas canvas) {
drawFanChart(canvas, Color.BLACK, (float) (angle/360.0),"属性动画展开的扇形");
}
private void drawFanChart(Canvas canvas,int color,float rate,String text){
//画笔
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(57);
paint.setColor(color);
//画扇形
int endAngle = (int) (360*rate);// 新绘制的扇形endAngle都在增大
canvas.drawArc(50,0,450,400, 0,endAngle, true,paint);
canvas.drawText(text,550,300,paint);
}
}
(四)xml(使用LinearLayout)
<com.example.test.FanAnimation
android:id="@+id/click"
android:layout_width="wrap_content"
android:layout_height="250dp"/>
<com.example.test.AutoFanAnimation
android:layout_width="wrap_content"
android:layout_height="200dp"/>
<com.example.test.ValueAnimator
android:layout_width="wrap_content"
android:layout_height="220dp"/>