画圆需要的一下步骤
package com.bwie.yuan.view;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import com.bwie.yuan.R;
/**
* Created by 老北城 on 2017/11/29.
*/
* Created by 老北城 on 2017/11/29.
*/
public class CircleProgressView extends View implements Runnable {
Context context;
//内部原形半径
private int innerCircleRadius = 100;
private Paint paint;
private Paint outCircleRingPaint;
//画边缘的宽度,画的是多宽
private int outCircleWidth = 20;
private RectF rectF;
private int centerX;
private int centerY;
//原形的半径
private int outRingRadius;
//定义一个初始值
private int progress=0;
//设置一个总进度
private int totalProgress=100;
private Paint mTextPaint;
private int x;
private int y;
//内部原形半径
private int innerCircleRadius = 100;
private Paint paint;
private Paint outCircleRingPaint;
//画边缘的宽度,画的是多宽
private int outCircleWidth = 20;
private RectF rectF;
private int centerX;
private int centerY;
//原形的半径
private int outRingRadius;
//定义一个初始值
private int progress=0;
//设置一个总进度
private int totalProgress=100;
private Paint mTextPaint;
private int x;
private int y;
public CircleProgressView(Context context) {
this(context, null);
this.context=context;
}
this(context, null);
this.context=context;
}
public CircleProgressView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
this.context=context;
}
this(context, attrs, 0);
this.context=context;
}
public CircleProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context=context;
init();
}
super(context, attrs, defStyleAttr);
this.context=context;
init();
}
private void init() {
paint = new Paint();
//为画笔设置颜色
paint.setColor(Color.parseColor("#D5982E"));
//设置抗锯齿
paint.setAntiAlias(true);
//创建外部的笔
outCircleRingPaint = new Paint();
outCircleRingPaint.setColor(Color.parseColor("#2A982E"));
//设置是否是填充的
outCircleRingPaint.setStyle(Paint.Style.STROKE);
//设置描边的宽度
outCircleRingPaint.setStrokeWidth(outCircleWidth);
//设置抗锯齿
outCircleRingPaint.setAntiAlias(true);
//设置这个角度
outCircleRingPaint.setStrokeCap(Paint.Cap.BUTT);
//创建文字画笔
mTextPaint = new Paint();
mTextPaint.setTextSize(35);
paint = new Paint();
//为画笔设置颜色
paint.setColor(Color.parseColor("#D5982E"));
//设置抗锯齿
paint.setAntiAlias(true);
//创建外部的笔
outCircleRingPaint = new Paint();
outCircleRingPaint.setColor(Color.parseColor("#2A982E"));
//设置是否是填充的
outCircleRingPaint.setStyle(Paint.Style.STROKE);
//设置描边的宽度
outCircleRingPaint.setStrokeWidth(outCircleWidth);
//设置抗锯齿
outCircleRingPaint.setAntiAlias(true);
//设置这个角度
outCircleRingPaint.setStrokeCap(Paint.Cap.BUTT);
//创建文字画笔
mTextPaint = new Paint();
mTextPaint.setTextSize(35);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawInnerCircle(canvas);
drawOutCircleRing(canvas);
drawText(canvas);
}
//设置文本
private void drawText(Canvas canvas){
String d=progress+"%";
//得到文本的宽高
Paint.FontMetrics fm=new Paint.FontMetrics();
//得到文本的高度
int textheight = (int) Math.ceil(fm.descent - fm.ascent);
//得到文本的宽度
int textwidth = (int) mTextPaint.measureText(d, 0, d.length());
canvas.drawText(d,getWidth()/2-(textwidth/2),getHeight()/2-(textheight/2),mTextPaint);
}
//拖动的时候圆也跟着动
@Override
public boolean onTouchEvent(MotionEvent event) {
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawInnerCircle(canvas);
drawOutCircleRing(canvas);
drawText(canvas);
}
//设置文本
private void drawText(Canvas canvas){
String d=progress+"%";
//得到文本的宽高
Paint.FontMetrics fm=new Paint.FontMetrics();
//得到文本的高度
int textheight = (int) Math.ceil(fm.descent - fm.ascent);
//得到文本的宽度
int textwidth = (int) mTextPaint.measureText(d, 0, d.length());
canvas.drawText(d,getWidth()/2-(textwidth/2),getHeight()/2-(textheight/2),mTextPaint);
}
//拖动的时候圆也跟着动
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
x = (int) event.getX();
y = (int) event.getY();
System.out.println("按下时: " + "x坐标:" + event.getRawX() + " " + "y坐标:" + event.getRawY());
case MotionEvent.ACTION_DOWN:
x = (int) event.getX();
y = (int) event.getY();
System.out.println("按下时: " + "x坐标:" + event.getRawX() + " " + "y坐标:" + event.getRawY());
//实现MotionEvent.ACTION_MOVE 记录移动的x,y坐标:getRawX()和getRawY()获得的是相对屏幕的位置
case MotionEvent.ACTION_MOVE:
x = (int) event.getX();
y = (int) event.getY();
System.out.println("移动时: " + "x坐标:" + event.getRawX() + " " + "y坐标:" + event.getRawY());
case MotionEvent.ACTION_MOVE:
x = (int) event.getX();
y = (int) event.getY();
System.out.println("移动时: " + "x坐标:" + event.getRawX() + " " + "y坐标:" + event.getRawY());
//实现MotionEvent.ACTION_UP 记录抬起的x,y坐标
case MotionEvent.ACTION_UP:
// 获取当前触摸点的x,y坐标,为X轴和Y轴坐标重新赋值:getX()和getY()获得的永远是view的触摸位置坐标
x = (int) event.getX();
y = (int) event.getY();
System.out.println("抬起时: " + "x坐标:" + event.getRawX() + " " + "y坐标:" + event.getRawY());
break;
}
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
int width = manager.getDefaultDisplay().getWidth();
int height = manager.getDefaultDisplay().getHeight();
if (x >= 100 && y >= 100 && x <= width - 100 && y <= height - 100) {
postInvalidate();
}
return true;
}
//测量模式
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
case MotionEvent.ACTION_UP:
// 获取当前触摸点的x,y坐标,为X轴和Y轴坐标重新赋值:getX()和getY()获得的永远是view的触摸位置坐标
x = (int) event.getX();
y = (int) event.getY();
System.out.println("抬起时: " + "x坐标:" + event.getRawX() + " " + "y坐标:" + event.getRawY());
break;
}
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
int width = manager.getDefaultDisplay().getWidth();
int height = manager.getDefaultDisplay().getHeight();
if (x >= 100 && y >= 100 && x <= width - 100 && y <= height - 100) {
postInvalidate();
}
return true;
}
//测量模式
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width = 0;
int height = 0;
switch (widthMode) {
case MeasureSpec.UNSPECIFIED: {
//很少用
}
break;
case MeasureSpec.AT_MOST: {
width = innerCircleRadius * 2 + outCircleWidth * 2;
}
break;
case MeasureSpec.EXACTLY: {
width = widthSize;
}
break;
}
switch (heightMode) {
case MeasureSpec.UNSPECIFIED: {
//很少用
}
break;
case MeasureSpec.AT_MOST: {
height = innerCircleRadius * 2 + outCircleWidth * 2;
}
break;
case MeasureSpec.EXACTLY: {
height = heightSize;
}
break;
}
//这个方法必须调用,不调用测量的高度会出现偏差
setMeasuredDimension(width, height);
}
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width = 0;
int height = 0;
switch (widthMode) {
case MeasureSpec.UNSPECIFIED: {
//很少用
}
break;
case MeasureSpec.AT_MOST: {
width = innerCircleRadius * 2 + outCircleWidth * 2;
}
break;
case MeasureSpec.EXACTLY: {
width = widthSize;
}
break;
}
switch (heightMode) {
case MeasureSpec.UNSPECIFIED: {
//很少用
}
break;
case MeasureSpec.AT_MOST: {
height = innerCircleRadius * 2 + outCircleWidth * 2;
}
break;
case MeasureSpec.EXACTLY: {
height = heightSize;
}
break;
}
//这个方法必须调用,不调用测量的高度会出现偏差
setMeasuredDimension(width, height);
}
//这个方法是测量后得到的真实宽高
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//得到中心点
centerX = w / 2;
centerY = h / 2;
rectF = new RectF();
//圆形的半径
outRingRadius = w / 2 - outCircleWidth;
//确定圆形的绘制区域
rectF.left = centerX - outRingRadius-10;
rectF.top = centerY - outRingRadius-10;
rectF.right = centerX + outRingRadius+10;
rectF.bottom = centerY + outRingRadius+10;
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//得到中心点
centerX = w / 2;
centerY = h / 2;
rectF = new RectF();
//圆形的半径
outRingRadius = w / 2 - outCircleWidth;
//确定圆形的绘制区域
rectF.left = centerX - outRingRadius-10;
rectF.top = centerY - outRingRadius-10;
rectF.right = centerX + outRingRadius+10;
rectF.bottom = centerY + outRingRadius+10;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
//绘制外面的描边
private void drawOutCircleRing(Canvas canvas){
canvas.drawArc(rectF,-90,(progress*360)/totalProgress,false,outCircleRingPaint);
}
private void drawOutCircleRing(Canvas canvas){
canvas.drawArc(rectF,-90,(progress*360)/totalProgress,false,outCircleRingPaint);
}
//绘制内部的实心圆
private void drawInnerCircle(Canvas canvas) {
canvas.drawCircle(getWidth() / 2, getHeight() / 2, innerCircleRadius, paint);
}
private void drawInnerCircle(Canvas canvas) {
canvas.drawCircle(getWidth() / 2, getHeight() / 2, innerCircleRadius, paint);
}
//重写run方法
@Override
public void run() {
while(true){
if(progress<100){
progress++;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
postInvalidate();
}else{
progress=0;
}
}
}
}
@Override
public void run() {
while(true){
if(progress<100){
progress++;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
postInvalidate();
}else{
progress=0;
}
}
}
}
然后在布局里面引用一下这个类就行了
开启线程在主方法里面也就是MainActivity里面设置
流式布局的设置
package com.bwie.customedemo.view;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
public class MyViewGroup extends ViewGroup {
public MyViewGroup(Context context) {
this(context,null);
}
this(context,null);
}
public MyViewGroup(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
this(context, attrs,0);
}
public MyViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
super(context, attrs, defStyleAttr);
}
/**
* 测量
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.d("MyViewGroup", "onMeasure");
//测量view
measureChildren(widthMeasureSpec,heightMeasureSpec);
}
* 测量
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.d("MyViewGroup", "onMeasure");
//测量view
measureChildren(widthMeasureSpec,heightMeasureSpec);
}
/**
* 绘制的方法
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d("MyViewGroup", "onDraw");
}
* 绘制的方法
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d("MyViewGroup", "onDraw");
}
/**
* 用来确定子View的位置
* @param changed
* @param l lef 相对于父容器
* @param t top
* @param r right
* @param b bottom
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
* 用来确定子View的位置
* @param changed
* @param l lef 相对于父容器
* @param t top
* @param r right
* @param b bottom
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Log.d("MyViewGroup", "onLayout");
int currentWidth = 0;
int currentHeight = 0;
//得到子View的个数
int childCount = getChildCount();
for (int i = 0; i < childCount; ++i){
//得到这个ViewGroup里面的每一个子View
View childView = getChildAt(i);
//得到每一个子View的宽高
int width = childView.getMeasuredWidth();
int height = childView.getMeasuredHeight();
//确定子View的高度
childView.layout(currentWidth,currentHeight,currentWidth + width,currentHeight + height);
//累加所有的子View宽高
currentWidth += width;
currentHeight += height;
}
}
}
int currentWidth = 0;
int currentHeight = 0;
//得到子View的个数
int childCount = getChildCount();
for (int i = 0; i < childCount; ++i){
//得到这个ViewGroup里面的每一个子View
View childView = getChildAt(i);
//得到每一个子View的宽高
int width = childView.getMeasuredWidth();
int height = childView.getMeasuredHeight();
//确定子View的高度
childView.layout(currentWidth,currentHeight,currentWidth + width,currentHeight + height);
//累加所有的子View宽高
currentWidth += width;
currentHeight += height;
}
}
}
最后在布局里面简单的引用一下就可以使用了