package UICtrl;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.view.animation.Interpolator;
import android.graphics.Paint;
import android.graphics.PointF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.RelativeLayout;
/**
* Created by wangchaomac on 2017/10/18.
*/
public class AroundCircleBall extends RelativeLayout {
private BallView mBall;
//角度
private float mBallRadius;
//小球的颜色
private int mBallColor;
private int mCircleRadius;
private int mCircleColor;
private int mDuration;
//笔头描宽
private float mStrokeWidth;
private int mInterpolator;
private final int ACCELERATE_DECELERATE_INTERPOLATOR = 1;
private final int LINEAR_INTERPOLATOR = 2;
private final int ACCELERATE = 3;
private final int DECELERATE = 4;
ObjectAnimator mRotateAnim;
PointF mCircleCenterPoint = new PointF(mCircleRadius + mBallRadius, mCircleRadius + mBallRadius);
Paint mPaint = new Paint();
public AroundCircleBall(Context context, AttributeSet attrs){
super(context, attrs);
// TODO Auto-generated constructor stub
init(context);
}
private void init(Context context){
init();
}
private void init() {
mBall = new BallView(getContext());
mBall.setRadius(mBallRadius);
mBall.setBallColor(mBallColor);
//小球的初始位置在圆环的最底部
LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.leftMargin = (int) (mCircleRadius);
params.topMargin = (int) (mCircleRadius * 2);
mBall.setLayoutParams(params);
addView(mBall);
}
@Override
protected void onDraw(Canvas canvas) {
//绘制圆
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(mStrokeWidth);
mPaint.setColor(mCircleColor);
canvas.drawCircle(mCircleCenterPoint.x, mCircleCenterPoint.y, mCircleRadius, mPaint);
super.onDraw(canvas);
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//测量控件宽高
int width = (int) (getPaddingLeft() + mCircleRadius * 2 + mBallRadius * 2 + getPaddingRight());
int height = (int) (getPaddingTop() + mCircleRadius * 2 + mBallRadius * 2 + getPaddingBottom());
setMeasuredDimension(width, height);
}
private void initRotateAnim(){
mRotateAnim = ObjectAnimator.ofFloat(mBall, "rotation", 0f, 360f);
//计算小球旋转的中心点(此点的左边是在小球自身的坐标系中)
float pivotX = mBall.getRadius();
float pivotY = mBall.getRadius() - mCircleRadius;
mBall.setPivotX(pivotX);
mBall.setPivotY(pivotY);
mRotateAnim.setDuration(mDuration);
mRotateAnim.setInterpolator(getInterpolator());
mRotateAnim.setRepeatCount(-1);
mRotateAnim.setStartDelay(500);
}
private Interpolator getInterpolator(){
Interpolator interpolator = null;
switch (mInterpolator){
case ACCELERATE_DECELERATE_INTERPOLATOR: //先加上后减速
interpolator = new AccelerateDecelerateInterpolator();
break;
case LINEAR_INTERPOLATOR: //匀速
interpolator = new LinearInterpolator();
break;
case ACCELERATE: //加速
interpolator = new AccelerateInterpolator();
break;
case DECELERATE: //减速
interpolator = new DecelerateInterpolator();
break;
}
return interpolator;
}
/**
* 启动旋转动画
*/
public void startRotate(){
if (mRotateAnim != null){
mRotateAnim.start();
}
}
/**
* 暂停旋转动画
*/
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void pauseRotate(){
if (mRotateAnim != null && mRotateAnim.isRunning()){
mRotateAnim.pause();
}
}
/**
* 取消旋转动画
*/
public void cancelRotate(){
if (mRotateAnim != null){
mRotateAnim.cancel();
}
}
}
package UICtrl;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by wangchaomac on 2017/10/18.
*/
public class BallView extends View {
private int mBallColor = Color.BLACK;
private float mRadius = 10f;
private PointF mCenterPoint;
private Paint mPaint;
public BallView(Context context) {
this(context, null);
}
public BallView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init(){
mPaint = new Paint();
mPaint.setAntiAlias(true);
mCenterPoint = new PointF(mRadius, mRadius);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = (int) (getPaddingLeft() + 2*mRadius + getPaddingRight());
int height = (int) (getPaddingTop() + 2*mRadius + getPaddingBottom());
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(mBallColor);
canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, mRadius, mPaint);
}
public void setBallColor(int mBallColor) {
this.mBallColor = mBallColor;
}
public void setRadius(float radius) {
this.mRadius = radius;
mCenterPoint.set(radius, radius);
}
public float getRadius() {
return mRadius;
}
}
<?xml version="1.0" encoding="utf-8"?>
<resources><!--AroundCircleBall自定义属性-->
<declare-styleable name="AroundCircleBall">
<!--绘制圆形轨迹的线宽-->
<attr name="circle_width" format="dimension"></attr>
<!--绘制圆形轨迹的颜色-->
<attr name="circle_color" format="color"></attr>
<!--圆形轨迹的半径-->
<attr name="circle_radius" format="dimension"></attr>
<!--小球的颜色-->
<attr name="ball_color" format="color"></attr>
<!--小球的半径-->
<attr name="ball_radius" format="dimension"></attr>
<!--设置旋转一周需要的时间(单位为秒)-->
<attr name="rotate_duration" format="integer"></attr>
<!--设置旋转动画的补间器-->
<attr name="rotate_interpolator" format="enum">
<enum name="accelerate_decelerate" value="1"/>
<enum name="linear" value="2"/>
<enum name="accelerate" value="3"/>
<enum name="decelerate" value="4"/>
</attr>
</declare-styleable></resources>