美文网首页
可调节音量View

可调节音量View

作者: 激扬飞雪 | 来源:发表于2019-06-25 12:02 被阅读0次

    一、需求简述

    1、定义音量调节View(如图示)

    2、通过监听供调用者使用


    image.png

    二、实现

    1、由于seekbar定义给开发者开放的只能定义规则一级、二级背景或滑块,如实现如图所示不规则的我们可以自己在onDraw()方法内根据progress值绘制灰色背景和上面二级背景

    2、绘制的图形拆分:先绘制半个圆、在绘制一个梯形、在绘制另外一个圆

    三、具体代码实现

    1、定义VolumeSeekbar所需要的属性,如背景、进度条背景、梯形最小高度及最大高度

        <declare-styleable name="VolumeSeekbar">
            <attr name="seekBarBgColor" format="color" />
            <attr name="seekBarProgressColor" format="color" />
            <attr name="seekBarMaxHeight" format="dimension" />
            <attr name="seekBarMinHeight" format="dimension" />
        </declare-styleable>
    

    2、重写SeekBar内onDraw()方法,向画布绘制背景及根据进度绘制半圆及梯形

    package com.chiyue.qiye.view;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.graphics.RectF;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.widget.SeekBar;
    
    import com.chiyue.qiye.R;
    import com.chiyue.qiye.service.AudioServiceManager;
    import com.chiyue.qiye.utils.DensityUtil;
    
    /**
     * 音量seekbar
     *
     * @date 2018/12/12 下午3:21
     * @author: kaily_zhou
     */
    public class VolumeSeekbar extends android.support.v7.widget.AppCompatSeekBar implements SeekBar.OnSeekBarChangeListener {
        private OnSeekBarChangeListener onSeekBarChangeListener;
        private Paint paint;
        private Paint progressPaint;
        public final static String TAG = "VolumeSeekbar";
        public final static int BG_DEFAULT_COLOR = 0XFFF1F1F1;
        public final static int PROGRESS_DEFAULT_COLOR = 0XFFF5B92E;
        public final static int MAX_HEIGHT = 16;
        public final static int MIN_HEIGHT = 8;
        private int maxHeight;
        private int minHeight;
        private int maxProgress;
        private int bgColor;
        private int progressColor;
    
        public VolumeSeekbar(Context context) {
            super(context);
            init(context, null);
        }
    
        public VolumeSeekbar(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context, attrs);
        }
    
        public VolumeSeekbar(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context, attrs);
        }
    
        private void init(Context context, AttributeSet attributeSet) {
            initAttr(context, attributeSet);
            initPaint(context);
            initListener();
            setPadding(getPaddingLeft(), getPaddingTop(), maxHeight / 2, getPaddingBottom());
        }
    
        private void initAttr(Context context, AttributeSet attrs) {
            if (attrs != null) {
                try {
                    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.VolumeSeekbar);
                    if (typedArray != null) {
                        bgColor = typedArray.getColor(R.styleable.VolumeSeekbar_seekBarBgColor, BG_DEFAULT_COLOR);
                        progressColor = typedArray.getColor(R.styleable.VolumeSeekbar_seekBarProgressColor, PROGRESS_DEFAULT_COLOR);
                        maxHeight = typedArray.getDimensionPixelSize(R.styleable.VolumeSeekbar_seekBarMaxHeight, DensityUtil.dip2px(context, MAX_HEIGHT));
                        minHeight = typedArray.getDimensionPixelSize(R.styleable.VolumeSeekbar_seekBarMinHeight, DensityUtil.dip2px(context, MIN_HEIGHT));
                        typedArray.recycle();
                    } else {
                        initDefaultAttr(context);
                    }
                } catch (Exception e) {
                    initDefaultAttr(context);
                }
            } else {
                initDefaultAttr(context);
            }
    
        }
    
        private void initDefaultAttr(Context context) {
            bgColor = BG_DEFAULT_COLOR;
            progressColor = PROGRESS_DEFAULT_COLOR;
            maxHeight = DensityUtil.dip2px(context, MAX_HEIGHT);
            minHeight = DensityUtil.dip2px(context, MIN_HEIGHT);
        }
    
        @Override
        protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            int width = getMeasuredWidth();
            if (width > 0) {
                int height = Math.max(maxHeight, minHeight);
                setMeasuredDimension(width, height);
            }
        }
    
        @Override
        protected synchronized void onDraw(Canvas canvas) {
            int width = getMeasuredWidth();
            //画背景
            drawSeekBarBg(width, canvas);
            width = width - (maxHeight / 2);
            maxProgress = getMax();
            if (maxProgress <= 0) {
                return;
            }
            double progressWidth = width * ((float) getProgress() / (float) maxProgress);
            if (progressWidth < minHeight / 2) {
                drawSeekBarProgressHeader(progressWidth, canvas);
            } else {
                drawSeekBarProgressHeader((double) minHeight / (double) 2, canvas);
                drawSeekBarProgress(width, progressWidth, canvas);
            }
        }
    
    
        private void drawSeekBarBg(int width, Canvas canvas) {
            //中间梯形
            Path path = new Path();
            path.moveTo(minHeight / 2, (maxHeight - minHeight) / 2);
            path.lineTo(width - (maxHeight / 2), 0);
            path.lineTo(width - (maxHeight / 2), maxHeight);
            path.lineTo(minHeight / 2, (maxHeight + minHeight) / 2);
            path.close();
            canvas.drawPath(path, paint);
            //画左边半圆
            Path pathLeft = new Path();
            RectF mRectF = new RectF(0, (maxHeight - minHeight) / 2, minHeight, (maxHeight + minHeight) / 2);
            pathLeft.arcTo(mRectF, 90, 180);
            pathLeft.close();
            canvas.drawPath(pathLeft, paint);
            //画右边半圆
            Path pathRight = new Path();
            RectF rectF = new RectF(width - maxHeight, 0, width, maxHeight);
            pathRight.arcTo(rectF, 270, 180);
            pathRight.close();
            canvas.drawPath(pathRight, paint);
        }
    
        private void drawSeekBarProgressHeader(double progressWidth, Canvas canvas) {
            float ratio = (float) progressWidth / ((float) minHeight / (float) 2);
            float angle = (180 - ratio * 180) / (float) 2;
            Path pathLeft = new Path();
            RectF mRectF = new RectF(0, (maxHeight - minHeight) / 2, minHeight, maxHeight / 2 + minHeight / 2);
            pathLeft.arcTo(mRectF, 90 + angle, 180 - angle * 2);
            pathLeft.close();
            canvas.drawPath(pathLeft, progressPaint);
        }
    
        private void drawSeekBarProgress(int width, double progressWidth, Canvas canvas) {
            int w = width - (minHeight / 2);
            int h = (maxHeight - minHeight) / 2;
            double z = Math.sqrt(Math.pow(w, 2) + Math.pow(h, 2));
            double pw = progressWidth - minHeight / 2;
            double pz = pw * z / (double) w;
            double ph = (int) Math.sqrt(Math.pow(pz, 2) - Math.pow(pw, 2));
            double top = (maxHeight - minHeight) / 2 - ph;
    
            Path progressPath = new Path();
            progressPath.moveTo(minHeight / 2, (maxHeight - minHeight) / 2);
            progressPath.lineTo((int) progressWidth, (int) top);
            progressPath.lineTo((int) progressWidth, (int) (maxHeight - top));
            progressPath.lineTo(minHeight / 2, (maxHeight + minHeight) / 2);
            progressPath.close();
            canvas.drawPath(progressPath, progressPaint);
    
            //画右边半圆
            double radius = (maxHeight - top * 2) / (double) 2;
            Path pathRight = new Path();
            RectF rectF = new RectF((int) (progressWidth - radius), (int) top, (int) (progressWidth + radius), (int) (top + radius * 2));
            pathRight.arcTo(rectF, 270, 180);
            pathRight.close();
            canvas.drawPath(pathRight, progressPaint);
        }
    
        @Override
        public void setOnSeekBarChangeListener(OnSeekBarChangeListener onSeekBarChangeListener) {
            this.onSeekBarChangeListener = onSeekBarChangeListener;
        }
    
        private void initListener() {
            super.setOnSeekBarChangeListener(this);
        }
    
        private void initPaint(Context context) {
            if (context == null) {
                return;
            }
            paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setStyle(Paint.Style.FILL);
            paint.setDither(true);
            paint.setAntiAlias(true);
            paint.setColor(bgColor);
    
            progressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            progressPaint.setStyle(Paint.Style.FILL);
            progressPaint.setDither(true);
            progressPaint.setAntiAlias(true);
            progressPaint.setColor(progressColor);
        }
    
        @Override
        public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
            if (onSeekBarChangeListener != null) {
                onSeekBarChangeListener.onProgressChanged(seekBar, i, b);
                postInvalidate();
            }
        }
    
        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            if (onSeekBarChangeListener != null) {
                onSeekBarChangeListener.onStartTrackingTouch(seekBar);
            }
        }
    
        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            if (onSeekBarChangeListener != null) {
                onSeekBarChangeListener.onStopTrackingTouch(seekBar);
            }
        }
    }
    
    

    3、VolumeSeekbar使用

    xml定义
    <com.chiyue.qiye.view.VolumeSeekbar
                android:id="@+id/seekBarVoice"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="13dp"
                android:background="@null"
                android:thumb="@null"
                app:seekBarBgColor="#F1F1F1"
                app:seekBarMaxHeight="16dip"
                app:seekBarMinHeight="8dip"
                app:seekBarProgressColor="#F5B92E" />
                
               
    代码监听           
    seekBarVoice.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                @Override
                public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                    AudioServiceManager.get().getMusicService().setVolume(i);
                    int currentVolume = AudioServiceManager.get().getMusicService().getCurrentVolume();
                    int maxVolume = AudioServiceManager.get().getMusicService().getMaxVolume();
                    seekBar.setProgress(currentVolume);
                    tvVoice.setText(currentVolume * 100 / maxVolume + "%");
                }
    
                @Override
                public void onStartTrackingTouch(SeekBar seekBar) {
    
                }
    
                @Override
                public void onStopTrackingTouch(SeekBar seekBar) {
    
                }
            });
    

    相关文章

      网友评论

          本文标题:可调节音量View

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