Android作业:一个3D相册源码
我们专业课有Android的学习,最后老师让做一个简单的Android应用程序.我在网上找些资料,加上自己改造一下做了一个3D相册.
程序仿照Android的相册功能,调用Gallery类对相片进行浏览.实现3D效果.其中不足的地方就是里面的图片都是写死的.这一点可以改进.程序中使用Png格式图片,注意图片不要太大,500*500一下最好.
首先:
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;
57:
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"11: />