您的位置:首页 > 移动开发 > Android开发

android 自定义View1 笔记

2011-12-13 18:16 363 查看
自定义 View的常用方法:

onFinishInflate() //当View中所有的子控件 均被映射成xml后触发
onMeasure(int, int) //确定所有子元素的大小
onLayout(boolean, int, int, int, int) //当View分配所有的子元素的大小和位置时触发
onSizeChanged(int, int, int, int) //当view的大小发生变化时触发
onDraw(Canvas)
onKeyDown(int, KeyEvent) //有按键按下后触发
onKeyUp(int, KeyEvent) //有按键按下后弹起时触发
onTrackballEvent(MotionEvent) //轨迹球事件
onTouchEvent(MotionEvent) //触屏事件
onFocusChanged(boolean, int, Rect) //当View获取 或失去焦点时触发
onWindowFocusChanged(boolean) //当窗口包含的view获取或失去焦点时触发
onAttachedToWindow() //当view被附着到一个窗口时触发
onDetachedFromWindow() //当view离开附着的窗口时触发,该方法和onAttachedToWindow() 是相反的。
onWindowVisibilityChanged(int) //当窗口中包含的可见的view发生变化时触发


以上是View实现的一些基本接口的回调方法,一般我们需要处理画布的显示时,重写onDraw(Canvas)用的的是最多的:

view
plain

@Override

protected void onDraw(Canvas canvas) {

//这里我们直接使用canvas对象处理当前的画布,比如说使用Paint来选择要填充的颜色

Paint paintBackground = new Paint();

paintBackground.setColor(getResources().getColor(R.color.xxx)); //从Res中找到名为xxx的color颜色定义

canvas.drawRect(0, 0, getWidth(), getHeight(), paintBackground); //设置当前画布的背景颜色为paintBackground中定义的颜色,以0,0作为为起点,以当前画布的宽度和高度为重点即整块画布来填充,具体的请查看Android123未来讲到的Canvas和Paint,在Canvas中我们可以实现画路径,图形,区域,线。而Paint作为绘画方式的对象可以设置颜色,大小,甚至字体的类型等等。

}

当然还有就是处理窗口还原状态问题(一般用于横竖屏切换),除了在Activity中可以调用外,开发游戏时我们尽量在View中使用类似

view
plain

@Override

protected Parcelable onSaveInstanceState() {

Parcelable p = super.onSaveInstanceState();

Bundle bundle = new Bundle();

bundle.putInt("x", pX);

bundle.putInt("y", pY);

bundle.putParcelable("android123_state", p);

return bundle;

}

@Override

protected void onRestoreInstanceState(Parcelable state) {

Bundle bundle = (Bundle) state;

dosomething(bundle.getInt("x"), bundle.getInt("y")); //获取刚才存储的x和y信息

super.onRestoreInstanceState(bundle.getParcelable("android123_state"));

return;

}

有关Android的自定义 View ,我们在View中需要处理以下几种问题: 1.控制事件 2.刷新View 3. 绘制View。

1. 对于控制事件今天我们只处理按键事件onKeyDown,以后的文章中将会讲到屏幕 触控的具体处理onTouchEvent以及Sensor重力感应等方法。

2. 刷新view的方法这里主要有invalidate(int l, int t, int r, int b) 刷新局部,四个参数分别为左、上、右、下。整个view刷新 invalidate(),刷新一个矩形区域 invalidate(Rect dirty) ,刷新一个特性Drawable, invalidateDrawable(Drawable drawable) ,执行invalidate类的方法将会设置 view为无效,最终导致onDraw方法被重新调用。由于今天的view比较简单,Android123提示大家如果在线程中刷新,除了使用handler方式外,可以在Thread中直接使用postInvalidate方法来实现。

3. 绘制View主要是onDraw()中通过形参canvas来处理,相关的绘制主要有drawRect、drawLine、drawPath等等。 view方法内部还重写了很多接口,其回调方法可以帮助我们判断出view的位置和大小,比如onMeasure(int, int) Called to determine the size requirements for this view and all of its children. 、onLayout(boolean, int, int, int, int)
Called when this view should assign a size and position to all of its children 和onSizeChanged(int, int, int, int) Called when the size of this view has changed. 具体的作用,大家可以用Logcat获取 当view变化时每个形参的变动。

下面cwjView是我们为今后游戏设计的一个简单自定义View框架,我们可以看到在Android平台 自定义view还是很简单的,同时Java 支持多继承可以帮助我们不断的完善复杂的问题。

view
plain

public class cwjView extends View {

public cwjView(Context context) {

super(context);

setFocusable(true); //允许获得焦点

setFocusableInTouchMode(true); //获取焦点时允许触控

}

@Override

protected Parcelable onSaveInstanceState() { //处理窗口保存事件

Parcelable pSaved = super.onSaveInstanceState();

Bundle bundle = new Bundle();

//dosomething

return bundle;

}

@Override

protected void onRestoreInstanceState(Parcelable state) { //处理窗口还原事件

Bundle bundle = (Bundle) state;

//dosomething

super.onRestoreInstanceState(bundle.getParcelable("cwj"));

return;

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) //处理窗口大小变化事件

{

super.onSizeChanged(w, h, oldw, oldh);

}

@Override

protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)

{

super.onMeasure(widthMeasureSpec, heightMeasureSpec); //如果不让父类处理记住调用setMeasuredDimension

}

@Override

protected void onLayout (boolean changed, int left, int top, int right, int bottom)

{

super.onLayout (changed,left,top, ight,bottom) ;

}

@Override

protected void onDraw(Canvas canvas) {

Paint bg = new Paint();

bg.setColor(Color.Red);

canvas.drawRect(0, 0, getWidth()/2, getHeight()/2, bg); //将view的左上角四分之一填充为红色

}

@Override

public boolean onTouchEvent(MotionEvent event) {

return super.onTouchEvent(event); //让父类处理屏幕触控事件

}

@Override

public boolean onKeyDown(int keyCode, KeyEvent event) { //处理按键事件,响应的轨迹球事件为 public boolean onTrackballEvent (MotionEvent event)

switch (keyCode) {

case KeyEvent.KEYCODE_DPAD_UP:

break;

case KeyEvent.KEYCODE_DPAD_DOWN:

break;

case KeyEvent.KEYCODE_DPAD_LEFT:

break;

case KeyEvent.KEYCODE_DPAD_RIGHT:

break;

case KeyEvent.KEYCODE_DPAD_CENTER: //处理中键按下

break;

default:

return super.onKeyDown(keyCode, event);

}

return true;

}

}

上面我们可以看到onMeasure使用的是父类的处理方法,如果我们需要解决 自定义View的大小,可以尝试下面的方法

view
plain

@Override

protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)

{

height = View.MeasureSpec.getSize(heightMeasureSpec);

width = View.MeasureSpec.getSize(widthMeasureSpec);

setMeasuredDimension(width,height); //这里面是原始的大小,需要重新计算可以修改本行

//dosomething

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: