zoukankan      html  css  js  c++  java
  • Android ViewTreeObserver的常用技巧

    原文地址: https://blog.csdn.net/geekzhe/article/details/47003811

    Aview tree observer is used to register listeners that can be notified of globalchanges in the view tree. Such global events include, but are not limited to,layout of the whole tree, beginning of the drawing pass, touch mode change....A ViewTreeObserver should never be instantiated by applications as it isprovided by the views hierarchy. Refer toView.getViewTreeObserver() for more information.

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

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

    interface ViewTreeObserver.OnGlobalFocusChangeListener

    interface ViewTreeObserver.OnGlobalLayoutListener

    interface ViewTreeObserver.OnPreDrawListener

    interface ViewTreeObserver.OnScrollChangedListener

    interface ViewTreeObserver.OnTouchModeChangeListener

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

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

    <?xml version="1.0" encoding="utf-8"?>

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/full_screen"

        android:orientation="vertical"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"

       

        <TextView

                       android:id="@+id/tv_show"

                 android:layout_width="fill_parent"

                 android:layout_height="wrap_content"

                 android:text=""

                 android:textSize="32px"

                 android:textColor="#FFFF00"

       />

       

        <EditText

        android:id="@+id/ed_enter1"

        android:layout_width="fill_parent"

                 android:layout_height="wrap_content"

                 android:text=""

             />

            

        <EditText

        android:id="@+id/ed_enter2"

        android:layout_width="fill_parent"

                 android:layout_height="wrap_content"

                 android:text=""

             />

            

             <TextView

                       android:id="@+id/tv_display"

                 android:layout_width="fill_parent"

                 android:layout_height="wrap_content"

                 android:text=""

       />

       

             <Button

                       android:id="@+id/button"

                 android:layout_width="fill_parent"

                 android:layout_height="wrap_content"

                 android:text="OK"

        />   

    </LinearLayout>

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

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

    publicclass ControlViewTreeObserver extends Activity

    implements

    OnClickListener,

    ViewTreeObserver.OnTouchModeChangeListener,            // 用于监听Touch和非Touch模式的转换

    ViewTreeObserver.OnGlobalLayoutListener,                       // 用于监听布局之类的变化,比如某个空间消失了

    ViewTreeObserver.OnPreDrawListener,                               // 用于在屏幕上画View之前,要做什么额外的工作

    ViewTreeObserver.OnGlobalFocusChangeListener          // 用于监听焦点的变化

    {

             private TextView tv_show;

        private ViewTreeObserver vto;

        private View all;

       

        private EditText ed1;

        private EditText ed2;   

        private TextView tv_display;

        private Button button;

        privatebooleanbtnClicked;

       

        @Override

        publicvoid onCreate(Bundle savedInstanceState)

        {

            super.onCreate(savedInstanceState);

            setContentView(R.layout.main);

           

            tv_show = (TextView)this.findViewById(R.id.tv_show);

            all = this.findViewById(R.id.full_screen);                                  // 得到整个屏幕对象因为顶层layoutwidthheight都是fill_parent

            vto = (ViewTreeObserver)all.getViewTreeObserver();           // 通过getViewTreeObserver获得ViewTreeObserver对象

           

            tv_display = (TextView)this.findViewById(R.id.tv_display);

            ed1 = (EditText)this.findViewById(R.id.ed_enter1);

            ed2 = (EditText)this.findViewById(R.id.ed_enter2);

            button = (Button)this.findViewById(R.id.button);

            button.setOnClickListener(this);

           

            vto.addOnTouchModeChangeListener(this);                          // 增加对应的Listener

            vto.addOnGlobalFocusChangeListener(this);                        // 增加对应的Listener

            vto.addOnPreDrawListener(this);                                              // 增加对应的Listener

            vto.addOnGlobalLayoutListener(this);                                      // 增加对应的Listener

        }

     

        // onTouchModeChanged是接口ViewTreeObserver.OnTouchModeChangeListener

        // 中定义的方法。

             @Override

             publicvoid onTouchModeChanged(boolean isInTouchMode)

             {

                       if(isInTouchMode)tv_show.setText("In touch mode");

                       elsetv_show.setText("Not in touch mode");

             }

     

             // onGlobalLayout是接口ViewTreeObserver.OnGlobalLayoutListener

             // 中定义的方法。

             // Callback method to be invokedwhen the global layout state or the

             // visibility of views within the viewtree changes

             @Override

             publicvoid onGlobalLayout()

             {

                       if(btnClicked)

                       {

                                if(!ed2.isShown())

                                         ed1.setText("第二个EditText不见了");

                                else

                                         ed1.setText("第二个EditText出来了");

                       }

             }

     

             // onPreDraw是接口ViewTreeObserver.OnPreDrawListener

            // 中定义的方法。

             @Override

             publicboolean onPreDraw()

             {

                       // 在屏幕上画出ed1控件之间给它增加一个提示并改变其字体大小

                       ed1.setHint("onPreDraw方法中增加一个提示信息");

                       ed1.setTextSize((float) 20.0);

                      

                       //return false;    // Return true to proceed with the current drawing pass, or falseto cancel.

                       returntrue;        // 如果此处不返回true则整个界面不能完整显示。

             }                                            

     

             // onGlobalFocusChanged是接口ViewTreeObserver.OnGlobalFocusChangeListener

             // 中定义的方法。

             // 焦点发生变化时,会触发这个方法的执行

             @Override

             publicvoid onGlobalFocusChanged(View oldFocus, ViewnewFocus)

             {

                       if(oldFocus != null && newFocus != null)

                       {

                                tv_display.setText("Focus /nFROM:/t" + oldFocus.toString() + "/n     TO:/t" + newFocus.toString());

                       }

             }

     

             @Override

             publicvoid onClick(View v)

             {

                       // 改变ed2的可见性会触发onGlobalLayout方法的执行

                       btnClicked = true;

                       if(v.getId() == R.id.button)

                       {

                                if(ed2.isShown())

                                         ed2.setVisibility(View.INVISIBLE);

                                else

                                         ed2.setVisibility(View.VISIBLE);

                       }

             }

    }

    3.    运行结果:

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

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

    有两个变化:

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

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

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

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

  • 相关阅读:
    加载默认图片,如何避免img标签陷入onerror事件死循环
    Windows 7安装解压版MySQL 5.6(不包含配置文件优化)
    【总结2】PhpStorm利用XDebug调试PHP技巧
    【总结1】PhpStorm配置XDebug(远程)调试PHP
    JavaScript跳转到页面某个锚点#
    数据库查询中的特殊字符的问题
    CSS3/jQuery自己定义弹出窗体
    4.Maven概念模型,maven的生命周期,Maven坐标,依赖管理(依赖范围,依赖声明),仓库管理,私服概念
    从Wolframserver获取DC comics卡通人物数据
    S5PV210开发系列四_uCGUI的移植
  • 原文地址:https://www.cnblogs.com/l-h-h/p/10438327.html
Copyright © 2011-2022 走看看