我们专业课有Android的学习,最后老师让做一个简单的Android应用程序.我在网上找些资料,加上自己改造一下做了一个3D相册.
程序仿照Android的相册功能,调用Gallery类对相片进行浏览.实现3D效果.其中不足的地方就是里面的图片都是写死的.这一点可以改进.程序中使用Png格式图片,注意图片不要太大,500*500一下最好.
首先:
GalleryFlow.java 类 用来实现图片放映查看效果.
package com.android.CustomGallery;
2:
import android.content.Context;
import android.graphics.Camera;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.Transformation;
import android.widget.Gallery;
import android.widget.ImageView;
12:
extends Gallery {
14:
/**
* Graphics Camera used for transforming the matrix of ImageViews
*/
new Camera();
19:
/**
* The maximum angle the Child ImageView will be rotated by
*/
int mMaxRotationAngle = 60;
24:
/**
* The maximum zoom on the centre Child
*/
int mMaxZoom = -120;
29:
/**
* The Centre of the Coverflow
*/
int mCoveflowCenter;
34:
public GalleryFlow(Context context) {
super(context);
this.setStaticTransformationsEnabled(true);
38: }
39:
public GalleryFlow(Context context, AttributeSet attrs) {
super(context, attrs);
this.setStaticTransformationsEnabled(true);
43: }
44:
int defStyle) {
super(context, attrs, defStyle);
this.setStaticTransformationsEnabled(true);
48: }
49:
/**
* Get the max rotational angle of the image
*
* @return the mMaxRotationAngle
*/
int getMaxRotationAngle() {
return mMaxRotationAngle;
57: }
58:
/**
* Set the max rotational angle of each image
*
* @param maxRotationAngle
* the mMaxRotationAngle to set
*/
int maxRotationAngle) {
66: mMaxRotationAngle = maxRotationAngle;
67: }
68:
/**
* Get the Max zoom of the centre image
*
* @return the mMaxZoom
*/
int getMaxZoom() {
return mMaxZoom;
76: }
77:
/**
* Set the max zoom of the centre image
*
* @param maxZoom
* the mMaxZoom to set
*/
int maxZoom) {
85: mMaxZoom = maxZoom;
86: }
87:
/**
* Get the Centre of the Coverflow
*
* @return The centre of this Coverflow.
*/
int getCenterOfCoverflow() {
return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2
96: + getPaddingLeft();
97: }
98:
/**
* Get the Centre of the View
*
* @return The centre of the given view.
*/
int getCenterOfView(View view) {
+ view.getHeight());*/
return view.getLeft() + view.getWidth() / 2;
108: }
109:
/**
* {@inheritDoc}
*
* @see #setStaticTransformationsEnabled(boolean)
*/
boolean getChildStaticTransformation(View child, Transformation t) {
116:
int childCenter = getCenterOfView(child);
int childWidth = child.getWidth();
int rotationAngle = 0;
120:
121: t.clear();
122: t.setTransformationType(Transformation.TYPE_MATRIX);
123:
if (childCenter == mCoveflowCenter) {
125: transformImageBitmap((ImageView) child, t, 0);
else {
float) (mCoveflowCenter - childCenter) / childWidth) * mMaxRotationAngle);
if (Math.abs(rotationAngle) > mMaxRotationAngle) {
129: rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle
130: : mMaxRotationAngle;
131: }
132: transformImageBitmap((ImageView) child, t, rotationAngle);
133: }
134:
return true;
136: }
137:
/**
* This is called during layout when the size of this view has changed. If
* you were just added to the view hierarchy, you're called with the old
* values of 0.
*
* @param w
* Current width of this view.
* @param h
* Current height of this view.
* @param oldw
* Old width of this view.
* @param oldh
* Old height of this view.
*/
int oldh) {
153: mCoveflowCenter = getCenterOfCoverflow();
super.onSizeChanged(w, h, oldw, oldh);
155: }
156:
/**
* Transform the Image Bitmap by the Angle passed
*
* @param imageView
* ImageView the ImageView whose bitmap we want to rotate
* @param t
* transformation
* @param rotationAngle
* the Angle by which to rotate the Bitmap
*/
void transformImageBitmap(ImageView child, Transformation t,
int rotationAngle) {
169: mCamera.save();
final Matrix imageMatrix = t.getMatrix();
int imageHeight = child.getLayoutParams().height;
int imageWidth = child.getLayoutParams().width;
int rotation = Math.abs(rotationAngle);
174:
// 在Z轴上正向移动camera的视角,实际效果为放大图片。
// 如果在Y轴上移动,则图片上下移动;X轴上对应图片左右移动。
177: mCamera.translate(0.0f, 0.0f, 100.0f);
178:
// As the angle of the view gets less, zoom in
if (rotation < mMaxRotationAngle) {
float) (mMaxZoom + (rotation * 1.5));
182: mCamera.translate(0.0f, 0.0f, zoomAmount);
183: }
184:
// 在Y轴上旋转,对应图片竖向向里翻转。
// 如果在X轴上旋转,则对应图片横向向里翻转。
187: mCamera.rotateY(rotationAngle);
188: mCamera.getMatrix(imageMatrix);
// 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 图片适配器类,用来将文件中的图片资源加载到应用程序
package com.android.CustomGallery;
2:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
19:
/*
* Copyright (C) 2010 Neil Davies
*
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This code is base on the Android Gallery widget and was Created
* by Neil Davies neild001 'at' gmail dot com to be a Coverflow widget
*
* @author Neil Davies
*/
extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
43:
int[] mImageIds;
45:
private ImageView[] mImages;
47:
int[] ImageIds) {
49: mContext = c;
50: mImageIds = ImageIds;
new ImageView[mImageIds.length];
52: }
53:
boolean createReflectedImages() {
// The gap we want between the reflection and the original image
int reflectionGap = 4;
57:
58:
59:
int index = 0;
int imageId : mImageIds) {
62: Bitmap originalImage = BitmapFactory.decodeResource(mContext
63: .getResources(), imageId);
int width = originalImage.getWidth();
int height = originalImage.getHeight();
66:
// This will not scale but will flip on the Y axis
new Matrix();
69: matrix.preScale(1, -1);
70:
// Create a Bitmap with the flip matrix applied to it.
// 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:
// Create a new bitmap with same width but taller to fit
// reflection
78: Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
79: (height + height / 2), Config.ARGB_8888);
80:
// Create a new Canvas with the bitmap that's big enough for
// the image plus gap plus reflection
new Canvas(bitmapWithReflection);
// Draw in the original image
85: canvas.drawBitmap(originalImage, 0, 0, null);
// Draw in the gap
new Paint();
88: canvas.drawRect(0, height, width, height + reflectionGap,
89: deafaultPaint);
// Draw in the reflection
91: canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
92:
// Create a shader that is a linear gradient that covers the
// reflection
new Paint();
new LinearGradient(0, originalImage
97: .getHeight(), 0, bitmapWithReflection.getHeight()
98: + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
// Set the paint to use this shader (linear gradient)
100: paint.setShader(shader);
// Set the Transfer mode to be porter duff and destination in
new PorterDuffXfermode(Mode.DST_IN));
// Draw a rectangle using the paint with our linear gradient
104: canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
105: + reflectionGap, paint);
//解决图片的锯齿现象
new BitmapDrawable(bitmapWithReflection);
108: bd.setAntiAlias(true);
109:
new ImageView(mContext);
//imageView.setImageBitmap(bitmapWithReflection);
112: imageView.setImageDrawable(bd);
new GalleryFlow.LayoutParams(160, 240));
// imageView.setScaleType(ScaleType.MATRIX);
115: mImages[index++] = imageView;
116:
117: }
return true;
119: }
120:
int getCount() {
return mImageIds.length;
123: }
124:
int position) {
return position;
127: }
128:
int position) {
return position;
131: }
132:
int position, View convertView, ViewGroup parent) {
134:
// Use this code if you want to load from resources
/*
* ImageView i = new ImageView(mContext);
* i.setImageResource(mImageIds[position]); i.setLayoutParams(new
* CoverFlow.LayoutParams(350,350));
* i.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
*
* //Make sure we set anti-aliasing otherwise we get jaggies
* BitmapDrawable drawable = (BitmapDrawable) i.getDrawable();
* drawable.setAntiAlias(true); return i;
*/
146:
return mImages[position];
148: }
149:
/**
* Returns the size (0.0f to 1.0f) of the views depending on the 'offset' to
* the center.
*/
int offset) {
/* Formula: 1 / (2 ^ offset) */
float) Math.pow(2, Math.abs(offset)));
157: }
158:
159: }
MainActivity.java 用来显示界面
package com.android.CustomGallery;
2:
/**
* 一个实现了3D效果的Gallery,就像iPhone中的相册浏览一样炫……
*/
import android.app.Activity;
import android.os.Bundle;
8:
extends Activity {
/** Called when the activity is first created. */
11: @Override
void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
14:
15: setContentView(R.layout.main);
16:
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:
this, images);
22: adapter.createReflectedImages();
23:
24: GalleryFlow galleryFlow = (GalleryFlow) findViewById(R.id.gallery_flow);
25: galleryFlow.setAdapter(adapter);
26:
27: }
28: }
main.xml 程序设置文件
?>
6: >
11: />