天天看點

Android作業:一個3D相冊源碼

我們專業課有Android的學習,最後老師讓做一個簡單的Android應用程式.我在網上找些資料,加上自己改造一下做了一個3D相冊.

程式仿照Android的相冊功能,調用Gallery類對相片進行浏覽.實作3D效果.其中不足的地方就是裡面的圖檔都是寫死的.這一點可以改進.程式中使用Png格式圖檔,注意圖檔不要太大,500*500一下最好.

Android作業:一個3D相冊源碼

首先:

GalleryFlow.java 類 用來實作圖檔放映檢視效果.

1: package com.android.CustomGallery;      
2:        
3: import android.content.Context;      
4: import android.graphics.Camera;      
5: import android.graphics.Matrix;      
6: import android.util.AttributeSet;      
7: import android.util.Log;      
8: import android.view.View;      
9: import android.view.animation.Transformation;      
10: import android.widget.Gallery;      
11: import android.widget.ImageView;      
12:        
13: public class GalleryFlow extends Gallery {      
14:        
15:         /**      
16:          * Graphics Camera used for transforming the matrix of ImageViews      
17:          */      
18:         private Camera mCamera = new Camera();      
19:        
20:         /**      
21:          * The maximum angle the Child ImageView will be rotated by      
22:          */      
23:         private int mMaxRotationAngle = 60;      
24:        
25:         /**      
26:          * The maximum zoom on the centre Child      
27:          */      
28:         private int mMaxZoom = -120;      
29:        
30:         /**      
31:          * The Centre of the Coverflow      
32:          */      
33:         private int mCoveflowCenter;      
34:        
35:         public GalleryFlow(Context context) {      
36:                 super(context);      
37:                 this.setStaticTransformationsEnabled(true);      
38:         }      
39:        
40:         public GalleryFlow(Context context, AttributeSet attrs) {      
41:                 super(context, attrs);      
42:                 this.setStaticTransformationsEnabled(true);      
43:         }      
44:        
45:         public GalleryFlow(Context context, AttributeSet attrs, int defStyle) {      
46:                 super(context, attrs, defStyle);      
47:                 this.setStaticTransformationsEnabled(true);      
48:         }      
49:        
50:         /**      
51:          * Get the max rotational angle of the image      
52:          *       
53:          * @return the mMaxRotationAngle      
54:          */      
55:         public int getMaxRotationAngle() {      
56:                 return mMaxRotationAngle;      
57:         }      
58:        
59:         /**      
60:          * Set the max rotational angle of each image      
61:          *       
62:          * @param maxRotationAngle      
63:          *            the mMaxRotationAngle to set      
64:          */      
65:         public void setMaxRotationAngle(int maxRotationAngle) {      
66:                 mMaxRotationAngle = maxRotationAngle;      
67:         }      
68:        
69:         /**      
70:          * Get the Max zoom of the centre image      
71:          *       
72:          * @return the mMaxZoom      
73:          */      
74:         public int getMaxZoom() {      
75:                 return mMaxZoom;      
76:         }      
77:        
78:         /**      
79:          * Set the max zoom of the centre image      
80:          *       
81:          * @param maxZoom      
82:          *            the mMaxZoom to set      
83:          */      
84:         public void setMaxZoom(int maxZoom) {      
85:                 mMaxZoom = maxZoom;      
86:         }      
87:        
88:         /**      
89:          * Get the Centre of the Coverflow      
90:          *       
91:          * @return The centre of this Coverflow.      
92:          */      
93:         private int getCenterOfCoverflow() {      
94:                 //Log.e("CoverFlow Width+Height", getWidth() + "*" + getHeight());      
95:                 return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2      
96:                                 + getPaddingLeft();      
97:         }      
98:        
99:         /**      
100:          * Get the Centre of the View      
101:          *       
102:          * @return The centre of the given view.      
103:          */      
104:         private static int getCenterOfView(View view) {      
105:                 /*Log.e("ChildView Width+Height", view.getWidth() + "*"      
106:                                 + view.getHeight());*/      
107:                 return view.getLeft() + view.getWidth() / 2;      
108:         }      
109:        
110:         /**      
111:          * {@inheritDoc}      
112:          *       
113:          * @see #setStaticTransformationsEnabled(boolean)      
114:          */      
115:         protected boolean getChildStaticTransformation(View child, Transformation t) {      
116:        
117:                 final int childCenter = getCenterOfView(child);      
118:                 final int childWidth = child.getWidth();      
119:                 int rotationAngle = 0;      
120:        
121:                 t.clear();      
122:                 t.setTransformationType(Transformation.TYPE_MATRIX);      
123:        
124:                 if (childCenter == mCoveflowCenter) {      
125:                         transformImageBitmap((ImageView) child, t, 0);      
126:                 } else {      
127:                         rotationAngle = (int) (((float) (mCoveflowCenter - childCenter) / childWidth) * mMaxRotationAngle);      
128:                         if (Math.abs(rotationAngle) > mMaxRotationAngle) {      
129:                                 rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle      
130:                                                 : mMaxRotationAngle;      
131:                         }      
132:                         transformImageBitmap((ImageView) child, t, rotationAngle);      
133:                 }      
134:        
135:                 return true;      
136:         }      
137:        
138:         /**      
139:          * This is called during layout when the size of this view has changed. If      
140:          * you were just added to the view hierarchy, you're called with the old      
141:          * values of 0.      
142:          *       
143:          * @param w      
144:          *            Current width of this view.      
145:          * @param h      
146:          *            Current height of this view.      
147:          * @param oldw      
148:          *            Old width of this view.      
149:          * @param oldh      
150:          *            Old height of this view.      
151:          */      
152:         protected void onSizeChanged(int w, int h, int oldw, int oldh) {      
153:                 mCoveflowCenter = getCenterOfCoverflow();      
154:                 super.onSizeChanged(w, h, oldw, oldh);      
155:         }      
156:        
157:         /**      
158:          * Transform the Image Bitmap by the Angle passed      
159:          *       
160:          * @param imageView      
161:          *            ImageView the ImageView whose bitmap we want to rotate      
162:          * @param t      
163:          *            transformation      
164:          * @param rotationAngle      
165:          *            the Angle by which to rotate the Bitmap      
166:          */      
167:         private void transformImageBitmap(ImageView child, Transformation t,      
168:                         int rotationAngle) {      
169:                 mCamera.save();      
170:                 final Matrix imageMatrix = t.getMatrix();      
171:                 final int imageHeight = child.getLayoutParams().height;      
172:                 final int imageWidth = child.getLayoutParams().width;      
173:                 final int rotation = Math.abs(rotationAngle);      
174:        
175:                 // 在Z軸上正向移動camera的視角,實際效果為放大圖檔。      
176:                 // 如果在Y軸上移動,則圖檔上下移動;X軸上對應圖檔左右移動。      
177:                 mCamera.translate(0.0f, 0.0f, 100.0f);      
178:        
179:                 // As the angle of the view gets less, zoom in      
180:                 if (rotation < mMaxRotationAngle) {      
181:                         float zoomAmount = (float) (mMaxZoom + (rotation * 1.5));      
182:                         mCamera.translate(0.0f, 0.0f, zoomAmount);      
183:                 }      
184:        
185:                 // 在Y軸上旋轉,對應圖檔豎向向裡翻轉。      
186:                 // 如果在X軸上旋轉,則對應圖檔橫向向裡翻轉。      
187:                 mCamera.rotateY(rotationAngle);      
188:                 mCamera.getMatrix(imageMatrix);      
189:                 // Preconcats matrix相當于右乘矩陣,Postconcats matrix相當于左乘矩陣。      
190:                 imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));      
191:                 imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));      
192:                 mCamera.restore();      
193:         }      
194: }      

ageAdapter.java 圖檔擴充卡類,用來将檔案中的圖檔資源加載到應用程式

1: package com.android.CustomGallery;      
2:        
3: import android.content.Context;      
4: import android.graphics.Bitmap;      
5: import android.graphics.BitmapFactory;      
6: import android.graphics.Canvas;      
7: import android.graphics.LinearGradient;      
8: import android.graphics.Matrix;      
9: import android.graphics.Paint;      
10: import android.graphics.PorterDuffXfermode;      
11: import android.graphics.Bitmap.Config;      
12: import android.graphics.PorterDuff.Mode;      
13: import android.graphics.Shader.TileMode;      
14: import android.graphics.drawable.BitmapDrawable;      
15: import android.view.View;      
16: import android.view.ViewGroup;      
17: import android.widget.BaseAdapter;      
18: import android.widget.ImageView;      
19:        
20: /*      
21: * Copyright (C) 2010 Neil Davies      
22: *      
23: * Licensed under the Apache License, Version 2.0 (the "License");      
24: * you may not use this file except in compliance with the License.      
25: * You may obtain a copy of the License at      
26: *      
27: * http://www.apache.org/licenses/LICENSE-2.0      
28: *      
29: * Unless required by applicable law or agreed to in writing, software      
30: * distributed under the License is distributed on an "AS IS" BASIS,      
31: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.      
32: * See the License for the specific language governing permissions and      
33: * limitations under the License.      
34: *       
35: * This code is base on the Android Gallery widget and was Created       
36: * by Neil Davies neild001 'at' gmail dot com to be a Coverflow widget      
37: *       
38: * @author Neil Davies      
39: */      
40: public class ImageAdapter extends BaseAdapter {      
41:         int mGalleryItemBackground;      
42:         private Context mContext;      
43:        
44:         private int[] mImageIds;      
45:        
46:         private ImageView[] mImages;      
47:        
48:         public ImageAdapter(Context c, int[] ImageIds) {      
49:                 mContext = c;      
50:                 mImageIds = ImageIds;      
51:                 mImages = new ImageView[mImageIds.length];      
52:         }      
53:        
54:         public boolean createReflectedImages() {      
55:                 // The gap we want between the reflection and the original image      
56:                 final int reflectionGap = 4;      
58:        
59:        
60:                 int index = 0;      
61:                 for (int imageId : mImageIds) {      
62:                         Bitmap originalImage = BitmapFactory.decodeResource(mContext      
63:                                         .getResources(), imageId);      
64:                         int width = originalImage.getWidth();      
65:                         int height = originalImage.getHeight();      
66:        
67:                         // This will not scale but will flip on the Y axis      
68:                         Matrix matrix = new Matrix();      
69:                         matrix.preScale(1, -1);      
70:        
71:                         // Create a Bitmap with the flip matrix applied to it.      
72:                         // We only want the bottom half of the image      
73:                         Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,      
74:                                         height / 2, width, height / 2, matrix, false);      
75:        
76:                         // Create a new bitmap with same width but taller to fit      
77:                         // reflection      
78:                         Bitmap bitmapWithReflection = Bitmap.createBitmap(width,      
79:                                         (height + height / 2), Config.ARGB_8888);      
80:        
81:                         // Create a new Canvas with the bitmap that's big enough for      
82:                         // the image plus gap plus reflection      
83:                         Canvas canvas = new Canvas(bitmapWithReflection);      
84:                         // Draw in the original image      
85:                         canvas.drawBitmap(originalImage, 0, 0, null);      
86:                         // Draw in the gap      
87:                         Paint deafaultPaint = new Paint();      
88:                         canvas.drawRect(0, height, width, height + reflectionGap,      
89:                                         deafaultPaint);      
90:                         // Draw in the reflection      
91:                         canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);      
92:        
93:                         // Create a shader that is a linear gradient that covers the      
94:                         // reflection      
95:                         Paint paint = new Paint();      
96:                         LinearGradient shader = new LinearGradient(0, originalImage      
97:                                         .getHeight(), 0, bitmapWithReflection.getHeight()      
98:                                         + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);      
99:                         // Set the paint to use this shader (linear gradient)      
100:                         paint.setShader(shader);      
101:                         // Set the Transfer mode to be porter duff and destination in      
102:                         paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));      
103:                         // Draw a rectangle using the paint with our linear gradient      
104:                         canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()      
105:                                         + reflectionGap, paint);      
106:                         //解決圖檔的鋸齒現象      
107:                         BitmapDrawable bd = new BitmapDrawable(bitmapWithReflection);      
108:                         bd.setAntiAlias(true);      
109:        
110:                         ImageView imageView = new ImageView(mContext);      
111:                         //imageView.setImageBitmap(bitmapWithReflection);      
112:                         imageView.setImageDrawable(bd);      
113:                         imageView.setLayoutParams(new GalleryFlow.LayoutParams(160, 240));      
114:                         // imageView.setScaleType(ScaleType.MATRIX);      
115:                         mImages[index++] = imageView;      
116:        
117:                 }      
118:                 return true;      
119:         }      
120:        
121:         public int getCount() {      
122:                 return mImageIds.length;      
123:         }      
124:        
125:         public Object getItem(int position) {      
126:                 return position;      
127:         }      
128:        
129:         public long getItemId(int position) {      
130:                 return position;      
131:         }      
132:        
133:         public View getView(int position, View convertView, ViewGroup parent) {      
134:        
135:                 // Use this code if you want to load from resources      
136:                 /*      
137:                  * ImageView i = new ImageView(mContext);      
138:                  * i.setImageResource(mImageIds[position]); i.setLayoutParams(new      
139:                  * CoverFlow.LayoutParams(350,350));      
140:                  * i.setScaleType(ImageView.ScaleType.CENTER_INSIDE);      
141:                  *       
142:                  * //Make sure we set anti-aliasing otherwise we get jaggies      
143:                  * BitmapDrawable drawable = (BitmapDrawable) i.getDrawable();      
144:                  * drawable.setAntiAlias(true); return i;      
145:                  */      
146:        
147:                 return mImages[position];      
148:         }      
149:        
150:         /**      
151:          * Returns the size (0.0f to 1.0f) of the views depending on the 'offset' to      
152:          * the center.      
153:          */      
154:         public float getScale(boolean focused, int offset) {      
155:                 /* Formula: 1 / (2 ^ offset) */      
156:                 return Math.max(0, 1.0f / (float) Math.pow(2, Math.abs(offset)));      
157:         }      
158:        
159: }      

MainActivity.java 用來顯示界面

1: package com.android.CustomGallery;      
2:        
3: /**      
4: * 一個實作了3D效果的Gallery,就像iPhone中的相冊浏覽一樣炫……      
5: */      
6: import android.app.Activity;      
7: import android.os.Bundle;      
8:        
9: public class MainActivity extends Activity {      
10:         /** Called when the activity is first created. */      
11:         @Override      
12:         public void onCreate(Bundle savedInstanceState) {      
13:                 super.onCreate(savedInstanceState);      
14:        
15:                 setContentView(R.layout.main);      
16:        
17:                 int[] images = { R.drawable.photo1, R.drawable.photo2,      
18:                                 R.drawable.photo3, R.drawable.photo4, R.drawable.photo5,      
19:                                 R.drawable.photo6, R.drawable.photo7, R.drawable.photo8, };      
20:        
21:                 ImageAdapter adapter = new ImageAdapter(this, images);      
22:                 adapter.createReflectedImages();      
23:        
24:                 GalleryFlow galleryFlow = (GalleryFlow) findViewById(R.id.gallery_flow);      
25:                 galleryFlow.setAdapter(adapter);      
26:        
27:         }      
28: }      

main.xml 程式設定檔案

1: 
   "1.0" encoding="utf-8"?>      
2: "http://schemas.android.com/apk/res/android"      
3:     android:orientation="vertical"      
4:     android:layout_width="fill_parent"      
5:     android:layout_height="fill_parent"      
6:     >      
7:          
8:         android:id="@+id/gallery_flow"      
9:         android:layout_width="fill_parent"      
10:         android:layout_height="fill_parent"