Android实现CoverFlow效果
6386 点击·0 回帖
![]() | ![]() | |
![]() | 先上一张效果图: ![]() 上代码,看了代码什么都明白 CoverFlow从Gallery继承过来 001 package com.coverflow; 002 003 import Android.content.Context; 004 import Android.graphics.Camera; 005 import Android.graphics.Matrix; 006 import Android.util.AttributeSet; 007 import Android.view.View; 008 import Android.view.animation.Transformation; 009 import Android.widget.Gallery; 010 import Android.widget.ImageView; 011 012 public class CoverFlow extends Gallery { 013 014 private Camera mCamera = new Camera(); 015 private int mMaxRotationAngle = 50; 016 private int mMaxZoom = -380; 017 private int mCoveflowCenter; 018 private boolean mAlphaMode = true; 019 private boolean mCircleMode = false; 020 021 public CoverFlow(Context context) { 022 super(context); 023 this.setStaticTransformationsEnabled(true); 024 } 025 026 public CoverFlow(Context context, AttributeSet attrs) { 027 super(context, attrs); 028 this.setStaticTransformationsEnabled(true); 029 } 030 031 public CoverFlow(Context context, AttributeSet attrs, int defStyle) { 032 super(context, attrs, defStyle); 033 this.setStaticTransformationsEnabled(true); 034 } 035 036 public int getMaxRotationAngle() { 037 return mMaxRotationAngle; 038 } 039 040 public void setMaxRotationAngle(int maxRotationAngle) { 041 mMaxRotationAngle = maxRotationAngle; 042 } 043 044 public boolean getCircleMode() { 045 return mCircleMode; 046 } 047 048 public void setCircleMode(boolean isCircle) { 049 mCircleMode = isCircle; 050 } 051 052 public boolean getAlphaMode() { 053 return mAlphaMode; 054 } 055 056 public void setAlphaMode(boolean isAlpha) { 057 mAlphaMode = isAlpha; 058 } 059 060 public int getMaxZoom() { 061 return mMaxZoom; 062 } 063 064 public void setMaxZoom(int maxZoom) { 065 mMaxZoom = maxZoom; 066 } 067 068 private int getCenterOfCoverflow() { 069 return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2 070 + getPaddingLeft(); 071 } 072 073 private static int getCenterOfView(View view) { 074 return view.getLeft() + view.getWidth() / 2; 075 } 076 077 protected boolean getChildStaticTransformation(View child, Transformation t) { 078 final int childCenter = getCenterOfView(child); 079 final int childWidth = child.getWidth(); 080 int rotationAngle = 0; 081 t.clear(); 082 t.setTransformationType(Transformation.TYPE_MATRIX); 083 if (childCenter == mCoveflowCenter) { 084 transformImageBitmap((ImageView) child, t, 0); 085 } else { 086 rotationAngle = (int) (((float) (mCoveflowCenter - childCenter) / childWidth) * mMaxRotationAngle); 087 if (Math.abs(rotationAngle) > mMaxRotationAngle) { 088 rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle 089 : mMaxRotationAngle; 090 } 091 transformImageBitmap((ImageView) child, t, rotationAngle); 092 } 093 return true; 094 } 095 096 /** 097 * 这就是所谓的在大小的布局时,这一观点已经发生了改变。如果 你只是添加到视图层次,有人叫你旧的观念 价值观为0。 098 * 099 * @param w 100 * Current width of this view. 101 * @param h 102 * Current height of this view. 103 * @param oldw 104 * Old width of this view. 105 * @param oldh 106 * Old height of this view. 107 */ 108 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 109 mCoveflowCenter = getCenterOfCoverflow(); 110 super.onSizeChanged(w, h, oldw, oldh); 111 } 112 113 /** 114 * 把图像位图的角度通过 115 * 116 * @param imageView 117 * ImageView the ImageView whose bitmap we want to rotate 118 * @param t 119 * transformation 120 * @param rotationAngle 121 * the Angle by which to rotate the Bitmap 122 */ 123 private void transformImageBitmap(ImageView child, Transformation t, 124 int rotationAngle) { 125 mCamera.save(); 126 final Matrix imageMatrix = t.getMatrix(); 127 final int imageHeight = child.getLayoutParams().height; 128 final int imageWidth = child.getLayoutParams().width; 129 final int rotation = Math.abs(rotationAngle); 130 mCamera.translate(0.0f, 0.0f, 100.0f); 131 132 // 如视图的角度更少,放大 133 if (rotation <= mMaxRotationAngle) { 134 float zoomAmount = (float) (mMaxZoom + (rotation * 1.5)); 135 mCamera.translate(0.0f, 0.0f, zoomAmount); 136 if (mCircleMode) { 137 if (rotation < 40) 138 mCamera.translate(0.0f, 155, 0.0f); 139 else 140 mCamera.translate(0.0f, (255 - rotation * 2.5f), 0.0f); 141 } 142 if (mAlphaMode) { 143 ((ImageView) (child)).setAlpha((int) (255 - rotation * 2.5)); 144 } 145 } 146 mCamera.rotateY(rotationAngle); 147 mCamera.getMatrix(imageMatrix); 148 imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2)); 149 imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2)); 150 mCamera.restore(); 151 } 152 } 这个就是CoverFlow类,说明几点: 1. 成员函数 mCamera是用来做类3D效果处理,比如z轴方向上的平移,绕y轴的旋转等 mMaxRotationAngle是图片绕y轴最大旋转角度,也就是屏幕最边上那两张图片的旋转角度 mMaxZoom是图片在z轴平移的距离,视觉上看起来就是放大缩小的效果. 其他的变量都可以无视 也就是说把这个属性设成true的时候每次viewGroup(看Gallery的源码就可以看到它是从ViewGroup间接继承过来的)在重新画它的child的时候都会促发getChildStaticTransformation这个函数,所以我们只需要在这个函数里面去加上旋转和放大的操作就可以了 其他的getter和setter函数都可以无视 ImageAdapter适配器: 001 package com.coverflow; 002 003 import Android.content.Context; 004 import Android.graphics.Bitmap; 005 import Android.graphics.BitmapFactory; 006 import Android.graphics.Canvas; 007 import Android.graphics.LinearGradient; 008 import Android.graphics.Matrix; 009 import Android.graphics.Paint; 010 import Android.graphics.PorterDuffXfermode; 011 import Android.graphics.Bitmap.Config; 012 import Android.graphics.PorterDuff.Mode; 013 import Android.graphics.Shader.TileMode; 014 import Android.graphics.drawable.BitmapDrawable; 015 import Android.view.View; 016 import Android.view.ViewGroup; 017 import Android.widget.BaseAdapter; 018 import Android.widget.ImageView; 019 020 import com.gallery.R; 021 022 public class ImageAdapter extends BaseAdapter { 023 int mGalleryItemBackground; 024 private Context mContext; 025 private Integer[] mImageIds = { 026 R.drawable.a1, 027 R.drawable.a2, 028 R.drawable.a3, 029 R.drawable.a4, 030 R.drawable.a5 }; 031 032 public ImageAdapter(Context c) { 033 mContext = c; 034 } 035 036 public int getCount() { 037 return mImageIds.length; 038 } 039 040 public Object getItem(int position) { 041 return position; 042 } 043 044 public long getItemId(int position) { 045 return position; 046 } 047 048 public View getView(int position, View convertView, ViewGroup parent) { 049 050 ImageView i = createReflectedImages(mContext,mImageIds[position]); 051 052 i.setLayoutParams(new CoverFlow.LayoutParams(120, 100)); 053 i.setScaleType(ImageView.ScaleType.CENTER_INSIDE); 054 055 // 设置的抗锯齿 056 BitmapDrawable drawable = (BitmapDrawable) i.getDrawable(); 057 drawable.setAntiAlias(true); 058 return i; 059 } 060 061 public float getScale(boolean focused, int offset) { 062 return Math.max(0, 1.0f / (float) Math.pow(2, Math.abs(offset))); 063 } 064 065 public ImageView createReflectedImages(Context mContext,int imageId) { 066 067 Bitmap originalImage = BitmapFactory.decodeResource(mContext.getResources(), imageId); 068 069 final int reflectionGap = 4; 070 071 int width = originalImage.getWidth(); 072 int height = originalImage.getHeight(); 073 074 Matrix matrix = new Matrix(); 075 matrix.preScale(1, -1); 076 077 Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, 078 height / 2, width, height / 2, matrix, false); 079 080 Bitmap bitmapWithReflection = Bitmap.createBitmap(width, 081 (height + height / 2), Config.ARGB_8888); 082 083 Canvas canvas = new Canvas(bitmapWithReflection); 084 085 canvas.drawBitmap(originalImage, 0, 0, null); 086 087 Paint deafaultPaint = new Paint(); 088 canvas.drawRect(0, height, width, height + reflectionGap, deafaultPaint); 089 090 canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null); 091 092 Paint paint = new Paint(); 093 LinearGradient shader = new LinearGradient(0, originalImage 094 .getHeight(), 0, bitmapWithReflection.getHeight() 095 + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.MIRROR); 096 097 paint.setShader(shader); 098 099 paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN)); 100 101 canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() 102 + reflectionGap, paint); 103 104 ImageView imageView = new ImageView(mContext); 105 imageView.setImageBitmap(bitmapWithReflection); 106 107 return imageView; 108 } 109 110 } BitmapDrawable drawable = (BitmapDrawable) i.getDrawable(); drawable.setAntiAlias(true); 是保证图片绕Y旋转了以后不会出现锯齿. 下面是Activity: 01 package com.coverflow; 02 03 import Android.app.Activity; 04 import Android.graphics.Color; 05 import Android.os.Bundle; 06 07 import com.gallery.R; 08 09 public class HelloAndroid extends Activity { 10 /** Called when the activity is first created. */ 11 @Override 12 public void onCreate(Bundle savedInstanceState) { 13 super.onCreate(savedInstanceState); 14 15 CoverFlow cf = new CoverFlow(this); 16 // cf.setBackgroundResource(R.drawable.shape); 17 cf.setBackgroundColor(Color.BLACK); 18 cf.setAdapter(new ImageAdapter(this)); 19 ImageAdapter imageAdapter = new ImageAdapter(this); 20 cf.setAdapter(imageAdapter); 21 // cf.setAlphaMode(false); 22 // cf.setCircleMode(false); 23 cf.setSelection(2, true); 24 cf.setAnimationDuration(1000); 25 setContentView(cf); 26 } 27 28 } 摘自 迷途ф書童 | |
![]() | ![]() |