1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        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)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            操P网 | 朝鲜一级黄色片 | 五月婷婷老师 | www性欧美 | 操逼网络| 亚洲成人AV在线观看 | 青青草在线播放 | 欧美一级黄色视屏 | 欧美操小嫩逼 | 爱爱视频日本 |