Android自定义简单控件(一)

闲暇无事 学习了下Android如何自定义控件.废话不多说~
首先通过Google官网的描述 了解下自定义组件的基本方法:

Here is a high level overview of what you need to know to get started in creating your own View components:

1.Extend an existing View class or subclass with your own class.
2.Override some of the methods from the superclass. The superclass methods to override start with 'on', for example, onDraw(), onMeasure(), and onKeyDown(). This is similar to the on... events in Activity or ListActivity that you override for lifecycle and other functionality hooks.
3.Use your new extension class. Once completed, your new extension class can be used in place of the view upon which it was based.

翻译大概意思,首先使新类继承自View类或其子类;其次重载父类特定方法。被重载的父类方法通常以“on”开头,例如:onDraw()int) onMeasure()android.view.KeyEvent) onKeyDown();然后使用该扩展类。完成后,这个扩展类便可代替其父类使用,并体现出新的特性

按照官方文档推荐的方法 我们一步一步实现

项目概括图:


  • 新建一个类,这个类表示我们要自定义的控件
    Paint paint;
    
    	public MyView(Context context) {
    		super(context);
    		paint = new Paint();
    	}
    
    	public MyView(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		paint = new Paint();
    		TypedArray array = context.obtainStyledAttributes(attrs,
    				R.styleable.MyView);
    		int color = array.getColor(R.styleable.MyView_background, 0XFFFFFFFF);
    		float size = array.getDimension(R.styleable.MyView_myviewtextsize, 15);
    
    		paint.setColor(color);
    		paint.setTextSize(size);
    		//setPadding(90, 60, 0, 0);
    
    		array.recycle();
    	}
    
    	@Override
    	protected void onDraw(Canvas canvas) {
    		super.onDraw(canvas);
    		//设置画笔的风格为实心
    		paint.setStyle(Style.FILL);
    		//去锯齿
    		paint.setAntiAlias(true);
    		//绘制矩形左上角坐标为(40 30) 右下角坐标为(150 170)
    		canvas.drawRect(40, 30, 150, 170, paint);
    		paint.setColor(Color.BLUE);
    		//绘制text 起始坐标为(40,200)
    		canvas.drawText("Hello!!!", 40, 200, paint);
    	}
    
    	// custom view's size
    	@Override
    	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    		// TODO Auto-generated method stub
    		setMeasuredDimension(measureWidth(widthMeasureSpec),
    				measureHeight(heightMeasureSpec));
    	}
    
    	private int measureWidth(int measureSpec) {
    		int result = 0;
    		int specMode = MeasureSpec.getMode(measureSpec);
    		int specSize = MeasureSpec.getSize(measureSpec);
    		Log.v("222", "www specSize = "+specSize);
    
    		if (specMode == MeasureSpec.EXACTLY) {
    			// We were told how big to be
    			result = specSize;
    			Log.v("222", "www EXACTLY--->result = "+result);
    		} else {
    			// Measure the text and Rect. 150-->矩形右下角x方向坐标
    			result = 150 +getPaddingLeft() + getPaddingRight();
    			if (specMode == MeasureSpec.AT_MOST) {
    				// Respect AT_MOST value if that was what is called for by
    				// measureSpec
    				result = Math.min(result, specSize);
    				Log.v("222", "www AT_MOST--->result=" + result + " PaddingLeft="
    						+ getPaddingLeft() + " getPaddingRight=" + getPaddingRight());
    			}
    		}
    
    		return result;
    	}
    
    	private int measureHeight(int measureSpec) {
    		int result = 0;
    		int specMode = MeasureSpec.getMode(measureSpec);
    		int specSize = MeasureSpec.getSize(measureSpec);
    		Log.v("222", "hhh specSize = "+specSize);
    
    		int as = (int) paint.ascent();
    		if (specMode == MeasureSpec.EXACTLY) {
    			// We were told how big to be
    			result = specSize;
    			Log.v("222", "hhh EXACTLY--->result = "+result);
    		} else {
    			// Measure the text and Rect. 170-->矩形右下角y方向坐标
    			result = (int) (-as + paint.descent()) + 170 + getPaddingTop()
    					+ getPaddingBottom();
    			Log.v("222", "hhh 222--->result = "+result);
    			if (specMode == MeasureSpec.AT_MOST) {
    				// Respect AT_MOST value if that was what is called for by
    				// measureSpec
    				result = Math.min(result, specSize);
    				Log.v("222", "hhh AT_MOST--->result = "+result + " PaddingTop=" + 
    						getPaddingTop() + " PaddingBottom= " + getPaddingBottom());
    			}
    		}
    		return result;
    	}

这里有两个构造方法 其中  public MyView(Context context, AttributeSet attrs)
这个构造表示的是自定义的控件存在自己定义的属性的时候 会调用这个构造方法去初始化(自定义控件属性将会在后边作介绍)
onDraw方法直接在画布上绘制图像,这里我们画了一个矩形和一行Text文字


通常我们自定义的控件放在布局文件里,设置为wrap_content后也是fill_parent的样式,不能在一个页面内同时显示两个自定义的组件,这时我们就需要重写onMeasure()方法来控制控件的大小
使用onMeasure方法 就必须实现setMeasuredDimension方法
请大家注意MeasureSpec这个Int型变量 它表示了组件的尺寸大小,还有大小的模式.这是一个32位的int型变量,前2位表示的是模式 后30位表示的组件大小的值.

另外在这里 需要注意的是measureWidth和measureHeight方法里的result这个变量,它描述了该组件在其模式下实际的长度或者宽度.

result = 150 +getPaddingLeft() + getPaddingRight();
表示PaddingLeft,PaddingRight还有所画控件横向所占的长度.这里的150是根据前面canvas.drawRect(40, 30, 150, 170, paint);右下角X左边得出的(不确定对不对,如有错请大家告知)

result = (int) (-as + paint.descent()) + 170 + getPaddingTop()     + getPaddingBottom();
表示矩形的高度+文字的高度+PaddingTop,PaddingButtom

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值