自定义view之实现内圆由中心放大至和外圆一致,并实现view可自由拖拽、移动
效果图:
直接上代码:
1:attrs:
<?xml version="1.0" encoding="utf-8"?> <resources> <!--自定义实现写字板--> <declare-styleable name="CustomPaint"> <attr name="boardBackground" format="color"></attr> <!--写字板背景颜色--> <attr name="paintColor" format="color"></attr><!--画笔颜色--> <attr name="paintWidth" format="dimension"></attr><!--画笔宽度--> </declare-styleable> <!--自定义进度条--> <declare-styleable name="CustomProgress"> <attr name="radius" format="dimension" /><!--半径--> <attr name="strokeWidth" format="dimension" /><!--画笔宽度--> <attr name="circleColor" format="color" /><!--内圆颜色--> <attr name="ringColor" format="color" /><!--进度条颜色--> <attr name="totalProgress" format="integer" /><!--总进度--> <attr name="textColor" format="color|reference" /><!--字体颜色--> <attr name="bigCircleColor" format="color" /><!--外圆颜色--> </declare-styleable> </resources>
2:自定义画笔类:
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.util.AttributeSet; import android.view.MotionEvent; import android.view.View; /** * @类的用途:自定义画笔 * @author: 李晓倩 * @date: 2017/6/12 */ public class CustomPaint extends View { private int mBoardBackground;//写字板背景颜色 private int mPaintColor;//画笔颜色 private int mPaintWidth;//画笔宽度 private Paint mPaint; private Path mPath; public CustomPaint(Context context) { this(context, null); } public CustomPaint(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CustomPaint(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } private void init(Context context, AttributeSet attrs) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomPaint); mBoardBackground = typedArray.getColor(R.styleable.CustomPaint_boardBackground, Color.WHITE); mPaintColor = typedArray.getColor(R.styleable.CustomPaint_paintColor, Color.BLACK); mPaintWidth = typedArray.getDimensionPixelSize(R.styleable.CustomPaint_paintWidth, 15); typedArray.recycle(); mPaint = new Paint(); mPath = new Path(); setBackgroundColor(mBoardBackground); mPaint.setColor(mPaintColor); mPaint.setStrokeWidth(mPaintWidth); mPaint.setStyle(Paint.Style.STROKE); mPaint.setAntiAlias(true); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawPath(mPath, mPaint); } @Override public boolean onTouchEvent(MotionEvent event) { float touchX = event.getX(); float touchY = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mPath.moveTo(touchX, touchY); break; case MotionEvent.ACTION_MOVE: mPath.lineTo(touchX, touchY); break; case MotionEvent.ACTION_UP: break; } invalidate(); return true; } }
3:自定义view类:
import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.ImageView; /** * @类的用途:自定义进度条 * @author: 李晓倩 * @date: 2017/6/12 */ public class CustomProgress extends ImageView { // 画实心圆的画笔 private Paint mCirclePaint; // 画圆环的画笔 private Paint mRingPaint; // 画字体的画笔 private Paint mTextPaint; // 圆形颜色 private int mCircleColor; // 圆环颜色 private int mRingColor; // 半径 private float mRadius; // 圆环半径 private float mRingRadius; // 圆环宽度 private float mStrokeWidth; // 圆心x坐标 private int mXCenter; // 圆心y坐标 private int mYCenter; // 字的长度 private float mTxtWidth; // 字的高度 private float mTxtHeight; // 总进度 private int mTotalProgress; // 当前进度 private int mProgress; //大圆 private Paint mBigPatient; //字体颜色 private int mTextColor; //外圆颜色 private int mBigCircleColor; public CustomProgress(Context context, AttributeSet attrs) { super(context, attrs); // 获取自定义的属性 initAttrs(context, attrs); initVariable(); } private void initAttrs(Context context, AttributeSet attrs) { TypedArray typeArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomProgress, 0, 0); mRadius = typeArray.getDimension(R.styleable.CustomProgress_radius, 300); mStrokeWidth = typeArray.getDimension(R.styleable.CustomProgress_strokeWidth, 20); mCircleColor = typeArray.getColor(R.styleable.CustomProgress_circleColor, Color.BLUE); mRingColor = typeArray.getColor(R.styleable.CustomProgress_ringColor, Color.GRAY); mTotalProgress = typeArray.getInt(R.styleable.CustomProgress_totalProgress, 100); mTextColor = typeArray.getColor(R.styleable.CustomProgress_textColor, Color.WHITE); mBigCircleColor = typeArray.getColor(R.styleable.CustomProgress_bigCircleColor, Color.WHITE); typeArray.recycle();//注意这里要释放掉 mRingRadius = mRadius + mStrokeWidth / 2; } private void initVariable() { mCirclePaint = new Paint(); mCirclePaint.setAntiAlias(true); mCirclePaint.setColor(mCircleColor); mCirclePaint.setStrokeCap(Paint.Cap.ROUND); mCirclePaint.setStyle(Paint.Style.FILL); mRingPaint = new Paint(); mRingPaint.setAntiAlias(true); mRingPaint.setColor(mRingColor); mRingPaint.setStrokeCap(Paint.Cap.ROUND); mRingPaint.setStyle(Paint.Style.FILL_AND_STROKE); mRingPaint.setStrokeWidth(mStrokeWidth); mTextPaint = new Paint(); mTextPaint.setAntiAlias(true); mTextPaint.setStyle(Paint.Style.FILL); mTextPaint.setColor(mTextColor); mTextPaint.setTextSize(mRadius / 2); mBigPatient = new Paint(); mBigPatient.setColor(mBigCircleColor); mBigPatient.setAntiAlias(true); mBigPatient.setStyle(Paint.Style.FILL); Paint.FontMetrics fm = mTextPaint.getFontMetrics(); mTxtHeight = (int) Math.ceil(fm.descent - fm.ascent); } @Override protected void onDraw(Canvas canvas) { mXCenter = getWidth() / 2; mYCenter = getHeight() / 2; canvas.drawCircle(mXCenter, mYCenter, mRadius + mStrokeWidth, mBigPatient); canvas.drawCircle(mXCenter, mYCenter, mRadius, mCirclePaint); canvas.drawPoint(mXCenter, mYCenter,mRingPaint); if (mProgress > 0) { /* RectF oval = new RectF(); oval.left = (mXCenter - mRingRadius+mStrokeWidth); oval.top = (mYCenter - mRingRadius+mStrokeWidth); oval.right = mRingRadius * 2 + (mXCenter - mRingRadius)-mStrokeWidth; oval.bottom = mRingRadius * 2 + (mYCenter - mRingRadius)-mStrokeWidth; canvas.drawArc(oval, -90, ((float) mProgress / mTotalProgress) * 360, true, mRingPaint); // String txt = (mProgress * 1.0f / mTotalProgress * 100) + "%"; mTxtWidth = mTextPaint.measureText(txt, 0, txt.length()); canvas.drawText(txt, mXCenter - mTxtWidth / 2, mYCenter + mTxtHeight / 4, mTextPaint);*/ canvas.drawCircle(mXCenter, mYCenter, mRingRadius*mProgress/100, mRingPaint); String txt = (mProgress * 1.0f / mTotalProgress * 100) + "%"; mTxtWidth = mTextPaint.measureText(txt, 0, txt.length()); canvas.drawText(txt, mXCenter - mTxtWidth / 2, mYCenter + mTxtHeight / 4, mTextPaint); } } public void setProgress(int progress) { mProgress = progress; postInvalidate(); } public void setmTotalProgress(int totalProgress) { mTotalProgress = totalProgress; } //图片可拖动 private int lastX = 0; private int lastY = 0; @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastX = (int) event.getRawX(); lastY = (int) event.getRawY(); break; case MotionEvent.ACTION_MOVE: int dx = (int) event.getRawX() - lastX; int dy = (int) event.getRawY() - lastY; int left = getLeft() + dx; int top = getTop() + dy; int right = getRight() + dx; int bottom = getBottom() + dy; layout(left, top, right, bottom); lastX = (int) event.getRawX(); lastY = (int) event.getRawY(); break; case MotionEvent.ACTION_UP: break; default: break; } return true; } }
4:布局文件:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="test.bwie.com.lixiaoqian20170612.MainActivity"> <test.bwie.com.lixiaoqian20170612.CustomProgress android:id="@+id/custom_progress" android:layout_width="100dp" android:layout_height="100dp" app:bigCircleColor="#888888" app:circleColor="#0f0" app:radius="30dp" app:strokeWidth="10dp" app:textColor="#000" android:layout_centerVertical="true" android:layout_alignParentEnd="true" android:layout_marginEnd="132dp"/> <Button android:textSize="20sp" android:layout_margin="15dp" android:text="Start Download" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentStart="true" android:id="@+id/button"/> </RelativeLayout>
5:需要使用到的activity:
import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; /** * @类的用途:主界面 * @author: 李晓倩 * @date: 2017/6/12 */ public class MainActivity extends AppCompatActivity implements View.OnClickListener { private CustomProgress custom_progress; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 1) { custom_progress.setProgress(msg.arg1); } super.handleMessage(msg); } }; private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); custom_progress.setmTotalProgress(100); } private void initView() { custom_progress = (CustomProgress) findViewById(R.id.custom_progress); button = (Button) findViewById(R.id.button); button.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.button: new Thread(new Runnable() { @Override public void run() { try { for (int i = 1; i <= 100; i++) { Thread.sleep(50); Message message = handler.obtainMessage(); message.what = 1; message.arg1 = i; handler.sendMessage(message); } } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); break; } } }