原文地址: 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); // 獲得整個屏幕對象,由於頂層layout的width和height都是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方法中設定的。