轉載請註明出處:http://blog.csdn.net/MAGIC_JSS/article/details/52245844;
看着魅族手機管家上的手機加速效果不錯,決定自己實現之。希望自己加深對自定義View的理解和使用,也希望幫助需要類似效果的朋友。
先上效果:
由於是模擬器上運行的效果不是很好,真機上運行會好很多。
1、繼承View
廢話少說,直接上碼;
/**
* Created by magic on 2016年8月11日.仿魅族手機加速(手機管家)的效果
*/
@SuppressLint({ "DrawAllocation", "Recycle" })
public class MyDataResidueView extends View {
private Paint paint, paintText;
private float arcWidth;
private float width, height;
// 中間數字描述
private double numberDesc = 99;
// 中間的底部描述
private String desc = "內存剩餘";
// 進度默認爲全部
private int progress = 270;
// 數值格式化
private DecimalFormat df;
// 百分比文字大小
private int numberDescSize = 80;
// 底部描述文字大小
private int descSize = 40;
// 邊框寬度大小
private int strokeWidth = 5;
private int color;
private int laterColor;
private int textColor;
private float paddingLeft, paddingTop, paddingRight, paddingBottom;
private float offsetTop, offsetLeft;
public MyDataResidueView(Context context) {
super(context);
init();
}
public MyDataResidueView(Context context, AttributeSet attrs) {
super(context, attrs);
getCustomAttribute(context, attrs);
init();
}
public MyDataResidueView(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
getCustomAttribute(context, attrs);
init();
}
/**
* 獲取自定義屬性
*
* @param context
* @param attrs
*/
private void getCustomAttribute(Context context, AttributeSet attrs) {
TypedArray array = context.obtainStyledAttributes(attrs,
R.styleable.MyDataResidueView);
desc = array
.getString(styleable.MyDataResidueView_MyDataResidueView_desc);
if (desc == null)desc = "內存剩餘";
color = array.getColor(
styleable.MyDataResidueView_MyDataResidueView_color, context
.getResources().getColor(R.color.white));
laterColor = array.getColor(
styleable.MyDataResidueView_MyDataResidueView_laterColor,
context.getResources().getColor(R.color.black));
textColor = array.getColor(
styleable.MyDataResidueView_MyDataResidueView_textColor,
context.getResources().getColor(R.color.white));
array.recycle();
}
/**
* 初始化畫筆
*/
private void init() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Style.FILL);
// paint.setStrokeWidth(5);
paintText = new Paint();
paintText.setAntiAlias(true);
paintText.setStyle(Style.STROKE);
paintText.setColor(textColor);
df = new DecimalFormat("0%");
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int wMode = MeasureSpec.getMode(widthMeasureSpec);
int wSize = MeasureSpec.getSize(widthMeasureSpec);
int hMode = MeasureSpec.getMode(heightMeasureSpec);
int hSize = MeasureSpec.getSize(heightMeasureSpec);
//處理寬高爲 wrap_content的情況
if (wMode == MeasureSpec.AT_MOST && hMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(200, 200);
} else if (wMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(200, hSize);
} else if (hMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(wSize, 200);
}
// 獲取padding
paddingLeft = getPaddingLeft();
paddingTop = getPaddingTop();
paddingRight = getPaddingRight();
paddingBottom = getPaddingBottom();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 考慮存在padding的情況
this.width = w - paddingLeft - paddingRight;
this.height = h - paddingTop - paddingBottom;
if (width >= height) {
arcWidth = height / 2;
} else if (width < height) {
arcWidth = width / 2;
}// 91
offsetLeft = paddingLeft;
offsetTop = paddingTop;
//動態計算文字大小
numberDescSize = (int) (numberDescSize / 320f * arcWidth);
descSize = numberDescSize / 2;
//動態設置畫筆寬度
paint.setStrokeWidth(strokeWidth / 320f * arcWidth);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//平移座標
canvas.translate(width / 2 + offsetLeft, height / 2 + offsetTop);
Rect rect = new Rect();
numberDesc = progress / 270f;
String num = df.format(numberDesc);
paintText.getTextBounds(num, 0, num.length(), rect);
// 獲取高度
int h = rect.height();
paintText.setTextSize(numberDescSize);
canvas.drawText(num, -(paintText.measureText(num) / 2), -(h / 2),
paintText);
paintText.setTextSize(descSize);
canvas.drawText(desc, -(paintText.measureText(desc) / 2), 1 * h,
paintText);
paint.setColor(color);
canvas.rotate(-3 * 45);
for (int i = 0; i < 90; i++) {
canvas.rotate(3);
canvas.drawLine(0, -arcWidth, 0,
-(arcWidth - 5 * paint.getStrokeWidth()), paint);
}
canvas.rotate(-(270 - progress));
canvas.drawLine(0, -arcWidth, 0,
-(arcWidth - 3 * 5 * paint.getStrokeWidth()), paint);
paint.setColor(laterColor);
canvas.rotate((270 - progress) + 3);
for (int i = 0; i < (270 - progress) / 3; i++) {
canvas.rotate(-3);
canvas.drawLine(0, -arcWidth, 0,
-(arcWidth - 5 * paint.getStrokeWidth()), paint);
}
}
/**
* 設置進度大小
*
* @param progress
*/
public void setProgress(int progress) {
this.progress = progress;
postInvalidate();
}
public int getProgress() {
return this.progress;
}
}
直接繼承View的自定義控件需要考慮兩個方面問題,當控件大小設置爲wrap_content的時候和存在padding的情況。處理控件大小爲wrap_content的情況一般是通過獲取View的測量模式設置默認值。而處理padding的情況則是通過相關要求處理偏移量。
以上代碼主要是在構造方法中進行畫筆初始化操作和自定義屬性獲取;在onMeasure中設置默認寬高,獲取padding值;onSizeChanged中獲取寬高並進行所畫弧高度、偏移量、文字大小、畫筆寬度的動態設置;在onDraw中通過畫布的平移和旋轉對內容進行繪製。
2、自定義屬性
在values文件夾下創建attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyDataResidueView">
<!-- 底部文字描述 -->
<attr name="MyDataResidueView_desc" format="string" />
<attr name="MyDataResidueView_color" format="color" />
<attr name="MyDataResidueView_laterColor" format="color" />
<!-- 文字顏色 -->
<attr name="MyDataResidueView_textColor" format="color" />
</declare-styleable>
</resources>
3、xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom_view="http://schemas.android.com/apk/res/com.magic.test_customview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.magic.customview.MyDataResidueView
android:id="@+id/myview"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@color/black"
android:padding="10dp"
android:visibility="visible"
custom_view:MyDataResidueView_color="@color/white"
custom_view:MyDataResidueView_desc="內存剩餘"
custom_view:MyDataResidueView_laterColor="@color/black"
custom_view:MyDataResidueView_textColor="@color/white" />
</LinearLayout>
引入自定義控件的命名控件,設置自定義屬性。
4、Activity中使用
/**
* Created by magic on 2016年8月11日.
*/
public class MainActivity extends Activity {
// 手機內存剩餘
MyDataResidueView myView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myView = (MyDataResidueView) findViewById(R.id.myview);
ObjectAnimator animator2 = ObjectAnimator.ofInt(myView, "progress", 135);
animator2.setDuration(2000);
animator2.setInterpolator(new AccelerateInterpolator());
animator2.start();
}
}
END!