Android ViewTreeObserver的經常使用技巧

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

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.android

從上面的描述中,不難看出,ViewTreeObserver是用來幫助咱們監聽某些View的某些變化的。app

 

在ViewTreeObserver中,包含了如下幾個接口:ide

interface ViewTreeObserver.OnGlobalFocusChangeListener佈局

interface ViewTreeObserver.OnGlobalLayoutListener測試

interface ViewTreeObserver.OnPreDrawListener字體

interface ViewTreeObserver.OnScrollChangedListenerthis

interface ViewTreeObserver.OnTouchModeChangeListenerspa

本文將測試除ViewTreeObserver.OnScrollChangedListener外的四個接口.net

 

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方法中設定的。

相關文章
相關標籤/搜索