在开始之前,必须了解什么是Context以及widget里的 BaseAdpater ,在Acitivity当中,Context就如同是张Canvas画布,随时等着被处理或覆盖。
主程序中较为重要的部分是在其中创建一个继承自BaseAdapter的ImageAdapter方法,这个ImageAdapter的存在目的,是为了要暂存欲显示的图片,并作为Gallery控件图片的源引用。
[代码] ActivityMain.java
01import Android.app.Activity;
02import Android.os.Bundle;
03import Android.view.View;
04import Android.widget.AdapterView;
05import Android.widget.Gallery;
06import Android.widget.Toast;
07import Android.widget.AdapterView.OnItemClickListener;
08
09public class ActivityMain extends Activity {
10
11 GalleryFlow galleryFlow = null;
12 OnItemClickListener onItemClickListen = null;
13 public void onCreate(Bundle savedInstanceState) {
14 super.onCreate(savedInstanceState);
15 setContentView(R.layout.layout_gallery);
16 Integer[] images = { R.drawable.img0001, R.drawable.img0030,
17 R.drawable.img0100, R.drawable.img0130, R.drawable.img0200,
18 R.drawable.img0230, R.drawable.img0300, R.drawable.img0330,
19 R.drawable.img0354 };
20 ImageAdapter adapter = new ImageAdapter(this, images);
21 adapter.createReflectedImages();
22 galleryFlow = (GalleryFlow) findViewById(R.id.Gallery01);
23 galleryFlow.setAdapter(adapter);
24 onItemClickListen = new OnItemClickListener()
25 {
26 public void onItemClick(AdapterViewparent, View view,int position, long id)
27 {
28 Toast.makeText( ActivityMain.this,"你选择了"+(position+1)+" 号图片", Toast.LENGTH_SHORT).show();
29 }
30 };
31 galleryFlow.setOnItemClickListener(onItemClickListen);
32
33 }
34}
[代码] GalleryFlow.java
001import Android.content.Context;
002import Android.graphics.Camera;
003import Android.graphics.Matrix;
004import Android.util.AttributeSet;
005import Android.view.View;
006import Android.view.animation.Transformation;
007import Android.widget.Gallery;
008import Android.widget.ImageView;
009
010public class GalleryFlow extends Gallery
011{
012 private Camera mCamera = new Camera();
013 private int mMaxRotationAngle = 60;
014 private int mMaxZoom = -120;
015 private int mCoveflowCenter;
016
017 public GalleryFlow(Context context)
018 {
019 super(context);
020 this.setStaticTransformationsEnabled(true);
021 }
022
023 public GalleryFlow(Context context, AttributeSet attrs)
024 {
025 super(context, attrs);
026 this.setStaticTransformationsEnabled(true);
027 }
028
029 public GalleryFlow(Context context, AttributeSet attrs, intdefStyle)
030 {
031 super(context, attrs, defStyle);
032 this.setStaticTransformationsEnabled(true);
033 }
034 public int getMaxRotationAngle()
035 {
036 return mMaxRotationAngle;
037 }
038 public void setMaxRotationAngle(int maxRotationAngle)
039 {
040 mMaxRotationAngle = maxRotationAngle;
041 }
042 public int getMaxZoom()
043 {
044 return mMaxZoom;
045 }
046
047 public void setMaxZoom(int maxZoom)
048 {
049 mMaxZoom = maxZoom;
050 }
051
052 private int getCenterOfCoverflow()
053 {
054 return (getWidth() - getPaddingLeft() - getPaddingRight()) /2+ getPaddingLeft();
055 }
056
057 private static int getCenterOfView(View view)
058 {
059 return view.getLeft() + view.getWidth() / 2;
060 }
061
062 protected boolean getChildStaticTransformation(View child, Transformation t)
063 {
064 final int childCenter = getCenterOfView(child);
065 final int childWidth = child.getWidth();
066 int rotationAngle = 0;
067 t.clear();
068 t.setTransformationType(Transformation.TYPE_MATRIX);
069
070 if (childCenter == mCoveflowCenter)
071 {
072 transformImageBitmap((ImageView) child, t, 0);
073 }
074 else
075 {
076 rotationAngle = (int) (((float) (mCoveflowCenter - childCenter) / childWidth) * mMaxRotationAngle);
077 if (Math.abs(rotationAngle) > mMaxRotationAngle)
078 {
079 rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle
080 : mMaxRotationAngle;
081 }
082 transformImageBitmap((ImageView) child, t, rotationAngle);
083 }
084 return true;
085 }
086
087 protected void onSizeChanged(int w, int h, int oldw, int oldh)
088 {
089 mCoveflowCenter = getCenterOfCoverflow();
090 super.onSizeChanged(w, h, oldw, oldh);
091 }
092
093 private void transformImageBitmap(ImageView child, Transformation t,
094 int rotationAngle)
095 {
096 mCamera.save();
097 final Matrix imageMatrix = t.getMatrix();
098 final int imageHeight = child.getLayoutParams().height;
099 final int imageWidth = child.getLayoutParams().width;
100 final int rotation = Math.abs(rotationAngle);
101
102 // 在Z轴上正向移动camera的视角,实际效果为放大图片。
103 // 如果在Y轴上移动,则图片上下移动;X轴上对应图片左右移动。
104 mCamera.translate(0.0f, 0.0f, 100.0f);
105
106 // As the angle of the view gets less, zoom in
107 if (rotation < mMaxRotationAngle) {
108 float zoomAmount = (float) (mMaxZoom + (rotation * 1.5));
109 mCamera.translate(0.0f, 0.0f, zoomAmount);
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}
[代码] ImageAdapter.java
001import Android.content.Context;
002import Android.content.res.Resources;
003import Android.graphics.Bitmap;
004import Android.graphics.BitmapFactory;
005import Android.graphics.Canvas;
006import Android.graphics.LinearGradient;
007import Android.graphics.Matrix;
008import Android.graphics.Paint;
009import Android.graphics.PorterDuffXfermode;
010import Android.graphics.Bitmap.Config;
011import Android.graphics.PorterDuff.Mode;
012import Android.graphics.Shader.TileMode;
013import Android.view.View;
014import Android.view.ViewGroup;
015import Android.widget.BaseAdapter;
016import Android.widget.ImageView;
017
018public class ImageAdapter extends BaseAdapter
019{
020 int mGalleryItemBackground;
021 private Context mContext;
022 private Integer[] mImageIds;
023 private ImageView[] mImages;
024
025 public ImageAdapter(Context c, Integer[] ImageIds)
026 {
027 mContext = c;
028 mImageIds = ImageIds;
029 mImages = new ImageView[mImageIds.length];
030 }
031 public ImageAdapter( Context c )
032 {
033 mContext = c;
034 }
035
036 public void SetImages( Integer[] ImageIds )
037 {
038 mImageIds = ImageIds;
039 mImages = new ImageView[mImageIds.length];
040 }
041
042 public boolean createReflectedImages()
043 {
044 final int reflectionGap = 4;
045 int index = 0;
046
047 for (int imageId : mImageIds)
048 {
049 Bitmap originalImage = BitmapFactory.decodeResource(mContext.getResources(), imageId);
050 int width = originalImage.getWidth();
051 int height = originalImage.getHeight();
052
053 Matrix matrix = new Matrix();
054 matrix.preScale(1, -1);
055
056 Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,
057 height / 2, width, height / 2, matrix, false);
058
059 Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
060 (height + height / 2), Config.ARGB_8888);
061
062 Canvas canvas = new Canvas(bitmapWithReflection);
063
064 canvas.drawBitmap(originalImage, 0, 0, null);
065
066 Paint deafaultPaint = new Paint();
067 canvas.drawRect(0, height, width, height + reflectionGap,
068 deafaultPaint);
069
070 canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
071
072 Paint paint = new Paint();
073 LinearGradient shader = new LinearGradient(0, originalImage
074 .getHeight(), 0, bitmapWithReflection.getHeight()
075 + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
076 paint.setShader(shader);
077 paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
078 canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint);
079
080 ImageView imageView = new ImageView(mContext);
081 imageView.setImageBitmap(bitmapWithReflection);
082 imageView.setLayoutParams(newGalleryFlow.LayoutParams(100, 100));
083// imageView.setScaleType(ScaleType.MATRIX);
084 mImages[index++] = imageView;
085 }
086 return true;
087 }
088
089 private Resources getResources()
090 {
091 // TODO Auto-generated method stub
092 return null;
093 }
094
095 public int getCount()
096 {
097 return mImageIds.length;
098 }
099
100 public Object getItem(int position)
101 {
102 return position;
103 }
104
105 public long getItemId(int position)
106 {
107 return position;
108 }
109
110 public View getView(int position, View convertView, ViewGroup parent)
111 {
112 return mImages[position];
113 }
114
115 public float getScale(boolean focused, int offset)
116 {
117 return Math.max(0, 1.0f / (float) Math.pow(2, Math.abs(offset)));
118 }
119}