你的位置:首页 > 操作系统

[操作系统]基于鸿洋博客自定于View实现的android音量调节控件


 

1.在values建立attrs.

 

<??><resources>  <attr name="firstColor" format="color" />  <attr name="secondColor" format="color" />  <attr name="circleWidth" format="dimension" />  <attr name="dotCount" format="integer" />  <attr name="splitSize" format="integer" />  <attr name="bg" format="reference" />  <declare-styleable name="CustomVolumControlBar">    <attr name="firstColor" />    <attr name="secondColor" />    <attr name="circleWidth" />    <attr name="dotCount" />    <attr name="splitSize" />    <attr name="bg" />  </declare-styleable></resources>

 

2.创建view类并实现所需要的业务,具体看代码,代码中写的很详细:

 

package com.zzw.Custom.widget;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.graphics.RectF;import android.media.AudioManager;import android.os.Handler;import android.util.AttributeSet;import android.util.Log;import android.util.TypedValue;import android.view.MotionEvent;import android.view.View;import com.zzw.Custom.R;/** * Created by zzw on 2016/6/1. * 描述: */public class CustomVolumControlBar extends View {  /**   * 第一圈的颜色   */  private int mFirstColor;  /**   * 第二圈的颜色   */  private int mSecondColor;  /**   * 圈的宽度   */  private int mCircleWidth;  /**   * 画笔   */  private Paint mPaint;  /**   * 当前进度   */  private int mCurrentCount = 3;  /**   * 中间的图片   */  private Bitmap mImage;  /**   * 每个块块间的间隙   */  private int mSplitSize;  /**   * 个数   */  private int mCount;  /**   * 中间图片界限   */  private Rect mRect;  private AudioManager mAudioManager;  private Handler mHandler = new Handler();  public CustomVolumControlBar(Context context) {    this(context, null);  }  public CustomVolumControlBar(Context context, AttributeSet attrs) {    this(context, attrs, 0);  }  public CustomVolumControlBar(Context context, AttributeSet attrs, int defStyleAttr) {    super(context, attrs, defStyleAttr);    init(context, attrs, defStyleAttr);  }  private void init(Context context, AttributeSet attrs, int defStyleAttr) {    TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomVolumControlBar, defStyleAttr, 0);    int n = a.getIndexCount();    for (int i = 0; i < n; i++) {      int attr = a.getIndex(i);      switch (attr) {        case R.styleable.CustomVolumControlBar_firstColor:          this.mFirstColor = a.getColor(attr, Color.BLACK);          break;        case R.styleable.CustomVolumControlBar_secondColor:          this.mSecondColor = a.getColor(attr, Color.WHITE);          break;        case R.styleable.CustomVolumControlBar_circleWidth:          this.mCircleWidth = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(              TypedValue.COMPLEX_UNIT_PX, 20, getResources().getDisplayMetrics()));          break;        case R.styleable.CustomVolumControlBar_dotCount:          this.mCount = a.getInt(attr, 20);// 默认20          break;        case R.styleable.CustomVolumControlBar_splitSize:          this.mSplitSize = a.getInt(attr, 20);          break;        case R.styleable.CustomVolumControlBar_bg:          this.mImage = BitmapFactory.decodeResource(getResources(), a.getResourceId(attr, 0));          break;      }    }    a.recycle();    mPaint = new Paint();    mRect = new Rect();    if (mAudioManager == null)      mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);    /**     * 获取到最大音量和当前音量     */    mCount = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);    mCurrentCount = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);    Log.e("=====", "mCount:" + mCount + "  mCurrentCount:" + mCurrentCount);  }  @Override  protected void onDraw(Canvas canvas) {    super.onDraw(canvas);    mPaint.setAntiAlias(true);//消除锯齿    mPaint.setStrokeWidth(mCircleWidth);//设置圆圈宽度    mPaint.setStrokeCap(Paint.Cap.ROUND);//定义线段电形状圆头    mPaint.setStyle(Paint.Style.FILL_AND_STROKE);//设置空心    int centre = getWidth() / 2;//得到圆心    int radius = centre - mCircleWidth / 2;//得到半径    drawOval(canvas, centre, radius);    /**     * 计算内切正方形的位置     */    int relRadius = radius - mCircleWidth / 2;// 获得内圆的半径    /**     * 内切正方形的距离顶部 = mCircleWidth + relRadius - √2 / 2     */    mRect.left = (int) (relRadius - Math.sqrt(2) * 1.0f / 2 * relRadius) + mCircleWidth;    /**     * 内切正方形的距离左边 = mCircleWidth + relRadius - √2 / 2     */    mRect.top = (int) (relRadius - Math.sqrt(2) * 1.0f / 2 * relRadius) + mCircleWidth;    mRect.bottom = (int) (mRect.left + Math.sqrt(2) * relRadius);    mRect.right = (int) (mRect.left + Math.sqrt(2) * relRadius);    /**     * 如果图片比较小,那么根据图片的尺寸放置到正中心     */    if (mImage.getWidth() < Math.sqrt(2) * relRadius) {      mRect.left = (int) (mRect.left + Math.sqrt(2) * relRadius * 1.0f / 2 - mImage.getWidth() * 1.0f / 2);      mRect.top = (int) (mRect.top + Math.sqrt(2) * relRadius * 1.0f / 2 - mImage.getHeight() * 1.0f / 2);      mRect.right = (int) (mRect.left + mImage.getWidth());      mRect.bottom = (int) (mRect.top + mImage.getHeight());    }    // 绘图    canvas.drawBitmap(mImage, null, mRect, mPaint);  }  /**   * 画块块去   */  private void drawOval(Canvas canvas, int centre, int radius) {    /**     * 根据需要画的个数以及间隙计算每个块块所占的比例*360     */    float itemSize = (360 * 1.0f - mCount * mSplitSize) / mCount;    /**     * 用于定义的圆弧的形状和大小的界限     */    RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius);    mPaint.setColor(mFirstColor);// 设置圆环的颜色    for (int i = 0; i < mCount; i++) {      canvas.drawArc(oval, i * (itemSize + mSplitSize), itemSize, false, mPaint);// 根据进度画圆弧    }    mPaint.setColor(mSecondColor); // 设置圆环的颜色    for (int i = 0; i < mCurrentCount; i++) {      canvas.drawArc(oval, i * (itemSize + mSplitSize), itemSize, false, mPaint); // 根据进度画圆弧    }  }  /**   * 当前数量+1   */  public synchronized void up() {    mHandler.postDelayed(new Runnable() {      @Override      public void run() {        mCurrentCount++;        if (mCurrentCount > mCount)          mCurrentCount = mCount;        postInvalidate();        setVolume(mCurrentCount);      }    }, 100);  }  /**   * 设置音量   *   * @param index   */  private void setVolume(int index) {    mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 1);  }  /**   * 当前数量-1   */  public synchronized void down() {    mHandler.postDelayed(new Runnable() {      @Override      public void run() {        mCurrentCount--;        if (mCurrentCount < 0)          mCurrentCount = 0;        postInvalidate();        setVolume(mCurrentCount);      }    }, 100);  }  private int lastY, nowY;  @Override  public boolean onTouchEvent(MotionEvent event) {    switch (event.getAction()) {      case MotionEvent.ACTION_DOWN:        lastY = (int) event.getY();        break;      case MotionEvent.ACTION_MOVE:        nowY = (int) event.getY();        int updateYCount = (nowY - lastY) / 30;        if (updateYCount > 0) {          for (int i = 0; i < updateYCount; i++) {            down();          }        } else if (updateYCount < 0) {          for (int i = updateYCount; i < 0; i++) {            up();          }        }        lastY = nowY;        break;    }    return true;  }}

 

3.在

<??><RelativeLayout ="http://schemas.android.com/apk/res/android"  ="http://schemas.android.com/apk/res-auto"  ="http://schemas.android.com/tools"  android:layout_width="match_parent"  android:layout_height="match_parent"  tools:context="com.zzw.Custom.MainActivity">  <com.zzw.Custom.widget.CustomVolumControlBar    android:layout_width="300dp"    android:layout_height="300dp"    android:layout_centerInParent="true"    app:bg="@mipmap/ic_horn"    app:circleWidth="5dp"    app:firstColor="@color/colorPrimary"    app:secondColor="@color/colorAccent"    app:splitSize="10" /></RelativeLayout>

当然,在实际操作中OnTouch事件一般是放在activity或者Fragment里面的,只需在代码中复制出去即可

最后十分感谢鸿洋大神,让我们学到了很多,该篇与鸿洋大神相关的的博客地址:http://blog.csdn.net/lmj623565791/article/details/24529807

 

CustomVolumControlBar