Android控件的组成

Android控件的组成

Android的控件都派生自View,控件容器是View Group

通过容器控件,可将交互界面的各个控件对象组织成控件树,上层父控件负责其下层控件的排列和绘制,并将交互事件自上而下传递到子控件树。每棵控件树都有一个ViewParent对象与其根控件绑定,该ViewParent对象是整棵控件树的交互事件的控制枢纽,负责将用户产生的交互事件传递到控件树的根控件,进行自顶而下的传播。控件树中的每个对象都有一个指向ViewParent的指针,当子控件的焦点、尺寸改变时会通知ViewParent,由ViewParent同一下发该事件。

从而每个控件只受父控件的控制,不受其他控件的影响。

 

Android交互事件的传输

Android控件中,交互事件沿着控件树自顶向下传输。

控件树上层的父控件收到交互事件后,会先行判定该事件的目标控件对象,如果该事件是自己所需的,则会截获事件进行处理;否则向下分发,递推逐级传递,直至事件被处理或忽略。

    AndroidView类中定义了一系列View.onXXX()事件函数来接听和处理各类交互事件。

    事件函数的返回值,如返回操作(KeyEvent.KEYCODE_BACK)是控制事件传播的重要手段。事件函数返回true说明已处理。

    容器控件ViewGroup的职责是将交互事件传播到其子控件。不同的事件,传播方式不同:触摸事件——ViewGroup判断事件发生区域在哪个子控件的领土上;对于按键事件,ViewGroup将事件转给具有焦点的子控件。

    继承的方式处理事件不灵活,会导致系统中出现大量的子控件类,且彼此复用性差。在面向对象设计中,提倡用“组合”的方式代替“继承”思想。

    View类提供了配套的事件监听函数应对事件。Android控件的事件监听模型是观察者模式。这种方式耦合性低。

 

 Android控件属性

标识:是一个正整数作为控件标识, View.getId()来获取。

可以使用View.findViewById()寻找控件。ID无需全局唯一,在给定子控件内唯一即可。

尺寸:每个控件都会占据一定的矩形区域。控件处理该矩形区域的事件,绘制交互界面。

控件的尺寸由父控件和自己共同决定。可以在代码中通过View.setLayoutParams(LayoutParams)设定。

Margin是设定容器控件中子控件与其矩形区域的距离,是控件容器的专有属性,通过MarginLayoutParams实现。Padding是控件对象内容与控件矩形区域边缘的距离,View.setPadding实现。

 位置:控件位置坐标系的原点在左上角,X轴自左向右,Y轴自上而下。可以通过View.getTopView.getLeft获取左上角坐标系(获取的是相对位置)。View.setLocationOnScreen实现绝对位置信息。

可见性:通过View.setVisibility实现。可见View.Visible,不可见View.INVISIBLE但还占据位置,消失View.GONE不占据位置。

焦点:控件焦点切换采用动态计算。用户通过方向键切换时,Android会计算在当前方向上与当前控件最接近的控件,并将焦点切换到这里。动态计算灵活,适配性强,但不一定准确。为了解决问题,Android提供了View.setNextFocusDownID,开发者可以精确设定上下左右的切换。

 

控件的丈量和绘制

控件从构造到呈现,还要经历控件尺寸的丈量和绘制。都是自上而下开始,由控件树的根控件发起,逐渐向下推。

各个控件尺寸的确定过程:

父控件开始向下调用View.measure函数,父控件将尺寸限制通知子控件,子控件结合自己需要的尺寸信息就可以推算出真实控件的大小。如果父控件尺寸不确定要根据子控件大小反向推推断。

控件明确尺寸后,重新从根控件开始,向下依次调用View.layout设置各个控件的最终位置和大小。

控件遍历整个控件树,在不同区域绘制。View.onDraw会被调用。当控件尺寸变化或内容变化时,会调用View.requestLayoutView.invalidate驱动控件树重新丈量和绘制

 

猜你喜欢

转载自aoyouzi.iteye.com/blog/1993107
今日推荐