Android自定义控件之自定义View(一)

转载请注明出处:http://blog.csdn.net/xiaohao0724/article/details/53994009

自定义控件是Android程序猿通向高手的必经之路,下面我们就从零开启自定义控件之旅。
自定义控件整体上分为自定义View和自定义ViewGroup,本文就义自定义View为例。
自定义View的一般步骤:
*1、自定义定义一个CustomView 继承Android系统控件View或View的某些子类(如:Button、TextView等)
 2、在res/values/目录下新建自定义属性attr.xml
*3、重写构造方法。构造方法有三个不同的重载适用于不同的场景,如果有自定义属性需要重写CustomView (Context context, AttributeSet attrs, int defStyleAttr)构造方法
 4、重写onMesure()方法测量自定义View的大小
*5、重写onDraw方法在绘制自定义的View
 6、在xml布局里面引用(注意添加自定义命名空间)
注:带 " * "的条目为必须要做的步骤

OK,接下来我们按步骤来一一实现,先放上效果图如下:



1、新建一个CustomView继承View 

public class CustomView extends View {


}

2、在values下面新建自定义属性attr.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="CicleCustom">
        <attr name="cicleColor" format="color" />
        <attr name="strokeWidth" format="dimension"></attr>
        <attr name="sleepTime" format="integer"></attr>
    </declare-styleable>

</resources>


更多自定义属性知识请参考:http://blog.csdn.net/xiaohao0724/article/details/50679467 


3、重写构造方法

public class CustomView extends View {
 

	/**
	 * 代码中实例化控件new时候使用
	 * 
	 * @param context
	 */
	public CustomView(Context context) {
		this(context, null);
	}

	/**
	 * 从XML加载到代码中时使用
	 * 
	 * @param context
	 * @param attrs
	 */
	public CustomView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	/**
	 * 获得自定义的样式属性
	 * 
	 * @param context
	 * @param attrs
	 * @param defStyleAttr
	 */
	public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
 

	}

}


4、此例不需要重写onMesure()方法,直接略过
5、重写onDraw()方法绘制View

 /**
	 * 在画布上绘制View
	 */
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		// 画圆
		canvas.drawCircle(width, height, radius, paint);
 
	}


完整自定义控件CustomView类

package com.havorld.customview.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.View;
import com.havorld.customview.R;
import com.havorld.customview.utils.ScreenInfoUtil;

public class CustomView extends View {

	private Paint paint;
	private int radius;
	private int width;
	private int height;
	private int cicleColor = Color.RED;
	private float strokeWidth = 3;
	private int sleepTime = 150;

	/**
	 * 代码中实例化控件new时候使用
	 * 
	 * @param context
	 */
	public CustomView(Context context) {
		this(context, null);
	}

	/**
	 * 从XML加载到代码中时使用
	 * 
	 * @param context
	 * @param attrs
	 */
	public CustomView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	/**
	 * 获得自定义的样式属性
	 * 
	 * @param context
	 * @param attrs
	 * @param defStyleAttr
	 */
	public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);

		// 获取我们的自定义属性
		TypedArray obtainStyledAttributes = context.getTheme()
				.obtainStyledAttributes(attrs, R.styleable.CicleCustom,
						defStyleAttr, 0);

		// 如果XML中不使用自定义属性,则obtainStyledAttributes.getIndexCount()为零
		for (int i = 0; i < obtainStyledAttributes.getIndexCount(); i++) {
			int attr = obtainStyledAttributes.getIndex(i);
			switch (attr) {
			case R.styleable.CicleCustom_cicleColor:
				cicleColor = obtainStyledAttributes.getColor(attr, Color.RED);
				break;
			case R.styleable.CicleCustom_strokeWidth:
				strokeWidth = obtainStyledAttributes.getDimension(attr, 3);
				break;
			case R.styleable.CicleCustom_sleepTime:
				sleepTime = obtainStyledAttributes.getInt(attr, 100);
				break;
			default:
				break;
			}
		}
		obtainStyledAttributes.recycle();
		getScreenInfo(context);
		initPaint();
		redrawView();

	}

	/**
	 * 重绘View圆环
	 */
	private void redrawView() {

		new Thread(new Runnable() {

			@Override
			public void run() {

				while (true) {

					if (radius <= 200) {

						radius += 10;

					} else {
						radius = 0;
					}
					// Android中提供了两个的方法来重绘更新View
					// invalidate(); // 在被调用的线程更新View(如果直接在子线程调用将报错)
					postInvalidate(); // 在UI线程更新View

					try {
						Thread.sleep(sleepTime);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}

			}
		}).start();

	}

	/**
	 * 获取屏幕的宽高
	 * 
	 * @param context
	 */
	private void getScreenInfo(Context context) {

		int[] screenMeasures = ScreenInfoUtil.getScreenMeasure(context);
		width = screenMeasures[0] / 2;
		height = screenMeasures[1] / 2;
	}

	/**
	 * 初始化画笔
	 */
	private void initPaint() {

		paint = new Paint();
		paint.setColor(cicleColor);
		paint.setStyle(Style.STROKE);
		paint.setStrokeWidth(strokeWidth);
		paint.setAntiAlias(true);
	}

	/**
	 * 在画布上绘制View
	 */
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		// 画圆
		canvas.drawCircle(width, height, radius, paint);
		// 画出矩形
//		canvas.drawRect(width - radius, height - radius, width + radius, height
//				+ radius, paint);

	}

}


ScreenInfoUtil类

package com.havorld.customview.utils;
import android.content.Context;
import android.view.Display;
import android.view.WindowManager;

public class ScreenInfoUtil {
	/**
	 * 获取屏幕的宽和高
	 * 
	 * @param context
	 * @return
	 */
	@SuppressWarnings("deprecation")
	public static int[] getScreenMeasure(Context context) {
		// 1、得到设备屏幕的分辨率的宽和高:
		// 得到系统提供的屏幕管理服务对象
		WindowManager wm = (WindowManager) context
				.getSystemService(Context.WINDOW_SERVICE);
		// 得到默认分辨率对象
		Display display = wm.getDefaultDisplay();
		// 得到屏幕的宽和高
		int screeWidth = display.getWidth();
		int screeHeigth = display.getHeight();

		return new int[] { screeWidth, screeHeigth };
	}

}

程序入口MainActivity
MainACtivity布局activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:havorld="http://schemas.android.com/apk/res/com.havorld.customview"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.havorld.customview.MainActivity" >

    <com.havorld.customview.widget.CustomView
        android:id="@+id/customView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        havorld:cicleColor="#0000ff"
        havorld:sleepTime="100"
        havorld:strokeWidth="5px" />
</RelativeLayout>


注:

引用自定义布局需要添加自定义命名空间:

xmlns:havorld="http://schemas.android.com/apk/res/com.havorld.customview"
其中com.havorld.customview是包名,也可以使用下面方式的命名空间
xmlns:havorld="http://schemas.android.com/apk/res-auto"
必须添加自定义命名空间后才可以使用下面的自定义属性
        havorld:cicleColor="#0000ff"
        havorld:sleepTime="100"
        havorld:strokeWidth="5px" 

点击下载源码



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值