自定义view

本文介绍了自定义View的基础,包括CustomView的测量、绘制与布局,着重讲解了如何创建自定义圆形视图Circle和带有触摸交互的进度条ProgressBar,并展示了CustomLinearLayout,它让子View按左右顺序排列。
摘要由CSDN通过智能技术生成

1.自定义view基础

public class CustomView extends View {
    // 创建对象时调用
    public CustomView(Context context) {
        super(context);
    }
    // xml文件调用
    public CustomView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
    @Override // 测量尺寸
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // widthMeasureSpec,heightMeasureSpec是父容器指定该控件的宽高,
        // 该控件需要setMeasureDimension(int,int)指定具体的宽高
        // 测量模式:1.EXACTLY:控件的宽高设置为具体值时,如100dp
        //        2.AT_MOST:控件的宽高设置为wrap_content时使用
        //        3.UNSPECIFIED:当父容器没有指定自定义控件的宽高时使用
    }
    @Override // 绘制图像
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
    @Override // 指定布局中子控件的位置
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        // changed表示自定义view的大小和位置是否发生变化
        // left,top,right,bottom分别表示子控件与父容器左边,顶部,右边,底部的距离
    }
}

2.自定义圆形

public class Circle extends View {

public Circle(Context context) {
    super(context);
}
public Circle(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    int radius = 50;
    // 圆心
    int centerX = getLeft() + radius;
    int centerY = getTop() + radius;
    Paint paint = new Paint();
    paint.setColor(Color.YELLOW);
    canvas.drawCircle(centerX, centerY, radius, paint);
}
}

3.自定义进度条

public class ProgressBar extends View {

    private static final String TAG = "xiao";
    private int progress;
    private int max;
    private int backgroundColor;
    private int progressColor;
    private Paint backgroundPaint;
    private Paint progressPaint;
    private RectF progressRect;

    public ProgressBar(Context context) {
        super(context);
        init();
    }

    public ProgressBar(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        progress = 0;
        max = 100;
        backgroundColor = Color.GRAY;
        progressColor = Color.BLUE;

        backgroundPaint = new Paint();
        backgroundPaint.setColor(backgroundColor);
        backgroundPaint.setStyle(Paint.Style.FILL);

        progressPaint = new Paint();
        progressPaint.setColor(progressColor);
        progressPaint.setStyle(Paint.Style.FILL);

        progressRect = new RectF();
    }

    public void setProgress(int progress) {
        this.progress = progress;
        invalidate();
    }

    public void setMax(int max) {
        this.max = max;
        invalidate();
    }

    public void setBackgroundColor(int color) {
        this.backgroundColor = color;
        backgroundPaint.setColor(color);
        invalidate();
    }

    public void setProgressColor(int color) {
        this.progressColor = color;
        progressPaint.setColor(color);
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int width = getWidth();
        int height = getHeight();

        Log.d(TAG, "onDraw: width = " + width + ",height=" + height);
        // Draw background
        canvas.drawRect(0, 0, width, height, backgroundPaint);
        // Calculate progress width
        float progressWidth = max * ((float) progress / max);

        // Draw progress
        progressRect.set(0, 0, progressWidth, height);
        canvas.drawRect(progressRect, progressPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int touchX;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touchX = (int) event.getX();
            case MotionEvent.ACTION_MOVE:
                touchX = (int) event.getX();
                Log.d(TAG, "ACTION_MOVE: touchX = " + touchX + ",max = " + max);
                if (touchX < max) {
                    setProgress(touchX);
                }
            case MotionEvent.ACTION_UP:
                touchX = (int) event.getX();
                Log.d(TAG, "ACTION_UP: touchX = " + touchX + ",max = " + max);
                if (touchX < max) {
                    setProgress(touchX);
                }
        }
        return super.onTouchEvent(event);
    }
}

4.自定义ViewGroup,子view依次在最左,最右

public class CustomLinearLayout extends ViewGroup {

    public CustomLinearLayout(Context context) {
        super(context);
    }

    public CustomLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int width = 0;
        int height = 0;

        // Measure children and calculate total width and height
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            width = Math.max(width, child.getMeasuredWidth());
            height += child.getMeasuredHeight();
        }

        // Consider padding and measured size
        width += getPaddingLeft() + getPaddingRight();
        height += getPaddingTop() + getPaddingBottom();

        // Consider layout constraints
        width = resolveSizeAndState(width, widthMeasureSpec, 0);
        height = resolveSizeAndState(height, heightMeasureSpec, 0);

        setMeasuredDimension(width, height);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        int top = 0;

        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            if ((i & 1) == 0) {// 偶数
                child.layout(0, top, child.getMeasuredWidth(), top + child.getMeasuredHeight());
            } else {
                child.layout(getMeasuredWidth() - child.getMeasuredWidth(), top, getMeasuredWidth(), top + child.getMeasuredHeight());
                top += child.getMeasuredHeight();
            }
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值