自定義View系列一 仿QQ計(jì)步器的實(shí)現(xiàn)

前言

自定義View作為安卓開發(fā)進(jìn)階必備的一個(gè)技能盾剩,其中不乏一些套路吭净,當(dāng)然更多的是相關(guān)Api的熟練使用以及一些數(shù)學(xué)計(jì)算陌选。學(xué)而時(shí)習(xí)之理郑,多學(xué)習(xí)多模仿,希望能更好的掌握自定義View的使用咨油。

先看下我們要實(shí)現(xiàn)的效果, 主要是進(jìn)度條和文字的更新

progressView.gif

要鞏固掌握的知識(shí)點(diǎn)

  1. 自定義view的步驟和流程

  2. Paint畫筆的使用您炉,畫圓弧,畫文字役电,文字基線的確定

  3. 屬性動(dòng)畫的使用

效果實(shí)現(xiàn)分析

  1. 自定義屬性:軌道圓弧的寬度和顏色赚爵,進(jìn)度圓弧的顏色,文字的大小和顏色

  2. 用畫筆繪制軌道圓弧法瑟,指定起始角度和結(jié)束角度

  3. 用畫筆繪制進(jìn)度圓弧冀膝,注意其sweepAngle是用屬性動(dòng)畫更新的一個(gè)變量實(shí)現(xiàn)動(dòng)畫效果

  4. 用畫筆繪制內(nèi)部文字,注意文字的y坐標(biāo)是基線位置

  5. 提供設(shè)置最大進(jìn)度和當(dāng)前進(jìn)度的方法給使用者調(diào)用

代碼實(shí)現(xiàn)

  1. 定義自定義屬性
 <declare-styleable name="ProgressView">
         <!-- 軌道顏色 -->
         <attr name="trackColor" format="color" />
         <!-- 軌道寬度 -->
         <attr name="trackWidth" format="dimension" />
         <!-- 進(jìn)度條顏色 -->
         <attr name="progressColor" format="color" />
         <!-- 文字顏色 -->
         <attr name="progressTextColor" format="color" />
         <!-- 文字大小 -->
         <attr name="progressTextSize" format="dimension" />
     </declare-styleable>
  1. 初始化軌道霎挟、進(jìn)度圓弧和文字畫筆
        //軌道畫筆
        mTrackPaint = new Paint();
        mTrackPaint.setColor(mTrackColor);
        mTrackPaint.setAntiAlias(true);
        mTrackPaint.setStrokeWidth(mTrackWidth);
        mTrackPaint.setStyle(Paint.Style.STROKE);
        mTrackPaint.setStrokeCap(Paint.Cap.ROUND);
        //進(jìn)度條畫筆
        mProgressPaint = new Paint();
        mProgressPaint.setColor(mProgressColor);
        mProgressPaint.setAntiAlias(true);
        mProgressPaint.setStrokeWidth(mTrackWidth);
        mProgressPaint.setStyle(Paint.Style.STROKE);
        mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
        //文字畫筆
        mTextPaint = new Paint();
        mTextPaint.setTextSize(mProgressTextSize);
        mTextPaint.setColor(mProgressTextColor);
        mTextPaint.setAntiAlias(true);

  1. 在onDraw()方法中繪制 軌道圓弧窝剖、進(jìn)度條圓弧、進(jìn)度文字

    • 進(jìn)度條圓弧sweepAngle的計(jì)算 = 軌道的圓弧的角度 * (當(dāng)前更新的進(jìn)度 / 總進(jìn)度)
    • 畫文字時(shí)酥夭,y坐標(biāo)是基線高度赐纱,如果直接給定控件高度的一半脊奋。則畫出來的文字會(huì)偏上,這里要計(jì)算基線高度
  @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //控件中心位置
        int center = getWidth() / 2;
        //軌道圓弧半徑
        int radius = getWidth() / 2 - mTrackWidth / 2;
        //畫軌道圓弧
        RectF rectF = new RectF(center - radius, center - radius, center + radius, center + radius);
        canvas.drawArc(rectF, 135, 270, false, mTrackPaint);
      
        //計(jì)算當(dāng)前進(jìn)度圓弧掃過的角度
        float sweepAngle = (mCurrentProgress / mMaxProgress) * 270;
        //畫進(jìn)度條圓弧
        canvas.drawArc(rectF, 135, sweepAngle, false, mProgressPaint);
        //畫文字
        String text = (int) mCurrentProgress + "";
        Rect rect = new Rect();
        mTextPaint.getTextBounds(text, 0, text.length(), rect);
        Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();
        float x = center - rect.width() / 2;
        //確定文字繪制的基線高度
        float dy = (fontMetrics.bottom - fontMetrics.top)/2 - fontMetrics.bottom;
        float baseline = getHeight() / 2 + dy; 
        canvas.drawText(text, 0, text.length(), x, baseline, mTextPaint);
    }
  1. 提供設(shè)置當(dāng)前進(jìn)度和最大進(jìn)度的方法
    • 使用屬性動(dòng)畫疙描,使記錄當(dāng)前進(jìn)度的局部變量mCurrentProgress的值從0變到設(shè)置的progress诚隙,開始動(dòng)畫。調(diào)用invalidate() 刷新淫痰,使界面不斷重繪以達(dá)到動(dòng)畫的效果
 /**
     * 設(shè)置當(dāng)前進(jìn)度
     * @param progress
     */
    public void setCurrentProgress(float progress) {
        //屬性動(dòng)畫更新進(jìn)度最楷,刷新界面
        ValueAnimator animator = ValueAnimator.ofFloat(0, progress);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                mCurrentProgress = (float) valueAnimator.getAnimatedValue();
                invalidate();
            }
        });
        animator.setInterpolator(new AccelerateInterpolator());
        animator.setDuration(2000);
        animator.start();
    }

    /**
     * 設(shè)置最大進(jìn)度
     * @param maxProgress
     */
    public void setMaxProgress(float maxProgress) {
        this.mMaxProgress = maxProgress;
    }
  1. 在Activity中測(cè)試和使用
 ProgressView progressView = (ProgressView) findViewById(R.id.progressView);
 progressView.setMaxProgress(4000);
 progressView.setCurrentProgress(2855);
?項(xiàng)目Github地址:https://github.com/m1Koi/CustomViewPractice

小結(jié)

這個(gè)效果,主要是使用的畫筆繪制圓弧并配合屬性動(dòng)畫更新進(jìn)度的顯示待错。以此類推籽孙,水平進(jìn)度條、圓形進(jìn)度條和App開屏頁(yè)的倒計(jì)時(shí)跳過的效果同樣可以實(shí)現(xiàn)火俄。效果中需要重點(diǎn)掌握和理解的是文字的繪制以及文字基線的定義和計(jì)算犯建。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市瓜客,隨后出現(xiàn)的幾起案子适瓦,更是在濱河造成了極大的恐慌,老刑警劉巖谱仪,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件玻熙,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡疯攒,警方通過查閱死者的電腦和手機(jī)嗦随,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來敬尺,“玉大人枚尼,你說我怎么就攤上這事∩巴蹋” “怎么了署恍?”我有些...
    開封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蜻直。 經(jīng)常有香客問我盯质,道長(zhǎng),這世上最難降的妖魔是什么袭蝗? 我笑而不...
    開封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任唤殴,我火速辦了婚禮,結(jié)果婚禮上到腥,老公的妹妹穿的比我還像新娘朵逝。我一直安慰自己,他們只是感情好乡范,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開白布配名。 她就那樣靜靜地躺著啤咽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪渠脉。 梳的紋絲不亂的頭發(fā)上宇整,一...
    開封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音芋膘,去河邊找鬼鳞青。 笑死,一個(gè)胖子當(dāng)著我的面吹牛为朋,可吹牛的內(nèi)容都是我干的臂拓。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼习寸,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼胶惰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起霞溪,我...
    開封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤孵滞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后鸯匹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坊饶,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年殴蓬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了幼东。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡科雳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出脓杉,到底是詐尸還是另有隱情糟秘,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布球散,位于F島的核電站尿赚,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蕉堰。R本人自食惡果不足惜凌净,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望屋讶。 院中可真熱鬧冰寻,春花似錦、人聲如沸皿渗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至划乖,卻和暖如春贬养,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背琴庵。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工误算, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人迷殿。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓儿礼,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親贪庙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蜘犁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,846評(píng)論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件止邮、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,066評(píng)論 4 62
  • 今天在感召過程中这橙,沒有走捷徑,沒有救助任何人导披,靠自己去完成屈扎。還是蠻有成就感的。我認(rèn)為認(rèn)真做事撩匕,還是能得到大家的喜歡...
    伏伏王閱讀 304評(píng)論 0 1
  • 現(xiàn)在躺在沙發(fā)上的我穿著粉色毛茸茸的睡衣鹰晨,非常愉快的開始寫作,剛剛看了幾章《寫出我心》止毕,發(fā)現(xiàn)其實(shí)要寫的東西真的很...
    D061張琴閱讀 276評(píng)論 0 0
  • 海里有一只叫做愛麗絲的鯨魚扁凛,孤獨(dú)的游著忍疾,希望遇見同伴。它發(fā)出的聲音谨朝,卻總是得不到回應(yīng)卤妒,因?yàn)樗念l率與眾不同,所以它...
    張小呆閱讀 39,520評(píng)論 5 13