昨天沒有做更新,原因是一直在看有關Gallery的內容,因為想做一個比較美觀的圖片瀏覽器,如果使用系統內建的Gallery類效果非常差,因此根據網上的總結,對Gallery類進行繼承,進而對其中的效果進行自訂,可以實現比較美觀的(偽)3D效果。下一節會把ImageSwitcher添加進來,進一步對圖片瀏覽器最佳化。另外對網上牛人的文章一併表示感謝。 首先是布局檔案: 複製代碼<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@android:color/background_dark" > <com.example.android_myowngallery.MyGallery android:id="@+id/myGallery" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>複製代碼注意這裡因為對View控制項進行了繼承,所以控制項的類型應該寫成自己定義的那個類類名,否則還會出現ClassCastException 然後是自己建立的MyGallery類 複製代碼package com.example.android_myowngallery; import android.content.Context;import android.graphics.Camera;import android.graphics.Matrix;import android.util.AttributeSet;import android.view.View;import android.view.animation.Transformation;import android.widget.Gallery; public class MyGallery extends Gallery{ /** * 注意Gallery類有三個建構函式,在繼承時必須要把這三個建構函式都繼承過來,否則會有異常 * @param context * @param attrs * @param defStyle */ public MyGallery(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub } public MyGallery(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public MyGallery(Context context) { super(context); // TODO Auto-generated constructor stub } /** * 覆寫 getChildStaticTransformation方法,正是通過這個方法對Gallery的效果進行修改 */ @Override protected boolean getChildStaticTransformation(View child, Transformation t) { // TODO Auto-generated method stub //對轉換資訊初始化 t.clear(); //setTransformationType(); //獲得子控制項(ImageView)位移父控制項位移量 (用比例表示,在-1到1之間) float offSet=getOffSet(child); //根據位移量,子控制項,轉換資訊 進行效果設定 tranformIamgeView(child, t, offSet); //不要忘記調用映像變換方法 return true; } /** * 求出子控制項位移父控制項中心的程度 */ //求出子控制項的中心 protected int getCenterOfChild(View view){ return view.getLeft()+view.getWidth()/2; //這裡的getLeft()是求出子控制項左邊界的橫座標,在加上一半寬度就是中心的橫座標了 } protected int getCenterOfParent() { //有效寬度=寬度-左右邊框 //中心橫座標=左邊框+有效寬度的一半 return getPaddingLeft()+(getWidth()-getPaddingLeft()-getPaddingRight())/2; } protected float getOffSet(View view) { float cCenter=getCenterOfChild(view); float pCenter=getCenterOfParent(); float offSet=(cCenter-pCenter)/pCenter; if(offSet<-1){ offSet=-1; } else if(offSet>1){ offSet=1; } return offSet; } /** * 該方法根據給定的參數進行修改映像的顯示內容,實際上就是根據子控制項位移父控制項中心的位移量決定不同的顯示 * 效果,從而使圖片的切換更加好看 */ protected void tranformIamgeView(View view, Transformation t, float offSet) { //這裡建立一個Camera對象通過Camera類的translate方法改變“相機”的角度,進而使圖片呈現不同的效果 /** * android.graphics.Camera * * @Camera.save(); * @Camera.restore(); 相機類的這兩個方法需要同時出現 */ Camera mCamera=new Camera(); /** * 通過Transformation對象獲得一個Matrix對象,這個對象的方法用於對於映像座標變換的屬性進行設定 * android.graphics.Matrix */ Matrix matrix=t.getMatrix(); mCamera.save(); /** * z座標為正時表示“相機”上升,意味著映像將變小,本例中打算將偏離父控制項中心的View縮小,、 * 所以z應該是正值 */ mCamera.translate(0, 0, Math.abs(offSet)*200); /**** * ERROR!! * * * 將圖片對象添加至矩陣中,這個方法必須再preTranslate的前面,否則對於變換中心的設定是無效的!! */ mCamera.getMatrix(matrix); //先寬後高,關於這個方法的意義下文討論 matrix.preTranslate(-view.getMeasuredWidth()/2, -view.getMeasuredHeight()/2); matrix.postTranslate(view.getMeasuredWidth()/2, view.getMeasuredHeight()/2); mCamera.restore(); //將相機的狀態儲存 //設定一下透明度Alpha,要注意這裡的透明度是子控制項ImageView的,如果透明度為0(不透明) //那麼圖片將不會顯示,如果透明度為1,圖片正常顯示 t.setAlpha(1-Math.abs(offSet)); } }複製代碼 這裡matrix.preTranslate(-view.getWidth()/2, -view.getHeight()/2); 是指在矩陣變換之前把View向左上移動,也就是把矩陣變換的中心點由childView的原點(圖片左上方)變成childView的中心點 matrix.postTranslate(view.getWidth()/2, view.getWidth()/2);指在矩陣變換完之後,再把childView向右下方進行平移,移動到原來的位置(即螢幕的中心位置) 另外注意 mCamera.getMatrix()方法應該放在preTranslate()方法前面! 如同ListView一樣,也要為Gallery設定適配器 複製代碼package com.example.android_myowngallery; import android.content.Context;import android.view.View;import android.view.ViewGroup;import android.view.ViewGroup.LayoutParams;import android.widget.BaseAdapter;import android.widget.Gallery;import android.widget.ImageView; public class MyAdapter extends BaseAdapter{ private Context context; private int[] picRes; public MyAdapter(Context context, int[] picRes) { super(); this.context = context; this.picRes = picRes; } @Override public int getCount() { // TODO Auto-generated method stub return picRes.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub /** * 說明:因為這裡只有一個控制項ImageView,所以為了簡化代碼在這裡直接建立ImageView對象, * 在處理每一個GalleryItem中有多個控制項時,還是要和ListView一樣自訂每個Item的布局檔案, * 一般自訂布局時才會使用LayoutInflater的inflate方法建立convertView,然後再進一步獲得子控制項的 * ID,這裡不用convertView,因為沒有定義item的布局檔案! */ ImageView i=new ImageView(context); //遺留問題:這裡換成Gallery是否可以?感覺MyGallery還是最好! i.setLayoutParams(new MyGallery.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT)); //這裡必須要建立新對象!並且要使用父控制項Gallery的內部類 i.setImageResource(picRes[position]); return i; } }複製代碼這裡注意本適配器中不需要利用convertView ,只有當有子布局檔案時才會通過inflate方法建立此view 最後是MainActivity 複製代碼package com.example.android_myowngallery; import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.widget.Gallery; public class MainActivity extends Activity { protected int[] picRes={R.drawable.ew23,R.drawable.girl0,R.drawable.girl1,R.drawable.girl2,R.drawable.image01, R.drawable.image02,R.drawable.qwe2,R.drawable.w21}; MyGallery g=null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); g=(MyGallery)findViewById(R.id.myGallery); MyAdapter adapter=new MyAdapter(this,picRes); g.setAdapter(adapter); }