Android Gallery实现苹果的coverflow效果

最近在学Gallery,功能是实现了,但是效果特别差,跟iphone的coverflow是没发比的,然后就在网上搜索了一些关于Gallery的高级用法什么的,网上很多实现了基于android的Gallery的coverflow效果,但看了源代码,我还是很多看不懂。(初学android,好多方法没看到过)后来我就按网上写的在自己的eclipes里运行了一下。在他代码的基础上实现了循环播放的效果。虽然结果出来了,但我还是一知半解的。(希望大家能给我个好的链接介绍这种效果的)。谢谢

第一步:编写布局layout_grally.xml文件,具体代码如下:

View Code
 1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:orientation="vertical"
4 android:layout_width="fill_parent"
5 android:layout_height="fill_parent"
6 android:background="#ffffff"
7 >
8 <cn.shaoyangjiang.com.GalleryFlow
9 android:id="@+id/Gallery01"
10 android:layout_width="fill_parent"
11 android:layout_height="wrap_content"
12 android:layout_centerInParent="true"
13 android:spacing="-60px"/>
14 </LinearLayout>

第二步:在values文件夹下修改string.xml文件,一开始,我就是因为没修改这个文件,然后一直编译不出来,浪费了很长时间。总结出一点,拷别人写的代码也要拷全了,不然编译不会通过

View Code
1 <?xml version="1.0" encoding="utf-8"?>
2 <resources>
3 <string name="hello">Hello World, ActivityMain!</string>
4 <string name="app_name">Gallery</string>
5 </resources>

第三步:编写主的ActivityMain.java文件,这个比较简单,主要是对Gallery设置Adapter就可以了,我想这个大家都应该看的懂,具体代码如下:

View Code
 1 package cn.shaoyangjiang.com;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5
6 public class ActivityMain extends Activity {
7 public void onCreate(Bundle savedInstanceState) {
8 super.onCreate(savedInstanceState);
9 setContentView(R.layout.layout_gallery);
10 Integer[] images = { R.drawable.shao4,
11 R.drawable.shao1, R.drawable.shao2, R.drawable.shao3,
12 R.drawable.shao5,R.drawable.hawana_0,R.drawable.huanyinghei_14,
13 R.drawable.huanyinghei_6,R.drawable.wulonghui_24,R.drawable.xuanfenghei_10};
14
15 ImageAdapter adapter = new ImageAdapter(this, images);
16 adapter.createReflectedImages();
17
18 GalleryFlow galleryFlow = (GalleryFlow) findViewById(R.id.Gallery01);
19 galleryFlow.setAdapter(adapter);
20
21 }
22 }

第四步,编写ImageAdapter.java这个类,这个类也还算简单,继承BaseAdapter,重写getCount(),getItem(),getItems,getView(),这四个方法,我在这里对网上的源码稍微做了点修改,

/*让Galllery循环播放的方法
 * 1. 使getCount方法返回一个很大的值。建议返回Integer.MAX_VALUE。,这个值可以到达20亿多
 * 2. 在getView方法中通过取余来循环取得resIds数组中的图像资源ID。
 * 3.循环Gallery参考http://blog.csdn.net/herryz/article/details/6141957
 */

具体代码如下:

View Code
  1 package cn.shaoyangjiang.com;
2
3 import android.content.Context;
4 import android.content.res.Resources;
5 import android.graphics.Bitmap;
6 import android.graphics.BitmapFactory;
7 import android.graphics.Canvas;
8 import android.graphics.LinearGradient;
9 import android.graphics.Matrix;
10 import android.graphics.Paint;
11 import android.graphics.PorterDuffXfermode;
12 import android.graphics.Bitmap.Config;
13 import android.graphics.PorterDuff.Mode;
14 import android.graphics.Shader.TileMode;
15 import android.view.View;
16 import android.view.ViewGroup;
17 import android.widget.BaseAdapter;
18 import android.widget.ImageView;
19 import android.widget.ImageView.ScaleType;
20
21 public class ImageAdapter extends BaseAdapter {
22
23 int mGalleryItemBackground;
24 private Context mContext;
25 private Integer[] mImageIds;
26 private ImageView[] mImages;
27
28 public ImageAdapter(Context c, Integer[] ImageIds) {
29 mContext = c;
30 mImageIds = ImageIds;
31 mImages = new ImageView[mImageIds.length];
32 }
33
34 public boolean createReflectedImages() {
35 final int reflectionGap = 4;
36 int index = 0;
37
38 for (int imageId : mImageIds) {
39 Bitmap originalImage = BitmapFactory.decodeResource(mContext
40 .getResources(), imageId);
41 int width = originalImage.getWidth();
42 int height = originalImage.getHeight();
43
44 Matrix matrix = new Matrix();
45 matrix.preScale(1, -1);
46
47 Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,
48 height / 2, width, height / 2, matrix, false);
49
50 Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
51 (height + height / 2), Config.ARGB_8888);
52
53 Canvas canvas = new Canvas(bitmapWithReflection);
54
55 canvas.drawBitmap(originalImage, 0, 0, null);
56
57 Paint deafaultPaint = new Paint();
58 canvas.drawRect(0, height, width, height + reflectionGap,
59 deafaultPaint);
60
61 canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
62
63 Paint paint = new Paint();
64 LinearGradient shader = new LinearGradient(0, originalImage
65 .getHeight(), 0, bitmapWithReflection.getHeight()
66 + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
67
68 paint.setShader(shader);
69
70 paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
71
72 canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
73 + reflectionGap, paint);
74
75 ImageView imageView = new ImageView(mContext);
76 imageView.setImageBitmap(bitmapWithReflection);
77 imageView.setLayoutParams(new GalleryFlow.LayoutParams(200, 350));
78 // imageView.setScaleType(ScaleType.MATRIX);
79 mImages[index++] = imageView;
80 }
81 return true;
82 }
83
84 private Resources getResources() {
85 // TODO Auto-generated method stub
86 return null;
87 }
88
89 public int getCount() {
90 //return mImageIds.length;
91 return Integer.MAX_VALUE;
92 }
93
94 public Object getItem(int position) {
95 return position;
96 }
97
98 public long getItemId(int position) {
99 return position;
100 }
101
102 public View getView(int position, View convertView, ViewGroup parent) {
103 return mImages[position%mImageIds.length];
104 //return mImages[position];
105 }
106 //
107 // public float getScale(boolean focused, int offset) {
108 // return Math.max(0, 1.0f / (float) Math.pow(2, Math.abs(offset)));
109 // }
110
111 }

第五步,也是最头疼,也是我看不懂的,我大致理解自定义一个类是继承了Gallery,贴上网上他们说的

/*仅仅实现了图片的倒影效果还不够,因为在coverflow中图片切换是有旋转和缩放效果的,
 * 而自带的gallery中并没有实现。因此,我们扩展自带的gallery,实现自己的galleryflow。
 * 在原gallery类中,提供了一个方法getChildStaticTransformation()以实现对图片的变换。
 * 我们通过覆写这个方法并在其中调用自定义的transformImageBitmap(“每个图片与gallery中心的距离”)方法,
 * ,即可实现每个图片做相应的旋转和缩放。其中使用了camera和matrix用于视图变换
 *
 *  1. 成员函数

       mCamera是用来做类3D效果处理,比如z轴方向上的平移,绕y轴的旋转等
       mMaxRotationAngle是图片绕y轴最大旋转角度,也就是屏幕最边上那两张图片的旋转角度
       mMaxZoom是图片在z轴平移的距离,视觉上看起来就是放大缩小的效果.
       其他的变量都可以无视

       也就是说把这个属性设成true的时候每次viewGroup(看Gallery的源码就可以看到它是从ViewGroup间接继承过来的)在重新画它的child的时候都会促发getChildStaticTransformation这个函数,所以我们只需要在这个函数里面去加上旋转和放大的操作就可以了

       其他的getter和setter函数都可以无视

 具体代码如下:

View Code
  1 package cn.shaoyangjiang.com;
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 private Camera mCamera = new Camera();
16 private int mMaxRotationAngle = 60;
17 private int mMaxZoom = -120;
18 private int mCoveflowCenter;
19
20 public GalleryFlow(Context context) {
21 super(context);
22 this.setStaticTransformationsEnabled(true);
23 }
24
25 public GalleryFlow(Context context, AttributeSet attrs) {
26 super(context, attrs);
27 this.setStaticTransformationsEnabled(true);
28 }
29
30 public GalleryFlow(Context context, AttributeSet attrs, int defStyle) {
31 super(context, attrs, defStyle);
32 this.setStaticTransformationsEnabled(true);
33 }
34
35 public int getMaxRotationAngle() {
36 return mMaxRotationAngle;
37 }
38
39 public void setMaxRotationAngle(int maxRotationAngle) {
40 mMaxRotationAngle = maxRotationAngle;
41 }
42
43 public int getMaxZoom() {
44 return mMaxZoom;
45 }
46
47 public void setMaxZoom(int maxZoom) {
48 mMaxZoom = maxZoom;
49 }
50
51 private int getCenterOfCoverflow() {
52 return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2
53 + getPaddingLeft();
54 }
55
56 private static int getCenterOfView(View view) {
57 return view.getLeft() + view.getWidth() / 2;
58 }
59
60 protected boolean getChildStaticTransformation(View child, Transformation t) {
61
62 final int childCenter = getCenterOfView(child);
63 final int childWidth = child.getWidth();
64 int rotationAngle = 0;
65
66 t.clear();
67 t.setTransformationType(Transformation.TYPE_MATRIX);
68 Log.v("tag", "getChildStaticTransformation>>>>>>>>>>>>>>>>>>>childCenter"+childCenter+">>>>>"+Math.abs((mCoveflowCenter-childCenter)/(childWidth)));
69 if (childCenter == mCoveflowCenter) {
70 transformImageBitmap((ImageView) child, t, 0);
71 } else {
72 if ((mCoveflowCenter - childCenter) > 0) {
73 rotationAngle = (int) mMaxRotationAngle;
74 } else {
75 rotationAngle = (int) -mMaxRotationAngle;
76 }
77 if(Math.abs((mCoveflowCenter-childCenter)/(childWidth/2))==0){
78 rotationAngle = (int) (((float) (mCoveflowCenter - childCenter) /
79 childWidth) * mMaxRotationAngle);
80 }
81
82 transformImageBitmap((ImageView) child, t, rotationAngle);
83 }
84
85 return true;
86 }
87
88 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
89 mCoveflowCenter = getCenterOfCoverflow();
90 super.onSizeChanged(w, h, oldw, oldh);
91 }
92
93 private void transformImageBitmap(ImageView child, Transformation t,
94 int rotationAngle) {
95 mCamera.save();
96 final Matrix imageMatrix = t.getMatrix();
97 final int imageHeight = child.getLayoutParams().height;
98 final int imageWidth = child.getLayoutParams().width;
99 final int rotation = Math.abs(rotationAngle);
100
101 // 在Z轴上正向移动camera的视角,实际效果为放大图片。
102 // 如果在Y轴上移动,则图片上下移动;X轴上对应图片左右移动。
103 mCamera.translate(0.0f, 0.0f, 100.0f);
104
105 //// As the angle of the view gets less, zoom in
106 // if (rotation < mMaxRotationAngle) {
107 // float zoomAmount = (float) (mMaxZoom + (rotation * 1.5));
108 // mCamera.translate(0.0f, 0.0f, zoomAmount);
109 // }
110
111 // 在Y轴上旋转,对应图片竖向向里翻转。
112 // 如果在X轴上旋转,则对应图片横向向里翻转。
113 mCamera.rotateY(rotationAngle);
114 mCamera.getMatrix(imageMatrix);
115 imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));
116 imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));
117 mCamera.restore();
118 }
119 }

显示演示效果:

注:这个程序基本上没自己敲写,都是网上复制粘帖的,哈哈,水平还是差了点,不过一直在努力学习中。



 

posted on 2012-02-25 14:02  forrest001  阅读(2804)  评论(1编辑  收藏  举报

导航