最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android自定義一個屬于自己的時間鐘表操作方法

 更新時間:2024年08月19日 09:30:32   作者:一笑輪回~  
本文主要講解的是如何自定義一個時間鐘表,通過簡單的練習可以簡單學習android當中自定義view的一些常用繪圖技巧,優(yōu)化android繪圖操作,感興趣的朋友跟隨小編一起看看吧

1、概述

本文主要講解的是如何自定義一個時間鐘表,通過簡單的練習可以簡單學習android當中自定義view的一些常用繪圖技巧,優(yōu)化android繪圖操作。言歸正傳,首先看下我們需要實現的效果:

當我們看到這個效果的時候腦子里應該有一定的思路了,我們應該把它分解成以下幾個步驟:

1、儀表盤(圓)

2、刻度線(長 中 短)

3、刻度值(1-12)

4、指針(時  分  秒)

5、移動指針,計算指針位置

現在我們已經很清楚自己的思路了,那么我們一個一個來。

第一步:1、自定義View的屬性,首先在res/values/  下建立一個attrs.xml , 在里面定義我們的屬性和聲明我們的整個樣式。

    <declare-styleable name="ClockView">
        <attr name="mRadius" format="dimension"/>
        <attr name="mCircleColor" format="color"/>
        <attr name="mCircleWidth" format="dimension"/>
        <attr name="mTextSize" format="dimension"/>
        <attr name="mTextColor" format="color"/>
        <attr name="mBigScaleColor" format="color"/>
        <attr name="mMiddlecaleColor" format="color"/>
        <attr name="mSmallScaleColor" format="color"/>
        <attr name="mHourHandColor" format="color"/>
        <attr name="mMinuteHandColor" format="color"/>
        <attr name="mSecondHandColor" format="color"/>
        <attr name="mHourHandWidth" format="dimension"/>
        <attr name="mMinuteHandWidth" format="dimension"/>
        <attr name="mSecondHandWidth" format="dimension"/>
    </declare-styleable>

我們定義了鐘表的半徑,背景顏色 ,刻度值(大,中,小)的顏色及指針(時分秒)的顏色和寬度。

然后自定義一個class類 為ClockView,在MainActivity的布局中引用:

  <com.dalong.customviewstudy.view.ClockView
      app:mSecondHandColor="@color/colorAccent"
      app:mCircleColor="@android:color/white"
      app:mBigScaleColor="@android:color/black"
      app:mMiddlecaleColor="@android:color/black"
      app:mSmallScaleColor="@color/colorAccent"
      app:mHourHandColor="@android:color/black"
      app:mMinuteHandColor="@android:color/black"
      app:mTextColor="@android:color/black"
      app:mHourHandWidth="13dp"
      app:mSecondHandWidth="5dp"
      app:mMinuteHandWidth="8dp"
      app:mTextSize="16sp"
      android:layout_centerInParent="true"
      android:layout_width="match_parent"
      android:layout_height="match_parent" />

2、在自定義View的構造方法中,獲得我們的自定義的樣式

 //文字畫筆對象
    private  Paint mTextPaint;
    //圓,指針,刻度畫筆
    private  Paint mPaint;
    //半徑
    public float mRadius;
    //外圓的顏色
    public int mCircleColor;
    // 外圓的寬度
    public float mCircleWidth;
    //文字的大小
    public float mTextSize;
    //文字的顏色
    public int mTextColor;
    //大刻度顏色
    public int mBigScaleColor;
    //中刻度
    public int mMiddlecaleColor;
    //小刻度顏色
    public int mSmallScaleColor;
    //時針顏色
    public int mHourHandColor;
    //分針顏色
    public int mMinuteHandColor;
    //秒針顏色
    public int mSecondHandColor;
    //時針寬度
    public float mHourHandWidth;
    //分針寬度
    public float mMinuteHandWidth;
    //秒針寬度
    public float mSecondHandWidth;
    //控件寬度
    public int mWidth;
    //控件高度
    public int mHeght;
    public ClockView(Context context) {
        this(context,null);
    }
    public ClockView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }
    public ClockView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray=context.obtainStyledAttributes(attrs, R.styleable.ClockView);
        mRadius=typedArray.getDimension(R.styleable.ClockView_mRadius,400);
        mCircleColor=typedArray.getColor(R.styleable.ClockView_mCircleColor, Color.WHITE);
        mCircleWidth=typedArray.getDimension(R.styleable.ClockView_mCircleWidth,20);
        mTextSize=typedArray.getDimension(R.styleable.ClockView_mCircleWidth,40);
        mTextColor=typedArray.getColor(R.styleable.ClockView_mTextColor,Color.DKGRAY);
        mBigScaleColor=typedArray.getColor(R.styleable.ClockView_mBigScaleColor,Color.BLACK);
        mSmallScaleColor=typedArray.getColor(R.styleable.ClockView_mSmallScaleColor,Color.RED);
        mMiddlecaleColor=typedArray.getColor(R.styleable.ClockView_mMiddlecaleColor,Color.BLACK);
        mHourHandColor=typedArray.getColor(R.styleable.ClockView_mHourHandColor,Color.BLACK);
        mMinuteHandColor=typedArray.getColor(R.styleable.ClockView_mMinuteHandColor,Color.BLACK);
        mSecondHandColor=typedArray.getColor(R.styleable.ClockView_mSecondHandColor,Color.BLACK);
        mHourHandWidth=typedArray.getDimension(R.styleable.ClockView_mHourHandWidth,20);
        mMinuteHandWidth=typedArray.getDimension(R.styleable.ClockView_mMinuteHandWidth,10);
        mSecondHandWidth=typedArray.getDimension(R.styleable.ClockView_mSecondHandWidth,5);
        mPaint=new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE);
        mTextPaint=new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setStyle(Paint.Style.STROKE);
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.setColor(mTextColor);
    }

3、我們重寫onDraw,onMesure調用系統(tǒng)提供的:

onMeure方法

  @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureSize(widthMeasureSpec),measureSize(heightMeasureSpec));
    }
    private int measureSize(int mMeasureSpec) {
        int result;
        int mode=MeasureSpec.getMode(mMeasureSpec);
        int size=MeasureSpec.getSize(mMeasureSpec);
        if(mode==MeasureSpec.EXACTLY){
            result=size;
        }else{
            result=400;
            if(mode==MeasureSpec.AT_MOST){
                result=Math.min(result,size);
            }
        }
        return  result;
    }

onDraw方法

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //設置寬高、半徑
        mWidth=getMeasuredWidth()-getPaddingLeft()-getPaddingRight();
        mHeght=getMeasuredHeight()-getPaddingBottom()-getPaddingTop();
        mRadius=Math.min(mWidth/2,mHeght/2);
        //首先繪制圓
        drawCircle(canvas);
        //繪制刻度
        drawScale(canvas);
        //繪制指針
        drawPointer(canvas);
        //發(fā)送消息刷新ui
        handler.sendEmptyMessageDelayed(START_CLOCK,1000);
    }

其中最核心的代碼就是這三個方法:

       //首先繪制圓
        drawCircle(canvas);
        //繪制刻度
        drawScale(canvas);
        //繪制指針
        drawPointer(canvas);

首先講第一個方法:

 /**
     * 畫圓
     * @param canvas
     */
    private void drawCircle(Canvas canvas) {
        mPaint.setStrokeWidth(mCircleWidth);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(mCircleColor);
        canvas.drawCircle(mWidth/2,mHeght/2,mRadius,mPaint);
    }

這個方法其實很簡單給我們的畫筆設置我們自定義的樣式之后取中心為圓心,以我們設定的半徑畫圓,這里設置的是Paint.Style.FILL一個實心的。也可以設置一個空心的??聪挛覀儓?zhí)行這個方法后的效果:

第二方法:

 /**
     * 刻度和文字
     * @param canvas
     */
    private void drawScale(Canvas canvas) {
        for (int i=0;i<60;i++){
            //設置大刻度
            if(i==0||i==15||i==30||i==45){
                mPaint.setStrokeWidth(6);
                mPaint.setColor(mBigScaleColor);
                canvas.drawLine(mWidth/2,mHeght/2-mWidth/2+mCircleWidth/2,
                        mWidth/2,mHeght/2-mWidth/2+mCircleWidth/2+60,mPaint);
                String scaleTv=String.valueOf(i==0?12:i/5);
                canvas.drawText(scaleTv,mWidth/2-mTextPaint.measureText(scaleTv)/2,
                        mHeght/2-mWidth/2+mCircleWidth/2+95,mTextPaint);
            }else if (i==5||i==10||i==20||i==25||i==35||i==40||i==50||i==55)
            //設置中刻度
            {
                mPaint.setStrokeWidth(4);
                mPaint.setColor(mMiddlecaleColor);
                canvas.drawLine(mWidth/2,mHeght/2-mWidth/2+mCircleWidth/2,
                        mWidth/2,mHeght/2-mWidth/2+mCircleWidth/2+40,mPaint);
                String scaleTv=String.valueOf(i/5);
                canvas.drawText(scaleTv,mWidth/2-mTextPaint.measureText(scaleTv)/2,
                        mHeght/2-mWidth/2+mCircleWidth/2+75,mTextPaint);
            }else
            //設置小刻度
            {
                mPaint.setColor(mSmallScaleColor);
                mPaint.setStrokeWidth(2);
                canvas.drawLine(mWidth/2,mHeght/2-mWidth/2+mCircleWidth/2,
                        mWidth/2,mHeght/2-mWidth/2+mCircleWidth+30,mPaint);
            }
            canvas.rotate(6,mWidth/2,mHeght/2);
        }
    }

這個方法代碼看起來也沒有什么主要是把一個圓分成60份,因為我們鐘表上是有60個刻度,其中設置了4個大刻度分別為0,15,30,45.分別對應的鐘表中12點  3點  6點和9點,如果這個地方你有什么疑惑的吧你可以看看你的手表或者鐘表就明白了,同時里面也設置了8個中等刻度分別為5,10,20,25,35,40,50,55為中刻度,其實對應的就是1,2,4,5,7,8,10,11點。這里主要是自己覺得這樣分明好看而已,如果沒有強迫癥的你可以直接設置都是大刻度就可以了。其他的都為小刻度,根據自己在attr設置的顏色和尺寸分別設置畫筆paint來繪制就可以了??聪挛覀兊男Ч兂闪诉@樣子:

第三個方法就是繪制指針:

 /**
     * 繪制指針
     * @param canvas
     */
    private void drawPointer(Canvas canvas) {
        Calendar mCalendar=Calendar.getInstance();
        //獲取當前小時數
        int hours = mCalendar.get(Calendar.HOUR);
        //獲取當前分鐘數
        int minutes = mCalendar.get(Calendar.MINUTE);
        //獲取當前秒數
        int seconds=mCalendar.get(Calendar.SECOND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        //繪制時針
        canvas.save();
        mPaint.setColor(mHourHandColor);
        mPaint.setStrokeWidth(mHourHandWidth);
        //這里計算時針需要旋轉的角度 實現原理是計算出一共多少分鐘除以60計算出真實的小時數(帶有小數,為了更加準確計算度數),已知12小時是360度,現在求出了實際小時數比例求出角度
        Float hoursAngle = (hours * 60 + minutes) / 60f / 12f  * 360;
        canvas.rotate(hoursAngle, mWidth / 2, mHeght / 2);
        canvas.drawLine(mWidth / 2, mHeght / 2 - mWidth/2f*0.5f, mWidth / 2, mHeght / 2 +  mWidth/2f*0.15f, mPaint);
        canvas.restore();
        //繪制分針
        canvas.save();
        mPaint.setColor(mMinuteHandColor);
        mPaint.setStrokeWidth(mMinuteHandWidth);
        //這里計算分針需要旋轉的角度  60分鐘360度,求出實際分鐘數所占的度數
        Float minutesAngle = (minutes*60+seconds) / 60f/ 60f * 360;
        canvas.rotate(minutesAngle, mWidth / 2, mHeght / 2);
        canvas.drawLine(mWidth / 2, mHeght / 2 -  mWidth/2f*0.7f, mWidth / 2, mHeght / 2 +  mWidth/2f*0.15f, mPaint);
        canvas.restore();
        //繪制中間的圓圈
        canvas.save();
        mPaint.setColor(mSecondHandColor);
        mPaint.setStrokeWidth(mSecondHandWidth);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(mWidth/2,mHeght/2,20,mPaint);
        canvas.restore();
        //繪制秒針
        canvas.save();
        mPaint.setColor(mSecondHandColor);
        mPaint.setStrokeWidth(mSecondHandWidth);
        mPaint.setStyle(Paint.Style.STROKE);
        //這里計算秒針需要旋轉的角度  60秒360度,求出實際秒數所占的度數
        Float secondAngle = seconds/60f*360;
        canvas.rotate(secondAngle, mWidth / 2, mHeght / 2);
        canvas.drawLine(mWidth / 2, mHeght / 2 -  mWidth/2f*0.8f, mWidth / 2, mHeght / 2 +  mWidth/2f*0.2f, mPaint);
        canvas.restore();
    }

其實這個方法我注釋已經寫的很詳細了,首先我們需要獲取到當前的時間,這個大家都是經常寫的沒啥問題。主要就是如何設定時分秒指針的位置才是關鍵。這里我使用一個很巧妙的方法,讓繪制變得簡單了些。

先看下繪制時針:

  //繪制時針
        canvas.save();
        mPaint.setColor(mHourHandColor);
        mPaint.setStrokeWidth(mHourHandWidth);
        //這里計算時針需要旋轉的角度 實現原理是計算出一共多少分鐘除以60計算出真實的小時數(帶有小數,為了更加準確計算度數),已知12小時是360度,現在求出了實際小時數比例求出角度
        Float hoursAngle = (hours * 60 + minutes) / 60f / 12f  * 360;
        canvas.rotate(hoursAngle, mWidth / 2, mHeght / 2);
        canvas.drawLine(mWidth / 2, mHeght / 2 - mWidth/2f*0.5f, mWidth / 2, mHeght / 2 +  mWidth/2f*0.15f, mPaint);
        canvas.restore();

前面三行代碼就不詳細說了,Canvas.save方法作用就是將之前所有已經繪制的圖片保存起來。為后續(xù)操作在新的圖層上操作。和photoshop有點一個意思。大家都知道當我們獲取到當前小時數了以后我們就應該直接把時針指到對應的時數上嗎?肯定不是吧,比如是3點半時針是指到3與4之間的位置對吧。所以我們這里需要獲取到當前的分鐘數再加上小時數才是真實的當前小時數(這里其實秒針也需要計算的,但是這里忽略不計了,如果你比我還強迫癥的話可以加上)。當我們知道當前實際的小時數的時候,就很簡單了,因為我們知道一圈360度平均分了12小時,這個別告訴我不知道啊,要是這個常識都不知道,你去面壁吧,所以只要360/12*真實的小時數就是需要旋轉的角度。這么想是不是很簡單了。計算出角度以后先吧canvas.rotate旋轉這個角度在繪制一個直線就ok了,哈哈哈,是不是so esey,其他分針和秒針一樣的道理,這里就不多說了,看代碼直接能看懂的。

        //繪制分針
        canvas.save();
        mPaint.setColor(mMinuteHandColor);
        mPaint.setStrokeWidth(mMinuteHandWidth);
        //這里計算分針需要旋轉的角度  60分鐘360度,求出實際分鐘數所占的度數
        Float minutesAngle = (minutes*60+seconds) / 60f/ 60f * 360;
        canvas.rotate(minutesAngle, mWidth / 2, mHeght / 2);
        canvas.drawLine(mWidth / 2, mHeght / 2 -  mWidth/2f*0.7f, mWidth / 2, mHeght / 2 +  mWidth/2f*0.15f, mPaint);
        canvas.restore();
        //繪制中間的圓圈
        canvas.save();
        mPaint.setColor(mSecondHandColor);
        mPaint.setStrokeWidth(mSecondHandWidth);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(mWidth/2,mHeght/2,20,mPaint);
        canvas.restore();
        //繪制秒針
        canvas.save();
        mPaint.setColor(mSecondHandColor);
        mPaint.setStrokeWidth(mSecondHandWidth);
        mPaint.setStyle(Paint.Style.STROKE);
        //這里計算秒針需要旋轉的角度  60秒360度,求出實際秒數所占的度數
        Float secondAngle = seconds/60f*360;
        canvas.rotate(secondAngle, mWidth / 2, mHeght / 2);
        canvas.drawLine(mWidth / 2, mHeght / 2 -  mWidth/2f*0.8f, mWidth / 2, mHeght / 2 +  mWidth/2f*0.2f, mPaint);
        canvas.restore();

其中有個繪制中間的圓圈是我的強迫癥所致,覺得中間加個圓圈好看點。執(zhí)行這個方法后我們的效果就成這樣了:

哈哈下面就剩下最后一步了,就是讓指針動起來,沒錯就是動起來,其實大家也在意了我們繪制指針的時候是在方法里直接獲取了當前時間設置指針的位置的,所以說只要我們搞個定時器一秒刷新下ui就大功告成了,這里就搞個hander發(fā)個空消息。

    private Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case START_CLOCK:
                    //更新時分秒
                    invalidate();
                    //每隔1秒更新一次
                    handler.sendEmptyMessageDelayed(START_CLOCK,1000);
                    break;
            }
        }
    };

就成了下面的效果了:

是不是很簡單呢?附上github:https://github.com/dalong982242260/CustomViewStudy

到此這篇關于Android自定義一個屬于自己的時間鐘表的文章就介紹到這了,更多相關Android時間鐘表內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關文章

  • Android電池電量跳變

    Android電池電量跳變

    本篇文章主要介紹了Android電池電量跳變的相關知識。具有很好的參考價值。下面跟著小編一起來看下吧
    2017-04-04
  • android關于native中Thread類的使用源碼解析

    android關于native中Thread類的使用源碼解析

    本文介紹了Android Native中Thread的使用,通過main.cpp啟動線程,TestThread類依次調用onFirstRef、readyToRun和threadLoop方法,展示線程生命周期及執(zhí)行流程,感興趣的朋友跟隨小編一起看看吧
    2025-06-06
  • Android仿微信底部菜單欄效果

    Android仿微信底部菜單欄效果

    這篇文章主要為大家詳細介紹了Android仿微信底部菜單欄效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • android實現簡單的活動轉盤

    android實現簡單的活動轉盤

    這篇文章主要為大家詳細介紹了android實現簡單的活動轉盤,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • Android MonoRepo多倉和單倉的差別理論

    Android MonoRepo多倉和單倉的差別理論

    這篇文章主要為大家介紹了Android MonoRepo多倉和單倉的差別理論,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Android開發(fā)之activity的生命周期詳解

    Android開發(fā)之activity的生命周期詳解

    這篇文章主要介紹了Android開發(fā)之activity的生命周期,詳細分析了activity的運行原理與生命周期,需要的朋友可以參考下
    2016-06-06
  • Activity配置、啟動和關閉activity實例詳解

    Activity配置、啟動和關閉activity實例詳解

    這篇文章主要介紹了Activity配置、啟動和關閉activity實例詳解,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-09-09
  • android中開啟actionbar的兩種方法

    android中開啟actionbar的兩種方法

    這篇文章主要介紹了android中開啟actionbar的兩種方法,本文給出了靜態(tài)開啟和動態(tài)開啟2種方法,需要的朋友可以參考下
    2015-06-06
  • 使用RecyclerView實現瀑布流高度自適應

    使用RecyclerView實現瀑布流高度自適應

    這篇文章主要為大家詳細介紹了使用RecyclerView實現瀑布流高度自適應,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • Android 自定義view和屬性動畫實現充電進度條效果

    Android 自定義view和屬性動畫實現充電進度條效果

    近期項目中需要使用到一種類似手機電池充電進度的動畫效果,以前沒學屬性動畫的時候,是用圖片+定時器的方式來完成的,下面給大家分享android自定義view和屬性動畫實現充電進度條
    2016-12-12

最新評論

越西县| 西峡县| 龙胜| 兴城市| 浠水县| 萨迦县| 壶关县| 高邑县| 郑州市| 阿克陶县| 沂南县| 黑河市| 宾阳县| 容城县| 大英县| 水城县| 侯马市| 平昌县| 开鲁县| 常德市| 英吉沙县| 晋江市| 江源县| 普宁市| 板桥市| 炉霍县| 铁岭县| 南乐县| 资兴市| 武城县| 巴东县| 建水县| 塘沽区| 阳高县| 合江县| 鄯善县| 藁城市| 乡宁县| 上栗县| 井陉县| 庄浪县|