自定义View仿魅族手机加速(手机管家)效果

转载请注明出处: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!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章