时钟骚起来真没你啥事

作者: ftc300_carl | 来源:发表于2017-04-13 18:27 被阅读216次

    本文属于装糊涂的猪原创,转载请注明出处作者
    文中的Demo地址位于:https://github.com/ftc300

    话不多说,先上效果图:

    clock.gif
    当你认为上半屏很鬼畜的时候,它其实是个方向传感器。首先平放手机置于桌面,抬起手机左边缘,时钟向右倾斜,然后就是各个边缘倾斜的情况咯;至于下半屏,米粉应该知道是 MIUI系统的时钟。。
    在Android平台中,传感器框架通常是使用一个标准的三维坐标系来表示一个值的。
    这个时候搞个官方的图装一波不过分吧:
    坐标系.jpg
    方向传感器的学习,言简意赅,有示例代码

    1、由于 onSizeChanged 方法在构造方法、onMeasure 之后,又在 onDraw 之前,此时已经完成全局变量初始化,也得到了控件的宽高,所以可以在这个方法中确定一些与宽高有关的数值,比如这个 View 的 半径啊、padding值 等,方便绘制的时候计算大小和位置:

        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            //宽和高分别去掉padding值,取min的一半即表盘的半径
            mRadius = Math.min(w - getPaddingLeft() - getPaddingRight(), h - getPaddingTop() - getPaddingBottom()) / 2;
            mDefaultPadding = 0.12f * mRadius;//根据比例确定默认padding大小
            mPaddingLeft = mDefaultPadding + w / 2 - mRadius + getPaddingLeft();
            mPaddingTop = mDefaultPadding + h / 2 - mRadius + getPaddingTop();
            mPaddingRight = mPaddingLeft;
            mPaddingBottom = mPaddingTop;
            mScaleLength = 0.12f * mRadius;//根据比例确定刻度线长度
        }
    

    2、然后开始绘制4个成3,6,9,12点方向的刻度线:

        /**
         * 90度一个刻度线
         */
        private void drawScaleLines()
        {
            mScalePadding = 0.03f * mRadius;
            mScaleLength = 0.13f * mRadius;
            mCanvas.drawLine(mPaddingLeft+mCircleStrokeWidth + mScalePadding,getHeight() / 2 , mPaddingLeft + mCircleStrokeWidth + mScalePadding + mScaleLength, getHeight() / 2, mScaleLinePaint);
            mCanvas.drawLine(getWidth() / 2,mPaddingTop + mCircleStrokeWidth + mScalePadding ,getWidth() / 2, mPaddingTop + mCircleStrokeWidth + mScalePadding + mScaleLength, mScaleLinePaint);
            mCanvas.drawLine(getWidth() - mCircleStrokeWidth - mScalePadding -mScaleLength - mPaddingRight , getHeight() / 2 ,getWidth() - mCircleStrokeWidth - mScalePadding - mPaddingRight, getHeight() / 2, mScaleLinePaint);
            mCanvas.drawLine(getWidth() / 2,getHeight()- mCircleStrokeWidth - mScalePadding -mScaleLength -mPaddingBottom ,getWidth() / 2, getHeight() - mCircleStrokeWidth - mScalePadding - mPaddingBottom, mScaleLinePaint);
        }
    

    3、根据不断变化的秒针角度旋转画布,自己要计算出缺口圆弧的角度 mSecondHandPath.arcTo(mCircleRectF,-87,354)

        private void drawSecondHand() {
            mCanvas.save();
            mCanvas.rotate(mSecondDegree, getWidth() / 2, getHeight() / 2);
            mSecondHandPath.reset();
            mCircleRectF.set(mPaddingLeft,mPaddingTop,getWidth()-mPaddingRight,getHeight()-mPaddingBottom);
            mSecondHandPath.arcTo(mCircleRectF,-87,354);
            mSecondHandPaint.setStyle(Paint.Style.STROKE);
            mSecondHandPaint.setStrokeWidth(mCircleStrokeWidth);
            mCanvas.drawPath(mSecondHandPath, mSecondHandPaint);
            mCircleRectF.set(getWidth() / 2 - mCircleStrokeWidth,mPaddingTop-mCircleStrokeWidth,getWidth() / 2  + mCircleStrokeWidth ,mPaddingTop + mCircleStrokeWidth);
            mSecondHandPaint.setStyle(Paint.Style.FILL);
            mCanvas.drawArc(mCircleRectF, 0, 360, false, mSecondHandPaint);
            mCanvas.restore();
        }
    

    4、时针和分针类似,针头为圆弧状,那么就用二阶贝赛尔曲线,路径为 moveTo( A),lineTo(B),quadTo(C,D),lineTo(E),close.

        private void drawHourHand() {
            mCanvas.save();
            mCanvas.rotate(mHourDegree, getWidth() / 2, getHeight() / 2);
            mHourHandPath.reset();
            float offset = mPaddingTop ;
            mHourHandPath.moveTo(getWidth() / 2 - 0.008f * mRadius, getHeight() / 2 - 0.01f * mRadius);
            mHourHandPath.lineTo(getWidth() / 2 - 0.007f * mRadius, offset + 0.4f * mRadius);
            mHourHandPath.quadTo(getWidth() / 2, offset + 0.38f * mRadius, getWidth() / 2 + 0.007f * mRadius, offset + 0.4f * mRadius);
            mHourHandPath.lineTo(getWidth() / 2 + 0.008f * mRadius, getHeight() / 2 - 0.02f * mRadius);
            mHourHandPath.close();
            mHourHandPaint.setStyle(Paint.Style.FILL);
            mCanvas.drawPath(mHourHandPath, mHourHandPaint);
            mCircleRectF.set(getWidth() / 2 - 0.02f * mRadius, getHeight() / 2 - 0.02f * mRadius, getWidth() / 2 + 0.02f * mRadius, getHeight() / 2 + 0.02f * mRadius);
            mCanvas.drawArc(mCircleRectF, 0, 360, false, mHourHandPaint);
            mCanvas.restore();
        }
    

    一张图带你彻底了解二阶贝塞尔曲线

    5、 最后由于path是close的,所以干脆画两个圆盖在上面

            mCircleRectF.set(getWidth() / 2 - 0.02f * mRadius, getHeight() / 2 - 0.02f * mRadius, 
            getWidth() / 2 + 0.02f * mRadius, getHeight() / 2 + 0.02f * mRadius);
            mCanvas.drawArc(mCircleRectF, 0, 360, false, mHourHandPaint);
    
    表心.png

    6、辣么接下来就是如何实现方向传感器了
    在构造函数中注册传感器:

            sManager = (SensorManager) context.getSystemService(SENSOR_SERVICE);
            mSensorOrientation = sManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
            sManager.registerListener(this, mSensorOrientation SensorManager.SENSOR_DELAY_UI);
    

    并实现SensorEventListener接口

        @Override
        public void onSensorChanged(SensorEvent sensorEvent) {
            int tbValue = (Math.round(sensorEvent.values[1]));
            int lrValue = (Math.round(sensorEvent.values[2]));
            offsetTopAndBottom(tempTBValue - tbValue);
            offsetLeftAndRight(tempLRValue - lrValue);
            tempTBValue = tbValue;
            tempLRValue = lrValue;
        }
    

    OVER!

    鲁迅说:Don't bb ,show me the code!


    鲁迅.jpg

    源码地址:https://github.com/ftc300/AwesomeClock
    同时以后我会定期更新我的博客到我的网址,欢迎光顾:https://ftc300.github.io/

    维护个公众号试试吧.png

    相关文章

      网友评论

      本文标题:时钟骚起来真没你啥事

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