简单的自定义View

最近不忙,打算简单的整理一下关于View的东西,也算是给自己梳理一下思路。

很多时候Android自带的控件不能满足我们需要实现的UI,因此就需要自己画这些控件,这就是自定义View的用途。其实Android中的任何一个布局、任何一个控件其实都是直接或间接继承自View的,如TextView、Button、ImageView、ListView等。

要知道,任何一个视图都不可能凭空突然出现在屏幕上,它们都是要经过非常科学的绘制流程后才能显示出来的。每一个视图的绘制过程都必须经历三个最主要的阶段,即onMeasure()、onLayout()和onDraw(),下面我们逐个对这三个阶段展开进行探讨。

一. onMeasure()

measure是测量的意思,那么onMeasure()方法顾名思义就是用于测量视图的大小的。View系统的绘制流程会从ViewRoot的performTraversals()方法中开始,在其内部调用View的measure()方法。measure()方法接收两个参数,widthMeasureSpec和heightMeasureSpec,这两个值分别用于确定视图的宽度和高度的规格和大小。

我们可以在XML中规定他的大小,也可以在代码中调用onMeasure函数来规定大小,如setMeasuredDimension(200, 200);只是这里的单位是像素,所以在不同的手机上显示的大小是不同的。

public class RoundRectView extends Button {

	private Paint mPaint;

	public RoundRectView(Context context, AttributeSet attrs) {
		super(context, attrs);
		mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);// 使位图抗锯齿的标志
	}

	WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
	@SuppressWarnings("deprecation")
	int windowHeight = wm.getDefaultDisplay().getHeight();
	int height = windowHeight/5;
	int bili = 1;
	int width = height * bili;
//	Bitmap mBackGround = ((BitmapDrawable) getResources().getDrawable
//			(R.drawable.examstart_starttest)).getBitmap(); // 获取背景图片

	
	@SuppressLint("DrawAllocation")
	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
		// 新建一只画笔,并设置为红色属性
		// Paint mPaint = new Paint();
		mPaint.setStyle(Paint.Style.STROKE);// 设置画笔为空心
		mPaint.setStrokeWidth(2); // 设置线宽
		mPaint.setColor(Color.RED);
		
		RectF re1 = new RectF(0,0, width, height);
		// 绘制圆角矩形
		canvas.drawRoundRect(re1, 15, 15, mPaint);
//		canvas.drawBitmap(mBackGround, 0, 0, mPaint); //画背景图片

	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		setMeasuredDimension(width, height);
		
	}
}</span>

以上是我写的一个小例子,我简单的自定义了一个button,我们先获取屏幕高度,然后设置按钮高度为屏幕的1/5,再设置长宽1:1,就得到一个正方形按钮,大小也会随着屏幕的改变而改变。我们只需在XML里添加<com.paintview.RoundRectView/>及其相应属性即可,按钮背景图片也可以在这里改变。

二. onLayout()

measure过程结束后,视图的大小就已经测量好了,接下来就是layout的过程了。正如其名字所描述的一样,这个方法是用于给视图进行布局的,也就是确定视图的位置。layout()方法接收四个参数,分别代表着左、上、右、下的坐标,当然这个坐标是相对于当前视图的父视图而言的。

例如childView.layout(00200200);  那么他的大小宽是右-左,第三个减去第一个,就是200-0=200,同理高为200-0=200。

三. onDraw()

这个方法才真的开始对图形进行绘制的过程,我们需要新建一支画笔,在其中进行绘制,下面的代码是绘制几种简单的图形 。

public class MyView extends View {

	private Paint mPaint;

	public MyView(Context context, AttributeSet attrs) {
		super(context, attrs);
		mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//使位图抗锯齿的标志
	}

	@SuppressLint("DrawAllocation")
	@Override
	protected void onDraw(Canvas canvas) {
		mPaint.setColor(Color.YELLOW);
		canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
		mPaint.setColor(Color.RED);
		mPaint.setTextSize(20);
		String text = "自定义View";
		canvas.drawText(text, 0, getHeight() / 2, mPaint);

		Paint paint = new Paint();
		// 去锯齿
		paint.setAntiAlias(true);
		paint.setColor(Color.BLUE);
		paint.setStyle(Paint.Style.STROKE);//设置画笔为空心
		paint.setStrokeWidth(3); //设置线宽
		// 绘制圆形
		canvas.drawCircle(40, 40, 30, paint);
		// 绘制正方形
		canvas.drawRect(10, 80, 70, 140, paint);
		// 绘制矩形
		canvas.drawRect(10, 150, 70, 190, paint);
		RectF re1 = new RectF(10, 200, 70, 230);
		// 绘制圆角矩形
		canvas.drawRoundRect(re1, 15, 15, paint);
		RectF rel1 = new RectF(10, 240, 70, 270);
		// 绘制椭圆
		canvas.drawOval(rel1, paint);
		// 定义一个Path对象,封闭成一个三角形
		Path path1 = new Path();
		path1.moveTo(10, 340);
		path1.lineTo(70, 340);
		path1.lineTo(40, 290);
		path1.close();
		// 根据path进行绘制,绘制三角形
		canvas.drawPath(path1, paint);

		// 根据path进行绘制,封闭成一个五角形
		Path path2 = new Path();
		path2.moveTo(26, 360);
		path2.lineTo(54, 360);
		path2.lineTo(70, 392);
		path2.lineTo(40, 420);
		path2.lineTo(10, 392);
		path2.close();
		// 根据path进行绘制,绘制五角形
		canvas.drawPath(path2, paint);
		// -----------------设置填充风格后绘制------------------
		paint.setStyle(Paint.Style.FILL);
		paint.setColor(Color.RED);
		canvas.drawCircle(120, 40, 30, paint);
		// 绘制正方形
		canvas.drawRect(90, 80, 150, 140, paint);
		// 绘制矩形
		canvas.drawRect(90, 150, 150, 190, paint);
		RectF re2 = new RectF(90, 200, 150, 230);
		// 绘制圆角矩形
		canvas.drawRoundRect(re2, 15, 15, paint);
		RectF re21 = new RectF(90, 240, 150, 270);
		// 绘制椭圆
		canvas.drawOval(re21, paint);
		Path path3 = new Path();
		path3.moveTo(90, 340);
		path3.lineTo(150, 340);
		path3.lineTo(120, 290);
		path3.close();
		// 绘制三角形
		canvas.drawPath(path3, paint);
		Path path4 = new Path();
		path4.moveTo(106, 360);
		path4.lineTo(134, 360);
		path4.lineTo(150, 392);
		path4.lineTo(120, 420);
		path4.lineTo(90, 392);
		path4.close();
		// 绘制五角形
		canvas.drawPath(path4, paint);
		// -----------------设置渐变后绘制------------------
		// 为Paint设置渐变器
		Shader mShader = new LinearGradient(0, 0, 40, 60, new int[] {
				Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW }, null,
				Shader.TileMode.REPEAT);
		// 为Paint设置渐变器
		paint.setShader(mShader);
		// 设置阴影
		paint.setShadowLayer(45, 10, 10, Color.GRAY);
		// 绘制圆形
		canvas.drawCircle(200, 40, 30, paint);
		// 绘制正方形
		canvas.drawRect(170, 80, 230, 140, paint);
		// 绘制矩形
		canvas.drawRect(170, 150, 230, 190, paint);
		RectF re3 = new RectF(170, 200, 230, 230);
		// 绘制圆角矩形
		canvas.drawRoundRect(re3, 15, 15, paint);
		RectF re31 = new RectF(170, 240, 230, 270);
		// 绘制椭圆
		canvas.drawOval(re31, paint);
		Path path5 = new Path();
		path5.moveTo(170, 340);
		path5.lineTo(230, 340);
		path5.lineTo(200, 290);
		path5.close();
		// 绘制三角形
		canvas.drawPath(path5, paint);
		Path path6 = new Path();
		path6.moveTo(186, 360);
		path6.lineTo(214, 360);
		path6.lineTo(230, 392);
		path6.lineTo(200, 420);
		path6.lineTo(170, 392);
		path6.close();
		// 绘制五角形
		canvas.drawPath(path6, paint);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// 在这里可以写死固定的宽高,在xml里定义就没用了,单位是sp
		int width = DensityUtil.dip2px(getContext(), 200);
		setMeasuredDimension(width, width);
	}

}
当然,还要在XML中设置基本的大小位置等。

    <com.paintview.MyView
        android:id="@+id/myview1"
        android:layout_width="200dp"
        android:layout_height="100dp" />

    <com.paintview.RoundRectView
        android:id="@+id/roundview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/myview1"
        android:layout_below="@+id/myview1" />
在这里我只是简单的进行一些介绍,可能很多都不够详细,如果有问题可以留言我会更新改进的,自己也不知道怎么写,就当做自己的简单笔记吧~



最后附上源码





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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值