package com.hesheng.myapplication;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.os.Handler;import android.util.AttributeSet;import android.view.View;import android.view.WindowManager;/** * Created by wangchaomac on 2017/11/25. */public class CounterView extends android.support.v7.widget.AppCompatImageView implements View.OnClickListener {// // 定义画笔// private Paint mPaint; // 用于获取文字的宽和高 private Rect mBounds; // 计数值,每点击一次本控件,其值增加1 private int mCount; private int width; private int height; private float scale; private float px1 = 450;//450 private float py1 = 450;//450 private float px = 0;//300 private float py = 0;//300 private float px2 = 0;//300 private float py2 = 0;//750// private float px1 = 500;// private float py1 = 600;// private float px = 300;// private float py = 300;// private float px2 = 300;// private float py2 = 900; private double i = 0; private boolean isStart = false; private boolean isInit = true; public float getPx() { return px; } public float getPy() { return py; } private Handler handler = new Handler(){ public void handleMessage(android.os.Message msg) { switch (msg.what) { case 0: if (isStart) {// if(i>2)// {// isStart = false;// return;// } i += 1; double y = (Math.PI * i) / 180; if (i <= 360) { if( i<= 90){ px = (float)radio + radio * (float) Math.sin(y); py = (float)radio - radio * (float) Math.cos(y); px2 = (float)radio - radio * (float) Math.sin(y); py2 = (float)radio + radio * (float) Math.cos(y); } else { px = radio + radio * (float) Math.sin(y); py = radio - radio * (float) Math.cos(y); px2 = radio - radio * (float) Math.sin(y); py2 = radio + radio * (float) Math.cos(y); }// px = radio + radio * (float) Math.sin(y);// py = radio - radio * (float) Math.cos(y);//////// px2 = radio - radio * (float) Math.sin(y);// py2 = radio + radio * (float) Math.cos(y); if (i == 360) { i = 0; } } invalidate(); // handler.sendEmptyMessageDelayed(0,10); } break; default: break; } }; }; private void getWindow(Context context) { WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); scale = context.getResources().getDisplayMetrics().density; } //写一个drawble转BitMap的方法 private Bitmap drawableToBitmap(Drawable drawable) { if (drawable instanceof BitmapDrawable) { BitmapDrawable bd = (BitmapDrawable) drawable; return bd.getBitmap(); } int w = drawable.getIntrinsicWidth(); int h = drawable.getIntrinsicHeight(); Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, w, h); drawable.draw(canvas); return bitmap; } private Paint mPaint; //画笔 private int mRadius; //圆形图片的半径// @Override// protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// super.onMeasure(widthMeasureSpec, heightMeasureSpec);// //因为是圆形图片,所以应该让宽高保持一致// int size = Math.min(getMeasuredWidth(), getMeasuredHeight());// mRadius = size / 2;//// setMeasuredDimension(size, size);// } private float mScale; //图片的缩放比例// @Override// protected void onDraw(Canvas canvas) {// super.onDraw(canvas);// Paint paint = new Paint();// paint.setStyle(Paint.Style.STROKE);// paint.setColor(Color.BLACK);// canvas.drawCircle(px1, py1, radio, paint);//// Paint paint2 = new Paint();// paint2.setStyle(Paint.Style.FILL);// paint2.setColor(Color.BLACK);// canvas.drawCircle( px + 200 , py + 600 ,10, paint2);////// Paint paint3 = new Paint();// paint3.setStyle(Paint.Style.FILL);// paint3.setColor(Color.BLACK);// if(isInit){// canvas.drawCircle( px2+200 , 300 ,10, paint3);// isInit = false;// System.out.println(" py2 = "+py2);// return;// }//// canvas.drawCircle( px2+200 , py2 + 300 ,10, paint3);// } public void start() { isStart = true; handler.sendEmptyMessageDelayed(0, 100); } public void stop() { isStart = false; } public CounterView(Context context, AttributeSet attrs) { super(context, attrs); // 初始化画笔、Rect mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mBounds = new Rect(); // 本控件的点击事件 setOnClickListener(this); getWindow(context); } private float radio = 300; /** * 比onDraw先执行 * <p> * 一个MeasureSpec封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求。 * 一个MeasureSpec由大小和模式组成 * 它有三种模式:UNSPECIFIED(未指定),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小; * EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小; * AT_MOST(至多),子元素至多达到指定大小的值。 * <p> * 它常用的三个函数: * 1.static int getMode(int measureSpec):根据提供的测量值(格式)提取模式(上述三个模式之一) * 2.static int getSize(int measureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小) * 3.static int makeMeasureSpec(int size,int mode):根据提供的大小值和模式创建一个测量值(格式) */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); final int minimumWidth = getSuggestedMinimumWidth(); final int minimumHeight = getSuggestedMinimumHeight(); int width = measureWidth(minimumWidth, widthMeasureSpec); int height = measureHeight(minimumHeight, heightMeasureSpec); radio = getMeasuredWidth()/ 2; px = Math.min(width,height) / 2; py = 0; px2 = Math.min(width,height) / 2; py2 = Math.min(width,height) / 2; setMeasuredDimension(width, height); } private int measureWidth(int defaultWidth, int measureSpec) { int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) { case MeasureSpec.AT_MOST: defaultWidth = getPaddingLeft() + getPaddingRight(); break; case MeasureSpec.EXACTLY: defaultWidth = specSize; break; case MeasureSpec.UNSPECIFIED: defaultWidth = Math.max(defaultWidth, specSize); } return defaultWidth; } private int measureHeight(int defaultHeight, int measureSpec) { int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) { case MeasureSpec.AT_MOST: defaultHeight = getPaddingTop() + getPaddingBottom(); break; case MeasureSpec.EXACTLY: defaultHeight = specSize; break; case MeasureSpec.UNSPECIFIED: defaultHeight = Math.max(defaultHeight, specSize);// 1.基准点是baseline// 2.ascent:是baseline之上至字符最高处的距离// 3.descent:是baseline之下至字符最低处的距离// 4.leading:是上一行字符的descent到下一行的ascent之间的距离,也就是相邻行间的空白距离// 5.top:是指的是最高字符到baseline的值,即ascent的最大值// 6.bottom:是指最低字符到baseline的值,即descent的最大值 break; } return defaultHeight; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //mPaint.setColor(Color.WHITE); // 绘制一个填充色为蓝色的矩形 //canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint); // canvas.drawCircle( getWidth()/2, getHeight()/2,radio, mPaint);// mPaint.setColor(Color.YELLOW);// mPaint.setTextSize(50);// String text = String.valueOf(mCount);// // 获取文字的宽和高// mPaint.getTextBounds(text, 0, text.length(), mBounds);// float textWidth = mBounds.width();// float textHeight = mBounds.height();//// // 绘制字符串// canvas.drawText(text, getWidth() / 2 - textWidth / 2, getHeight() / 2// + textHeight / 2, mPaint);// System.out.println("px1 = "+ px1 + " py1 =" +py1);//// Paint paint = new Paint();// paint.setStyle(Paint.Style.STROKE);// paint.setColor(Color.BLACK);// canvas.drawCircle(px1, py1, radio, paint); Paint paint2 = new Paint(); paint2.setStyle(Paint.Style.FILL); paint2.setColor(Color.GREEN); //px+150 py+150 canvas.drawCircle(px , py ,4, paint2);// Paint paint3 = new Paint(); paint3.setStyle(Paint.Style.FILL); paint3.setColor(Color.RED); if(isInit){ //px+150 py+150 canvas.drawCircle(px2 , py2 ,4, paint3); isInit = false; System.out.println(" py2 = "+py2); return; } //px+150 py+150 //canvas.drawCircle( px2+200 , py2 + 300 ,10, paint3); // canvas.drawCircle( px2+200 , py2 + 300 ,10, paint3); canvas.drawCircle(px2 ,py2 ,4, paint3); handler.sendEmptyMessageDelayed(0, 100); isStart = true; } @Override public void onClick(View v) { mCount ++; // 重绘 // invalidate(); }}
来源:https://www.cnblogs.com/wcLT/p/7906939.html