View類是ViewGroup的父類,ViewGroup具有View的所有特性,ViewGroup主要用來充當View的容器,將其中的View作為自己孩子,並對其進行管理,當然孩子也可以是ViewGroup類型。 View類一般用於繪圖操作,重寫它的onDraw方法,但它不可以包含其他組件,沒有addView(View view)方法。 ViewGroup是一個組件容器,它可以包含任何組件,但必須重寫onLayout(boolean changed,int l,int t,int r,int b)和onMesure(int widthMesureSpec,int heightMesureSpec)方法. 否則ViewGroup中添加組件是不會顯示的。 <strong><span style="font-family:FangSong_GB2312;font-size:14px;">package com.example.testrefreshview; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new MyViewGroup(this)); } public class MyViewGroup extends ViewGroup { public MyViewGroup(Context context) { super(context); Button button1 = new Button(context); button1.setText("button1"); Button button2 = new Button(context); button2.setText("button2"); TextView textView = new TextView(context); textView.setText("textView"); addView(button1); addView(button2); addView(textView); } @Override protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) { } } }</span></strong> View的layout(int left,int top,int right,int bottom)方法負責把該view放在參數指定位置,所以如果我們在自訂的ViewGroup::onLayout中遍曆每一個子view並用view.layout()指定其位置,每一個子View又會調用onLayout,這就構成了一個遞迴調用的過程 如果在ViewGroup中重寫onDraw方法,需要在構造方法中調用this.setWillNoDraw(flase); 此時,系統才會調用重寫過的onDraw(Canvas cancas)方法,否則系統不會調用onDraw(Canvas canvas)方法. 將上面代碼修改一下,就可以顯示出來。 <strong><span style="font-family:FangSong_GB2312;font-size:14px;">package com.example.testrefreshview; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new MyViewGroup(this)); } public class MyViewGroup extends ViewGroup { public MyViewGroup(Context context) { super(context); Button button1 = new Button(context); button1.setText("button1"); Button button2 = new Button(context); button2.setText("button2"); TextView textView = new TextView(context); textView.setText("textView"); addView(button1); addView(button2); addView(textView); } @Override protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) { int childCount = getChildCount(); int left = 0; int top = 10; for (int i = 0; i < childCount; i++) { View child = getChildAt(i); child.layout(left, top, left + 60, top + 60); top += 70; } } } }</span></strong> 再看一段代碼: <strong><span style="font-family:FangSong_GB2312;font-size:14px;">@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int childCount = getChildCount(); //設定該ViewGroup的大小 int specSize_width = MeasureSpec.getSize(widthMeasureSpec); int specSize_height = MeasureSpec.getSize(heightMeasureSpec); setMeasuredDimension(specSize_width, specSize_height); for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); childView.measure(80, 80); } } </span></strong> 通過重寫onMeasure方法不但可以為ViewGroup指定大小,還可以通過遍曆為每一個子View指定大小,在自訂ViewGroup中添加上面代碼為ViewGroup中的每一個子View分配了顯示的寬高。 下面我們讓子View動起來吧,添加代碼如下: <strong><span style="font-family:FangSong_GB2312;font-size:14px;">public boolean onTouchEvent(MotionEvent ev) { final float y = ev.getY(); switch(ev.getAction()) { case MotionEvent.ACTION_DOWN: mLastMotionY = y; break; case MotionEvent.ACTION_MOVE: int detaY = (int)(mLastMotionY - y); mLastMotionY = y; scrollBy(0, detaY); break; case MotionEvent.ACTION_UP: break; } return true; }</span></strong> 在上面用到了一個scrollBy方法,開啟官方API可以看到View類有如下兩個方法: 這兩個函數貌似都是行動裝置檢視的,那麼它們有什麼區別呢?帶著這個疑問我們向下看 首先 ,我們必須明白在Android View視圖是沒有邊界的,Canvas是沒有邊界的,只不過我們通過繪製特定的View時對 Canvas對象進行了一定的操作,例如 : translate(平移)、clipRect(剪下)等,以便達到我們的對該Canvas對象繪製的要求 ,我們可以將這種無邊界的視圖稱為“視圖座標”-----它不受物理螢幕限制。通常我們所理解的一個Layout布局檔案只是該視圖的顯示地區,超過了這個顯示地區將不能顯示到父視圖的地區中 ,對應的,我們可以將這種有邊界的視圖稱為“布局座標”------ 父視圖給子視圖分配的布局(layout)大小。而且, 一個視圖的在螢幕的起始座標位於視圖座標起始處,如所示。 由於布局座標只能顯示特定的一塊內容,所以我們只有移動布局座標的座標原點就可以將視圖座標的任何位置顯示出來。<strong><span style="font-family:FangSong_GB2312;font-size:14px;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:background="#888888"> <TextView android:id="@+id/txt" android:layout_width="300dip" android:layout_height="120dip" android:background="#cccccc" android:text="textview" /> <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="button" /> </LinearLayout></span></strong>