欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android 自定義View實現(xiàn)多節(jié)點進度條功能

 更新時間:2020年05月06日 10:04:06   作者:DMingO  
這篇文章主要介紹了Android 自定義View實現(xiàn)多節(jié)點進度條,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

前言

最近項目有一個節(jié)點進度條的小需求,完成后,想分享出來希望可以幫到有需要的同學。

真機效果圖

自定義View完整代碼

開箱即用~,注釋已經(jīng)炒雞詳細了

/**
 * @description: 節(jié)點進度條
 * @author: DMingO
 * @date: 2020/4/15
 */
public class PointProcessBar extends View {
  /**
   * 未選中時的連線畫筆
   */
  private Paint mLinePaint;
  /**
   * 選中時的連線畫筆
   */
  private Paint mLineSelectedPaint;
  /**
   * 未選中時的文字畫筆
   */
  private Paint mTextPaint;
  /**
   * 選中時的文字畫筆
   */
  private Paint mTextSelPaint;
  /**
   * 未選中時的實心圓畫筆
   */
  private Paint mCirclePaint;
  /**
   * 選中時的內(nèi)部實心圓畫筆
   */
  private Paint mCircleSelPaint;
  /**
   * 選中時的邊框圓畫筆
   */
  private Paint mCircleStrokeSelPaint;
  /**
   * 未選中時的線,節(jié)點圓的顏色
   */
  private int mColorUnselected = Color.parseColor("#1ca8b0d9");
  /**
   * 選中時的顏色
   */
  private int mColorSelected = Color.parseColor("#61A4E4");
  /**
   * 未選中的文字顏色
   */
  private int mColorTextUnselected = Color.parseColor("#5c030f09");
  /**
   * 繪制的節(jié)點個數(shù),由底部節(jié)點標題數(shù)量控制
   */
  int circleCount ;
  /**
   * 連線的高度
   */
  float mLineHeight = 7f;
  //圓的直徑
  float mCircleHeight = 50f;
  float mCircleSelStroke = 8f;
  float mCircleFillRadius = 15f;
  //文字大小
  float mTextSize = 35f;
  //文字離頂部的距離
  float mMarginTop = 40f;
  /**
   * 首個圓向中心偏移的距離
   */
  float marginLeft = 30f;
  /**
   * 最后一個圓向中心偏移的距離
   */
  float marginRight = marginLeft;
  /**
   * 每個節(jié)點相隔的距離
   */
  float divideWidth;
  int defaultHeight;
  /**
   * 節(jié)點底部的文字列表
   */
  List<String> textList = new ArrayList<>();
  /**
   * 文字同寬高的矩形,用來測量文字
   */
  List<Rect> mBounds;
  /**
   * 存儲每個圓心在同一直線上的節(jié)點圓的 x 坐標值
   */
  List<Float> circleLineJunctions = new ArrayList<>();
  /**
   * 選中項集合
   */
  Set<Integer> selectedIndexSet = new HashSet<>();
  public PointProcessBar(Context context) {
    super(context);
  }
  public PointProcessBar(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    initPaint();
  }
  public PointProcessBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }
  public PointProcessBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
  }
  /**
   * 初始化畫筆屬性
   */
  private void initPaint(){
    mLinePaint = new Paint();
    mLineSelectedPaint = new Paint();
    mCirclePaint = new Paint();
    mTextPaint = new Paint();
    mCircleStrokeSelPaint = new Paint();
    mTextSelPaint=new Paint();
    mCircleSelPaint = new Paint();
    mLinePaint.setColor(mColorDef);
    //設(shè)置填充
    mLinePaint.setStyle(Paint.Style.FILL);
    //筆寬像素
    mLinePaint.setStrokeWidth(mLineHeight);
    //鋸齒不顯示
    mLinePaint.setAntiAlias(true);
    mLineSelectedPaint.setColor(mColorSelected);
    mLineSelectedPaint.setStyle(Paint.Style.FILL);
    mLineSelectedPaint.setStrokeWidth(mLineHeight);
    mLineSelectedPaint.setAntiAlias(true);
    mCirclePaint.setColor(mColorDef);
    //設(shè)置填充
    mCirclePaint.setStyle(Paint.Style.FILL);
    //筆寬像素
    mCirclePaint.setStrokeWidth(1);
    //鋸齒不顯示
    mCirclePaint.setAntiAlias(true);
    //選中時外框空心圓圈畫筆
    mCircleStrokeSelPaint.setColor(mColorSelected);
    mCircleStrokeSelPaint.setStyle(Paint.Style.STROKE);
    mCircleStrokeSelPaint.setStrokeWidth(mCircleSelStroke);
    mCircleStrokeSelPaint.setAntiAlias(true);
    //選中時的內(nèi)部填充圓畫筆
    mCircleSelPaint.setStyle(Paint.Style.FILL);
    mCircleSelPaint.setStrokeWidth(1);
    mCircleSelPaint.setAntiAlias(true);
    mCircleSelPaint.setColor(mColorSelected);
    //普通狀態(tài)的文本 畫筆
    mTextPaint.setTextSize(mTextSize);
    mTextPaint.setColor(mColorTextDef);
    mTextPaint.setAntiAlias(true);
    mTextPaint.setTextAlign(Paint.Align.CENTER);
    //選中后的文本畫筆
    mTextSelPaint.setTextSize(mTextSize);
    mTextSelPaint.setColor(mColorSelected);
    mTextSelPaint.setAntiAlias(true);
    mTextSelPaint.setTextAlign(Paint.Align.CENTER);
  }
  /**
   * 測量文字的長寬,將文字視為rect矩形
   */
  private void measureText(){
    mBounds = new ArrayList<>();
    for(String name : textList){
      Rect mBound = new Rect();
      mTextPaint.getTextBounds(name, 0, name.length(), mBound);
      mBounds.add(mBound);
    }
  }

  /**
   * 測量view的高度
   */
  private void measureHeight(){
    if (mBounds!=null && mBounds.size()!=0) {
      defaultHeight = (int) (mCircleHeight + mMarginTop + mCircleSelStroke + mBounds.get(0).height()/2);
    } else {
      defaultHeight = (int) (mCircleHeight + mMarginTop+mCircleSelStroke);
    }
  }
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
    //寬高都設(shè)置為wrap_content
    if(widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST){
      //寬設(shè)置為wrap_content
      setMeasuredDimension(widthSpecSize,defaultHeight);
    }else if(widthSpecMode == MeasureSpec.AT_MOST){
      setMeasuredDimension(widthSpecSize,heightSpecSize);
    }else if(heightSpecMode == MeasureSpec.AT_MOST){
      //高設(shè)置為wrap_content
      setMeasuredDimension(widthSpecSize, defaultHeight);
    }else{
      //寬高都設(shè)置為match_parent或具體的dp值
      setMeasuredDimension(widthSpecSize, heightSpecSize);
    }
  }
  @Override
  protected void onDraw(Canvas canvas) {
    //若未設(shè)置節(jié)點標題或者選中項的列表,則取消繪制
    if (textList == null || textList.isEmpty() ||
        selectedIndexSet == null || selectedIndexSet.isEmpty() ||
        mBounds == null || mBounds.isEmpty()) {
      return;
    }
    //畫灰色圓圈的個數(shù)
    circleCount=textList.size();
    //每個圓相隔的距離(重要),可以通過這個調(diào)節(jié)節(jié)點間距
    divideWidth = (getWidth() - mCircleHeight ) / (circleCount - 1);
    //繪制文字和圓形
    for (int i=0; i < circleCount ;i++){
      float cx;
      float cy;
      float textX;
      if (i==0){
        //第一個節(jié)點,圓心需要向右偏移
        cx = mCircleHeight / 2 + i * divideWidth + marginLeft;
        cy = mCircleHeight / 2 + mCircleSelStroke;
        textX = cx;
        circleLineJunctions.add(cx + mCircleHeight / 2);
      }else if (i==textList.size()-1){
        //最后一個節(jié)點,圓心需要向左偏移
        cx = mCircleHeight / 2 + i * divideWidth - marginRight;
        cy = mCircleHeight / 2 + mCircleSelStroke;
        textX = cx;
        circleLineJunctions.add(cx - mCircleHeight / 2);
      }else {
        //中間部分的節(jié)點
        cx = mCircleHeight / 2 + i * divideWidth;
        cy = mCircleHeight / 2+mCircleSelStroke;
        textX = cx;
        circleLineJunctions.add(cx - mCircleHeight / 2);
        circleLineJunctions.add(cx + mCircleHeight / 2);
      }
      if (getSelectedIndexSet().contains(i)){
        //若當前位置節(jié)點被包含在選中項Set中,判定此節(jié)點被選中
        canvas.drawCircle(cx , cy, mCircleHeight / 2, mCircleStrokeSelPaint);
        canvas.drawCircle(cx, cy, mCircleFillRadius, mCircleSelPaint);
        canvas.drawText(textList.get(i), textX, (float) (mCircleHeight + mMarginTop +mCircleSelStroke+mBounds.get(i).height()/2.0), mTextSelPaint);
      }else {
        //若當前位置節(jié)點沒有被包含在選中項Set中,判定此節(jié)點沒有被選中
        canvas.drawCircle(cx , cy, mCircleHeight / 2, mCirclePaint);
        canvas.drawText(textList.get(i), textX, (float) (mCircleHeight + mMarginTop +mCircleSelStroke+mBounds.get(i).height()/2.0), mTextPaint);
      }
    }
    for(int i = 1 , j = 1 ; j <= circleLineJunctions.size() && ! circleLineJunctions.isEmpty() ; ++i , j=j+2){
      if(getSelectedIndexSet().contains(i)){
        canvas.drawLine(circleLineJunctions.get(j-1),mCircleHeight/2+mCircleSelStroke,
            circleLineJunctions.get(j) ,mCircleHeight/2+mCircleSelStroke,mLineSelectedPaint);
      }else {
        canvas.drawLine(circleLineJunctions.get(j-1),mCircleHeight/2+mCircleSelStroke,
            circleLineJunctions.get(j) ,mCircleHeight/2+mCircleSelStroke,mLinePaint);
      }
    }
  }
  /**
   * 供外部調(diào)用,顯示控件
   * @param titles 底部標題內(nèi)容列表
   * @param indexSet 選中項Set
   */
  public void show(List<String> titles , Set<Integer> indexSet){
    if(titles != null && ! titles.isEmpty()){
      this.textList = titles;
    }
    if(indexSet != null && ! indexSet.isEmpty()){
      this.selectedIndexSet = indexSet;
    }
    measureText();
    measureHeight();
    //繪制
    invalidate();
  }
  /**
   * 更新底部節(jié)點標題內(nèi)容
   * @param textList 節(jié)點標題內(nèi)容列表
   */
  public void refreshTextList(List<String> textList) {
    this.textList = textList;
    measureText();
    measureHeight();
    invalidate();
  }
  /**
   * 獲取節(jié)點選中狀態(tài)
   * @return 節(jié)點選中狀態(tài)列表
   */
  public Set<Integer> getSelectedIndexSet() {
    return selectedIndexSet;
  }
  /**
   * 更新選中項
   * @param set 選中項Set
   */
  public void refreshSelectedIndexSet(Set<Integer> set) {
    this.selectedIndexSet = set;
    invalidate();
  }
}

注意點

  • 控件的節(jié)點總個數(shù)是與傳入的節(jié)點底部標題列表中元素個數(shù)控制(相同)的,簡而言之就是傳入的標題列表中有多少個標題,節(jié)點就會繪制多少個
  • 控件通過show方法進行View的初始化和顯示內(nèi)容,傳入節(jié)點標題列表和節(jié)點選中項集合,控制View的選中狀態(tài)和顯示的內(nèi)容
  • 控件初始化顯示后,可以通過refreshTextList(),refreshSelectedIndexSet() 更新標題和選中項
  • 具體不同的顏色,大小可以具體在View中調(diào)整

總結(jié)

可以看到效果不復雜,因此自定義View的代碼行數(shù)不多,也很容易看懂,直接拿走代碼即可在項目中食用啦。

由于不同項目設(shè)計稿會有不同,這里也僅僅給有需要的同學一個思路,可以改造具體實現(xiàn)代碼~

到此這篇關(guān)于Android 自定義View實現(xiàn)多節(jié)點進度條功能的文章就介紹到這了,更多相關(guān)android 自定義view 進度條內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論