<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android自定義實(shí)現(xiàn)繪制時(shí)鐘表盤

          共 11688字,需瀏覽 24分鐘

           ·

          2022-06-30 19:34

          首先看下效果圖:



          實(shí)現(xiàn)步驟:


          • 繪制表盤[刻度,數(shù)字]

          • 繪制指針

          • 讓指針走起來(lái)~


          具體如下:


          繪制表盤:


          首先需要計(jì)算出刻度的起點(diǎn)和終點(diǎn)坐標(biāo)值,這里我們通過(guò)構(gòu)建兩個(gè)半徑不同的同心圓,大圓半徑減小圓半徑,就可以得到一條刻度,只用改變角度,就可以獲取所有刻度:



              /**     * 通過(guò)改變角度值,獲取不同角度方向的外圓一點(diǎn)到圓心連線過(guò)內(nèi)圓一點(diǎn)的路徑坐標(biāo)集合     * @param x0 圓心x     * @param y0 圓心y     * @param outRadius 外圓半徑     * @param innerRadius 內(nèi)圓半徑     * @param angle 角度     * @return 返回     */    private float[] getDialPaths(int x0,int y0,int outRadius,int innerRadius,int angle){        float[] paths = new float[4];        paths[0]  = (float) (x0 + outRadius * Math.cos(angle * Math.PI / 180));        paths[1]  = (float) (y0 + outRadius * Math.sin(angle * Math.PI / 180));        paths[2]  = (float) (x0 + innerRadius * Math.cos(angle * Math.PI / 180));        paths[3]  = (float) (y0 + innerRadius * Math.sin(angle * Math.PI / 180));        return paths;    }


          秒針刻度間隔360/60 = 6 度,循環(huán)繪制60次,每一次角度加6,就可以了,繪制代碼如下:

          for (int i = 0; i < 60 ; i++) {            if (i % 5 == 0){                //獲取刻度路徑                float[] dialKdPaths = getDialPaths(halfMinLength, halfMinLength, halfMinLength - 8, halfMinLength * 5 / 6, -i * 6);                canvas.drawLines(dialKdPaths,paintKd30);                float[] dialPathsStr = getDialPaths(halfMinLength, halfMinLength, halfMinLength - 8, halfMinLength * 3 / 4, -i * 6);                canvas.drawText(strKedu[i/5],dialPathsStr[2] - 16,dialPathsStr[3] + 14,paintKd30Text);                continue;            }            float[] dialKdPaths = getDialPaths(halfMinLength, halfMinLength, halfMinLength - 8, halfMinLength * 7 / 8, -i * 6);            canvas.drawLines(dialKdPaths,paintKdSecond);        }


          繪制指針和旋轉(zhuǎn)指針


          這里的重點(diǎn)在于對(duì)指針旋轉(zhuǎn)的理解:



          通過(guò)上圖可以看到,我們通過(guò)旋轉(zhuǎn)畫布,然后繪制指針,最后恢復(fù)畫布,從而改變了指針的指向,具體操作過(guò)程是:


          1. 保存已經(jīng)繪制畫面

          2. 以一定角度旋轉(zhuǎn)畫布

          3. 繪制指針

          4. 恢復(fù)畫布角度


          代碼如下:以時(shí)針繪制為例

                  //時(shí)針繪制        canvas.save(); //保存之前內(nèi)容        canvas.rotate(angleHour,halfMinLength,halfMinLength); //旋轉(zhuǎn)的是畫布,從而得到指針旋轉(zhuǎn)的效果        canvas.drawLine(halfMinLength,halfMinLength,halfMinLength,halfMinLength*3/4,paintHour);        canvas.restore(); //恢復(fù)


          讓時(shí)間走起來(lái)

          通過(guò)實(shí)時(shí)的計(jì)算時(shí)針,分針,秒針的角度,然后通知重新繪制畫面,我們就看到時(shí)間在走動(dòng)。

          /**     * 更新時(shí)分秒針的角度,開始繪制     */    public void startRun(){        new Thread(new Runnable() {            @Override            public void run() {                while (drawable){                    try {                        Thread.sleep(1000); // 睡1s                        updataAngleSecond(); //更新秒針角度                        updataAngleMinute(); //更新分針角度                        updataAngleHour(); //更新時(shí)針角度                        postInvalidate(); //重新繪制                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }).start();    }

          完整代碼如下:

          public class DialView extends View {
          private boolean drawable = true; //是否可以繪制 private int halfMinLength; //最小寬/高的一半長(zhǎng)度 private Paint paintKd30; //時(shí)針刻度線畫筆 private Paint paintKd30Text; // 時(shí)針數(shù)字畫筆 private Paint paintKdSecond; //秒針刻度線畫筆 private Paint paintHour; //時(shí)針畫筆 private Paint paintCircleBar;//指針圓心畫筆 private Paint paintMinute; //分針畫筆 private Paint paintSecond; //秒針畫筆 private float angleHour; //時(shí)針旋轉(zhuǎn)角度 private float angleMinute; //分針旋轉(zhuǎn)角度 private float angleSecond; //秒針旋轉(zhuǎn)角度 private int cuurSecond; //當(dāng)前秒 private int cuurMinute; //當(dāng)前分 private int cuurHour; //當(dāng)前時(shí) private Calendar mCalendar; private boolean isMorning = true; //上午/下午 private String[] strKedu = {"3","2","1","12","11","10","9","8","7","6","5","4"};

          public DialView(Context context) { this(context,null); }
          public DialView(Context context, AttributeSet attrs) { this(context, attrs,-1); }
          public DialView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr);
          initPaint(); //初始化畫筆 initTime(); //初始化時(shí)間
          }
          @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); halfMinLength = Math.min(width,height) / 2; System.out.println(halfMinLength); }
          @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //表盤刻度繪制 for (int i = 0; i < 60 ; i++) { if (i % 5 == 0){ //獲取刻度路徑 float[] dialKdPaths = getDialPaths(halfMinLength, halfMinLength, halfMinLength - 8, halfMinLength * 5 / 6, -i * 6); canvas.drawLines(dialKdPaths,paintKd30); float[] dialPathsStr = getDialPaths(halfMinLength, halfMinLength, halfMinLength - 8, halfMinLength * 3 / 4, -i * 6); canvas.drawText(strKedu[i/5],dialPathsStr[2] - 16,dialPathsStr[3] + 14,paintKd30Text); continue; } float[] dialKdPaths = getDialPaths(halfMinLength, halfMinLength, halfMinLength - 8, halfMinLength * 7 / 8, -i * 6); canvas.drawLines(dialKdPaths,paintKdSecond); } //指針繪制 //時(shí)針繪制 canvas.save(); //保存之前內(nèi)容 canvas.rotate(angleHour,halfMinLength,halfMinLength); //旋轉(zhuǎn)的是畫布,從而得到指針旋轉(zhuǎn)的效果 canvas.drawLine(halfMinLength,halfMinLength,halfMinLength,halfMinLength*3/4,paintHour); canvas.restore(); //恢復(fù) //繪制分針 canvas.save(); canvas.rotate(angleMinute,halfMinLength,halfMinLength); //旋轉(zhuǎn)的是畫布,從而得到指針旋轉(zhuǎn)的效果 canvas.drawLine(halfMinLength,halfMinLength,halfMinLength,halfMinLength/2,paintMinute); paintCircleBar.setColor(Color.rgb(75,75,75)); paintCircleBar.setShadowLayer(4,4,8,Color.argb(70,40,40,40)); canvas.drawCircle(halfMinLength,halfMinLength,24,paintCircleBar); canvas.restore(); //繪制秒針 canvas.save(); canvas.rotate(angleSecond,halfMinLength,halfMinLength); //旋轉(zhuǎn)的是畫布,從而得到指針旋轉(zhuǎn)的效果 canvas.drawLine(halfMinLength,halfMinLength + 40,halfMinLength,halfMinLength / 4 - 20,paintSecond); paintCircleBar.setColor(Color.rgb(178,34,34)); paintCircleBar.setShadowLayer(4,4,8,Color.argb(50,80,0,0)); canvas.drawCircle(halfMinLength,halfMinLength,12,paintCircleBar); canvas.restore(); }
          /** * 初始化時(shí),分,秒 */ private void initTime() { mCalendar = Calendar.getInstance(); cuurHour = mCalendar.get(Calendar.HOUR_OF_DAY); cuurMinute = mCalendar.get(Calendar.MINUTE); cuurSecond = mCalendar.get(Calendar.SECOND); if (cuurHour >= 12){ cuurHour = cuurHour - 12; isMorning = false; }else{ isMorning = true; } angleSecond = cuurSecond * 6f; angleMinute = cuurMinute * 6f; angleHour = cuurHour * 6f * 5f; }
          /** * 更新時(shí)分秒針的角度,開始繪制 */ public void startRun(){ new Thread(new Runnable() { @Override public void run() { while (drawable){ try { Thread.sleep(1000); // 睡1s updataAngleSecond(); //更新秒針角度 updataAngleMinute(); //更新分針角度 updataAngleHour(); //更新時(shí)針角度 postInvalidate(); //重新繪制 } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); }
          private void updataAngleHour() { //更新時(shí)針角度 angleHour = angleHour + (30f/3600); if (angleHour >= 360){ angleHour = 0; cuurHour = 0; } }
          private void updataAngleMinute() { //更新分針角度 angleMinute = angleMinute + 0.1f; if (angleMinute >= 360){ angleMinute = 0; cuurMinute = 0; cuurHour += 1; } }
          private void updataAngleSecond() { //更新秒針角度 angleSecond = angleSecond + 6; cuurSecond += 1; if (angleSecond >= 360){ angleSecond = 0; cuurSecond = 0; cuurMinute += 1; //一分鐘同步一次本地時(shí)間 mCalendar = Calendar.getInstance(); cuurHour = mCalendar.get(Calendar.HOUR_OF_DAY); cuurMinute = mCalendar.get(Calendar.MINUTE); cuurSecond = mCalendar.get(Calendar.SECOND); if (cuurHour >= 12){ cuurHour = cuurHour - 12; isMorning = false; }else{ isMorning = true; } angleSecond = cuurSecond * 6f; angleMinute = cuurMinute * 6f; angleHour = cuurHour * 6f * 5f; } } /** * 停止繪制 */ public void stopDrawing(){ drawable = false; }
          /** * 通過(guò)改變角度值,獲取不同角度方向的外圓一點(diǎn)到圓心連線過(guò)內(nèi)圓一點(diǎn)的路徑坐標(biāo)集合 * @param x0 圓心x * @param y0 圓心y * @param outRadius 外圓半徑 * @param innerRadius 內(nèi)圓半徑 * @param angle 角度 * @return 返回 */ private float[] getDialPaths(int x0,int y0,int outRadius,int innerRadius,int angle){ float[] paths = new float[4]; paths[0] = (float) (x0 + outRadius * Math.cos(angle * Math.PI / 180)); paths[1] = (float) (y0 + outRadius * Math.sin(angle * Math.PI / 180)); paths[2] = (float) (x0 + innerRadius * Math.cos(angle * Math.PI / 180)); paths[3] = (float) (y0 + innerRadius * Math.sin(angle * Math.PI / 180)); return paths; }
          /** * 初始化畫筆參數(shù) */ private void initPaint() { paintKd30 = new Paint(); paintKd30.setStrokeWidth(8); paintKd30.setColor(Color.rgb(75,75,75)); paintKd30.setAntiAlias(true); paintKd30.setDither(true); paintKd30.setStrokeCap(Paint.Cap.ROUND);
          paintKd30Text = new Paint(); paintKd30Text.setTextAlign(Paint.Align.LEFT); //左對(duì)齊 paintKd30Text.setStrokeWidth(6); //設(shè)置寬度 paintKd30Text.setTextSize(40); //文字大小 paintKd30Text.setTypeface(Typeface.DEFAULT_BOLD); //加粗 paintKd30Text.setColor(Color.rgb(75,75,75)); //畫筆顏色 paintKd30Text.setAntiAlias(true); //抗鋸齒 paintKd30Text.setDither(true); //抖動(dòng) paintKd30Text.setStrokeCap(Paint.Cap.ROUND); //筆尖圓角 paintKd30Text.setShadowLayer(4,2,4,Color.argb(60,90,90,90)); //陰影
          paintKdSecond = new Paint(); paintKdSecond.setStrokeWidth(6); paintKdSecond.setColor(Color.rgb(75,75,75)); paintKdSecond.setAntiAlias(true); paintKdSecond.setDither(true); paintKdSecond.setStrokeCap(Paint.Cap.ROUND); paintKdSecond.setShadowLayer(4,5,10,Color.argb(50,80,80,80));
          paintHour = new Paint(); paintHour.setStrokeWidth(30); paintHour.setColor(Color.rgb(75,75,75)); paintHour.setAntiAlias(true); paintHour.setDither(true); paintHour.setStrokeCap(Paint.Cap.ROUND); paintHour.setShadowLayer(4,5,10,Color.argb(50,80,80,80));
          paintCircleBar = new Paint(); paintCircleBar.setStrokeWidth(6);// paintCircleBar.setColor(Color.rgb(178,34,34)); paintCircleBar.setAntiAlias(true); paintCircleBar.setDither(true); paintCircleBar.setStrokeCap(Paint.Cap.ROUND);// paintCircleBar.setShadowLayer(4,5,10,Color.argb(100,80,80,80));
          paintMinute = new Paint(); paintMinute.setStrokeWidth(30); paintMinute.setColor(Color.rgb(75,75,75)); paintMinute.setAntiAlias(true); paintMinute.setDither(true); paintMinute.setStrokeCap(Paint.Cap.ROUND); paintMinute.setShadowLayer(4,5,10,Color.rgb(80,80,80));
          paintSecond = new Paint(); paintSecond.setStrokeWidth(6); paintSecond.setColor(Color.rgb(180,30,30)); paintSecond.setAntiAlias(true); paintSecond.setDither(true); paintSecond.setStrokeCap(Paint.Cap.ROUND); paintSecond.setShadowLayer(4,2,10,Color.argb(100,90,90,90));
          }}


          代碼中有比較詳細(xì)的注釋。

          瀏覽 74
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  爱爱亚洲| 在线日韩aaa | 欧洲亚洲中文字幕 | 豆花视频在线观看视频 | 亚洲精品成a在线 |