Android仿mac音量拖动view实现

来源:互联网 发布:照片冲印排版软件 编辑:程序博客网 时间:2024/06/07 18:49

前言

雨后江岸天破晓,老舟新客知多少;远山见竹林芳草,晨风拂绿了芭蕉。

简介

今天给大家带来的是自定义view的相关知识,我们实现的是仿mac音量加减的拖动view。我们先来看下效果图。

效果图

这里写图片描述

实现

下面我们讲一下具体的实现逻辑。

  • 自定义styleable
<declare-styleable name="VolumeView">    <attr name="ball_color" format="color" />    <attr name="left_color" format="color" />    <attr name="right_color" format="color" />    <attr name="ball_radius" format="dimension" />    <attr name="start_value" format="dimension" /></declare-styleable>

ball_color:拖动小球的颜色
left_color:左边线条的颜色
right_color:右边线条的颜色
ball_radius:小球的半径
start_value:音量默认初始值

  • VolumeView
/** * Created by kuangxiaoguo on 2016/11/3. */public class VolumeView extends View {    private static final float DEFAULT_WIDTH = 220;    private static final float DEFAULT_HEIGHT = 50;    private static final int DEFAULT_BALL_RADIUS = 10;    private static final int START_VALUE = 0;    private Paint mBallPaint;    private Paint mLeftPaint;    private Paint mRightPaint;    private int mBallColor;    private float mBallRadius;    private int mStartValue;    private TouchEnum state;    private float downX;    private int mWidth;    private int endValue;    private RectF mRectF;    private int mLeftColor;    private int mRightColor;    public VolumeView(Context context) {        this(context, null);    }    public VolumeView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public VolumeView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initAttrs(context, attrs, defStyleAttr);    }    private void initAttrs(Context context, AttributeSet attrs, int defStyleAttr) {        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.VolumeView, defStyleAttr, 0);        mBallColor = typedArray.getColor(R.styleable.VolumeView_ball_color, Color.GREEN);        mLeftColor = typedArray.getColor(R.styleable.VolumeView_left_color, Color.BLUE);        mRightColor = typedArray.getColor(R.styleable.VolumeView_right_color, Color.LTGRAY);        mBallRadius = typedArray.getDimension(R.styleable.VolumeView_ball_radius, dp2px(DEFAULT_BALL_RADIUS));        mStartValue = (int) typedArray.getDimension(R.styleable.VolumeView_start_value, dp2px(START_VALUE));        typedArray.recycle();        initPaint();    }    private void initPaint() {        mBallPaint = new Paint();        mLeftPaint = new Paint();        mRightPaint = new Paint();        initPaint(mBallPaint, mBallColor);        initPaint(mLeftPaint, mLeftColor);        initPaint(mRightPaint, mRightColor);        mLeftPaint.setStrokeWidth(mBallRadius / 2);        mRightPaint.setStrokeWidth(mBallRadius / 2);    }    private void initPaint(Paint paint, int color) {        paint.setAntiAlias(true);        paint.setColor(color);        paint.setStyle(Paint.Style.FILL);        paint.setStrokeCap(Paint.Cap.BUTT);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                downX = event.getX();                /**                 * 点击小球                 */                if (downX > mStartValue && downX < mStartValue + 2 * mBallRadius) {                    state = TouchEnum.TOUCH_BALL;                } else {                    /**                     * 点击位置位于最左边小于球的直径处                     */                    if (downX < 2 * mBallRadius) {                        downX = 0;                    } else if (downX > endValue) {                        /**                         * 点击位置位于最右边                         */                        downX = endValue;                    }                    /**                     * 使得mStartValue为我们按下的值刷新view                     * 并把state的状态置为TouchEnum.TOUCH_BALL                     */                    mStartValue = (int) downX;                    invalidate();                    state = TouchEnum.TOUCH_BALL;                }                break;            case MotionEvent.ACTION_MOVE:                if (state == TouchEnum.TOUCH_BALL) {                    float moveX = event.getX();                    float moveDistance = moveX - downX;                    mStartValue += moveDistance;                    if (mStartValue < 0) {                        mStartValue = 0;                    } else if (mStartValue > endValue) {                        mStartValue = endValue;                    }                    invalidate();                    /**                     * 每刷新一次view之后把moveX的值赋给downX,这样在下次又重新获取moveX,两者相减就是我们滑动的距离。                     */                    downX = moveX;                }                break;        }        return true;    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        mWidth = getWidth();        endValue = (int) (mWidth - 2 * mBallRadius);        mRectF = new RectF(0, 0, mWidth, h);    }    @Override    protected void onDraw(Canvas canvas) {        mBallPaint.setColor(getResources().getColor(R.color.colorGray));        canvas.drawRoundRect(mRectF, getHeight() / 5, getHeight() / 5, mBallPaint);        mBallPaint.setColor(mBallColor);        int verticalCenter = getHeight() / 2;        canvas.drawLine(0, verticalCenter, mStartValue, verticalCenter, mLeftPaint);        canvas.drawCircle(mStartValue + mBallRadius, verticalCenter, mBallRadius, mBallPaint);        canvas.drawLine(mStartValue + 2 * mBallRadius, verticalCenter, mWidth, verticalCenter, mRightPaint);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        if (widthMode == MeasureSpec.AT_MOST) {            widthSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_WIDTH, getResources().getDisplayMetrics());        }        if (heightMode == MeasureSpec.AT_MOST) {            heightSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_HEIGHT, getResources().getDisplayMetrics());        }        setMeasuredDimension(widthSize, heightSize);    }    public enum TouchEnum {        TOUCH_BALL, TOUCH_LEFT, TOUCH_RIGHT    }    private int dp2px(int dp) {        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());    }}
  • xml使用VolumeView
 <com.asiatravel.macvolumeview.wediget.VolumeView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        app:left_color="#4A9AF9"        app:right_color="#BBB9BB"        app:ball_color="#fff"        app:start_value="20dp" />

总结

由于整体的实现思路比较简单,所以我们直接贴出了view源码并在一些逻辑处理的地方加了部分注释,当然,如果有哪里不明白的地方,大家可以在下面留言。
另外有需要项目源码的童鞋可以去https://github.com/kuangxiaoguo0123/MacVolumeView下载。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 王者荣耀太卡了怎么办 想卖王者号qq怎么办 小米4电视发热严重怎么办 三星玩王者荣耀卡怎么办 华为麦芒5网络差怎么办 华为麦芒无线信号不好怎么办 华为麦芒6网络不好怎么办 华为麦芒6信号差怎么办 华为手机无线网信号差怎么办 华为麦芒6数据信号差怎么办 华为麦芒54g信号差怎么办 华为手机wifi信号差怎么办 华为手机导航信号弱怎么办 华为手机gps信号弱怎么办 麦芒5指纹消失了怎么办 华为应用锁密码忘了怎么办 华为麦芒5密码忘了怎么办 华为卡1无服务怎么办 经常卡1无服务怎么办 华为手机进水无服务怎么办 苹果手机进水后无服务怎么办 苹果6进水无服务怎么办 华为手机突然无服务怎么办 sim卡显示无服务怎么办 华为麦芒进水无限开关机怎么办 华为麦芒5进水黑屏怎么办 华为麦芒6进水了怎么办 4g手机开不开机怎么办 全屏钢化膜总是翘边怎么办 华为麦芒屏幕触屏失灵怎么办 华为麦芒5运行慢怎么办 手机屏保密码忘记了怎么办 麦芒5密码锁忘了怎么办 超薄手机壳松了怎么办 华为麦芒5声音小怎么办 笔记本外壳a面裂了怎么办 苹果手机外壳摔坏了怎么办 挂衣服肩膀出包怎么办 摩拜单车手机号注销了怎么办 摩拜单车手机号码换了怎么办 摩拜单车换手机号码打不开怎么办