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 >
2 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( " 第二个 EditText 出来了 " );
}
}
// onPreDraw 是接口 ViewTreeObserver.OnPreDrawListener
// 中定义的方法。
@Override
public boolean onPreDraw()
{
// 在屏幕上画出 ed1 控件之间 , 给它增加一个提示 , 并改变其字体大小
ed1 .setHint( " 在 onPreDraw 方法中增加一个提示信息 " );
ed1 .setTextSize(( float ) 20.0);
//return false; // Return true to proceed with the current drawing pass, or false to cancel.
return true ; // 如果此处不返回 true , 则整个界面不能完整显示。
}
// onGlobalFocusChanged 是接口 ViewTreeObserver.OnGlobalFocusChangeListener
// 中定义的方法。
// 焦点发生变化时,会触发这个方法的执行
@Override
public void onGlobalFocusChanged(View oldFocus, View newFocus)
{
if (oldFocus != null && newFocus != null )
{
tv_display .setText( "Focus /nFROM:/t" + oldFocus.toString() + "/n TO:/t" + newFocus.toString());
}
}
@Override
public void 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 );
}
}
}