仿苹果音量调节柱

平板升级之后,发现新的 IOS 系统中,上划之后出现的调节音量的控件让人看起来非常舒适,不错,尝试在Android 上实现以下。
上图:

这里写图片描述

最终的效果就是这样的。
实现思路:
这里写图片描述

第一步,画一个矩形。
第二步,在矩形上边画一个圆角矩形,通过
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
方法,使得两者重合的地方变成透明。
最终在代码中操纵第一次绘制的矩形,实现上图中的效果。

控件的扩展:

        <attr name="bgColor" format="color|integer"></attr>
        <attr name="radius" format="integer"></attr>
        <attr name="isWrappeLine" format="boolean"></attr>

在代码中,添加了

    public void setValues(float v){
        ......
    }
    public IphoneSwitchView setColor(int color){
        ......
    }

两个方法,使得我们可以去动态的修改控件的背景颜色。
还添加了一个回调,方便后续的开发工作。

    public void registerCallback(ValueChangeCallback callback){
        mCallback = callback;
    }
    interface ValueChangeCallback{
        void onValueChanged(double value);
    }

最后贴上关键代码:

public class IphoneSwitchView extends View{

    private int mWidth,mHeight;
    private int strokenWidth;
    private boolean isWrapperLine;
    private float lastX,lastY,curX,curY;
    private int mCurrValue=100,mLastValue=0;
    private int curPoint;
    private int mBgColor;
    private Paint paint;
    private ValueChangeCallback mCallback;
    public IphoneSwitchView(Context context) {
        this(context,null);
    }

    public IphoneSwitchView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

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

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        mWidth = getWidth();
        mHeight = getHeight();
        //初始化弧度大小
        strokenWidth = strokenWidth!=-1?strokenWidth:mWidth/5;
    }

    private void init(Context context,AttributeSet attrs) {
        TypedArray array =  context.obtainStyledAttributes(attrs,R.styleable.IphoneSwitchView);
        int color = (int) array.getInt(R.styleable.IphoneSwitchView_bgColor,-1);
        mBgColor = color!=-1?color:getResources().getColor(R.color.colorAccent);
        strokenWidth = (int) array.getInt(R.styleable.IphoneSwitchView_radius,-1);
        isWrapperLine = array.getBoolean(R.styleable.IphoneSwitchView_isWrappeLine,true);
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStrokeWidth(4);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 绘制底部的矩形
        RectF rectF = new RectF(0,mHeight-mCurrValue,mWidth,mHeight);
        int layerId = canvas.saveLayer(0, 0, mWidth, mHeight, null, Canvas.ALL_SAVE_FLAG);
        paint.setColor(mBgColor);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawRect(rectF,paint);
        // 开始绘制圆角矩形
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.WHITE);
        paint.setStrokeWidth(strokenWidth);
        rectF = new RectF(0,0,mWidth,mHeight);
        canvas.drawRoundRect(rectF,strokenWidth,strokenWidth,paint);
        paint.setXfermode(null);
        canvas.restoreToCount(layerId);
        // 判断是否需要外边框
        if(isWrapperLine){
            paint.setStrokeWidth(2);
            paint.setColor(Color.BLACK);
            rectF = new RectF(1,1,mWidth-1,mHeight-1);
            canvas.drawRoundRect(rectF,strokenWidth,strokenWidth,paint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                lastX =  event.getX();
                lastY =  event.getY();
                //切记要进行事件拦截消费操作
                return true;
            case MotionEvent.ACTION_MOVE:
                curX = event.getX();
                curY = event.getY();
                resetValues(lastY-curY);
                lastX =  event.getX();
                lastY =  event.getY();
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return super.onTouchEvent(event);
    }

    private void resetValues(float v) {
        float cacheValue = mCurrValue+v;
        Log.d("chenxiaoping","v := "+v+"  "+cacheValue+"  mHeight "+mHeight);
        if(cacheValue<=mHeight&&cacheValue>=0){
            mCurrValue = (int) cacheValue;
            if(mCallback!=null){
                mCallback.onValueChanged(cacheValue/mHeight);
            }
        }
        postInvalidate();
    }

    public void setValues(float v){
        setInitialValue(v);
    }

    public IphoneSwitchView setColor(int color){
        mBgColor = color;
        postInvalidate();
        return this;
    }

    /**
     * persent 0-1
     * @param value
     * @return
     */
    public IphoneSwitchView setInitialValue(double value){
        if(value>1||value<0){
            mCurrValue = 0;
        }else{
            mCurrValue = (int) (mHeight*value);
        }

        if(mCallback!=null){
            mCallback.onValueChanged(mCurrValue/mHeight);
        }

        mLastValue = mCurrValue;
        postInvalidate();
        return this;
    }

    public void registerCallback(ValueChangeCallback callback){
        mCallback = callback;
    }

    interface ValueChangeCallback{
        void onValueChanged(double value);
    }
}

介绍完毕,继续努力。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值