<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自定義View實(shí)現(xiàn)可拖拽的進(jìn)度條

          共 5379字,需瀏覽 11分鐘

           ·

          2021-09-12 12:28

          目錄


          效果展示



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

          1、計(jì)算出控件寬度的直線路徑


          在onSizeChanged方法中進(jìn)行計(jì)算,這時(shí)可以得到一條與控件寬度相同的直線,并把路徑設(shè)置給PathMeasure

              @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        //進(jìn)度條繪制在控件中央,寬度為控件寬度(mProgressHeight/2是為了顯示出左右兩邊的圓角)        mPathProgressBg.moveTo(mProgressHeight / 2,h / 2f);        mPathProgressBg.lineTo(w - mProgressHeight / 2,h / 2f);        //將進(jìn)度條路徑設(shè)置給PathMeasure        mPathMeasure.setPath(mPathProgressBg,false);        invalidate();    }



          2、計(jì)算當(dāng)前進(jìn)度的路徑

          使用PathMeasure得出當(dāng)前進(jìn)度的路徑并進(jìn)行繪制,這里我將上一步的繪制放在了一起

          private void drawProgress(Canvas canvas) {        mPathProgressFg.reset();        mPaintProgress.setColor(mColorProgressBg);        //繪制進(jìn)度背景        canvas.drawPath(mPathProgressBg, mPaintProgress);        //計(jì)算進(jìn)度條的進(jìn)度        float stop = mPathMeasure.getLength() * mProgress;        //得到與進(jìn)度對(duì)應(yīng)的路徑        mPathMeasure.getSegment(0,stop,mPathProgressFg,true);        mPaintProgress.setColor(mColorProgressFg);        //繪制進(jìn)度        canvas.drawPath(mPathProgressFg, mPaintProgress);    }



          3、計(jì)算顯示進(jìn)度的圓角矩形

          這個(gè)矩形的寬度需要我們用繪制最長(zhǎng)的文字來(lái)確定其寬高



          另外矩形的顯示位置也是以當(dāng)前進(jìn)度所在的點(diǎn)為中心點(diǎn)



          private void drawShowProgressRoundRect(Canvas canvas) {        float stop = mPathMeasure.getLength() * mProgress;//計(jì)算進(jìn)度條的進(jìn)度        //根據(jù)要繪制的文字的最大長(zhǎng)寬來(lái)計(jì)算要繪制的圓角矩形的長(zhǎng)寬        Rect rect = new Rect();        mPaintProgressText.getTextBounds(mProgressMaxText,0, mProgressMaxText.length(),rect);        //要繪制矩形的寬、高        float rectWidth = rect.width() + (mProgressStrMarginH * 2);        float rectHeight = rect.height() + (mProgressStrMarginV * 2);        //計(jì)算邊界值(為了不讓矩形在左右兩邊超出邊界)        if(stop < rectWidth / 2f){            stop = rectWidth / 2f;        }else if(stop > (getWidth() - rectWidth / 2f)){            stop = getWidth() - rectWidth / 2f;        }        //定義繪制的矩形        float left = stop - rectWidth / 2f;        float right = stop + rectWidth / 2f;        float top = getHeight() / 2f - rectHeight / 2f;        float bottom = getHeight() / 2f + rectHeight / 2f;        mProgressRoundRectF = new RectF(left,top,right,bottom);        //繪制為圓角矩形        canvas.drawRoundRect(mProgressRoundRectF, mRoundRectRadius, mRoundRectRadius,mPaintRoundRect);    }



          4、計(jì)算文字的顯示位置

          文字顯示的位置計(jì)算起來(lái)就比較簡(jiǎn)單了,直接用上一步算出的矩形的中心點(diǎn)即可,不過(guò)這里需要調(diào)整文字繪制的垂直的偏移,這樣才能實(shí)現(xiàn)文字垂直居中

          private void drawProgressText(Canvas canvas) {        String progressText = (int)Math.floor(100 * mProgress) + "%";        //讓文字垂直居中的偏移        int offsetY = (mFontMetricsInt.bottom - mFontMetricsInt.ascent) / 2 - mFontMetricsInt.bottom;        //將文字繪制在矩形的中央        canvas.drawText(progressText,mProgressRoundRectF.centerX(),mProgressRoundRectF.centerY() + offsetY,mPaintProgressText);    }



          5、實(shí)現(xiàn)拖拽

          實(shí)現(xiàn)拖拽需要對(duì)onTouchEvent方法進(jìn)行處理,也就是當(dāng)手指觸摸矩形區(qū)域的時(shí)候,根據(jù)手指橫向滑動(dòng)的偏移來(lái)設(shè)置當(dāng)前的進(jìn)度,具體如下:

              @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()){            case MotionEvent.ACTION_DOWN:                //判斷手指是否觸摸了顯示進(jìn)度的圓角矩形塊,這樣才可以拖拽                if(mProgressRoundRectF != null && mProgressRoundRectF.contains(event.getX(),event.getY())){                    //記錄手指剛接觸屏幕的X軸坐標(biāo)(因?yàn)橹恍枰赬軸上平移)                    mStartTouchX = event.getX();                    mIsTouchSeek = true;                }                break;            case MotionEvent.ACTION_MOVE:                if(mIsTouchSeek){                    //計(jì)算橫向移動(dòng)的距離                    float moveX = event.getX() - mStartTouchX;                    //計(jì)算出當(dāng)前進(jìn)度的X軸所顯示的進(jìn)度長(zhǎng)度                    float currentProgressWidth = mPathMeasure.getLength() * mProgress;//計(jì)算進(jìn)度條的進(jìn)度                    //計(jì)算滑動(dòng)后的X軸的坐標(biāo)                    float showProgressWidth = currentProgressWidth + moveX;                    //計(jì)算邊界值                    if(showProgressWidth < 0){                        showProgressWidth = 0;                    }else if(showProgressWidth > mPathMeasure.getLength()){                        showProgressWidth = mPathMeasure.getLength();                    }                    //計(jì)算滑動(dòng)后的進(jìn)度                    mProgress = showProgressWidth / mPathMeasure.getLength();                    //重繪                    invalidate();                    //刷新用于計(jì)算移動(dòng)的X軸坐標(biāo)                    mStartTouchX = event.getX();                }                break;            case MotionEvent.ACTION_UP:                mIsTouchSeek = false;                break;        }        return mIsTouchSeek;    }


          6、計(jì)算當(dāng)前自定義View的寬高

          為了適配高度的wrap_content屬性,我們需要計(jì)算出控件最小需要顯示的高度



          這里我們是用顯示進(jìn)度的矩形的高度作為控件最小的高度的,因?yàn)榫匦蔚母叨仁撬袌D形最高的一個(gè)



          而矩形的高度又是文字的大小與邊距之和

           @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        setMeasuredDimension(measureSizeWidth(widthMeasureSpec), measureSizeHeight(heightMeasureSpec));    }
          //計(jì)算寬度 private int measureSizeWidth(int size) { int mode = MeasureSpec.getMode(size); int s = MeasureSpec.getSize(size); if (mode == MeasureSpec.EXACTLY) { return s; } else{ return Math.min(s, 200); } } //計(jì)算高度 private int measureSizeHeight(int size) { int mode = MeasureSpec.getMode(size); int s = MeasureSpec.getSize(size); if (mode == MeasureSpec.EXACTLY) { return s; }else { //自適應(yīng)模式,返回所需的最小高度 return (int) (mTextSize + mProgressStrMarginV * 2); } }


          源碼地址:

          https://gitee.com/itfitness/seek-progress-bar

          瀏覽 130
          點(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>
                  交欧美| 草草在线观看 | 久久加勒比婷婷 | 国产精品一三 | 日本黄色链接 |