Android自定義可控制精度帶刻度盤和波紋效果的炫酷SeekBar

一、前言

最近項(xiàng)目里面需要用到多個(gè)seekbar并且需要顯示不同的精度,于是參考了部分博客模仿華為的天氣刻度盤添加了精度控制和自己定義的seekbar實(shí)現(xiàn)了如下效果(畫面模糊是因?yàn)殇浿艷if圖的工具導(dǎo)致的)。

本控件最低兼容到API16 更低的版本沒有g(shù)etThumb()函數(shù)

二、刻度盤部分

  • 1.刻度:刻度的繪制類似于繪制時(shí)鐘刻度繪制出一條刻度通過旋轉(zhuǎn)canvas繪制出其他刻度

  • 2.波浪:波浪的繪制是通過兩個(gè)正弦函數(shù)y = Asin(wx+b)+h 實(shí)時(shí)變換sin的初相

  • 3.精度控制:通過設(shè)定 精度模式,最大進(jìn)度值和顯示的最大值共同決定。最大進(jìn)度值/當(dāng)前進(jìn)度值=實(shí)際顯示的最大值/當(dāng)前顯示的值

  • 4.WaveDialView代碼:

      package com.hubin.scaleseekbar;
      /*
       *  @項(xiàng)目名:  ScaleSeekBar
       *  @包名:    com.hubin.scaleseekbar
       *  @文件名:   DigitalThumbSeekbar
       *  @創(chuàng)建者:   胡英姿
       *  @創(chuàng)建時(shí)間:  2018-03-10 14:38
       *  @描述:    一個(gè)帶水波紋的刻度盤自定義view
       */
      
      import android.content.Context;
      import android.graphics.Canvas;
      import android.graphics.Color;
      import android.graphics.Paint;
      import android.graphics.Path;
      import android.graphics.RectF;
      import android.util.AttributeSet;
      import android.view.View;
      
      import java.text.DecimalFormat;
      import java.util.Timer;
      import java.util.TimerTask;
      
      public class WaveDialView extends View {
          private static final String TAG = "ScaleView";
      
          public static final int PRECISION_MODE_INTEGER =0; //整數(shù)模式
          public static final int PRECISION_MODE_ONE_DECIMAL_PLACES =1; //精確到小數(shù)點(diǎn)后一位
          public static final int PRECISION_MODE_TWO_DECIMAL_PLACES =2;//精確到小數(shù)點(diǎn)后兩位
          public  int PRECISION_MODE_DEFUALE =PRECISION_MODE_INTEGER;//默認(rèn)精度模式  整數(shù)模式
      
          private float mMaxValue = 100; //顯示的最大值
      
          private String textUnit = ""; //右上角文字 單位
          private String textName = "";//中間要顯示的文字名字
      
          // 畫圓弧的畫筆
          private Paint paint;
          // 正方形的寬高
          private int len;
          // 圓弧的半徑
          private float radius;
          // 矩形
          private RectF oval;
          // 圓弧的起始角度
          private float startAngle = 120;
          // 圓弧的經(jīng)過總范圍角度角度
          private float sweepAngle = 300;
      
          // 刻度經(jīng)過角度范圍
          private float targetAngle = 300;
      
          // 繪制文字
          Paint textPaint;
      
          // 監(jiān)聽角度變化對(duì)應(yīng)的顏色變化
          private OnAngleColorListener onAngleColorListener;
      
          public WaveDialView(Context context) {
              this(context,null);
          }
      
          public WaveDialView(Context context, AttributeSet attrs) {
              super(context, attrs);
              paint = new Paint();
              paint.setColor(Color.WHITE);
              paint.setAntiAlias(true);
              paint.setStyle(Paint.Style.STROKE);
      
              textPaint = new Paint();
              textPaint.setARGB(255, 255, 255, 255);
              textPaint.setAntiAlias(true);
      
              waterPaint = new Paint();
              waterPaint.setAntiAlias(true);
      
              moveWaterLine();//讓水波紋開始運(yùn)動(dòng)
          }
      
          /**
           * 設(shè)置動(dòng)畫效果,開啟子線程定時(shí)繪制
           *
           * @param trueAngle
           */
          // 前進(jìn)或者后退的狀態(tài),1代表前進(jìn),2代表后退。初始為后退狀態(tài)。
          int state = 2;
          // 每次后退時(shí)的值,實(shí)現(xiàn)越來越快的效果
          private int[] back = {2, 2, 4, 4, 6, 6, 8, 8, 10};
          // 每次前進(jìn)時(shí)的值,實(shí)現(xiàn)越來越慢的效果
          private int[] go = {10, 10, 8, 8, 6, 6, 4, 4, 2};
          // 前進(jìn)的下標(biāo)
          private int go_index = 0;
          // 后退的下標(biāo)
          private int back_index = 0;
          private float score;
          private int color;
      
          private boolean isRunning;
      
          /**
           * 使用定時(shí)器自動(dòng)開始變幻刻度
           *
           * @param trueAngle
           */
          public void change(final float trueAngle) {
              if (isRunning) {
                  return;
              }
              final Timer timer = new Timer();
              timer.schedule(new TimerTask() {
      
                  @Override
                  public void run() {
                      switch (state) {
                          case 1:
                              // 開始增加
                              targetAngle += go[go_index];
                              go_index++;
                              if (go_index == go.length) {// 到最后的元素時(shí),下標(biāo)一直為最后的
                                  go_index--;
                              }
                              if (targetAngle >= trueAngle) {// 如果畫過刻度大于等于真實(shí)角度
                                  // 畫過刻度=真實(shí)角度
                                  targetAngle = trueAngle;
                                  // 狀態(tài)改為2
                                  state = 2;
                                  isRunning = false;
                                  timer.cancel();
                              }
                              break;
                          case 2:
                              isRunning = true;
                              targetAngle -= back[back_index];
                              back_index++;
                              if (back_index == back.length) {
                                  back_index--;
                              }
      
                              if (targetAngle <= 0) {
                                  targetAngle = 0;
                                  state = 1;
                              }
                              break;
                          default:
                              break;
                      }
                      computerScore();// 計(jì)算當(dāng)前比例應(yīng)該的多少分
                      // 計(jì)算出當(dāng)前所占比例,應(yīng)該增長(zhǎng)多少
                      computerUp();
      
                      postInvalidate();
                  }
              }, 500, 30);
          }
      
          /**
           * 手動(dòng)設(shè)置刻度盤的值
           * @param trueAngle  0-300
           */
          public void setChange(final float trueAngle) {
              targetAngle = trueAngle;
              computerScore();//計(jì)算得分
      
              if (clipRadius == 0) {
                  final Timer timer = new Timer();
                  timer.schedule(new TimerTask() {
                      @Override
                      public void run() {
                          if (clipRadius != 0) {
                              // 計(jì)算出當(dāng)前所占比例,應(yīng)該增長(zhǎng)多少
                              computerUp();
                              postInvalidate();
                              timer.cancel();
                          }
                      }
                  }, 0, 10);
              } else {
                  computerUp();
                  invalidate();
              }
          }
      
      
          //計(jì)算當(dāng)前比例應(yīng)該得多少分
          private void computerScore() {
              score = targetAngle / 300 * mMaxValue;
          }
      
          //計(jì)算水位
          private void computerUp() {
              up = (int) (targetAngle / 360 * clipRadius * 2);
          }
      
          /**
           * 調(diào)用此方法水波紋開始運(yùn)動(dòng)
           */
          public void moveWaterLine() {
              final Timer timer = new Timer();
              timer.schedule(new TimerTask() {
      
                  @Override
                  public void run() {
                      move += 1;
                      if (move == 100) {
                          timer.cancel();
                      }
                      postInvalidate();
                  }
              }, 500, 200);
          }
      
          // 存放第一條水波Y值
          private float[] firstWaterLine;
          // 第二條
          private float[] secondWaterLine;
          // 畫水球的畫筆
          private Paint waterPaint;
          // 影響三角函數(shù)的初相
          private float move;
          // 剪切圓的半徑
          private int clipRadius;
          // 水球的增長(zhǎng)值
          int up = 0;
      
          @Override
          protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
              super.onMeasure(widthMeasureSpec, heightMeasureSpec);
      
              // 通過測(cè)量規(guī)則獲得寬和高
              int width = MeasureSpec.getSize(widthMeasureSpec);
              int height = MeasureSpec.getSize(heightMeasureSpec);
              // 取出最小值
              len = Math.min(width, height);
              oval = new RectF(0, 0, len, len);
              radius = len / 2;
              clipRadius = (len / 2) - 45;
              firstWaterLine = new float[len];
              secondWaterLine = new float[len];
              setMeasuredDimension(len, len);
          }
      
          @Override
          protected void onDraw(Canvas canvas) {
              // 繪制一個(gè)圓弧,如果懂得坐標(biāo)系的旋轉(zhuǎn),可以不寫。
              // canvas.drawArc(oval, startAngle, sweepAngle, false, paint);
              // 畫布,圓心左邊,半徑,起始角度,經(jīng)過角度,
              // 說白了就是canvas沒有提供畫特殊圖形的方法,就需要我們自己去實(shí)現(xiàn)這種功能了
              // 畫刻度線
              drawLine(canvas);
              // 畫刻度線內(nèi)的內(nèi)容
              drawText(canvas);
      
          }
      
          /**
           * 畫水球的功能
           *
           * @param canvas
           */
          private void drawWaterView(Canvas canvas) {
              // y = Asin(wx+b)+h ,w影響周期,A影響振幅,h影響y位置,b為初相;
              // 將周期定為view總寬度
              float mCycleFactorW = (float) (2 * Math.PI / len);
      
              // 得到第一條波的y值
              for (int i = 0; i < len; i++) {
                  firstWaterLine[i] = (float) (10 * Math
                          .sin(mCycleFactorW * i + move) - up);
              }
              // 得到第一條波的y值
              for (int i = 0; i < len; i++) {
                  secondWaterLine[i] = (float) (15 * Math.sin(mCycleFactorW * i
                          + move + 10) - up);
      
              }
      
              canvas.save();
      
              // 裁剪成圓形區(qū)域
              Path path = new Path();
              waterPaint.setColor(color);
              path.reset();
              canvas.clipPath(path);
      
              path.addCircle(len / 2, len / 2, clipRadius, Path.Direction.CCW);
              canvas.clipPath(path, android.graphics.Region.Op.REPLACE);
              // 將坐標(biāo)系移到底部
              canvas.translate(0, len / 2 + clipRadius);
      
              for (int i = 0; i < len; i++) {
                  canvas.drawLine(i, firstWaterLine[i], i, len, waterPaint);
              }
              for (int i = 0; i < len; i++) {
                  canvas.drawLine(i, secondWaterLine[i], i, len, waterPaint);
              }
              canvas.restore();
          }
      
          /**
           * 實(shí)現(xiàn)畫刻度線內(nèi)的內(nèi)容
           *
           * @param canvas
           */
          private void drawText(Canvas canvas) {
              Paint cPaint = new Paint();
              // cPaint.setARGB(50, 236, 241, 243);
              cPaint.setAlpha(50);
              cPaint.setARGB(50, 236, 241, 243);
              // 畫圓形背景
              RectF smalloval = new RectF(40, 40, radius * 2 - 40, radius * 2 - 40);
              // 畫水波
              drawWaterView(canvas);
              canvas.drawArc(smalloval, 0, 360, true, cPaint);
              // 在小圓圈的外圍畫一個(gè)白色圈
              canvas.drawArc(smalloval, 0, 360, false, paint);
              // 設(shè)置文本對(duì)齊方式,居中對(duì)齊
              textPaint.setTextAlign(Paint.Align.CENTER);
              textPaint.setTextSize(clipRadius / 2);
              // 畫分?jǐn)?shù)
              switch (PRECISION_MODE_DEFUALE) {
                  case PRECISION_MODE_ONE_DECIMAL_PLACES://小數(shù)點(diǎn)后一位
                      float  f1Score   =  (float)(Math.round(score*10))/10;
                      canvas.drawText("" + f1Score, radius, radius, textPaint);
                      break;
                  case PRECISION_MODE_TWO_DECIMAL_PLACES://小數(shù)點(diǎn)后兩位
                      DecimalFormat   fnum  =   new DecimalFormat("##0.00");
                      String   f2Score=fnum.format(score);
                      canvas.drawText( f2Score, radius, radius, textPaint);
                      break;
                  default://默認(rèn) 整數(shù)模式
                      canvas.drawText("" + (int)score, radius, radius, textPaint);
                      break;
              }
      
              textPaint.setTextSize(clipRadius / 6);
      
              // 畫固定值分
              canvas.drawText(textUnit, radius + clipRadius / 2, radius - clipRadius / 4, textPaint);
              textPaint.setTextSize(clipRadius / 6);
              // 畫固定值立即優(yōu)化
              canvas.drawText(textName, radius, radius + clipRadius / 2, textPaint);
      
          }
      
      
          float a = sweepAngle / 100;
          private Paint linePaint;
      
          /**
           * 實(shí)現(xiàn)畫刻度線的功能
           *
           * @param canvas
           */
          private void drawLine(final Canvas canvas) {
              // 保存之前的畫布狀態(tài)
              canvas.save();
              // 移動(dòng)畫布,實(shí)際上是改變坐標(biāo)系的位置
              canvas.translate(radius, radius);
              // 旋轉(zhuǎn)坐標(biāo)系,需要確定旋轉(zhuǎn)角度
              canvas.rotate(30);
              // 初始化畫筆
              linePaint = new Paint();
              // 設(shè)置畫筆的寬度(線的粗細(xì))
              linePaint.setStrokeWidth(2);
              // 設(shè)置抗鋸齒
              linePaint.setAntiAlias(true);
              // 累計(jì)疊加的角度
              float c = 0;
              for (int i = 0; i <= 100; i++) {
      
                  if (c <= targetAngle && targetAngle != 0) {// 如果累計(jì)畫過的角度,小于當(dāng)前有效刻度
                      // 計(jì)算累計(jì)劃過的刻度百分比(畫過的刻度比上中共進(jìn)過的刻度)
                      double p = c / (double) sweepAngle;
      
                      int red = 255 - (int) (p * 255);
                      int green = (int) (p * 255);
                      color = linePaint.getColor();
                      if (onAngleColorListener != null) {
                          onAngleColorListener.onAngleColorListener(red, green);
                      }
                      linePaint.setARGB(255, red, green, 50);
                      canvas.drawLine(0, radius, 0, radius - 20, linePaint);
                      // 畫過的角度進(jìn)行疊加
                      c += a;
                  } else {
                      linePaint.setColor(Color.WHITE);
                      canvas.drawLine(0, radius, 0, radius - 20, linePaint);
                  }
      
                  canvas.rotate(a);
              }
              // 恢復(fù)畫布狀態(tài)。
              canvas.restore();
          }
      
      
          public void setOnAngleColorListener(
                  OnAngleColorListener onAngleColorListener) {
              this.onAngleColorListener = onAngleColorListener;
          }
      
          /**
           * 默認(rèn)初始化配置  精度模式為整數(shù) 最大值為100
           * @param textName  水球中間顯示的名字
           * @param textUnit  右上角的單位
           */
          public  void setInitConfig(String textName,String textUnit) {
              this.textName = textName;
              this.textUnit = textUnit;
          }
      
          /**
           * 默認(rèn)初始化配置  精度模式為整數(shù)
           * @param maxValue  最大值
           * @param textName  水球中間顯示的名字
           * @param textUnit  右上角的單位
           */
          public  void setInitConfig(int maxValue,String textName,String textUnit) {
              mMaxValue= maxValue;
              this.textName = textName;
              this.textUnit = textUnit;
          }
          /**
           * 初始化配置
           * @param precisionModeDefuale 精度模式
           * @param maxValue  最大值
           * @param textName  水球中間顯示的名字
           * @param textUnit  右上角的單位
           */
          public  void setInitConfig(int precisionModeDefuale,float maxValue,String textName,String textUnit) {
              PRECISION_MODE_DEFUALE = precisionModeDefuale;
              mMaxValue= maxValue;
              this.textName = textName;
              this.textUnit = textUnit;
          }
      
      
          /**
           * 監(jiān)聽角度和顏色變化的接口
           *
           * @author Administrator
           */
          public interface OnAngleColorListener {
              void onAngleColorListener(int red, int green);
          }
      }
    

三、自定義seekbar

  • 1.thumb(滑塊):通過擴(kuò)展已有的seekbar控件獲取滑塊位置并且通過canvas繪制圖像和進(jìn)度的數(shù)值

  • 2.進(jìn)度線:進(jìn)度線條是一個(gè)圓角的矩形通過滑塊的位置繪制矩形的長(zhǎng)度,滑塊左邊一根右邊一根拼起來

  • 3.尺寸的確定都是基于滑塊而繪制的所以在初始化時(shí)需要先有一個(gè)確定尺寸的滑塊,我是在drawable中定義的一個(gè)只有尺寸的滑塊,這樣做的缺陷在于在XML布局文件中的android:layout_height="" 任何設(shè)置均無效設(shè)置成wrap_content即可,要調(diào)整大小就修改drawable中繪制的滑塊的尺寸

  • 4.精度控制:原理同刻度盤精度控制

  • 5.DigitalThumbSeekbar代碼:

      package com.hubin.scaleseekbar;
      
      /*
       *  @項(xiàng)目名:  ScaleSeekBar 
       *  @包名:    com.hubin.scaleseekbar
       *  @文件名:   DigitalThumbSeekbar
       *  @創(chuàng)建者:   胡英姿
       *  @創(chuàng)建時(shí)間:  2018-03-10 14:38
       *  @描述:    自定義進(jìn)度顯示在thumb上的Seekbar
       */
      
      import android.content.Context;
      import android.content.res.TypedArray;
      import android.graphics.Canvas;
      import android.graphics.Color;
      import android.graphics.Paint;
      import android.graphics.Rect;
      import android.graphics.RectF;
      import android.graphics.drawable.Drawable;
      import android.support.v7.widget.AppCompatSeekBar;
      import android.util.AttributeSet;
      
      import java.text.DecimalFormat;
      
      public class DigitalThumbSeekbar extends AppCompatSeekBar {
      
          private Paint mTextPaint;
          private Paint mLinePaint;
          private RectF mRectF;
          private Paint mCirclePaint;
          private Paint mCirclePaint2;
      
          private Drawable mThumb;
      
      
          private float mMaxShowValue; //需要顯示的最大值
          private int mPrecisionMode;//精度模式
          private int mViewWidth;
          private int mCenterX;
          private int mCenterY;
          private int mThumbHeight;
      
          public DigitalThumbSeekbar(Context context) {
              this(context, null);
          }
      
      
          public DigitalThumbSeekbar(Context context, AttributeSet attrs) {
              this(context, attrs, 0);
          }
      
          public DigitalThumbSeekbar(Context context, AttributeSet attrs, int defStyleAttr) {
              super(context, attrs, defStyleAttr);
      
              TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DigitalThumbSeekbar);
              mMaxShowValue = typedArray.getFloat(R.styleable.DigitalThumbSeekbar_maxShowValue, getMax());//獲取最大顯示值
              mPrecisionMode = typedArray.getInt(R.styleable.DigitalThumbSeekbar_PrecisionMode, 0);//進(jìn)度模式
              typedArray.recycle();//釋放資源
      
              //設(shè)置滑塊樣式
              mThumb = context.getResources().getDrawable(R.drawable.circle_thumb);
              setThumb(mThumb);
              setThumbOffset(0);
              initPaint();//初始化畫筆
          }
      
          private void initPaint() {
              //文字畫筆
              mTextPaint = new Paint();
              mTextPaint.setARGB(255, 255, 255, 255);
              mTextPaint.setAntiAlias(true);
              mTextPaint.setTextSize(mThumb.getMinimumHeight() * 3 / 7);//文字大小為滑塊高度的2/3
              mTextPaint.setTextAlign(Paint.Align.CENTER); // 設(shè)置文本對(duì)齊方式,居中對(duì)齊
      
              //進(jìn)度畫筆
              mLinePaint = new Paint();
              mLinePaint.setAntiAlias(true);
      
              //實(shí)心圓
              mCirclePaint = new Paint();
      //        mCirclePaint.setColor(0xFFFFFFFF);
              mCirclePaint.setARGB(255, 255, 65, 130);
              mCirclePaint.setAntiAlias(true);
              mCirclePaint.setStyle(Paint.Style.FILL_AND_STROKE);
      //        mCirclePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
      
              //空心圓
              mCirclePaint2 = new Paint();
              mCirclePaint2.setARGB(255, 255, 255, 255);
              mCirclePaint2.setAntiAlias(true);
              mCirclePaint2.setStrokeWidth(mThumb.getMinimumHeight() / 20);
              mCirclePaint2.setStyle(Paint.Style.STROKE);
          }
      
          @Override
          protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      
             //父容器傳過來的寬度的值
             mViewWidth = MeasureSpec.getSize(widthMeasureSpec) -getPaddingLeft() - getPaddingRight();
             //根據(jù)滑塊的尺寸確定大小 布局文件中的android:layout_height="" 任何設(shè)置不會(huì)改變繪制的大小
             heightMeasureSpec = MeasureSpec.makeMeasureSpec(mThumb.getMinimumHeight(), MeasureSpec.EXACTLY);
             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
          }
      
          @Override
          protected void onDraw(Canvas canvas) {
              super.onDraw(canvas);
              //獲取滑塊坐標(biāo)
              Rect thumbRect = getThumb().getBounds();
              mCenterX = thumbRect.centerX();//中心X坐標(biāo)
              mCenterY = thumbRect.centerY(); //中心Y坐標(biāo)
              mThumbHeight = thumbRect.height();//滑塊高度
      
              //繪制進(jìn)度條
              drawRect(canvas);
      
              //繪制滑塊
              canvas.drawCircle(mCenterX, mCenterY, mThumbHeight / 2, mCirclePaint);
              canvas.drawCircle(mCenterX, mCenterY, mThumbHeight / 2 - mThumbHeight / 20, mCirclePaint2);//描邊
      
              //繪制進(jìn)度文字
              drawProgress(canvas);
          }
      
          /**
           * 繪制進(jìn)度條
           * @param canvas
           */
          private void drawRect(Canvas canvas) {
              //繪制左邊的進(jìn)度
              mRectF = new RectF();
              mRectF.left = 0;
      //        mRectF.right = thumbRect.left;
              mRectF.right = mCenterX;
              mRectF.top = mCenterY - mThumbHeight / 4;
              mRectF.bottom = mCenterY + mThumbHeight / 4;
              mLinePaint.setColor(Color.GREEN);
              canvas.drawRoundRect(mRectF, mThumbHeight / 4, mThumbHeight / 4, mLinePaint);
      
              //繪制右邊剩余的進(jìn)度
              mRectF.left= mCenterX;
              mRectF.right = mViewWidth;
              mRectF.top = mCenterY - mThumbHeight / 15;
              mRectF.bottom = mCenterY + mThumbHeight / 15;
              mLinePaint.setARGB(255,255,65,130);
              canvas.drawRoundRect(mRectF, mThumbHeight / 15, mThumbHeight /15, mLinePaint);
          }
      
      
          /**
           * 繪制顯示的進(jìn)度文本
           * @param canvas
           */
          private void drawProgress(Canvas canvas) {
              String progress;
              float score = mMaxShowValue*getProgress()/getMax();
              switch (mPrecisionMode) {
                  case 1://小數(shù)點(diǎn)后一位
                      float  f1Score   =  (float)(Math.round(score*10))/10;
                      progress="" + f1Score;
                      break;
                  case 2://小數(shù)點(diǎn)后兩位
                      DecimalFormat fnum  =   new DecimalFormat("##0.00");
                      progress=fnum.format(score);
                      break;
                  default://默認(rèn) 整數(shù)模式
                      progress="" +(int)score;
                      break;
              }
              //測(cè)量文字高度
              Rect bounds = new Rect();
              mTextPaint.getTextBounds(progress, 0, progress.length(), bounds);
              int mTextHeight = bounds.height();//文字高度
      //      float mTextWidth = mTextPaint.measureText(progress);
              canvas.drawText(progress, mCenterX, mCenterY + mTextHeight / 2, mTextPaint);
          }
      
      }
    

四、包裝

刻度盤顯示在PopupWindow中,當(dāng)觸摸Seekbar顯示PopupWindow并且使得sin函數(shù)開始運(yùn)動(dòng),通過進(jìn)度值去控制進(jìn)度盤的指示位置和水的深度以及顏色ARGB值,所以整個(gè)對(duì)刻度盤的控制都包裝在Seekbar 的監(jiān)聽器里面:

    package com.hubin.scaleseekbar;
    
    /*
     *  @項(xiàng)目名:  ScaleSeekBar 
     *  @包名:    com.hubin.scaleseekbar
     *  @文件名:   WaveDialSeekbarListener
     *  @創(chuàng)建者:   胡英姿
     *  @創(chuàng)建時(shí)間:  2018-03-09 16:26
     *  @描述:    一個(gè)將SoftDialView 包裝在里面的seekbar監(jiān)聽器
     */
    
    import android.graphics.Color;
    import android.view.Gravity;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.PopupWindow;
    import android.widget.SeekBar;
    
    import java.lang.ref.WeakReference;
    
    public class WaveDialSeekbarListener implements SeekBar.OnSeekBarChangeListener {
        private static final String TAG = "WaveDialSeekbarListener";
        private WeakReference<MainActivity> mActivityWeakReference;  //activity的弱應(yīng)用
        private WaveDialView mWaveDialView;
        private PopupWindow mPopupWindow;
        private int mMaxProgress; //最大進(jìn)度值
        private float mMaxShowValue; //最大顯示值
        private String textUnit = ""; //右上角文字 單位
        private String textName = "";//中間要顯示的文字名字
    
        private int precisionModeDefuale;//精度模式
        /**
         * 構(gòu)造函數(shù)
         * @param activity activity的引用
         * @param maxProgress seekbar 的最大進(jìn)度值
         * @param maxShowValue 刻度盤上需要顯示的最大值
         * @param textName  中間要顯示的文字名字
         * @param textUnit  右上角文字 單位
         * @param precisionModeDefuale 精度模式  整數(shù),1位小數(shù),2位小數(shù)
         */
        public WaveDialSeekbarListener(MainActivity activity, int maxProgress, float maxShowValue, String textName, String textUnit, int precisionModeDefuale) {
            mActivityWeakReference = new WeakReference(activity);
            mMaxProgress= maxProgress;
            mMaxShowValue = maxShowValue;
            this.textName = textName;
            this.textUnit = textUnit;
            this.precisionModeDefuale = precisionModeDefuale;
        }
    
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
          if (mWaveDialView != null) {
            mWaveDialView.setChange((float) progress*300/mMaxProgress);
            }
        }
    
        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            mWaveDialView = new WaveDialView(mActivityWeakReference.get());
            mWaveDialView.setInitConfig(precisionModeDefuale,mMaxShowValue,textName,textUnit);
            mWaveDialView.moveWaterLine();
            mWaveDialView.setOnAngleColorListener(onAngleColorListener);//顏色監(jiān)聽器 可自行設(shè)置
            //窗口寬度
            int windowWidth = mActivityWeakReference.get().getWindowManager().getDefaultDisplay().getWidth();
    
            mPopupWindow = new PopupWindow(mWaveDialView, windowWidth/2, ViewGroup
                    .LayoutParams.WRAP_CONTENT, true);
            mPopupWindow.showAtLocation(View.inflate(mActivityWeakReference.get(),R.layout.activity_main, null),
                    Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL, 0, 0);    //顯示位置
        }
    
        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            mWaveDialView=null;
            mPopupWindow.dismiss();
        }
    
    
    
        private WaveDialView.OnAngleColorListener onAngleColorListener=new WaveDialView.OnAngleColorListener() {
            @Override
            public void onAngleColorListener(int red, int green) {
                int c=Color.argb(150, red, green, 0);
               mActivityWeakReference.get().setBgColor(c);
            }
        };
    }

五、項(xiàng)目下載(記得Star)

https://github.com/CNHubin/ScaleSeekBar

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,818評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,185評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,656評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,647評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,446評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,951評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,041評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,189評(píng)論 0 287
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,718評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,602評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,800評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,045評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,419評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評(píng)論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,420評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,755評(píng)論 2 371