Android内置了很多View,包括:
关于View更多的信息,可以参考:http://developer.android.com/guide/tutorials/views/index.html
总的来说,有三种方法来创建新的View:
创建某种View的子类并重写父类的方法,即可通过修改已有View来创建自定义的View,例如:
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.TextView;
public class MyTextView extends TextView {
public MyTextView (Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public MyTextView (Context context) {
Super(context);
}
public MyTextView (Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent keyEvent) {
[ … Perform some special processing … ]
[ … based on a particular key press … ]
// Use the existing functionality implemented by
// the base class to respond to a key press event.
return super.onKeyDown(keyCode, keyEvent);
}
}
复合控件由多个View组成,是ViewGroup的子类。通过继承ViewGroup并重写父类的构造函数,在构造过程中inflate某个Layout,是常用的生成复合控件的方法之一,例如:
public class ClearableEditText extends LinearLayout {
EditText editText;
Button clearButton;
public ClearableEditText(Context context) {
super(context);
// Inflate the view from the layout resource.
String infService = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater li;
li = (LayoutInflater)getContext().getSystemService(infService);
li.inflate(R.layout.clearable_edit_text, this, true);
// Get references to the child controls.
editText = (EditText)findViewById(R.id.editText);
clearButton = (Button)findViewById(R.id.clearButton);
// Hook up the functionality
hookupButton();
}
}
配置文件:
使用
通过继承View或SurfaceView,程序员就可以实现自定义的View。View类有一个Canvas对象,可以在上面绘制自己的UI。SurfaceView类有一个Surface对象,Surface支持后台线程绘制,并可以使用OpenGL进行绘制。对于需要经常重绘并且不需要3D效果的UI,推荐使用轻量级的View来实现。
View中的OnMeasure()方法用于确定View的长和高,OnDraw()方法则用于绘制图形,下面是创建一个自定义View的示例代码:
public class MyView extends View {
// Constructor required for in-code creation
public MyView(Context context) {
super(context);
}
// Constructor required for inflation from resource file
public MyView (Context context, AttributeSet ats, int defaultStyle) {
super(context, ats, defaultStyle );
}
//Constructor required for inflation from resource file
public MyView (Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int wMeasureSpec, int hMeasureSpec) {
int measuredHeight = measureHeight(hMeasureSpec);
int measuredWidth = measureWidth(wMeasureSpec);
// MUST make this call to setMeasuredDimension or you will cause a runtime exception when the control is laid out.
setMeasuredDimension(measuredHeight, measuredWidth);
}
private int measureHeight(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
[ … Calculate the view height … ]
return specSize;
}
private int measureWidth(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
[ … Calculate the view width … ]
return specSize;
}
@Override
protected void onDraw(Canvas canvas) {
[ … Draw your visual interface … ]
}
}
@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 views’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 text string.
float textWidth = mTextPaint.measureText(displayText);
// Draw the text string in the center of the control.
canvas.drawText(displayText, px-textWidth/2, py, mTextPaint);
}
Android中View的默认大小是100*100像素,重写OnMeasure()方法,可以实现自定义长和宽:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredHeight = measureHeight(heightMeasureSpec);
int measuredWidth = measureWidth(widthMeasureSpec);
setMeasuredDimension(measuredHeight, measuredWidth);
}
private int measureHeight(int measureSpec) {
// Return measured widget height.
}
private int measureWidth(int measureSpec) {
// Return measured widget width.
}
处于效率的考虑,measureSpec和measureSpec直接作为int参数传给了onMeasure(),但在使用之前,首先要decode:
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
下面的代码是一个典型的处理Measure的例子:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredHeight = measureHeight(heightMeasureSpec);
int measuredWidth = measureWidth(widthMeasureSpec);
setMeasuredDimension(measuredHeight, measuredWidth);
}
private int measureHeight(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
// Default size if no limits are specified.
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 measureWidth(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
// Default size if no limits are specified.
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;
}
通过重写类似下面列举的这些方法,可以处理常见的UI交互事件:
手机扫一扫
移动阅读更方便
你可能感兴趣的文章