自定义控件

原文地址:https://blog.csdn.net/a362523/article/details/48919949

Android自定义控件总结

  1. Android已经为我们提供了很多控件,但是大多数控件功能都比较单一简单,不能满足我们的需求,我们可以通过自定义控件的方式来实现自己想要的功能。
  2. Android实现自定义控件的方式一般有三种,第一种是继承现有的控件,重写相应的方法来扩展该控件的功能;第二种是继承View类或者ViewGroup类,通过onDraw方法绘制控制,然后通过onMeasure方法设置控件的显现,最后为自己绘制的控件设置监听;第三种是通过组合控件来实现自定义控件,譬如说可以自定义一个控件,让它既有ToggleButton的功能,又有ImageView的功能。
  3. 实现步骤为: 
    1、在res/values/目录下创建attrs.xml文件,为自定义的控件设置属性; 
    3、在构造函数中将自定义控件与atrrs.xml中的属性绑定起来 
    4、在layout.xml文件中为自定义控件的属性设置值。 
    5、setContentView显示组件布局

Android UI 引入

Android UI:不要觉得做UI不算什么本事,Android app开发一定要过UI这一关,而不要只知道写业务逻辑,只有想不到没有做不到,乔布斯将UI与各种心理学绑上了关系,用户交互设计师而不叫美工了,(有时间要好好学学,UI很重要,这样才能实现一个完整的app) 
课程目标

  1. 掌握View和ViewGroup
  2. 常用控件的使用
  3. View的本质
  4. Android 2D显示图形库:Skia(openGF)——FrameBuffer
  5. 了解Android界面世界机制
  6. 熟练掌握自定义AndroidUI组件
  7. 熟练掌握Canvas(画布)&Drawable画自定义组件及事件处理
  8. NinePatch图像的熟练使用。

重点难点

  1. ListView控件的使用
  2. 了解Android界面事件的机制
  3. 熟练掌握自定义AndroidUI组件
  4. 熟练掌握Canvas(画布)&Drawable画自定义组件及事件处理熟练
  5. NinePatch图像的熟练使用 
    (NinePatch:譬如说一个按钮随着所能容纳的字数而拉伸)

考核目标 
(面试中常见的问题)

  1. View类是所有控件的基类,能否说一下它与Activity的关系
  2. View的核心是什么,能否说一下里面的onDraw函数
  3. 自定义组件如何实现自定义事件
  4. NinePatch是干什么的?会用么?
  5. 简单介绍一下Android界面事件机制

移动设备界面设计的共性

  1. 怎么做界面:界面别人设计好的app(抄袭 + 改良 = 创新)
  2. UI角色介绍 
    1、用户交互设计师:给想法和具体UI草图 
    2、视觉设计师(美工):实现想法、真正的界面效果图 
    3、界面实现:程序猿,或者编码能力强的美工 
    所以为什么我们界面要用XML:将UI和代码分离
  3. 应用程序图标要求 
    1、一个应用程序的图片不要超过2564、 
    2、图标的使用(像素级的图)怎么让自己的应用程序图片比较醒目
  4. 资源的控制,能耗的控制(现在一般是以空间换时间,现在硬件的成本越来越廉价了,三星、硬件比较强、软件比较弱) 
    (对于能耗优化如果只是停止Service的线程外,不会怎么省电,省电的方法有:关掉后台、调节亮度、禁用其他不必要的功能。) 
    能源消耗的主要部分:屏幕亮度 + CPU运行
  5. 不要满足标准化的界面:只有想不到 没有做不到

在Android UI就是由一个个View构成的,所有组件都是继承View的,因此有必要通读一下view类的源码

学习UI组件的方法:2 + 1原则

UI组件的实现(2 + 1 法则)

  1. 组件的呈现 
    View的视图呈现关系: 
    1、呈现的两种方式: 
    什么是动态布局:一般的我们布局是有一个Activity对应的xml布局文件,然后再Activity中使用方法setContentView(R.layout.XXX),这种方式成为静态布局,但是在动态布局中,可以直接在Activity中创建一个ViewGroup,然后添加View,最后才调用setContentView(ViewGroup)动态显示布局
//创建一个容器类,布局类,也就是ViewGroup
LinearLayout linearLayout = new LinearLayout(this);
//为LinearLayout设置属性,略
//创建View对象,添加到ViewGroup中
Button btn = new Button(this);
linearLayout.addView(button);
//Viewgroup容器内的呈现
setContentView(linaerLayout(可以使ViewGroup,也可以是View))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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(四个点坐标,画笔)
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

步骤2:View的呈现 
动态UI的加载,new一个UI对象,setContentView(UI对象)动态呈现布局。

setContentView(new CostomView());
  • 1

在主线程中重画:要重画的时候调用invalidate(),就会重新调用onDraw方法 
在子线程中重画:postInvalidate() 
步骤3:为自定义的空间设置监听。 
譬如说点击事件:

customView.setOnClickListener(new OnClickListener(){
     onClick(){
    }
})
  • 1
  • 2
  • 3
  • 4

知识点补充:Android中UI的显示需要底层类库的支持,譬如说2D显示的图片:surface:(内核中:FrameBuffer驱动 + SurfaceFlinger)——Skia(2D图像的显示引擎,也就是图形显示库)——View、Canvas、Widget——Application 
3D的显示图片:surface——OpenGL(3D图像显示引擎)——Application

Android中事件

Android事件分类 
1. keyEvent:与硬按钮有关的事件,譬如说back按钮、home按钮、keyBoard按钮 
2. touchEvent:与屏幕交互的事件,点击、滑动、长按、多点触摸 
3. 轨迹球(现在估计都没有了,一直都在简化按钮)

事件触发的两种方法 
4. 扩展View的时候实现回调函数,即在控件内部(View)中实现,譬如说我们要实现自定义控件的时候。 
5. 在Activity为空间注册事件监听器,内部已经有了该事件,在外部继承来实现。

时间的分发

  1. KeyEvent分发:例如,点击收集上的一个按键的事件分发过程:点击消息发送到当前Activity—Activity再发给PhoneWindow—最后发给相应焦点的View
  2. touchEvent分发:与keyEvent反过来了

在自定义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();
  • 1
  • 2
  • 3

}

遵循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 & Drawable

用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类画图

  1. Drawable:抽象类,可以被画出来的,包括BitMap(用的最多)、Nine Patch、Shape、Layers等
  2. 画BitMap的时候必须调用setBound为图片设置大小;
  3. 可以联想到sources文件下的Drawable文件,即Drawable目录下不止包括Bitmap,可画的都可以放在里面。
  4. Drawable(主要指的是Bitmap)的三种使用方式: 
    1、用资源文件中的图片 
    Android中支持的图片格式:png(推荐)、jpg(可接受)、gif(不推荐)
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);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

2、从XML文件中的图片 
在res/Drawable/目录下创建xml文件 
例如TransitionDrawable 
3、也可以自定义Drawable对象 
(实际开发中Drawable中比Canvas用得多得多)

Nine patch九宫图

例如,button控件上,中间部分自适应控件中的文字。 
nine - patch图片的后缀为.9.png,Android中提供了相应制作Nine Patch图片的工具(draw9Patch工具)。设置好可拉伸的位置。

3D-OpenGL

支持画3D图片给,做游戏的时候会用到3D技术,不过现在OpenGL也很少用来画3D图片了,而是用引擎,譬如说Utinity

Spinner和ListViewer中的Adapter模式

ListView啊Spinner啊这些控件有相应的display方法将数据源中的数据显示在每一个Item上,但是数据源中的数据类型呢可能有很多种,譬如说ArrayList数组类型的数据源啊,从数据库中查询得到的Coursor结果集,又或者是混合了多种控件的XML数据,如果ListView直接显示这些数据源数据的话可能要重载很多个display方法。这里采用适配器模式的话就是将这些不同类型的数据源数据统一封装成一个ArrayList类型的适配器,再在ListView中显示这个ArrayList数据源数据就行了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值