Android UI:不要觉得做UI不算什么本事,Android app开发一定要过UI这一关,而不要只知道写业务逻辑,只有想不到没有做不到,乔布斯将UI与各种心理学绑上了关系,用户交互设计师而不叫美工了,(有时间要好好学学,UI很重要,这样才能实现一个完整的app)
课程目标
重点难点
考核目标
(面试中常见的问题)
在Android UI就是由一个个View构成的,所有组件都是继承View的,因此有必要通读一下view类的源码
UI组件的实现(2 + 1 法则)
//创建一个容器类,布局类,也就是ViewGroup
LinearLayout linearLayout = new LinearLayout(this);
//为LinearLayout设置属性,略
//创建View对象,添加到ViewGroup中
Button btn = new Button(this);
linearLayout.addView(button);
//Viewgroup容器内的呈现
setContentView(linaerLayout(可以使ViewGroup,也可以是View))
2、呈现的核心
牢牢把握onDraw:Canvas + Drawable介绍
1、UI的呈现:布局 + 位置
2、UI的事件:
了解了这两个的话就知道怎么实现自己的UI了
画一个简单的东西
可以在view或者SurfaceView(用在游戏比较多,对图片的切换要求更高),继承View对象,实现onDraw(Canvas canvas)回调方法,在回调函数中:
步骤1:画出一个布局:继承View,用Paint在Canvas画画
public class CustomView extends View{
onDraw(Canvas canvas){
//创建一个画笔对象
Paint paint = new Paint();
//为画笔设置颜色
paint.setColor(Color.Blue);
//在画布上调用画笔画画
canvas.drawRect(四个点坐标,画笔)
}
}
步骤2:View的呈现
动态UI的加载,new一个UI对象,setContentView(UI对象)动态呈现布局。
setContentView(new CostomView());
在主线程中重画:要重画的时候调用invalidate(),就会重新调用onDraw方法
在子线程中重画:postInvalidate()
步骤3:为自定义的空间设置监听。
譬如说点击事件:
customView.setOnClickListener(new OnClickListener(){
onClick(){
}
})
知识点补充:Android中UI的显示需要底层类库的支持,譬如说2D显示的图片:surface:(内核中:FrameBuffer驱动 + SurfaceFlinger)——Skia(2D图像的显示引擎,也就是图形显示库)——View、Canvas、Widget——Application
3D的显示图片:surface——OpenGL(3D图像显示引擎)——Application
Android事件分类
1. keyEvent:与硬按钮有关的事件,譬如说back按钮、home按钮、keyBoard按钮
2. touchEvent:与屏幕交互的事件,点击、滑动、长按、多点触摸
3. 轨迹球(现在估计都没有了,一直都在简化按钮)
事件触发的两种方法
4. 扩展View的时候实现回调函数,即在控件内部(View)中实现,譬如说我们要实现自定义控件的时候。
5. 在Activity为空间注册事件监听器,内部已经有了该事件,在外部继承来实现。
时间的分发
在自定义View中使用回调事件
即在CustomView中添加方法:
public boolean onKeyUp(int keyCode, keyEvent event) {
if(keyCode == keyEvent.KEYCODE_DPAD_CENTER){
//点击后执行的操作
}
super();
}
public boolean onTouchEvent(MotionEvent evnet) {
if(event.getAction == MotionEvent.ACTION_UP) {
}
super();
}
遵循2 + 1 原则
2:布局的呈现 (onMeasure:度量屏幕大小,用于摆放布局;哦onDraw:用画布画出来)+ 布局
1:事件(setXXLintener + 回调函数)
自定义组件的分类:
1、Customized Component(自定义组件):当前组件不够完善,想加入其它的功能,一般要继承View,增加更多的属性和时间。是一种深层次的扩展方式(纵向扩展)
2、Compound Component(复合空间):继承ViewGroup,把多个简单空间通过布局拼装一个复合控件,是一种横向扩展。
自定义控件的步骤
1、选择继承类(肯定是View (View的子类)、Viewgroup)
2、类的初始化:初始化新增属性 + 属性的初始设定
3、重载方法:
a、布局及呈现:onDraw + onMeasure
b、事件:自定义事件
4、组件的使用
用Canvas画图
(实际上Canvas用的不多)
1. Canvas的基本使用
1、drawXXX:创建画笔对象,为画笔设置属性(SetXXX)、画XXX图形,使用View.invalidate()或者View.postInvalidate()方法实现重新调用drawXXX
2、matrix.setRotate(degree)旋转 + matrix.setScale()放大/缩小; canvas.setMatrix(matrix)
3、clipRect(left、top、right、bottom)//裁剪一个区域
4、canvas.save + canvas.restore
2. 使用SurfaceView来画图:在游戏中常用、双缓存、更快更平滑
Drawable类画图
public class DrawableView extends View {
BitmapDrawable bd;
public DrawaleView(Context context) {
bd = (BitMapDrawable)getResources().getDrawable(R.id.XX);
bd.setBounds(设置边界);
}
public void onDraw(Canvas canvas) {
//将Bitmap显示在Canvas上
super.onDraw(canvas);
bd.draw(canvas);
}
}
2、从XML文件中的图片
在res/Drawable/目录下创建xml文件
例如TransitionDrawable
3、也可以自定义Drawable对象
(实际开发中Drawable中比Canvas用得多得多)
例如,button控件上,中间部分自适应控件中的文字。
nine - patch图片的后缀为.9.png,Android中提供了相应制作Nine Patch图片的工具(draw9Patch工具)。设置好可拉伸的位置。
支持画3D图片给,做游戏的时候会用到3D技术,不过现在OpenGL也很少用来画3D图片了,而是用引擎,譬如说Utinity
ListView啊Spinner啊这些控件有相应的display方法将数据源中的数据显示在每一个Item上,但是数据源中的数据类型呢可能有很多种,譬如说ArrayList数组类型的数据源啊,从数据库中查询得到的Coursor结果集,又或者是混合了多种控件的XML数据,如果ListView直接显示这些数据源数据的话可能要重载很多个display方法。这里采用适配器模式的话就是将这些不同类型的数据源数据统一封装成一个ArrayList类型的适配器,再在ListView中显示这个ArrayList数据源数据就行了。