A view tree observer is used to register listeners that canbe notified of global changes in the view tree. Such global eventsinclude, but are not limited to, layout of the whole tree,beginning of the drawing pass, touch mode change.... AViewTreeObserver should never be instantiated by applications as itis provided by the views hierarchy. Refer toView.getViewTreeObserver() for moreinformation.

从上面的描述中,不难看出,ViewTreeObserver是用来帮助我们监听某些View的某些变化的。

在 ViewTreeObserver 中,包含了以下几个接口:

interfaceViewTreeObserver.OnGlobalFocusChangeListener

interfaceViewTreeObserver.OnGlobalLayoutListener

interface ViewTreeObserver.OnPreDrawListener

interfaceViewTreeObserver.OnScrollChangedListener

interfaceViewTreeObserver.OnTouchModeChangeListener

本文将测试除 ViewTreeObserver.OnScrollChangedListener外的四个接口

1.    创建一个 Android Project ,修改 main.xml 使之如下:

  1. <? xml version = "1.0" encoding = "utf-8" ?>
  2. < LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
  3. android:id = "@+id/full_screen"
  4. android:orientation= "vertical"
  5. android:layout_width= "fill_parent"
  6. android:layout_height= "fill_parent"
  7. >
  8. < TextView
  9. android:id = "@+id/tv_show"
  10. android:layout_width= "fill_parent"
  11. android:layout_height= "wrap_content"
  12. android:text = ""
  13. android:textSize = "32px"
  14. android:textColor = "#FFFF00"
  15. />
  16. < EditText
  17. android:id = "@+id/ed_enter1"
  18. android:layout_width= "fill_parent"
  19. android:layout_height= "wrap_content"
  20. android:text = ""
  21. />
  22. < EditText
  23. android:id = "@+id/ed_enter2"
  24. android:layout_width= "fill_parent"
  25. android:layout_height= "wrap_content"
  26. android:text = ""
  27. />
  28. < TextView
  29. android:id = "@+id/tv_display"
  30. android:layout_width= "fill_parent"
  31. android:layout_height= "wrap_content"
  32. android:text = ""
  33. />
  34. < Button
  35. android:id = "@+id/button"
  36. android:layout_width= "fill_parent"
  37. android:layout_height= "wrap_content"
  38. android:text = "OK"
  39. />
  40. </ LinearLayout >

注意:给 layout 增加一个 id : full_screen

2.    Activity 对应的 Java 代码如下:

  1. public class ControlViewTreeObserver extends Activity
  2. implements
  3. OnClickListener,
  4. ViewTreeObserver.OnTouchModeChangeListener,          // 用于监听 Touch 和非 Touch 模式的转换
  5. ViewTreeObserver.OnGlobalLayoutListener,                     // 用于监听布局之类的变化,比如某个空间消失了
  6. ViewTreeObserver.OnPreDrawListener,                              // 用于在屏幕上画 View 之前,要做什么额外的工作
  7. ViewTreeObserver.OnGlobalFocusChangeListener         // 用于监听焦点的变化
  8. {
  9. private TextView tv_show ;
  10. private ViewTreeObserver vto ;
  11. private View all ;
  12. private EditText ed1 ;
  13. private EditText ed2 ;
  14. private TextView tv_display ;
  15. private Button button ;
  16. private boolean btnClicked ;
  17. @Override
  18. public void onCreate(Bundle savedInstanceState)
  19. {
  20. super .onCreate(savedInstanceState);
  21. setContentView(R.layout. main );
  22. tv_show = (TextView) this .findViewById(R.id. tv_show );
  23. all = this .findViewById(R.id. full_screen );                                 // 得到整个屏幕对象 , 因为顶层 layout 的 width 和 height 都是 fill_parent
  24. vto = (ViewTreeObserver) all .getViewTreeObserver();         // 通过 getViewTreeObserver 获得 ViewTreeObserver 对象
  25. tv_display = (TextView) this .findViewById(R.id. tv_display );
  26. ed1 = (EditText) this .findViewById(R.id. ed_enter1 );
  27. ed2 = (EditText) this .findViewById(R.id. ed_enter2 );
  28. button = (Button) this .findViewById(R.id. button );
  29. button .setOnClickListener( this );
  30. vto .addOnTouchModeChangeListener( this );                         // 增加对应的 Listener
  31. vto .addOnGlobalFocusChangeListener(this );                       // 增加对应的 Listener
  32. vto .addOnPreDrawListener( this );                                              // 增加对应的 Listener
  33. vto .addOnGlobalLayoutListener( this );                                     // 增加对应的 Listener
  34. }
  35. // onTouchModeChanged 是接口 ViewTreeObserver.OnTouchModeChangeListener
  36. // 中定义的方法。
  37. @Override
  38. public void onTouchModeChanged( boolean isInTouchMode)
  39. {
  40. if (isInTouchMode) tv_show .setText( "In touch mode" );
  41. else tv_show .setText( "Not in touch mode" );
  42. }
  43. // onGlobalLayout 是接口 ViewTreeObserver.OnGlobalLayoutListener
  44. // 中定义的方法。
  45. // Callback method to be invokedwhen the global layout state or the
  46. // visibility of views within the view treechanges
  47. @Override
  48. public void onGlobalLayout()
  49. {
  50. if ( btnClicked )
  51. {
  52. if (! ed2 .isShown())
  53. ed1 .setText( " 第二个 EditText 不见了 " );
  54. else
  55. ed1 .setText( " 第二个 EditText 出来了 " );
  56. }
  57. }
  58. // onPreDraw 是接口 ViewTreeObserver.OnPreDrawListener
  59. // 中定义的方法。
  60. @Override
  61. public boolean onPreDraw()
  62. {
  63. // 在屏幕上画出 ed1 控件之间 , 给它增加一个提示 , 并改变其字体大小
  64. ed1 .setHint( " 在 onPreDraw 方法中增加一个提示信息 " );
  65. ed1 .setTextSize(( float ) 20.0);
  66. //return false;   // Return true to proceed with the current drawing pass, or falseto cancel.
  67. return true ;       // 如果此处不返回 true , 则整个界面不能完整显示。
  68. }
  69. // onGlobalFocusChanged 是接口 ViewTreeObserver.OnGlobalFocusChangeListener
  70. // 中定义的方法。
  71. // 焦点发生变化时,会触发这个方法的执行
  72. @Override
  73. public void onGlobalFocusChanged(View oldFocus, ViewnewFocus)
  74. {
  75. if (oldFocus != null && newFocus!= null )
  76. {
  77. tv_display .setText( "Focus /nFROM:/t" + oldFocus.toString() + "/n    TO:/t" + newFocus.toString());
  78. }
  79. }
  80. @Override
  81. public void onClick(View v)
  82. {
  83. // 改变 ed2 的可见性 , 会触发 onGlobalLayout 方法的执行
  84. btnClicked = true ;
  85. if (v.getId() == R.id. button )
  86. {
  87. if ( ed2 .isShown())
  88. ed2 .setVisibility(View. INVISIBLE );
  89. else
  90. ed2 .setVisibility(View. VISIBLE );
  91. }
  92. }
  93. }

3.    运行结果:

可以看到第一个 EditText 中存在字体发生了变化的提示信息,这种效果是在 onPreDraw() 方法中实现的。

用鼠标点击屏幕上的第二个 EditText ,

有两个变化:

一个是有 Not in touch mode 变成了 In touch mode ,二是显示了焦点变化方面的信息。它们分别是 onTouchModeChanged 和 onGlobalFocusChanged 这两个方法所输出的信息。

如果用模拟器右边的键盘进行操作,将交掉移动到第一个 EditText ,则又会回到 Not in touch mode 的状态。

点击 OK 按钮,改变第二个 EditText 的可见性:

第一个 EditText 中的内容是在 onGlobalLayout 方法中设定的。

view变化监听器ViewTreeObserver介绍的更多相关文章

  1. View和监听器

    View的基本概念 View就是Activity当中显示出来的控件,用对象来表示,如文本框的TextView类,按钮的Button类等等 每一种控件都对应一个类,都属于View的子类 在Activit ...

  2. ViewPager的简单用法+适配器+监听器的介绍

    之前的actionbar+fragment文章中写过viewpager的简单用法,但因为是融合的文章,所以今天把viewpager提取出来写了.方便查询浏览~ 思路: 1.在布局文件中设置viewpa ...

  3. Swift - iOS中各种视图控制器(View Controller)的介绍

    在iOS中,不同的视图控制器负责不同的功能,采用不同的风格向用户呈现信息.下面对各个视图控制器做个总结: 1,标准视图控制器 - View Controller 这个控制器只是用来呈现内容.通常会用来 ...

  4. Cocos2d-x场景变化相关功能介绍

    现场由导演级交换机Director实现.之间的相关的功能,如下面: runWithScene(Scene* scene).该函数能够执行场景.仅仅能在启动第一个场景时候调用该函数.假设已经有一个场景执 ...

  5. Java中的过滤器,拦截器,监听器---------简单易懂的介绍

    过滤器: 过滤器其主要特点在于:取你需要的东西,忽视那些不需要的东西!在程序中,你希望选择中篇文章中的所有数字,你就可以针对性的挑选数字! 拦截器: 拦截器其主要特点在于:针对你不要的东西进行拦截,比 ...

  6. Oracle 11gR2 RAC监听器原理介绍

    一.基本概念 oracle11gR2 RAC开始引入scan概念,一般通过dns服务器或gns服务器解析scan,也可以使用/etc/hosts文件解析scan,只不过oracle官方不建议这样做,h ...

  7. android 深入浅出 群内“每日一问” 问答总结

    永远不变的就是变. 俗话说的好,环境改变人生. 常常面对的是一群积极奋进的人,那么你的心态和生活也会变的充满斗志.青春在于折腾,趁我们还年轻,拿出你的激情.踏着泪水载着梦,才干拥有自己的一片天空. 上 ...

  8. 解析 ViewTreeObserver 源码(上)

    主要内容:ViewTreeObserver 是被用来注册监听视图树的观察者,在视图树发生全局改变时将收到通知.本文从 ViewTreeObserver 源码出发,带你剖析 ViewTreeObserv ...

  9. 关于Android中的ViewTreeObserver

    ViewTreeObserver结构 extends Object java.lang.Object ↳ android.view.ViewTreeObserver ViewTreeObserver概 ...

随机推荐

  1. QT笔记:数据库总结(三)之SQL模型类-QSqlTableModel模型

    QSqlTableModel类继承至QSqlQueryModel类,该类提供了一个可读写单张SQL表的可编辑数据模型,功能:修改,插入,删除,查询,和排序 常用函数 QVariant headerDa ...

  2. 用于Web开发的8 个最好的跨平台编辑器

    1) Best Cross Platform IDE - Brackets Brackets是一个在前端Web开发和设计人员中最流行的开放源码IDE/代码编辑器之一.它拥有一些实用工具能够将HTML ...

  3. 变量声明置顶规则、函数声明及函数表达式和函数的arguments属性初始化

    一.变量声明和变量赋值: if (!("a" in window)) { ; } alert(a);//a为? 你可能认为alert出来的结果是1,然后实际结果是“undefine ...

  4. 在CentOS/RHEL上设置SSH免密码登录

    本文会告诉你怎样在 CentOS/RHEL 上设置 SSH 免密码登录.自动登录配置好以后,你可以通过它使用 SSH (Secure Shell)和安全复制 (SCP)来移动文件. SSH 是开源的, ...

  5. 简单账本-用完即走的微信小程序

    作为一个记账强迫症患者,对当前手机中的记账App都不太满意.这类软件越来越臃肿,越来越慢,启动要半天.联网同步要半天,进入界面又有一堆新功能要介绍.好不容易开始记账,又得各种高大上的选择设定,一笔帐下 ...

  6. Install Identity management Database

    Install Identity management Database         Installing Oracle Fusion Applications > Setting up I ...

  7. Jmeter-Maven-Plugin高级应用:Remote Server Configuration

    Remote Server Configuration Pages 12 Home Adding additional libraries to the classpath Advanced Conf ...

  8. 【Python】在控制台输出不同颜色的文字

    今天调程序出了一个极为奇怪的问题,由于控制台输出挺多,就想把问题着重表示一下,具体即是在控制台输出红色文字. 于是在网上搜寻到了这篇:https://www.cnblogs.com/gongxr/p/ ...

  9. redis学习笔记——主从同步(复制)

    在Redis中,用户可以通过执行SLAVEOF命令或者设置slaveof选项,让一个服务器去复制(replicate)另一个服务器,我们称呼被复制的服务器为主服务器(master),而对主服务器进行复 ...

  10. vue 渲染流程

    1.DOM 节点树 高效的更新所有这些节点会是比较困难的,因为原生的DOM节点属性很多,渲染性能差. 2.虚拟 DOM “虚拟 DOM”是我们对由 Vue 组件树建立起来的整个 VNode 树的称呼. ...