package io.virtualapp.widgets; import android.animation.Animator; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; public class TwoGearsView extends BaseView { ValueAnimator valueAnimator = null; float mAnimatedValue = 0f; float hypotenuse = 0f; float smallRingCenterX = 0f; float smallRingCenterY = 0f; float bigRingCenterX = 0f; float bigRingCenterY = 0f; private float mWidth = 0f; private Paint mPaint, mPaintAxle; private Paint mPaintRing; private float mPadding = 0f; private float mWheelLength; private int mWheelSmallSpace = 10; private int mWheelBigSpace = 8; public TwoGearsView(Context context) { super(context); } public TwoGearsView(Context context, AttributeSet attrs) { super(context, attrs); } public TwoGearsView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (getMeasuredWidth() > getHeight()) mWidth = getMeasuredHeight(); else mWidth = getMeasuredWidth(); } private void drawSmallRing(Canvas canvas) { hypotenuse = (float) (mWidth * Math.sqrt(2)); smallRingCenterX = (float) ((hypotenuse / 6.f) * Math.cos(45 * Math.PI / 180f)); smallRingCenterY = (float) ((hypotenuse / 6.f) * Math.sin(45 * Math.PI / 180f)); mPaintRing.setStrokeWidth(dip2px(1.0f)); canvas.drawCircle(mPadding + smallRingCenterX, smallRingCenterY + mPadding, smallRingCenterX, mPaintRing); mPaintRing.setStrokeWidth(dip2px(1.5f)); canvas.drawCircle(mPadding + smallRingCenterX, smallRingCenterY + mPadding, smallRingCenterX / 2, mPaintRing); } private void drawSmallGear(Canvas canvas) { mPaint.setStrokeWidth(dip2px(1)); for (int i = 0; i < 360; i = i + mWheelSmallSpace) { int angle = (int) (mAnimatedValue * mWheelSmallSpace + i); float x3 = (float) ((smallRingCenterX) * Math.cos(angle * Math.PI / 180f)); float y3 = (float) ((smallRingCenterY) * Math.sin(angle * Math.PI / 180f)); float x4 = (float) ((smallRingCenterX + mWheelLength) * Math.cos(angle * Math.PI / 180f)); float y4 = (float) ((smallRingCenterY + mWheelLength) * Math.sin(angle * Math.PI / 180f)); canvas.drawLine(mPadding + smallRingCenterX - x4, smallRingCenterY + mPadding - y4, smallRingCenterX + mPadding - x3, smallRingCenterY + mPadding - y3, mPaint); } } private void drawBigGear(Canvas canvas) { bigRingCenterX = (float) ((hypotenuse / 2.f) * Math.cos(45 * Math.PI / 180f)); bigRingCenterY = (float) ((hypotenuse / 2.f) * Math.sin(45 * Math.PI / 180f)); float strokeWidth = dip2px(1.5f) / 4; mPaint.setStrokeWidth(dip2px(1.5f)); for (int i = 0; i < 360; i = i + mWheelBigSpace) { int angle = (int) (360 - (mAnimatedValue * mWheelBigSpace + i)); float x3 = (float) ((bigRingCenterX - smallRingCenterX) * Math.cos(angle * Math.PI / 180f)); float y3 = (float) ((bigRingCenterY - smallRingCenterY) * Math.sin(angle * Math.PI / 180f)); float x4 = (float) ((bigRingCenterX - smallRingCenterX + mWheelLength) * Math.cos(angle * Math.PI / 180f)); float y4 = (float) ((bigRingCenterY - smallRingCenterY + mWheelLength) * Math.sin(angle * Math.PI / 180f)); canvas.drawLine(bigRingCenterX + mPadding - x4 + mWheelLength * 2 + strokeWidth, bigRingCenterY + mPadding - y4 + mWheelLength * 2 + strokeWidth, bigRingCenterX + mPadding - x3 + mWheelLength * 2 + strokeWidth, bigRingCenterY + mPadding - y3 + mWheelLength * 2 + strokeWidth, mPaint); } } private void drawBigRing(Canvas canvas) { float strokeWidth = dip2px(1.5f) / 4; mPaintRing.setStrokeWidth(dip2px(1.5f)); canvas.drawCircle(bigRingCenterX + mPadding + mWheelLength * 2 + strokeWidth, bigRingCenterY + mPadding + mWheelLength * 2 + strokeWidth, bigRingCenterX - smallRingCenterX - strokeWidth, mPaintRing); mPaintRing.setStrokeWidth(dip2px(1.5f)); canvas.drawCircle(bigRingCenterX + mPadding + mWheelLength * 2 + strokeWidth, bigRingCenterY + mPadding + mWheelLength * 2 + strokeWidth, (bigRingCenterX - smallRingCenterX) / 2 - strokeWidth, mPaintRing); } private void drawAxle(Canvas canvas) { for (int i = 0; i < 3; i++) { float x3 = (float) ((smallRingCenterX) * Math.cos(i * (360 / 3) * Math.PI / 180f)); float y3 = (float) ((smallRingCenterY) * Math.sin(i * (360 / 3) * Math.PI / 180f)); canvas.drawLine(mPadding + smallRingCenterX, mPadding + smallRingCenterY, mPadding + smallRingCenterX - x3, mPadding + smallRingCenterY - y3, mPaintAxle); } for (int i = 0; i < 3; i++) { float x3 = (float) ((bigRingCenterX - smallRingCenterX) * Math.cos(i * (360 / 3) * Math.PI / 180f)); float y3 = (float) ((bigRingCenterY - smallRingCenterY) * Math.sin(i * (360 / 3) * Math.PI / 180f)); canvas.drawLine(bigRingCenterX + mPadding + mWheelLength * 2, bigRingCenterY + mPadding + mWheelLength * 2, bigRingCenterX + mPadding + mWheelLength * 2 - x3, bigRingCenterY + mPadding + mWheelLength * 2 - y3, mPaintAxle); } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPadding = dip2px(5); canvas.save(); canvas.rotate(180, mWidth / 2, mWidth / 2); drawSmallRing(canvas); drawSmallGear(canvas); drawBigGear(canvas); drawBigRing(canvas); drawAxle(canvas); canvas.restore(); } private void initPaint() { mPaintRing = new Paint(); mPaintRing.setAntiAlias(true); mPaintRing.setStyle(Paint.Style.STROKE); mPaintRing.setColor(Color.WHITE); mPaintRing.setStrokeWidth(dip2px(1.5f)); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.WHITE); mPaint.setStrokeWidth(dip2px(1)); mPaintAxle = new Paint(); mPaintAxle.setAntiAlias(true); mPaintAxle.setStyle(Paint.Style.FILL); mPaintAxle.setColor(Color.WHITE); mPaintAxle.setStrokeWidth(dip2px(1.5f)); mWheelLength = dip2px(2f); } public void setViewColor(int color) { mPaint.setColor(color); mPaintAxle.setColor(color); mPaintRing.setColor(color); postInvalidate(); } @Override protected void InitPaint() { initPaint(); } @Override protected void OnAnimationUpdate(ValueAnimator valueAnimator) { mAnimatedValue = (float) valueAnimator.getAnimatedValue(); postInvalidate(); } @Override protected void OnAnimationRepeat(Animator animation) { } @Override protected int OnStopAnim() { postInvalidate(); return 1; } @Override protected int SetAnimRepeatMode() { return ValueAnimator.RESTART; } @Override protected void AnimIsRunning() { } @Override protected int SetAnimRepeatCount() { return ValueAnimator.INFINITE; } private int dip2px(float dpValue) { final float scale = getContext().getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } }