1.在values建立attrs.xml,寫出你需要的屬性: 2.創建view類並實現所需要的業務,具體看代碼,代碼中寫的很詳細: 3.在xml中引用: 當然,在實際操作中OnTouch事件一般是放在activity或者Fragment裡面的,只需在代碼中複製出去即可 最後十分感謝鴻洋大神,讓我們學 ...
1.在values建立attrs.xml,寫出你需要的屬性:
<?xml version="1.0" encoding="utf-8"?> <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.在xml中引用:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="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