自定义View 可以完全控制View的外观和view的行为,如需对预设的widget做修改可以继承于该widget,若需完全自定义可根据以下步骤:
- 创建自定义的控件类(MyView)继承于View或其子类(若只有该activity会使用到自定义的控件类,则可创建自定义控件类做为activity的内部类)
- 在attrs中定义在MyView中需要用到的属性,在res/layout/XXX.xml中MyView中添加需要的attrs属性
- 在MyView的构造器中通过TypeArray初始化通过xml定义的属性值
- override一些view的方法,onMeasure()(用于控制控件的位置宽高),onDraw()(用于控件的外观渲染),onKeyDown(),layout()(用于设置子view的位置,当自定义的view为ViewGroup时才会用到)等方法等,并设置自定义的监听事件
- 完成以上就可以在activity中应用自定义的view了
**
* 继承于View只能绘制2D的UI,如需要绘制3D的UI则需要继承于SurfaceView
*/
public class MyView extends View {
private boolean showText;//自定义的属性变量
private final int defaultWidth = 100;
private final int defaultHeight = 150;
public MyView(Context context) {
super(context);
showText = false;
}
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyView, 0, 0);
try {
//通过typedArray把在xml中定义的属性值初始化给自定义的属性变量
showText = typedArray.getBoolean(R.styleable.MyView_showText, false);
} finally {
typedArray.recycle();
}
}
//onMeasure()方法,用于定义自定义控件的宽高
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureDimension(defaultWidth, widthMeasureSpec);
int height = measureDimension(defaultHeight, heightMeasureSpec);
//重写onMeasure()方法时必须调用setMeasuredDimension()方法,否则会抛出异常
setMeasuredDimension(width, height);
}
private int measureDimension(int defaultSize, int measureSpec) {
int result = defaultSize;
int measureSpecMode = MeasureSpec.getMode(measureSpec);
int measureSize = MeasureSpec.getSize(measureSpec);
//1. layout给出了确定的值,比如:100dp
//2. layout使用的是match_parent,但父控件的size已经可以确定了,比如设置的是具体的值或者match_parent
if (measureSpecMode == MeasureSpec.EXACTLY) {
result = measureSize;
//1. layout使用的是wrap_content
//2. layout使用的是match_parent,但父控件使用的是确定的值或者wrap_content
} else if (measureSpecMode == MeasureSpec.AT_MOST) {
result = Math.min(defaultSize, measureSize);
//没有任何限制,多用于layout父控件,用于自由控制大小
} else {
result = defaultSize;
}
return result;
}
//绘制自定义View的外观
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制外观图形
}
}
- 关于view的getTop(),getLeft(),getRight(),getBotton(),getX(),getY(),getTranslationX(),getTranslationY()的关系和坐标系