<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Android自定義一款帶進度條的精美按鍵

        Android中自定義View并沒有什么可怕的,拿到一個需要自定義的View,首先要做的就是把它肢解,然后思考每一步是怎樣實現的,按分析的步驟一步一步的編碼實現,最后你就會發現達到了你想要的效果。本文就按這樣的步驟帶你打造一款精美的按鈕。


      效果預覽

      ??在開始本文之前,照例,先看下實現后的效果,如下圖


      不想閱讀本文,可以直接到這里獲取源碼

      閱讀本文你需要掌握

      自定義屬性
      ValueAnimator動畫
      Viwe的測量、繪制
      Paint和Path的用法

      動手實現

      拆解

      ??在動手編碼之前,要靜下心來分析一下,這款View是怎樣組成的,也就是要把這個View拆解一下。分析后,不難發現主要有一下部分組成

      • 圓形背景
      • 圓環的背景
      • 圓環
      • 文字

      知道這個View是怎樣組成的,然后完成相應部分的編碼,最后將這些部分按時間順序進行拼裝展示,就能達到文章開頭那樣的效果了。

      分析原理

      ??經過拆解,知道了這個View都有那幾部分組成了,下面就來分析一下是怎樣將以上部分進行整合的

      1. 在沒點擊之前,是一個中間帶有文字的圓形。
      2. 點擊之后圓形縮小,當縮小到一定程度后,圓環背景出現,同時,圓環進度條開始加載。
      3. 如果進度條加載完成,則改變文字(回調接口),抬起手后恢復原來的形狀;如果沒有加載完成,抬起手后,恢復原裝,下次點擊從新執行此步驟。

      為了理解清楚,可以自己畫一下流程圖。

      編碼實現

      ??相信,經過分析拆解之后,你腦子里應該有一個實現的流程了,下面就動手開始實現吧!

      先將需要的畫筆和路徑進行初始化

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      //初始化畫筆及路徑
      private void initPaintOrPath() {
      circleBgPaint = new Paint();
      circleBgPaint.setAntiAlias(true);
      circleBgPaint.setStyle(Paint.Style.FILL_AND_STROKE);
      ringBgPaint = new Paint();
      ringBgPaint.setColor(ringBgColor.getColorForState(getDrawableState(),0));
      ringBgPaint.setAntiAlias(true);
      ringBgPaint.setStrokeWidth(ringSize);
      ringBgPaint.setStyle(Paint.Style.STROKE);
      ringPaint = new Paint();
      ringPaint.setColor(ringColor.getColorForState(getDrawableState(),0));
      ringPaint.setAntiAlias(true);
      ringPaint.setStrokeWidth(ringSize);
      ringPaint.setStyle(Paint.Style.STROKE);
      path = new Path();
      textPaint = new Paint();
      textPaint.setAntiAlias(true);
      textPaint.setTextAlign(Paint.Align.CENTER);
      textPaint.setColor(textColor.getColorForState(getDrawableState(),0));
      textPaint.setTextSize(textSize);
      }

      自定義View需要經過三個重要的步驟,測量,布局,繪制,分別對應onMeasure(),onLayout(),onDraw()方法。這里的onLayout()主要是對自定義ViewGroup的,自定義View只要重寫onMeasure()onDraw()方法就行了,按照自定義View的套路來,先進行測量,直接看代碼

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      @Override
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
      //獲得父View傳遞過來的寬度的大小和類型
      int widthMode = MeasureSpec.getMode(widthMeasureSpec);
      int widthSize = MeasureSpec.getSize(widthMeasureSpec);
      //獲得父View傳遞過來的高度的大小和類型
      int heightMode = MeasureSpec.getMode(heightMeasureSpec);
      int heightSize = MeasureSpec.getSize(heightMeasureSpec);
      //初始化最終的寬高
      int resultWidth = widthSize;
      int resultHeight = heightSize;
      //為了讓文字可以在背景(圓形)中完全顯示
      if (mRadius * 2 < textPaint.measureText(contentText)) {
      mRadius = (int) textPaint.measureText(contentText);
      }
      if (widthMode == MeasureSpec.AT_MOST) {
      //獲取我們需要的寬度
      int contentWidth = (mRadius + space + ringSize)*2+ getPaddingLeft() + getPaddingRight();
      //得到最終的寬度
      resultWidth = (contentWidth < widthSize) ? resultWidth : contentWidth;
      }
      if (heightMode == MeasureSpec.AT_MOST) {
      //獲取我們需要的高度
      int contentHeight = (mRadius + space + ringSize)*2 + getPaddingTop() + getPaddingBottom();
      //得到最終的高度
      resultHeight = (contentHeight < heightSize) ? resultHeight : contentHeight;
      }
      //設置測量后的寬高
      setMeasuredDimension(resultWidth,resultHeight);
      }

      代碼中都有注釋,相信你可以看的懂。下面就開始畫我們需要的圓形,圓環背景,圓環和文字了,我們需要在onDraw()方法中進行作畫,代碼如下

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      @Override
      protected void onDraw(Canvas canvas) {
      super.onDraw(canvas);
      //畫圓,改變ringRadius就可以改變圓形背景的大小,主要控制value值的改變
      ringRadius = mRadius - DPUtils.dip2px(getContext(),value/2);
      circleBgPaint.setColor(circleColor.getColorForState(getDrawableState(),0));
      canvas.drawCircle(getWidth() / 2, getHeight() / 2, ringRadius, circleBgPaint);
      //用戶按鍵時開始畫圓環
      if (startDrawLine){
      //計算外環的半徑,記得要減去外環的寬度的一半
      result = ringRadius + space +ringSize/2;
      //畫完整的進度條
      canvas.drawCircle(getWidth() / 2, getHeight() / 2, result, ringBgPaint);
      //畫進度條路徑
      path.reset();//重置路徑,否則下次精度條不會從開始位置,可以注釋掉此代碼,看下效果
      //計算畫路徑的矩形
      float left = getWidth()/2-result;
      float top = getHeight()/2-result;
      float right = getWidth()/2+result;
      float bottom = getHeight()/2+result;
      RectF rect = new RectF(left,top, right ,bottom);
      path.addArc(rect, -90, angle);//通過改變angle就可以動態的改變進度條
      //畫圓環的路徑
      canvas.drawPath(path, ringPaint);
      }
      canvas.drawText(contentText,getWidth()/2,getHeight()/2,textPaint);//文字
      }

      完成以上幾步,點擊view時并沒有反應,因為還沒有為View添加觸摸事件,也沒有添加動畫,進過分析原理那步,可以知道,手指按下時改變圓形背景的大小,既改變半徑的大小……,這里就不在重復說了,直接看代碼,代碼中會有講解

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      @Override
      public boolean onTouchEvent(final MotionEvent event) {
      //控制加載完成時候是否還可以相應點擊事件,可以通過setEnable()方法來控制
      if (!enable && event.getAction()!=MotionEvent.ACTION_UP) {
      return false;
      }
      switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN: {
      //當手指按下時,移除手指抬起時的監聽
      if (animator != null) {
      animator.removeAllUpdateListeners();
      }
      //改變narrowDown的值
      animatorValue = ValueAnimator.ofInt(0, narrowDown);
      animatorValue.setDuration(50);
      animatorValue.setInterpolator(new LinearInterpolator());
      animatorValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
      @Override
      public void onAnimationUpdate(ValueAnimator valueAnimator) {
      value = (int) valueAnimator.getAnimatedValue();//改變value的值也就是按下手指讓圓形背景縮小
      if (value == narrowDown) {
      //當縮小到一定值時開始畫圓環和精度條
      startDrawLine = true;//控制什么時候開始畫圓環和進度條
      animatorValue.removeAllUpdateListeners();//當開始畫進度條時移除改變背景大小的動畫,既停止改變
      }
      postInvalidate();//刷新畫布
      }
      });
      animatorValue.start();//開始縮小

      angleAnimator = ValueAnimator.ofFloat(0, 360f);
      angleAnimator.setDuration(2000);
      angleAnimator.setInterpolator(new LinearInterpolator());
      angleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
      @Override
      public void onAnimationUpdate(ValueAnimator valueAnimator) {
      angle = (float) valueAnimator.getAnimatedValue();//angle用來畫進度條,動態改變進度條加載的進度
      if (angle == 360) {
      //加載完成移除動畫,既進度條停止加載
      angleAnimator.removeAllUpdateListeners();
      //進度條加載完成后的回調
      onViewClick.onFinish(ImitateKeepButton.this);
      }
      postInvalidate();
      }
      });
      angleAnimator.start();//開始加載
      }
      break;
      case MotionEvent.ACTION_UP: {
      angleAnimator.removeAllUpdateListeners();
      animatorValue.removeAllUpdateListeners();
      animator = ValueAnimator.ofInt(value,0);
      animator.setDuration(300);
      animator.setInterpolator(new LinearInterpolator());
      animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
      @Override
      public void onAnimationUpdate(ValueAnimator valueAnimator) {
      value = (int) valueAnimator.getAnimatedValue();
      postInvalidate();
      }
      });
      animator.start();//開始恢復背景原來的大小
      }
      startDrawLine = false;
      break;
      }
      return true;
      }

      好了,到這里已經達到了文章開始時的效果,可以結束本文了。

      結束語

      ??文中代碼,只是粘貼部分比較重要的,不完整,完整代碼可以到這里獲取源碼

      轉載請注明出處:www.wizardev.com

      posted @ 2017-08-29 11:22  igeekbar  閱讀(883)  評論(0)    收藏  舉報

      中文互聯: GBin1.com | RSS訂閱 | 郵件訂閱 | 手機訂閱

      主站蜘蛛池模板: 欧美激情一区二区久久久| 中文字幕日韩精品人妻| 成人自拍短视频午夜福利| 珲春市| 久热天堂在线视频精品伊人| 99精品国产一区在线看| 制服丝袜国产精品| 亚洲精品国产免费av| 999精品色在线播放| 视频一本大道香蕉久在线播放| 久久先锋男人AV资源网站| 精品国产三级a∨在线欧美| av亚洲一区二区在线| 无码日韩精品一区二区三区免费 | 国产精品成人久久电影| a片免费视频在线观看| 欧美人与动牲交A免费观看| 精品一区二区久久久久久久网站| 麻花传媒免费网站在线观看| 日韩有码av中文字幕| 亚洲高清国产拍精品熟女| 一区二区亚洲人妻精品| 亚洲最大中文字幕无码网站| 少妇高潮流白浆在线观看| 亚洲偷自拍国综合| 麻豆aⅴ精品无码一区二区| 国产精品一区二区三区激情| 国产精品不卡区一区二| 久久久www免费人成精品| 国产无遮挡真人免费视频| 亚洲一本二区偷拍精品| 国产无吗一区二区三区在线欢| 搡老熟女老女人一区二区| 国内精品久久久久影院蜜芽 | 亚洲一区二区啊射精日韩| 亚洲AV日韩精品久久久久| 色先锋av影音先锋在线| 18禁网站免费无遮挡无码中文| 狠狠亚洲色一日本高清色| 国产精品综合一区二区三区| 亚洲国产精品人人做人人爱|