package com.com.mr_wrong.CustomJobView; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PathMeasure; import android.graphics.RectF; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; import com.Utils.LogUtils; import com.example.mr_wrong.androidstudioproject.R; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; /** * Created by Mr_Wrong on 15/7/7. */ public class ArcView extends View { private int mArcColor; private int mArcWidth; private float mDegree; private int mInColor; private int mOutColor; private Paint mPaint; private Path mPath; private Path mPath1; private int mWidth; private int mHeight; private float ctrx, ctry;//控制点 boolean isinc; int centre; int cricle_radius_width; int arc_radius_width; int degree; float arcwidth; float archeight; public ArcView(Context context) { this(context, null); } public ArcView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ArcView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ArcView, defStyleAttr, 0); mArcColor = array.getColor(R.styleable.ArcView_arccolor, Color.RED); mInColor = array.getColor(R.styleable.ArcView_incriclecolor, Color.BLACK); mOutColor = array.getColor(R.styleable.ArcView_outcriclecolor, Color.GRAY); mDegree = array.getFloat(R.styleable.ArcView_degree, 0); mArcWidth = array.getDimensionPixelSize(R.styleable.ArcView_arcwidth, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_PX, 20, getResources().getDisplayMetrics())); mPointsList = new ArrayList<Point>(); timer = new Timer(); mPaint = new Paint(); mPaint.setStyle(Paint.Style.FILL); mPaint.setAntiAlias(true); mPath = new Path(); mPath1 = new Path(); } private float mWaveHeight = 80; /** * 波长 */ private float mWaveWidth = 200; /** * 被隐藏的最左边的波形 */ private float mLeftSide; private float mMoveLen; /** * 水波平移速度 */ public static final float SPEED = 1.7f; private List<Point> mPointsList; private Timer timer; private MyTimerTask mTask; @Override public void onWindowFocusChanged(boolean hasWindowFocus) { super.onWindowFocusChanged(hasWindowFocus); // 开始波动 start(); } private void start() { if (mTask != null) { mTask.cancel(); mTask = null; } mTask = new MyTimerTask(updateHandler); timer.schedule(mTask, 0, 10); } Handler updateHandler = new Handler() { @Override public void handleMessage(Message msg) { // 记录平移总位移 mMoveLen += SPEED; mLeftSide += SPEED; // 波形平移 for (int i = 0; i < mPointsList.size(); i++) { mPointsList.get(i).setX(mPointsList.get(i).getX() + SPEED); switch (i % 4) { case 0: case 2: mPointsList.get(i).setY(archeight); break; case 1: mPointsList.get(i).setY(archeight + mWaveHeight); break; case 3: mPointsList.get(i).setY(archeight - mWaveHeight); break; } } if (mMoveLen >= mWaveWidth) { // 波形平移超过一个完整波形后复位 mMoveLen = 0; resetPoints(); } invalidate(); } }; private void resetPoints() { mLeftSide = -mWaveWidth; for (int i = 0; i < mPointsList.size(); i++) { mPointsList.get(i).setX(i * mWaveWidth / 4 - mWaveWidth); } } class MyTimerTask extends TimerTask { Handler handler; public MyTimerTask(Handler handler) { this.handler = handler; } @Override public void run() { handler.sendMessage(handler.obtainMessage()); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); centre = getWidth() / 2; cricle_radius_width = centre - mArcWidth;//内圆的半径 arc_radius_width = centre - mArcWidth / 2;//圆环半径 degree = (int) (0.5 * mDegree * 360); mWidth = getWidth(); mHeight = getHeight(); arcwidth = (float) (2 * cricle_radius_width * Math.sin(degree * Math.PI / 180)); archeight = (float) (mHeight - (cricle_radius_width - cricle_radius_width * Math.cos(degree * Math.PI / 180))); // 根据View宽度计算波形峰值 mWaveHeight = arcwidth / 5f; // 波长等于四倍View宽度也就是View中只能看到四分之一个波形,这样可以使起伏更明显 mWaveWidth = (float) (arcwidth * 1.5); // 左边隐藏的距离预留一个波形 mLeftSide = -mWaveWidth; // 这里计算在可见的View宽度中能容纳几个波形,注意n上取整 int n = (int) Math.round(arcwidth / mWaveWidth + 0.5); // n个波形需要4n+1个点,但是我们要预留一个波形在左边隐藏区域,所以需要4n+5个点 for (int i = 0; i < (4 * n + 5); i++) { // 从P0开始初始化到P4n+4,总共4n+5个点 float x = i * mWaveWidth / 4 - mWaveWidth; float y = 0; switch (i % 4) { case 0: case 2: // 零点位于水位线上 y = archeight; break; case 1: // 往下波动的控制点 y = archeight + mWaveHeight; break; case 3: // 往上波动的控制点 y = archeight - mWaveHeight; break; } mPointsList.add(new Point(x, y)); } } @Override protected void onDraw(Canvas canvas) { //内圆 mPaint.setColor(mInColor); canvas.drawCircle(centre, centre, cricle_radius_width, mPaint); //外圆 mPaint.setStrokeWidth(mArcWidth); mPaint.setColor(mOutColor); mPaint.setStyle(Paint.Style.STROKE); canvas.drawCircle(centre, centre, arc_radius_width, mPaint); //圆弧 RectF rect = new RectF(centre - arc_radius_width, centre - arc_radius_width , centre + arc_radius_width, centre + arc_radius_width); float startangle = (float) (0.5 * (1 - mDegree) * 360); float sweepangle = mDegree * 360; mPaint.setColor(mArcColor); canvas.drawArc(rect, startangle - 90, sweepangle, false, mPaint); mPath.reset(); int i = 0; mPath.moveTo(mPointsList.get(0).getX(), mPointsList.get(0).getY()); for (; i < mPointsList.size() - 2; i = i + 2) { mPath.quadTo(mPointsList.get(i + 1).getX(), mPointsList.get(i + 1).getY(), mPointsList.get(i + 2) .getX(), mPointsList.get(i + 2).getY()); } mPath.arcTo(rect, startangle - 90, sweepangle); mPath1.arcTo(rect, startangle - 90, 360, true); LogUtils.e(startangle - 90); mPaint.setColor(Color.BLUE); mPaint.setStyle(Paint.Style.FILL); canvas.clipPath(mPath1); canvas.drawPath(mPath, mPaint); //获取path上的点 PathMeasure pathMeasure = new PathMeasure(mPath1, false); float length = pathMeasure.getLength(); float speed = length / 100; float dis = 0; int count = 0; float[] aCoordinates = new float[2]; mPaint.setColor(Color.RED); mPaint.setStyle(Paint.Style.FILL); FlaotPoint[] pointArray = new FlaotPoint[200]; while (dis < length && count < 100) { pathMeasure.getPosTan(dis, aCoordinates, null); dis += speed; count++; pointArray[count] = new FlaotPoint(aCoordinates[0], aCoordinates[1]); canvas.drawCircle(pointArray[count].getX(), pointArray[count].getY(), 20, mPaint); mPaint.setColor(Color.BLACK); if(pointArray[count-1]!=null){ canvas.drawCircle(pointArray[count-1].getX(), pointArray[count-1].getY(), 20, mPaint); } // LogUtils.e("x--->"+aCoordinates[0]+" y--->"+aCoordinates[1]); if (pointArray[50] != null) { //LogUtils.e(pointArray[50].getY()); LogUtils.e(pointArray[50].getX()); // canvas.drawCircle(pointArray[50].getX(), pointArray[50].getY(), 20, mPaint); } } } class FlaotPoint { float x, y; public FlaotPoint(float x, float y) { this.x = x; this.y = y; } public float getX() { return x; } public float getY() { return y; } } class Point { private float x; private float y; public float getX() { return x; } public void setX(float x) { this.x = x; } public float getY() { return y; } public void setY(float y) { this.y = y; } public Point(float x, float y) { this.x = x; this.y = y; } } }