Android 创建自定义View

ALFA DeV工作室原创文章如转载,请注明:转载自博客原文地址:http://blog.csdn.net/kongre/article/details/6746146

创建自定义的View能够从根本上塑造你的应用程序的外观,你可以通过创建自定义视图的方式去满足用户独特的需求。你可以继承View类或者是SurfaceView类。View类提供了一个Canvas对象,你可以去使用这个对象的很多画图的方法以及Paint对象去绘制你的自定义视图。当然你可以通过覆盖screen touch, key press等的UI事件,对这些事件进行响应,与用户进行交互。SurfaceView类提供了一个Surface对象用来支持使用后台独立线程来对用户自定义视图进行绘制的这么一个核心的对象,并且可以使用openGL技术进行3D绘图。主要用于用户自定义视图更新频繁或者是显示一些复杂的3D效果的场景,在游戏开发当中经常使用。本篇博客我们介绍继承View类的自定义视图,在后面的博客当中,我们将为大家讲解继承SurfaceView的自定义View的构建方法。

步骤一、创建一个新的可视界面

View类默认展现100像素*100像素的区域,如果需要改变这个视图的大小,你需要去重写onMeasure()和onDraw()方法。onDraw()方法用来在Canvas上绘图,onMeasure()方法用来计算在给定的边界情况下,我们自定义的视图的高度和宽度各是多少。Skeleton Code:

public class MyView extends View {

	public MyView(Context context) {
		super(context);
	}

	public MyView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public MyView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int measuredHeight = measureHeight(heightMeasureSpec);
		int measuredWidth = measureWidth(widthMeasureSpec);
		//Must make this call to setMeasuredDimension
		//or you will cause a runtime exception when the control is laid out
		setMeasuredDimension(measuredWidth, measuredHeight);
	}

	private int measureWidth(int widthMeasureSpec) {
		int specMode = MeasureSpec.getMode(widthMeasureSpec);
		int specSize = MeasureSpec.getSize(widthMeasureSpec);
		//calculate the width
		return specSize;
	}

	private int measureHeight(int heightMeasureSpec) {
		int specMode = MeasureSpec.getMode(heightMeasureSpec);
		int specSize = MeasureSpec.getSize(heightMeasureSpec);
		//calculate the height
		return specSize;
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		//draw your user interface
	}

}
注意在我们重写的onMeasure()方法当中,必须调用setMeasuredDimension()方法。不然的话,有的自定义视图在使用的时候将会抛出运行时异常。
步骤二、绘制你的自定义视图

onDraw()方法是奇迹发生的地方。Android提供了一系列的工具帮助我们开发者使用种类繁多的Paint(画笔)对象在Canvas(画布)上绘制我们希望的视图。Canvas对象提供了一些辅助的方法用来绘制一些原生的2D图像,比如说:圆形,直线,矩形,文本以及图形图像等等。有了这些辅助的方法和辅助的工具,你绘制的视图的复杂性和详细情况仅仅取决于屏幕的大小以及处理器的渲染能力。

注意:在Android平台之上写出高效代码的最重要的技巧就是避免对象的重复创建和回收。对于任何在onDraw()方法当中创建的对象,只要屏幕一刷新,此对象就会被回收。所以把onDraw()方法中所用到的对象最好都定义为成员变量,在构造器当中可以对其初始化。

	protected void onDraw(Canvas canvas) {
		//get the size of the control based on the last call to onMeasure()
		int height = getMeasuredHeight();
		int width = getMeasuredWidth();
		
		//Find the center
		int px = width/2;
		int py = height/2;	
		
		//create the new paint brushes
		//note:For efficiency this should be done in the view's constructor
		Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mTextPaint.setColor(Color.WHITE);
		
		//define the string
		String displayText = "Hello World!";
		
		//measure the width of the string
		float textWidth = mTextPaint.measureText(displayText);
		
		canvas.drawText(displayText, px - textWidth/2, py, mTextPaint);
		super.onDraw(canvas);
	}
步骤三、计算你的视图的高度和宽度
onMeasure()方法在我们自定义视图的父级元素布局我们的自定义的时候,父级元素会提出一个问题:"How much space will you use?", 并且传递两个参数, widthMeasureSpec和heightMeasureSpec.这两个参数指明了对于我们自定义的视图而言,有多大的空间是可以用的以及可用空间的一些元数据信息。但是切记:我们需要在onMeasure()方法当中调用setMeasuredDimension()方法。

public class MyView extends View {

	public MyView(Context context) {
		super(context);
	}

	public MyView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public MyView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int measuredHeight = measureHeight(heightMeasureSpec);
		int measuredWidth = measureWidth(widthMeasureSpec);
		//Must make this call to setMeasuredDimension
		//or you will cause a runtime exception when the control is laid out
		setMeasuredDimension(measuredWidth, measuredHeight);
	}

	private int measureWidth(int widthMeasureSpec) {
		int specMode = MeasureSpec.getMode(widthMeasureSpec);
		int specSize = MeasureSpec.getSize(widthMeasureSpec);
		int result = 500;
		if(specMode == MeasureSpec.AT_MOST){
			//calculate the ideal size of your control within this maximum size.
			//if your control fills the available  space return the outer bound.
			result = specSize;
		}else if(specMode == MeasureSpec.EXACTLY){
			//if your control can fit within these bounds return that value
			result = specSize;
		}
		return result;
	}

	private int measureHeight(int heightMeasureSpec) {
		int specMode = MeasureSpec.getMode(heightMeasureSpec);
		int specSize = MeasureSpec.getSize(heightMeasureSpec);
		int result = 500;
		if(specMode == MeasureSpec.AT_MOST){
			result = specSize;
		}else if(specMode == MeasureSpec.EXACTLY){
			result = specSize;
		}
		return result;
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		//get the size of the control based on the last call to onMeasure()
		int height = getMeasuredHeight();
		int width = getMeasuredWidth();
		
		//Find the center
		int px = width/2;
		int py = height/2;	
		
		//create the new paint brushes
		//note:For efficiency this should be done in the view's constructor
		Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mTextPaint.setColor(Color.WHITE);
		
		//define the string
		String displayText = "Hello World!";
		
		//measure the width of the string
		float textWidth = mTextPaint.measureText(displayText);
		
		canvas.drawText(displayText, px - textWidth/2, py, mTextPaint);
		super.onDraw(canvas);
	}

}
步骤四、怎么使用我们的自定义视图
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<com.freedie.customerizedview.MyView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    />
</LinearLayout>
真机运行效果如下:


最后如果你还是觉得我写的不够详细 看的不够爽 不要紧我把源代码的下载地址贴出来 欢迎大家一起讨论学习ALFA DeV工作室希望可以和大家一起进步。

下载地址:
http://download.csdn.net/source/3573096



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值