美文网首页
自定义View控件 实现进度条SeekBar效果

自定义View控件 实现进度条SeekBar效果

作者: 头秃到底 | 来源:发表于2024-02-04 17:53 被阅读0次

    一、实现目标

    自定义一个view控件,实现像seekbar一样的拖动效果

    二、学习目的

    1. 了解view和view的工作流程
    2. 了解自定义控件的流程

    三、实现

    用通俗的话解释,自制控件就是写个类继承自view或者viewgroup,经过measurelayoutdraw之后可以像原生控件一样被使用

    Measure(测量)

    在Android中,measure是在View的生命周期中的第一个阶段,用于确定View的大小。在这里,我们没有重写onMeasure方法,因此使用了View的默认测量行为。这意味着视图的大小将由其内容和布局参数来确定

    Layout(布局)

    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        layoutTrack();
        layoutProgress();
        layoutThumb();
    }
    
    private void layoutTrack() {
        trackRect.set(getPaddingLeft(), getHeight() / 2f - 10, getWidth() - getPaddingRight(), getHeight() / 2f + 10);
    }
    
    private void layoutProgress() {
        float progressWidth = trackRect.width() * ((float) progress / max);
        progressRect.set(trackRect.left, trackRect.top, trackRect.left + progressWidth, trackRect.bottom);
    }
    
    private void layoutThumb() {
        float thumbCenterX = trackRect.left + progressRect.width();
        thumbRect.set(thumbCenterX - thumbRadius, trackRect.top - thumbRadius, thumbCenterX + thumbRadius, trackRect.bottom + thumbRadius);
    }
    
    

    在这个类中,onLayout方法被重写,用于确定视图的位置。在onLayout方法中,调用了layoutTrack()layoutProgress()layoutThumb()方法,这些方法分别用于布局背景轨道、进度和thumb。

    Draw(绘制)

    onDraw方法中,首先通过canvas.drawRect方法绘制了背景轨道,然后通过计算进度的宽度,使用canvas.drawRect方法绘制了进度条。最后,通过canvas.drawRoundRect方法绘制了一个圆角矩形,代表进度条上的thumb。

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    
    
        canvas.drawRect(trackRect, trackPaint);
    
    
        float progressWidth = trackRect.width() * ((float) progress / max);
        progressRect.set(trackRect.left, trackRect.top, trackRect.left + progressWidth, trackRect.bottom);
        canvas.drawRect(progressRect, progressPaint);
    
    
        float thumbCenterX = Math.max(trackRect.left + thumbRadius, Math.min(trackRect.left + progressWidth, trackRect.right - thumbRadius));
    
    
        thumbRect.set(thumbCenterX - thumbRadius, trackRect.top - thumbRadius, thumbCenterX + thumbRadius, trackRect.bottom + thumbRadius);
    
    
        canvas.drawRoundRect(thumbRect, thumbRadius, thumbRadius, thumbPaint);
    
    
    }
    
    

    TouchEvent(触摸事件)

    onTouchEvent方法中,处理了触摸事件。当用户按下或滑动时,计算出当前的进度值,并通过setProgress方法更新进度条。在用户释放手指时,如果设置了进度变化监听器,则通知监听器。

    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
    
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                float progressValue = (x / getWidth()) * max;
                setProgress((int) progressValue, false);
                break;
            case MotionEvent.ACTION_UP:
                if (onProgressChangeListener != null) {
                    onProgressChangeListener.onProgressChanged(progress);
                }
                break;
        }
    
        invalidate();
        return true;
    }
    
    

    四、代码

    package com.example.uicustomviews;
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.RectF;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.ViewGroup;
    import androidx.core.content.ContextCompat;
    
    public class CustomProgressBar2 extends View {
        private int max = 100;
        private int progress=0;
        private Paint trackPaint;
        private Paint progressPaint;
        private Paint thumbPaint;
    
        private RectF trackRect;
        private RectF progressRect;
        private RectF thumbRect;
    
        private float thumbRadius;
        private CustomProgressBar.OnProgressChangeListener onProgressChangeListener;
    
        public interface OnProgressChangeListener {
            void onProgressChanged(int progress);
        }
    
        public CustomProgressBar2(Context context) {
            super(context);
            initView();
        }
    
        public CustomProgressBar2(Context context, AttributeSet attrs) {
            super(context, attrs);
            initView();
        }
        public CustomProgressBar2(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initView();
        }
    
    
        private void initView(){
            trackPaint=new Paint();
            trackPaint.setColor(ContextCompat.getColor(getContext(), R.color.progressBackgroud));
            trackPaint.setStyle(Paint.Style.FILL);
    
            progressPaint=new Paint();
            progressPaint.setColor(ContextCompat.getColor(getContext(), R.color.progress));
            progressPaint.setStyle(Paint.Style.FILL);
    
            thumbPaint=new Paint();
            thumbPaint.setColor(ContextCompat.getColor(getContext(), R.color.progressBackgroud));
            thumbPaint.setStyle(Paint.Style.FILL);
    
    
            thumbRadius=10;
    
            trackRect=new RectF();
            progressRect=new RectF();
            thumbRect=new RectF();
    
        }
    
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            layoutTrack();
            layoutProgress();
            layoutThumb();
        }
    
        private void layoutTrack() {
            trackRect.set(getPaddingLeft(), getHeight() / 2f - 10, getWidth() - getPaddingRight(), getHeight() / 2f + 10);
        }
    
        private void layoutProgress() {
            float progressWidth = trackRect.width() * ((float) progress / max);
            progressRect.set(trackRect.left, trackRect.top, trackRect.left + progressWidth, trackRect.bottom);
        }
    
        private void layoutThumb() {
            float thumbCenterX = trackRect.left + progressRect.width();
            thumbRect.set(thumbCenterX - thumbRadius, trackRect.top - thumbRadius, thumbCenterX + thumbRadius, trackRect.bottom + thumbRadius);
        }
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
    
            canvas.drawRect(trackRect, trackPaint);
    
    
            float progressWidth = trackRect.width() * ((float) progress / max);
            progressRect.set(trackRect.left, trackRect.top, trackRect.left + progressWidth, trackRect.bottom);
            canvas.drawRect(progressRect, progressPaint);
    
    
            float thumbCenterX = Math.max(trackRect.left + thumbRadius, Math.min(trackRect.left + progressWidth, trackRect.right - thumbRadius));
    
    
            thumbRect.set(thumbCenterX - thumbRadius, trackRect.top - thumbRadius, thumbCenterX + thumbRadius, trackRect.bottom + thumbRadius);
    
    
            canvas.drawRoundRect(thumbRect, thumbRadius, thumbRadius, thumbPaint);
    
    
        }
        /*@Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
    
            trackRect.set(1, h / 2f - 10, w, h / 2f + 10);
        }*/
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX();
    
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_MOVE:
                    float progressValue = (x / getWidth()) * max;
                    setProgress((int) progressValue, false);
                    break;
                case MotionEvent.ACTION_UP:
                    if (onProgressChangeListener != null) {
                        onProgressChangeListener.onProgressChanged(progress);
                    }
                    break;
            }
    
            invalidate();
            return true;
        }
    
        public void setProgress(int progress, boolean notifyListener) {
            if (progress < 0) {
                this.progress = 0;
            } else if (progress > max) {
                this.progress = max;
            } else {
                this.progress = progress;
            }
    
            if (notifyListener && onProgressChangeListener != null) {
                onProgressChangeListener.onProgressChanged(this.progress);
            }
    
            invalidate();
        }
    
        public void setOnProgressChangeListener(CustomProgressBar.OnProgressChangeListener listener) {
            this.onProgressChangeListener = listener;
        }
    }
    
    

    相关文章

      网友评论

          本文标题:自定义View控件 实现进度条SeekBar效果

          本文链接:https://www.haomeiwen.com/subject/pjvfadtx.html