自定义view简单的画圆和自定义流式布局

画圆需要的一下步骤

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 com.bwie.yuan.R;

/**
 * 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;

    public CircleProgressView(Context context) {
        this(context, null);
        this.context=context;
    }

    public CircleProgressView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
        this.context=context;
    }

    public CircleProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        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);

    }

    @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) {

        switch (event.getAction()){
            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());

                //实现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);

        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);
    }

    //这个方法是测量后得到的真实宽高

    @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;
    }

    @Override
    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 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;
            }
        }
    }
}

然后在布局里面引用一下这个类就行了
开启线程在主方法里面也就是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;


public class MyViewGroup extends ViewGroup {

    public MyViewGroup(Context context) {
        this(context,null);
    }

    public MyViewGroup(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public MyViewGroup(Context context, AttributeSet attrs, int 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 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) {

        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;
        }
    }
}

最后在布局里面简单的引用一下就可以使用了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值