1、android 界面开发java
一、三个重要的类:View视图、Canvas画布、Paint画笔
二、android 界面开发经常使用三种视图
View --只能在主线程中更新,没有缓存机制,适合画面更新较少的界面,好比有按键按下才变化的界面。
SurfaceView --能够设置独立的线程,有缓存机制,主要用于2D游戏
GLSurfaceView --主要用于3D游戏,暂时不学习android
2、View框架canvas
同SWIMG、AWT同样,Android也提供大量的View组件给开发者,全部组件都是View的子类,包括之前介绍的经常使用控件和ViewGroup也是。ViewGroup是View的子类,因此它也具备View的特性,但它主要用来充当View的容器,将其中的View视做本身的孩子,对它的子View进行管理,固然它的孩子也能够是ViewGroup类型。ViewGroup(树根)和它的孩子们(View和ViewGroup)以树形结构造成了一个层次结构,View类有接受和处理消息的功能,android系统所产生的消息会在这些ViewGroup和 View之间传递。设计模式
一、View类结构缓存
java.lang.Object
-------android.view.View安全
直接子类:AnalogClock, ImageView, KeyboardView, ProgressBar, SurfaceView, TextView, ViewGroup, ViewStub框架
固然还有许多其余间接子类。ide
二、ViewGroup函数
ViewGroup继承于View,它能够包含其余的View,就像一个View的容器,咱们能够调用其成员函数addView()将View看成孩子放到ViewGroup中。布局
咱们常用的LinearLayout、relativeLayout等都是ViewGroup的子类,ViewGroup类中有一个内部类ViewGroup.LayoutParams,咱们常用LayoutParams的子类来构造布局参数。
咱们也能够自定义本身的布局,以方便往后使用和维护,这时咱们就须要继承ViewGroup类并在派生类中重写ViewGroup的一些方法。
三、自定义View
有些自带组件可能没法知足需求,这时候每每须要自定义View,通常只要主要底下两点就能够了。
(1) 继承View
(2) 重写感兴趣的方法
自定义View的经常使用方法:
onFinishInflate() 当View中全部的子控件 均被映射成xml后触发
onMeasure(int, int) 肯定全部子元素的大小
onLayout(boolean, int, int, int, int) 当View分配全部的子元素的大小和位置时触发
onSizeChanged(int, int, int, int) 当view的大小发生变化时触发
onDraw(Canvas) view渲染内容的细节
onKeyDown(int, KeyEvent) 有按键按下后触发
onKeyUp(int, KeyEvent) 有按键按下后弹起时触发
onTrackballEvent(MotionEvent) 轨迹球事件
onTouchEvent(MotionEvent) 触屏事件
onFocusChanged(boolean, int, Rect) 当View获取 或失去焦点时触发
onWindowFocusChanged(boolean) 当窗口包含的view获取或失去焦点时触发
onAttachedToWindow() 当view被附着到一个窗口时触发
onDetachedFromWindow() 当view离开附着的窗口时触发,Android123提示该方法和 onAttachedToWindow() 是相反的。
onWindowVisibilityChanged(int) 当窗口中包含的可见的view发生变化时触发
四、View实例
在View上 写"GameView" ,按方向键 上下左右会随之移动,触摸屏幕、拖动也会移到相应位置。
新建MyView类 继承View基类
1 package com.example.gameview; 2 3 import android.content.Context; 4 import android.graphics.Canvas; 5 import android.graphics.Color; 6 import android.graphics.Paint; 7 import android.view.KeyEvent; 8 import android.view.MotionEvent; 9 import android.view.View; 10 11 public class MyView extends View { 12 13 private int x=10,y=10; 14 15 public MyView(Context context) { 16 super(context); 17 setFocusable(true);//设置当前view为焦点操做 18 // TODO Auto-generated constructor stub 19 } 20 21 @Override 22 protected void onDraw(Canvas canvas) { 23 // TODO Auto-generated method stub 24 Paint paint = new Paint(); 25 paint.setColor(Color.BLACK); 26 canvas.drawText("GameView", x, y, paint); 27 28 super.onDraw(canvas); 29 } 30 31 @Override 32 public boolean onKeyDown(int keyCode, KeyEvent event) { 33 // TODO Auto-generated method stub 34 if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { 35 y-=2; 36 } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN){ 37 y+=2; 38 } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT){ 39 x-=2; 40 } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT){ 41 x+=2; 42 } 43 44 invalidate(); 45 //postInvalidate(); 46 return super.onKeyDown(keyCode, event); 47 } 48 49 @Override 50 public boolean onKeyUp(int keyCode, KeyEvent event) { 51 // TODO Auto-generated method stub 52 return super.onKeyUp(keyCode, event); 53 } 54 55 @Override 56 public boolean onTouchEvent(MotionEvent event) { 57 // TODO Auto-generated method stub 58 int tx = (int)event.getX(); 59 int ty = (int)event.getY(); 60 //玩家手指点击屏幕的动做 61 if (event.getAction() == MotionEvent.ACTION_DOWN) { 62 x = tx; 63 y = ty; 64 //玩家手指抬起离开屏幕的动做 65 } else if (event.getAction() == MotionEvent.ACTION_MOVE) { 66 x = tx; 67 y = ty; 68 //玩家手指在屏幕上移动的动做 69 } else if (event.getAction() == MotionEvent.ACTION_UP) { 70 x = tx; 71 y = ty; 72 } 73 // //获取用户手指触屏的X坐标赋值与文本的X坐标 74 // x = (int)event.getX(); 75 // //获取用户手指触屏的Y坐标赋值与文本的Y坐标 76 // y = (int)event.getY(); 77 // //重绘画布 78 79 //重绘画布 80 invalidate(); 81 //postInvalidate(); 82 return true; 83 } 84 85 }
须要特别注意的知识点以下:
一、Activity全屏显示
1 // 去掉Activity标题栏 2 this.requestWindowFeature(Window.FEATURE_NO_TITLE); 3 // 去掉 电量、时间等状态栏,全屏显示 4 this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
也能够在AndroidManifest里设置
1 android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
二、设置模拟器方向键生效
C:\Users\XX\.android\avd\XX.avd
config.ini
hw.dPad=no,把no改为yes,以下:
hw.dPad=yes
重启模拟器便可
XX根据我的命名不一样而不一样
三、重写onDraw方法
1 Paint paint = new Paint();// 画笔类 2 paint.setColor(Color.BLACK);// 初始画布为白色,设置画笔为黑色 3 canvas.drawText("GameView", x, y, paint);// 坐标不管横屏竖屏都是从右上角为 0,0点开始的 4 5 super.onDraw(canvas);
四、onKeyDown、onKeyUp、onTouchEvent
分别表示按钮 按下、抬起、触摸屏幕的事件
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return super.onKeyDown(keyCode, event);
}
第一个参数为键值,手机中每个按钮都拥有一个彻底独立的键值 经过按键键值就能够肯定当前按下的是那一个按键。
第二个参数为按键事件, 该对象中保存着当前按键的全部信息 好比 按键发生的时间 按键发生的次数 按键发生的类型等等。
经过以上两个参数就能够拿到当前按键事件的所附带的一切信息。
另外两个方法的参数也同样。
keyCode == KeyEvent.KEYCODE_DPAD_UP 表示 向上的方向键按下
其余方向键命名相似。
五、设置当前view为焦点操做才能进行操做
在View中需要监听按键的话必需在构造方法中给当前View 设置控制焦点 需要调用 setFocusable(true); 若是没有设置的话 onKeyDown 与onKeyUp 等跟按键有关的 永远没法监听到按键事件。 在onKeyDown 与onKeyUp 经过keyCode 的值就能够判断当前按下那一个按键 ,而后根据event 事件对象就能够拿到当前触发事件的时间等等。
六、重画
invalidate();// 重绘View树,即draw()过程,在UI主线程调用,不符合单线程安全设计模式 postInvalidate(); //可在本身建立的线程 经过handler通知UI主线程调用