闲暇无事 学习了下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; }