導(dǎo)言
有時候我們需要自定義音量效果忿晕。很顯然這種效果也可以用自定義View。
題外話:
1.不要看到一個有圖片和其他元素組合一起的就是一個自定義ViewGroup
2.假如自定義view不需要用到wrap_content的情況的時候逻杖,可以不用重寫onMeasure方法
如下這種情況:
分析
1.需要畫出兩種顏色圓弧
2.這些圓弧具有一定的間隙
3.畫圖片
4.計(jì)算圓的內(nèi)切正方形的位置
5.如果圖片小于內(nèi)切正方形,就居中畫出圖片
6.如果圖片大于內(nèi)切正方形贩耐,就顯示整個圖片到內(nèi)切正方形處
1.畫圓弧的時候要設(shè)置畫筆參數(shù)
mPaint.setAntiAlias(true); // 消除鋸齒
mPaint.setStrokeWidth(mCircleWidth); // 設(shè)置圓環(huán)的寬度
mPaint.setStrokeCap(Paint.Cap.ROUND); // 定義線段斷電形狀為圓頭
mPaint.setAntiAlias(true); // 消除鋸齒
mPaint.setStyle(Paint.Style.STROKE); // 設(shè)置空心
2. canvas.drawArc // 這是畫圓弧的api
3.canvas.drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst,
@Nullable Paint paint): 第二個參數(shù)設(shè)置為null弧腥, 第三個參數(shù)是圖片的Rect
1.attrs.xml
<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"></attr>
<declare-styleable name="CustomVolumControlBar">
<attr name="firstColor" />
<attr name="secondColor" />
<attr name="circleWidth" />
<attr name="dotCount" />
<attr name="splitSize" />
<attr name="bg" />
</declare-styleable>
2.CustomVolumeControlBar.java
package com.zhy.customeview04.view;
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.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import com.zhy.customeview04.R;
public class CustomVolumControlBar extends View
{
/**
* 第一圈的顏色
*/
private int mFirstColor;
/**
* 第二圈的顏色
*/
private int mSecondColor;
/**
* 圈的寬度
*/
private int mCircleWidth;
/**
* 畫筆
*/
private Paint mPaint;
/**
* 當(dāng)前進(jìn)度
*/
private int mCurrentCount = 3;
/**
* 中間的圖片
*/
private Bitmap mImage;
/**
* 每個塊塊間的間隙
*/
private int mSplitSize;
/**
* 個數(shù)
*/
private int mCount;
private Rect mRect;
public CustomVolumControlBar(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public CustomVolumControlBar(Context context)
{
this(context, null);
}
/**
* 必要的初始化,獲得一些自定義的值
*
* @param context
* @param attrs
* @param defStyle
*/
public CustomVolumControlBar(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomVolumControlBar, defStyle, 0);
int n = a.getIndexCount();
for (int i = 0; i < n; i++)
{
int attr = a.getIndex(i);
switch (attr)
{
case R.styleable.CustomVolumControlBar_firstColor:
mFirstColor = a.getColor(attr, Color.GREEN);
break;
case R.styleable.CustomVolumControlBar_secondColor:
mSecondColor = a.getColor(attr, Color.CYAN);
break;
case R.styleable.CustomVolumControlBar_bg:
mImage = BitmapFactory.decodeResource(getResources(), a.getResourceId(attr, 0));
break;
case R.styleable.CustomVolumControlBar_circleWidth:
mCircleWidth = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_PX, 20, getResources().getDisplayMetrics()));
break;
case R.styleable.CustomVolumControlBar_dotCount:
mCount = a.getInt(attr, 20);// 默認(rèn)20
break;
case R.styleable.CustomVolumControlBar_splitSize:
mSplitSize = a.getInt(attr, 20);
break;
}
}
a.recycle();
mPaint = new Paint();
mRect = new Rect();
}
@Override
protected void onDraw(Canvas canvas)
{
mPaint.setAntiAlias(true); // 消除鋸齒
mPaint.setStrokeWidth(mCircleWidth); // 設(shè)置圓環(huán)的寬度
mPaint.setStrokeCap(Paint.Cap.ROUND); // 定義線段斷電形狀為圓頭
mPaint.setAntiAlias(true); // 消除鋸齒
mPaint.setStyle(Paint.Style.STROKE); // 設(shè)置空心
int centre = getWidth() / 2; // 獲取圓心的x坐標(biāo)
int radius = centre - mCircleWidth / 2;// 半徑
/**
* 畫塊塊去
*/
drawOval(canvas, centre, radius);
/**
* 計(jì)算內(nèi)切正方形的位置
*/
int relRadius = radius - mCircleWidth / 2;// 獲得內(nèi)圓的半徑
/**
* 內(nèi)切正方形的距離頂部 = mCircleWidth + relRadius - √2 / 2
*/
mRect.left = (int) (relRadius - Math.sqrt(2) * 1.0f / 2 * relRadius) + mCircleWidth;
/**
* 內(nèi)切正方形的距離左邊 = 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);
/**
* 如果圖片比較小潮太,那么根據(jù)圖片的尺寸放置到正中心
*/
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);
}
/**
* 根據(jù)參數(shù)畫出每個小塊
*
* @param canvas
* @param centre
* @param radius
*/
private void drawOval(Canvas canvas, int centre, int radius)
{
/**
* 根據(jù)需要畫的個數(shù)以及間隙計(jì)算每個塊塊所占的比例*360
*/
float itemSize = (360 * 1.0f - mCount * mSplitSize) / mCount;
RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius); // 用于定義的圓弧的形狀和大小的界限
mPaint.setColor(mFirstColor); // 設(shè)置圓環(huán)的顏色
for (int i = 0; i < mCount; i++)
{
canvas.drawArc(oval, i * (itemSize + mSplitSize), itemSize, false, mPaint); // 根據(jù)進(jìn)度畫圓弧
}
mPaint.setColor(mSecondColor); // 設(shè)置圓環(huán)的顏色
for (int i = 0; i < mCurrentCount; i++)
{
canvas.drawArc(oval, i * (itemSize + mSplitSize), itemSize, false, mPaint); // 根據(jù)進(jìn)度畫圓弧
}
}
/**
* 當(dāng)前數(shù)量+1
*/
public void up()
{
mCurrentCount++;
postInvalidate();
}
/**
* 當(dāng)前數(shù)量-1
*/
public void down()
{
mCurrentCount--;
postInvalidate();
}
private int xDown, xUp;
@Override
public boolean onTouchEvent(MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
xDown = (int) event.getY();
break;
case MotionEvent.ACTION_UP:
xUp = (int) event.getY();
if (xUp > xDown)// 下滑
{
down();
} else
{
up();
}
break;
}
return true;
}
}
3.使用activity.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:zhy="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#55ffffff"
android:orientation="vertical"
tools:context=".MainActivity" >
<com.xsh.customviewstudy.view.CustomVolumControlBar
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginTop="20dp"
zhy:bg="@drawable/customize"
zhy:circleWidth="12dp"
zhy:dotCount="20"
zhy:firstColor="#252420"
zhy:secondColor="#FDFDFD"
zhy:splitSize="25" />
<com.xsh.customviewstudy.view.CustomVolumControlBar
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_gravity="center"
android:layout_marginTop="20dp"
zhy:bg="@drawable/icon"
zhy:circleWidth="10dp"
zhy:dotCount="10"
zhy:firstColor="#00ff00"
zhy:secondColor="#ff0000"
zhy:splitSize="15" />
<com.xsh.customviewstudy.view.CustomVolumControlBar
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="bottom"
android:layout_marginLeft="10dp"
android:layout_marginBottom="20dp"
zhy:bg="@drawable/icon_qq_small"
zhy:circleWidth="10dp"
zhy:dotCount="8"
zhy:firstColor="#ADC6E5"
zhy:secondColor="#0362DB"
zhy:splitSize="25" />
</LinearLayout>
源碼參考我的github地址