圆形seekbar,音量旋钮

在做一个音频的项目,想在网上找一个圆形aseekbar,但是一直没找到合适的,只好自己动手写了,上网找了一个demo进行了大修改效果如下




源码

package com.jian.View;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;

import com.example.jian.bluetooth.R;

public class DutyViewThumb extends View {
   
   int width;
   int height;
   
   private boolean selectState = false;
   
   public void setSelected(boolean state)
   {
      if(selectState != state)
      {
         selectState = state;
         postInvalidate();
      }
   }
      
   public boolean isSelected()
   {
      return selectState;
   }
   
   public DutyViewThumb(Context context, AttributeSet attrs) {
      super(context, attrs);
      // TODO Auto-generated constructor stub
      
      try {
         thumbUp = BitmapFactory.decodeResource(getResources(), R.drawable.thumb_up);
         upSrc.set(0, 0, thumbUp.getWidth(), thumbUp.getHeight());        
         
         thumbDn = BitmapFactory.decodeResource(getResources(), R.drawable.thumb_dn);
         dnSrc.set(0,0,thumbDn.getWidth(),thumbDn.getHeight()); 
      } catch (Exception e) {
         // TODO: handle exception
         e.printStackTrace();
      }
      /*
      setOnTouchListener(new OnTouchListener() {
         
         @Override
         public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
      
               if(selectState == false)
               {
                  selectState = true;
                  invalidate();
                  Log.i("userLog", "onSelected");
               }
               return true;
   

            default:
               break;
            }
            return false;
         }
      });       */
      
   }

   
   private Bitmap thumbUp;
   private Bitmap thumbDn;
   private Rect upSrc = new Rect();
   private Rect dnSrc = new Rect();
   
   private Rect dstRect = new Rect();
   
   @Override
   protected void onDraw(Canvas canvas) {
      // TODO Auto-generated method stub
      
      try {
         if(isSelected())
         {
            canvas.drawBitmap(thumbDn, dnSrc, dstRect, null);
         }
         else {
            canvas.drawBitmap(thumbUp, upSrc, dstRect, null);
         }
         
      } catch (Exception e) {
         // TODO: handle exception
         e.printStackTrace();
      }
      
      
   }
   
   @Override
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      // TODO Auto-generated method stub
      
      if(MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY)
      {
         width = MeasureSpec.getSize(widthMeasureSpec);
      }
      else {
         width = DensityUtils.dp2px(getContext(), 40);
      }
      height = width;
      
      setMeasuredDimension(width, height);
      
      dstRect.set(width/4, height/4, width*3/4, height*3/4);
   }
}


package com.jian.View;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;

import com.example.jian.bluetooth.R;

public class DutyView extends ViewGroup implements OnTouchListener{
   
   
   int width;
   int height;    

   /**
    * duty最大值
    */
   public static final int MAX_DUTY = 100;
   
   public int getMaxDuty()
   {
      return MAX_DUTY;
   }
   /**
    * duty当前值
    */
   private int duty;
   
   public int getDuty() {
      return duty;
   }
   
   public void setDuty(int value)
   {
      if(value >= 0 && value <= MAX_DUTY)
      {
         duty = value;
         postInvalidate();
      }
   }
   
   /**
    * 文本大小
    */
   private float textSize;    
   
   public float getTextSize() {
      return textSize;
   }

   public void setTextSize(float textSize) {
      this.textSize = textSize;
   }

   /**
    * 文本颜色
    */
   public static final int DEFAULT_TEXT_COLOR = 0xff326ee9;
   
   private int textColor = DEFAULT_TEXT_COLOR;
   
   public void setTextColor(int color)
   {
      this.textColor = color;
      postInvalidate();
   }
   
   public int getTextColor()
   {
      return this.textColor;
   }
   
   
   /**
    * 圆弧颜色
    */
   public static final int DEFAULT_PROGRESS_BG_COLOR = 0xffffffff;
   
   private int progressBgColor = DEFAULT_PROGRESS_BG_COLOR;
   
   public int getProgressBgColor() {
      return progressBgColor;
   }

   public void setProgressBgColo(int arcColor) {
      this.progressBgColor = arcColor;
      postInvalidate();
   }
   
   public static final int DEFAULT_PROGRESS_COLOR = 0xffff4e00;
   
   private int ProgressColor = DEFAULT_PROGRESS_COLOR;
   
   public int getProgressColor()
   {
      return ProgressColor;
   }
   
   public void setProgressColor(int value)
   {
      this.ProgressColor = value;
      postInvalidate();
   }
   
   /**
    * 圆弧尺寸
    */
   private float arcWidth;
   /**
    * 抗锯齿
    */
   private PaintFlagsDrawFilter pfd;

   public float getArcWidth() {
      return arcWidth;
   }

   public void setArcWidth(float arcWidth) {
      this.arcWidth = arcWidth;
   }
   public void setRotatDrawableResource(int id) {

      BitmapDrawable drawable = (BitmapDrawable)getContext().getResources().getDrawable(id);

      setRotatDrawable(drawable);
   }

   public void setRotatDrawable(BitmapDrawable drawable) {

      thumbUp =  drawable.getBitmap();
      upSrc.set(0, 0, thumbUp.getWidth(), thumbUp.getHeight());

      postInvalidate();
   }

   public DutyView(Context context, AttributeSet attrs) {
      super(context, attrs);
      // TODO Auto-generated constructor stub
      TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.DutyView);
      pfd = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);
      duty = array.getInteger(R.styleable.DutyView_initDuty, 0);
      textColor = array.getColor(R.styleable.DutyView_textColor, DEFAULT_TEXT_COLOR);
      textSize = array.getDimension(R.styleable.DutyView_textSize, DensityUtils.sp2px(context, 18));
      progressBgColor = array.getColor(R.styleable.DutyView_progressBgColor, DEFAULT_PROGRESS_BG_COLOR);
      ProgressColor = array.getColor(R.styleable.DutyView_progressColor, DEFAULT_PROGRESS_COLOR);
      arcWidth = array.getDimension(R.styleable.DutyView_arcWidth, DensityUtils.dp2px(context, 5));
      array.recycle();
      arcPaint = new Paint();
      arcPaint.setColor(progressBgColor);
      arcPaint.setAntiAlias(true);
      arcPaint.setStyle(Style.STROKE);
      arcPaint.setStrokeWidth(arcWidth);
      textPaint = new Paint();
      textPaint.setColor(textColor);
      textPaint.setTextSize(textSize);
      textPaint.setAntiAlias(true);
      setOnTouchListener(this);
      this.setBackgroundColor(0x00ffffff);
      try {

         bgPaint = new Paint();
         bgPaint.setColor(Color.GRAY);
         bgPaint.setStrokeWidth(6);
      } catch (Exception e) {
         // TODO: handle exception
         e.printStackTrace();
      }
   }
   Paint arcPaint = null;
   RectF arcRectF = new RectF();
   Paint bgPaint = null;
   Canvas bgcanvas;

   Paint textPaint = null;
   private void drawText(Canvas canvas)
   {
      String text = String.valueOf((int)duty);
      
      float length = textPaint.measureText(text);
      float x = width/2-length/2;
      float y = height/2+length/4;
      canvas.drawText(text, x, y, textPaint);
   }
   private Bitmap thumbUp;
   private Bitmap thumbDn;
   private Rect upSrc = new Rect();
   private Rect dnSrc = new Rect();
   private Rect dstRect = new Rect();
   //DutyViewProgress progressView;
   DutyViewThumb thumbView;
   int thumbWidth;
   int thumbHeight;
   @Override
   protected void onDraw(Canvas canvas) {
      // TODO Auto-generated method stub
      //抗锯齿
      canvas.setDrawFilter(pfd);
      canvas.drawBitmap(thumbUp, upSrc, dstRect, null);
      drawProgressBar(canvas);
      drawText(canvas);
      drawgraduation(canvas);
      super.onDraw(canvas);     
      
   }
   private int lineHeight = 20;
   private void drawProgressBar(Canvas canvas) {
      // TODO Auto-generated method stub
//    arcPaint.setColor(progressBgColor);
//    canvas.drawArc(arcRectF, 135, 270, false, arcPaint);
//    arcPaint.setColor(ProgressColor);
//    canvas.drawArc(arcRectF, 135, 270*duty/MAX_DUTY, false, arcPaint);
   }
   private int countGraduation = 20;//刻度数
   private void drawgraduation(Canvas canvas) {canvas.save();
      float degrees = (float) (270.0/countGraduation);
      float Graduation = ((float)duty*21/MAX_DUTY);
      Log.i("jian","duty"+duty+"max"+MAX_DUTY);
      int pointX =  width/2;
      int pointY = height/2;
      canvas.save();
      canvas.translate(0,pointY);
      canvas.rotate(-45, pointX, 0);
      for(int i = 0;i<countGraduation+1;i++){
         if(i<Graduation||duty == MAX_DUTY){
            bgPaint.setColor(Color.BLUE);
         }else{
            bgPaint.setColor(Color.GRAY);
         }
         if(i==0||i==countGraduation) {
            canvas.drawLine(0, 0, lineHeight, 0, bgPaint);
         }else{
            canvas.drawCircle(8,8,10,bgPaint);
         }
         canvas.rotate(degrees, pointX, 0);
      }
      canvas.restore();
//    for(int i= 0;i<)
//    canvas.drawLine();
   }
   @Override
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      // TODO Auto-generated method stub
      measureChildren(widthMeasureSpec, heightMeasureSpec);
      width = MeasureSpec.getSize(widthMeasureSpec);
      height = MeasureSpec.getSize(heightMeasureSpec);
      setMeasuredDimension(width, height);
      if(thumbView == null)
      {
         thumbView = (DutyViewThumb) getChildAt(0);
         thumbWidth = thumbView.getMeasuredWidth()/2;
         thumbHeight = thumbView.getMeasuredHeight()/2;
      }
      arcRectF.set(thumbWidth, thumbWidth, width-thumbWidth,height-thumbWidth);
      dstRect.set(40, 40, width-40, height-40);
      invaliArea.set(width/3, height/2, width*2/3, height);
   }
   RectF thumbRect = new RectF();
   
   
   @Override
   protected void onLayout(boolean changed, int l, int t, int r, int b) {
      // TODO Auto-generated method stub
      try {
         if(thumbView == null)
         {
            thumbView = (DutyViewThumb) getChildAt(0);
            thumbWidth = thumbView.getMeasuredWidth()/2;
            thumbHeight = thumbView.getMeasuredHeight()/2;
         }
         calculateThumbPosition();
         thumbView.layout((int)thumbRect.left,
                              (int)thumbRect.top, 
                              (int)thumbRect.right, 
                              (int)thumbRect.bottom);
      } catch (Exception e) {
         // TODO: handle exception
         e.printStackTrace();
      }           
   }
   
   /**
    * 输入坐标,求出对应象限
    * @param x
    * @param y
    * @return
    */
   private static int getQuadrant(double x, double y) {
      if (x >= 0) {
         return y >= 0 ? 1 : 4;
      } else {
         return y >= 0 ? 2 : 3;
      }
   }
   
   /**
    * 获取指定坐标对应的角度
    * @param xTouch
    * @param yTouch
    * @return
    */
   double angle;
   double changeAngle;
   private double getAngle(double xTouch, double yTouch) {
      double x = xTouch - (width / 2d);
      double y = height - yTouch - (height / 2d);
      double a;
      switch (getQuadrant(x, y)) {
         case 1:
            return Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;

         case 2:
         case 3:
            return 180 - (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);

         case 4:
            return 360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;

         default:
            // ignore, does not happen
            return 0;
      }
//    switch (getQuadrant(x, y)) {
//    case 1:
//       a = 180 - (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
//       break;
//       case 2:
//    case 4:
//       a =  360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
//       break;
//    default:
//       // ignore, does not happen
//       a =  0;
//       break;
//    }
//
//    changeAngle = a-angle;
//    angle = a;
//
//    return angle;
   }
   private final float angleRate = MAX_DUTY/270f;
   /**
    * 角度对应的百分比
    * @param angle
    * @return
    */
   private int angle2pesent(double angle)
   {
      //无效角度
      if(angle < 300 && angle > 240)
         return -1;
      
      if(angle > 225)
         angle-=360;
      
      return (int) (Math.abs(angle-225)*angleRate);
   }
   
   /**
    * 根据当前的duty值计算thumb的位置
    */
   private void calculateThumbPosition()
   {
      double angle = duty/angleRate;    
      angle += 135;
      if(angle > 360)
         angle-=360;
      float xPoint = (float) (width/2+(width/2-thumbWidth*2)*Math.cos(Math.toRadians(angle)));//修改这里可修改thumb的位置
      float yPoint = (float) (height/2+(height/2-thumbHeight*2)*Math.sin(Math.toRadians(angle)));
      thumbRect.left = xPoint-thumbWidth;
      thumbRect.top = yPoint-thumbHeight;
      thumbRect.right = xPoint+thumbWidth;
      thumbRect.bottom = yPoint+thumbHeight;
      
   }
   
   //触摸的无效区域
   RectF invaliArea = new RectF();
   float last_x;
   float last_y;
   @Override
   public boolean onTouch(View v, MotionEvent event) {
      // TODO Auto-generated method stub
      
      float x = event.getX();
      float y = event.getY();    
      
      //触摸无效区域禁止横向滑动
      if(invaliArea.contains(x, y))
      {        
         if(thumbView.isSelected())
         {
            thumbView.setSelected(false);
            if(listener != null)
               listener.onDutyChanged(duty);
         }        
         Log.i("userLog", "无效区域");
         return true;
      }
      
      switch (event.getAction()) 
      {

      case MotionEvent.ACTION_DOWN:
         Log.i("userLog", "action down");
         if(thumbView.isSelected())
         {
            /*thumbView.setSelected(false);
            if(listener != null)
            {
               listener.onDutyChanged(duty);
            }  */       
         }
         else {
            //是否点击滑动块
            if(thumbRect.contains((int)x, (int)y))
            {
               thumbView.setSelected(true);
               last_x = x;
               last_y = y;
               Log.i("userLog", "点击滑块");
            }
            
         }
         break;
                     
      case MotionEvent.ACTION_MOVE:              

         if(thumbView.isSelected())
         {
            Log.i("userLog", "滑动");
            //触摸不连续,防止多点触控
            if(Math.abs(x-last_x) > 150 || Math.abs(y-last_y) > 150)
            {
               Log.i("userLog", "滑动不连续");
               thumbView.setSelected(false);
               if(listener != null)
               {
                  listener.onDutyChanged(duty);
               }
               return true;
            }
            
            //计算角度和百分比
            double angle = getAngle(x, y);          
            int _duty = angle2pesent(angle);
            
            if(_duty != -1)
            {
               setDuty(_duty);                
            }
            else {
               if(duty < 10)
               {
                  setDuty(0);
               }
               else if(duty > 90)
               {
                  setDuty(100);
               }
               
               
               thumbView.setSelected(false);
               if(listener != null)
               {
                  listener.onDutyChanged(duty);
               }
            }
            
            last_x = x;
            last_y = y;
            calculateThumbPosition();
            thumbView.layout((int)thumbRect.left,
                                 (int)thumbRect.top, 
                                 (int)thumbRect.right, 
                                 (int)thumbRect.bottom);
         }
         break;
         
      case MotionEvent.ACTION_UP:    
         Log.i("userLog", "action up");
         if(thumbView.isSelected())
         {
            thumbView.setSelected(false);  
            if(listener != null)
            {
               listener.onDutyChanged(duty);
            }
         }
         break;

      default:
         break;
      }
      return true;
   }
   public interface onDutyChangedListener
   {
      void onDutyChanged(int currentDuty);      
   }
   
   onDutyChangedListener listener = null;
   
   public void setOnDutyChangedListener(onDutyChangedListener listener)
   {
      this.listener = listener;
   }
   

}

attr中

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="DutyView">


    <attr name="viewType">

    <enum name="progress" value="0"/>

    <enum name="thumb" value="1"/>

</attr>
    <attr name="initDuty" format="integer"/>
    <attr name="progressBgColor" format="color"/>

    <attr name="progressColor" format="color"/>

    <attr name="arcWidth" format="dimension"/>

    <attr name="textColor" format="color"/>

    <attr name="textSize" format="dimension"/>

</declare-styleable>
</resources>
布局中

<com.jian.View.DutyView
    android:id="@+id/dutyView"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:layout_centerInParent="true"
    DutyView:arcWidth="6dp"
    DutyView:initDuty="33"

    DutyView:progressBgColor="@android:color/darker_gray"
    DutyView:textSize="32sp">

    <com.jian.View.DutyViewThumb
        android:layout_marginLeft="10dp"
        android:layout_width="30dp"
        android:layout_height="30dp" />

</com.jian.View.DutyView>

在activity中


DutyView dutyView=(DutyView)v.findViewById(R.id.dutyView);
dutyView.setRotatDrawableResource(R.mipmap.cilcle);

r.mipmap.cicle为旋钮图片


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
好的,以下是使用SeekBar控制Android手机音量的一般步骤: 1. 在布局文件中添加SeekBar 在布局文件中添加SeekBar组件,例如: ``` <SeekBar android:id="@+id/seekBar" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="100" android:progress="50" /> ``` 其中,max属性表示SeekBar的最大值,progress属性表示SeekBar的初始值。 2. 在Activity中获取SeekBar对象 在Activity中获取SeekBar对象,例如: ``` SeekBar seekBar = findViewById(R.id.seekBar); ``` 3. 获取AudioManager对象 获取AudioManager对象,例如: ``` AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); ``` 4. 监听SeekBar变化 使用seekBar.setOnSeekBarChangeListener()方法监听SeekBar变化,并在onProgressChanged()方法中设置音量,例如: ``` seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, progress, 0); } @Override public void onStartTrackingTouch(SeekBar seekBar) {} @Override public void onStopTrackingTouch(SeekBar seekBar) {} }); ``` 其中,setStreamVolume()方法的第一个参数表示要设置的音频流的类型,第二个参数表示要设置的音量大小,第三个参数表示是否显示系统音量控制UI。 希望这些信息可以帮助您实现使用SeekBar控制Android手机音量的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值