MainActivity
package org.wp.activity;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CoverFlow coverFlow = new CoverFlow(this);
ImageAdapter imageAdapter = new ImageAdapter(this);
imageAdapter.createReflectedImages();
coverFlow.setAdapter(imageAdapter);
coverFlow.setSpacing(-(int) convertDip2Pixel(this, 40));
coverFlow.setSelection(2, true);
coverFlow.setAnimationDuration(1000);
coverFlow.setBackgroundColor(Color.WHITE);
setContentView(coverFlow);
}
public class ImageAdapter extends BaseAdapter {
private Integer[] mImageIds = { R.drawable.images1, R.drawable.images2,
R.drawable.images3, R.drawable.images4, R.drawable.images5,
R.drawable.images6, R.drawable.images7, R.drawable.images8,
R.drawable.images9, R.drawable.images10 };
private Context mContext;
private ImageView[] mImages;
public ImageAdapter(Context c) {
mContext = c;
mImages = new ImageView[mImageIds.length];
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return mImages[position % mImages.length];
}
public boolean createReflectedImages() {
final int reflectionGap = 4;
int index = 0;
for (int imageId : mImageIds) {
Bitmap originalBitmap = BitmapFactory.decodeStream(mContext
.getResources().openRawResource(imageId));
int width = originalBitmap.getWidth();
int height = originalBitmap.getHeight();
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
Bitmap reflectionBitmap = Bitmap.createBitmap(originalBitmap,
0, height * 7 / 8, width, height / 8, matrix, false);
Bitmap withReflectionBitmap = Bitmap.createBitmap(width,
(height + height / 8 + reflectionGap), Config.ARGB_8888);
Canvas canvas = new Canvas(withReflectionBitmap);
canvas.drawBitmap(originalBitmap, 0, 0, null);
Paint defaultPaint = new Paint();
canvas.drawRect(0, height, width, height + reflectionGap, defaultPaint);
canvas.drawBitmap(reflectionBitmap, 0, height + reflectionGap, null);
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, originalBitmap.getHeight(),
0, withReflectionBitmap.getHeight(), 0x70ffffff, 0x00ffffff,
TileMode.MIRROR);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawRect(0, height, width, withReflectionBitmap.getHeight(), paint);
ImageView imageView = new ImageView(mContext);
imageView.setImageBitmap(withReflectionBitmap);
imageView.setLayoutParams(new CoverFlow.LayoutParams(
(int) convertDip2Pixel(mContext, 120),
(int) convertDip2Pixel(mContext, 300)));
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
// 消除图片移动过程中的锯齿
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
drawable.setAntiAlias(true);
mImages[index++] = imageView;
}
return true;
}
}
public float convertDip2Pixel(Context context, int dip) {
final float scale = context.getResources().getDisplayMetrics().density;
float pixel = (int) (dip * scale + 0.5f);
return pixel;
}
}
CoverFlow
package org.wp.activity;
import android.content.Context;
import android.graphics.Camera;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Transformation;
import android.widget.Gallery;
import android.widget.ImageView;
/**
* protected void setStaticTransformationsEnabled (boolean enabled)
*
* When this property is set to true, this ViewGroup supports static
* transformations on children;
*
* this causes getChildStaticTransformation(View, android.view.animation.Transformation)
* to be invoked when a child is drawn.
*
* Any subclass overriding getChildStaticTransformation(View,
* android.view.animation.Transformation) should set this property to true.
*
* (Gallery ==> AbsSpinner ==> AdapterView<T extends Adapter> ==> ViewGroup)
*/
public class CoverFlow extends Gallery {
/** 视角 **/
private Camera mCamera = new Camera();
/** Child ImageView 最大的旋转角度 **/
private int mMaxRotationAngle = 45;
/** Center Child Z轴最大缩放距离 **/
private int mMaxZoom = -120;
/** Coverflow 的中心位置 **/
private int mCoverflowCenter;
/** 反转变量 **/
private int lastPosition = 0;
public CoverFlow(Context context) {
super(context);
this.setStaticTransformationsEnabled(true);
}
public CoverFlow(Context context, AttributeSet attrs) {
super(context, attrs);
this.setStaticTransformationsEnabled(true);
}
public CoverFlow(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.setStaticTransformationsEnabled(true);
}
public int getmMaxRotationAngle() {
return mMaxRotationAngle;
}
public void setmMaxRotationAngle(int mMaxRotationAngle) {
this.mMaxRotationAngle = mMaxRotationAngle;
}
public int getmMaxZoom() {
return mMaxZoom;
}
public void setmMaxZoom(int mMaxZoom) {
this.mMaxZoom = mMaxZoom;
}
/** 获得CoverFlow的中心点 **/
private int getCenterOfCoverflow() {
return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2
+ getPaddingLeft();
}
/** 获得指定View的中心点 **/
private int getCenterOfView(View view) {
return view.getLeft() + view.getWidth() / 2;
}
/**
* This method is called every time the widget changes size
* e.g. when we change the orientation of the phone from portrait to landscape.
* In the onSizeChanged method we just get the centre position
* of the coverflow widget.
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mCoverflowCenter = getCenterOfCoverflow();
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected int getChildDrawingOrder(int childCount, int i) {
if (i == 0) lastPosition = 0;
int centerPosition = getSelectedItemPosition()
- getFirstVisiblePosition();
// 当索引的位置是最后一个,返回中心点的child索引
// 当索引的位置大于中心点child的索引,从右往左
// 剩余的按正常顺序
if (i == (childCount - 1)) {
return centerPosition;
} else if (i >= centerPosition) {
lastPosition++;
return childCount - lastPosition;
} else {
return i;
}
}
@Override
protected boolean getChildStaticTransformation(View child, Transformation t) {
final int childCenter = getCenterOfView(child);
final int childWidth = child.getWidth();
int rotationAngle = 0;
t.clear();
// Indicates a transformation that applies a matrix only (alpha = 1.)
t.setTransformationType(Transformation.TYPE_MATRIX);
// 如果图片移动到中心点
if (childCenter == mCoverflowCenter) {
transformImageBitmap((ImageView) child, t, 0);
} else {
rotationAngle = (int) (((float) (mCoverflowCenter - childCenter) / childWidth) * mMaxRotationAngle);
// 最大旋转角度不超过mMaxRotationAngle
if (Math.abs(rotationAngle) > mMaxRotationAngle) {
rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle : mMaxRotationAngle;
}
transformImageBitmap((ImageView) child, t, rotationAngle);
}
return true;
}
private void transformImageBitmap(ImageView child, Transformation t,
int rotationAngle) {
mCamera.save();
final Matrix imageMatrix = t.getMatrix();
final int imageWidth = child.getLayoutParams().width;
final int imageHeight = child.getLayoutParams().height;
final int rotation = Math.abs(rotationAngle);
// 默认的缩小值
mCamera.translate(0.0f, 0.0f, 100.0f);
if (rotation < mMaxRotationAngle) {
// 不断的放大
float zoomAmount = (float) (mMaxZoom + (rotation * 1.5));
mCamera.translate(0.0f, 0.0f, zoomAmount);
}
mCamera.rotateY(rotationAngle);
mCamera.getMatrix(imageMatrix);
imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));
imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));
mCamera.restore();
}
}