自定義View之CircleIndicatorView實(shí)現(xiàn)圓形指示器

項(xiàng)目中的自定義控件比較多檀咙,今天應(yīng)該是最后一個(gè)了,看下UI效果


圓形指示器UI圖

UI分析

  1. 內(nèi)側(cè)一個(gè)白色的虛線弧
  2. 外側(cè)有兩條弧璃诀,一個(gè)是灰色的實(shí)線弧弧可,一個(gè)是白色的虛線弧,實(shí)線弧尾部有一個(gè)小圓點(diǎn)
  3. 中間是文字劣欢,大小不一致棕诵,顏色是白色
  4. 加載的時(shí)候需要一個(gè)加載動(dòng)畫(huà),實(shí)線橢圓進(jìn)度條跟可用額度數(shù)字需要同時(shí)從小到達(dá)變化
  • 效果圖
圓形指示器效果圖

下面根據(jù)UI的分析凿将,來(lái)分享一下實(shí)現(xiàn)的過(guò)程

自定義屬性

  • 文字的大小
  • 線的顏色
  • 虛線的間距

代碼

//定義屬性
 <declare-styleable name="CircleIndicatorView">
        <attr name="largeSize" format="dimension"/>
        <attr name="smallSize" format="dimension"/>
        <attr name="grayColor" format="color"/>
        <attr name="whiteColor" format="color"/>
        <attr name="lineSpace" format="dimension"/>
    </declare-styleable>
    
//獲取屬性

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CircleIndicatorView);
        mLargeSize = (int) ta.getDimension(R.styleable.CircleIndicatorView_largeSize, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 15, context.getResources().getDisplayMetrics()));
        mSmallSize = (int) ta.getDimension(R.styleable.CircleIndicatorView_smallSize, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 13, context.getResources().getDisplayMetrics()));
        mGrayColor = ta.getColor(R.styleable.CircleIndicatorView_grayColor, Color.GRAY);
        mWhiteColor = ta.getColor(R.styleable.CircleIndicatorView_whiteColor, Color.WHITE);
        ta.recycle();

onMeasure

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
    }
    
        private int measureWidth(int widthMeasureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);
        switch (specMode) {
            case MeasureSpec.EXACTLY:
                result = specSize;
                break;
            case MeasureSpec.UNSPECIFIED:
            case MeasureSpec.AT_MOST:
                break;
        }
        return result;
    }
    

這里其實(shí)不需要考慮MeasureSpec.AT_MOST校套,因?yàn)檫@個(gè)圓的半徑是一般是固定的,所以沒(méi)有處理MeasureSpec.AT_MOST牧抵,如果需求需要處理的話其實(shí)也很簡(jiǎn)單笛匙,跟自定義View之IndexView進(jìn)度條(一)中的一樣,把相應(yīng)的寬高進(jìn)行累加即可犀变,不是分析的重點(diǎn)膳算,所以一筆帶過(guò)。

onDraw

  1. 繪制內(nèi)側(cè)白色虛線弧度
//不加的話在高版本上虛線不顯示
setLayerType(View.LAYER_TYPE_SOFTWARE,dashPaint);
//設(shè)置虛線間隔
PathEffect effects = new DashPathEffect(new float[]{20, 6}, 0);
        dashPaint.setPathEffect(effects);
         RectF dashedRectF = new RectF(mCenter - mRadius + 20 + getPaddingLeft(), mCenter - mRadius + 20 + getPaddingTop(), mCenter + mRadius - 20 - getPaddingRight(), mCenter + mRadius - 20 - getPaddingBottom());
        float startAngle = 150;
        canvas.drawArc(dashedRectF, startAngle, sweepAngle, false, dashPaint);
  1. 繪制外側(cè)灰色弧度
        canvas.drawArc(rectF, startAngle, sweepAngle, false, outPaint);
  1. 繪制外側(cè)進(jìn)度弧度
 canvas.drawArc(rectF, startAngle, getInSweepAngle(), false, inPaint);

4.繪制外側(cè)進(jìn)度弧度的小圓點(diǎn)弛作,實(shí)際上是一個(gè)Bitmap,注釋比較詳細(xì)涕蜂,也比較簡(jiǎn)單,就是畫(huà)布的平移跟旋轉(zhuǎn)這個(gè)需要好好理解一下

  //繪制發(fā)光的小圓點(diǎn)
        Paint paintCircle = new Paint();
        paintCircle.setStyle(Paint.Style.FILL);
        paintCircle.setAntiAlias(true);//抗鋸齒功能
        canvas.translate(getWidth() / 2, getHeight() / 2);//畫(huà)布平移到圓心
        canvas.rotate(getInSweepAngle() + 60);//旋轉(zhuǎn)畫(huà)布使得畫(huà)布的Y軸經(jīng)過(guò)小圓點(diǎn)
        canvas.translate(0, getHeight() / 2 - getPaddingLeft());//再次平移畫(huà)布至小圓點(diǎn)繪制的位置
       //此處省略了Bitmap的處理過(guò)程bmp
        Bitmap dotBitmap = Bitmap.createBitmap(bmp, 0, 0, width, height, matrix, true);
        canvas.drawBitmap(dotBitmap, -15, -15, paintCircle);
        canvas.rotate(-(getInSweepAngle() + 60));//恢復(fù)canvas

5.繪制文字
這個(gè)在繪制數(shù)字的時(shí)候需要注意一下映琳,因?yàn)閭鬟^(guò)來(lái)的是一個(gè)浮點(diǎn)數(shù)机隙,需要拆分成整數(shù)跟小數(shù)兩部分,但是當(dāng)你講float轉(zhuǎn)化為String然后切割的時(shí)候萨西,注意下需要將小數(shù)點(diǎn)進(jìn)行轉(zhuǎn)義有鹿,不然會(huì)分割失敗

DecimalFormat decimalFormat = new DecimalFormat(".00");//構(gòu)造方法的字符格式這里如果小數(shù)不足2位,會(huì)以0補(bǔ)足.
        String value = decimalFormat.format(indexValue);//format 返回的是字符串
        Log.d("value---->", value);
        String[] split = value.split("\\.");
        String text = split[0];//整數(shù)部分

剛進(jìn)來(lái)時(shí)候的加載動(dòng)畫(huà)

這個(gè)其實(shí)就是兩個(gè)屬性動(dòng)畫(huà)同時(shí)播放而已,通過(guò)計(jì)算扇形掃過(guò)的角度與數(shù)字增長(zhǎng)的幅度
谎脯,然后在屬性動(dòng)畫(huà)的update里面進(jìn)行重新繪制整個(gè)View葱跋,就可以搞定

       float inSweepAngle = sweepAngle * value / 100;
        ValueAnimator angleAnim = ValueAnimator.ofFloat(0f, inSweepAngle);//角度的ValueAnimator
        float inValue = value * 8888 / 100;
        ValueAnimator valueAnim = ValueAnimator.ofFloat(0, inValue);//數(shù)字變化的ValueAnimator
        //一起播放動(dòng)畫(huà)
         animatorSet.playTogether(angleAnim, valueAnim);
        

提供一個(gè)方法,供外部調(diào)用

 public void goToPoint(float value) {
       //在方法中進(jìn)行播放動(dòng)畫(huà)
    }

使用方法

mCircleIndicatorView.goToPoint(value);

Demo下載地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末源梭,一起剝皮案震驚了整個(gè)濱河市娱俺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌废麻,老刑警劉巖荠卷,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異烛愧,居然都是意外死亡油宜,警方通過(guò)查閱死者的電腦和手機(jī)掂碱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)慎冤,“玉大人疼燥,你說(shuō)我怎么就攤上這事∫系蹋” “怎么了悴了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)违寿。 經(jīng)常有香客問(wèn)我,道長(zhǎng)熟空,這世上最難降的妖魔是什么藤巢? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮息罗,結(jié)果婚禮上掂咒,老公的妹妹穿的比我還像新娘。我一直安慰自己迈喉,他們只是感情好绍刮,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著挨摸,像睡著了一般孩革。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上得运,一...
    開(kāi)封第一講書(shū)人閱讀 51,287評(píng)論 1 301
  • 那天膝蜈,我揣著相機(jī)與錄音,去河邊找鬼熔掺。 笑死饱搏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的置逻。 我是一名探鬼主播推沸,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼券坞!你這毒婦竟也來(lái)了鬓催?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤恨锚,失蹤者是張志新(化名)和其女友劉穎深浮,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體眠冈,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡飞苇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年菌瘫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片布卡。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡雨让,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出忿等,到底是詐尸還是另有隱情栖忠,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布贸街,位于F島的核電站庵寞,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏薛匪。R本人自食惡果不足惜捐川,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望逸尖。 院中可真熱鬧古沥,春花似錦、人聲如沸娇跟。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)苞俘。三九已至盹沈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吃谣,已是汗流浹背襟诸。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留基协,地道東北人歌亲。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像澜驮,于是被迫代替她去往敵國(guó)和親陷揪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容