1. 程式人生 > >AndroidGUI13:ViewTreeObserver的常用技巧

AndroidGUI13:ViewTreeObserver的常用技巧

A view tree observer is used to register listeners that can be notified of global changes 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 is provided by the views hierarchy. Refer to View.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. 建立一個 Android Project ,修改 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 程式碼如下:

public class 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 ;

private boolean btnClicked ;

@Override

public void 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

public void onTouchModeChanged( boolean isInTouchMode)

{

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

else tv_show .setText( "Not in touch mode" );

}

// onGlobalLayout 是介面 ViewTreeObserver.OnGlobalLayoutListener

// 中定義的方法。

// Callback method to be invoked when the global layout state or the

// visibility of views within the view tree changes

@Override

public void onGlobalLayout()

{

if ( btnClicked )

{

if (! ed2 .isShown())

ed1 .setText( " 第二個 EditText 不見了 " );

else

ed1 .setText( "