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()
從上面的描述中,不難看出,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( "