├── images
└── 0.jpg
├── res
├── drawable-normal
│ ├── a.jpg
│ ├── b.jpg
│ ├── c.jpg
│ ├── d.jpg
│ ├── e.jpg
│ ├── f.jpg
│ ├── g.jpg
│ ├── h.jpg
│ ├── i.jpg
│ ├── j.jpg
│ ├── k.jpg
│ ├── l.jpg
│ └── m.jpg
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-ldpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── values
│ └── strings.xml
└── layout
│ └── main.xml
├── lib
└── universal-image-loader-1.8.6.jar
├── README.md
├── .settings
└── org.eclipse.jdt.core.prefs
├── project.properties
├── .classpath
├── src
└── com
│ └── demo
│ └── coverflow
│ ├── MyApp.java
│ ├── CoverflowDemoActivity.java
│ ├── ImageLoaderUtils.java
│ ├── CoverFlow.java
│ └── ImageAdapter.java
├── AndroidManifest.xml
├── .project
└── proguard.cfg
/images/0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/images/0.jpg
--------------------------------------------------------------------------------
/res/drawable-normal/a.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/res/drawable-normal/a.jpg
--------------------------------------------------------------------------------
/res/drawable-normal/b.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/res/drawable-normal/b.jpg
--------------------------------------------------------------------------------
/res/drawable-normal/c.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/res/drawable-normal/c.jpg
--------------------------------------------------------------------------------
/res/drawable-normal/d.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/res/drawable-normal/d.jpg
--------------------------------------------------------------------------------
/res/drawable-normal/e.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/res/drawable-normal/e.jpg
--------------------------------------------------------------------------------
/res/drawable-normal/f.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/res/drawable-normal/f.jpg
--------------------------------------------------------------------------------
/res/drawable-normal/g.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/res/drawable-normal/g.jpg
--------------------------------------------------------------------------------
/res/drawable-normal/h.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/res/drawable-normal/h.jpg
--------------------------------------------------------------------------------
/res/drawable-normal/i.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/res/drawable-normal/i.jpg
--------------------------------------------------------------------------------
/res/drawable-normal/j.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/res/drawable-normal/j.jpg
--------------------------------------------------------------------------------
/res/drawable-normal/k.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/res/drawable-normal/k.jpg
--------------------------------------------------------------------------------
/res/drawable-normal/l.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/res/drawable-normal/l.jpg
--------------------------------------------------------------------------------
/res/drawable-normal/m.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/res/drawable-normal/m.jpg
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/lib/universal-image-loader-1.8.6.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuningjack/CoverFlow/HEAD/lib/universal-image-loader-1.8.6.jar
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CoverFlow
2 | Infinite loop photo wall, which support sliding around(无限循环照片墙,支持左右滑动)
3 | 效果图:
4 | 
5 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
3 | org.eclipse.jdt.core.compiler.compliance=1.6
4 | org.eclipse.jdt.core.compiler.source=1.6
5 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello World, CoverflowDemoActivity!
5 | CoverflowDemo
6 |
7 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system use,
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 |
10 | # Project target.
11 | target=android-14
12 |
--------------------------------------------------------------------------------
/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/com/demo/coverflow/MyApp.java:
--------------------------------------------------------------------------------
1 | package com.demo.coverflow;
2 |
3 | import com.nostra13.universalimageloader.core.ImageLoader;
4 | import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
5 |
6 | import android.app.Application;
7 | import android.util.DisplayMetrics;
8 |
9 | public class MyApp extends Application {
10 |
11 | @Override
12 | public void onCreate() {
13 |
14 | super.onCreate();
15 | //注册ImageLoader
16 | DisplayMetrics displayMetrics = this.getResources().getDisplayMetrics();
17 | ImageLoaderConfiguration config = ImageLoaderUtils.getApplicationOptions(displayMetrics.widthPixels , displayMetrics.heightPixels, getApplicationContext());
18 | ImageLoader.getInstance().init(config);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/com/demo/coverflow/CoverflowDemoActivity.java:
--------------------------------------------------------------------------------
1 | package com.demo.coverflow;
2 |
3 | import android.app.Activity;
4 |
5 | import android.graphics.Color;
6 | import android.os.Bundle;
7 |
8 | /**
9 | * 主界面
10 | * @author Jack
11 | * @version 创建时间:2013-10-31 下午2:13:47
12 | */
13 | public class CoverflowDemoActivity extends Activity {
14 |
15 | @Override
16 | public void onCreate(Bundle savedInstanceState) {
17 |
18 | super.onCreate(savedInstanceState);
19 | setContentView(R.layout.main);
20 | CoverFlow cf = new CoverFlow(this);
21 | cf.setBackgroundColor(Color.BLACK);
22 | cf.setAdapter(new ImageAdapter(this));
23 | ImageAdapter imageAdapter = new ImageAdapter(this);
24 | cf.setAdapter(imageAdapter);
25 | // cf.setAlphaMode(false); //两边未selected的图片不透明
26 | // cf.setCircleMode(false);
27 | cf.setSelection(Integer.MAX_VALUE / 2, true);
28 | cf.setAnimationDuration(1000);
29 | setContentView(cf);
30 | }
31 | }
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | Android_Coverflow
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/proguard.cfg:
--------------------------------------------------------------------------------
1 | -optimizationpasses 5
2 | -dontusemixedcaseclassnames
3 | -dontskipnonpubliclibraryclasses
4 | -dontpreverify
5 | -verbose
6 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
7 |
8 | -keep public class * extends android.app.Activity
9 | -keep public class * extends android.app.Application
10 | -keep public class * extends android.app.Service
11 | -keep public class * extends android.content.BroadcastReceiver
12 | -keep public class * extends android.content.ContentProvider
13 | -keep public class * extends android.app.backup.BackupAgentHelper
14 | -keep public class * extends android.preference.Preference
15 | -keep public class com.android.vending.licensing.ILicensingService
16 |
17 | -keepclasseswithmembernames class * {
18 | native ;
19 | }
20 |
21 | -keepclasseswithmembers class * {
22 | public (android.content.Context, android.util.AttributeSet);
23 | }
24 |
25 | -keepclasseswithmembers class * {
26 | public (android.content.Context, android.util.AttributeSet, int);
27 | }
28 |
29 | -keepclassmembers class * extends android.app.Activity {
30 | public void *(android.view.View);
31 | }
32 |
33 | -keepclassmembers enum * {
34 | public static **[] values();
35 | public static ** valueOf(java.lang.String);
36 | }
37 |
38 | -keep class * implements android.os.Parcelable {
39 | public static final android.os.Parcelable$Creator *;
40 | }
41 |
--------------------------------------------------------------------------------
/src/com/demo/coverflow/ImageLoaderUtils.java:
--------------------------------------------------------------------------------
1 | package com.demo.coverflow;
2 |
3 | import java.io.File;
4 | import android.content.Context;
5 |
6 | import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
7 | import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;
8 | import com.nostra13.universalimageloader.core.DisplayImageOptions;
9 | import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
10 | import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
11 | import com.nostra13.universalimageloader.utils.StorageUtils;
12 |
13 | /**
14 | * 图片加载配置工具类
15 | * @author nick
16 | */
17 | public class ImageLoaderUtils {
18 |
19 | public static ImageLoaderConfiguration getApplicationOptions(int width,int height,Context context){
20 |
21 | File cacheDir = StorageUtils.getCacheDirectory(context);
22 | ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
23 | .threadPoolSize(5) // default
24 | .tasksProcessingOrder(QueueProcessingType.FIFO) // default
25 | .memoryCache(new LruMemoryCache(4 * 1024 * 1024))
26 | .memoryCacheSize(4 * 1024 * 1024)
27 | .discCache(new UnlimitedDiscCache(cacheDir)) // default
28 | .discCacheSize(50 * 1024 * 1024)
29 | .discCacheFileCount(100)
30 | .writeDebugLogs()
31 | .build();
32 | return config;
33 | }
34 |
35 | /**
36 | * 默认配置
37 | * @return
38 | */
39 | public static DisplayImageOptions getDefaultOptions(){
40 | DisplayImageOptions options = new DisplayImageOptions.Builder()
41 | .cacheInMemory(true)
42 | .cacheOnDisc(true)
43 | .build();
44 | return options;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/com/demo/coverflow/CoverFlow.java:
--------------------------------------------------------------------------------
1 | package com.demo.coverflow;
2 |
3 | import android.content.Context;
4 | import android.graphics.Camera;
5 | import android.graphics.Matrix;
6 | import android.util.AttributeSet;
7 | import android.view.View;
8 | import android.view.animation.Transformation;
9 | import android.widget.Gallery;
10 | import android.widget.ImageView;
11 |
12 | /**
13 | * 自定义gallery,未被选中项有角度的显示
14 | * @author Jack
15 | * @version 创建时间:2013-10-31 下午12:58:45
16 | */
17 | public class CoverFlow extends Gallery {
18 |
19 | private Camera mCamera = new Camera();
20 | private int mMaxRotationAngle = 50;
21 | private int mMaxZoom = -380;
22 | private int mCoveflowCenter;
23 | private boolean mAlphaMode = true;
24 | private boolean mCircleMode = false;
25 |
26 | /**构造方法必须有一个*/
27 | public CoverFlow(Context context) {
28 |
29 | super(context);
30 | this.setStaticTransformationsEnabled(true);
31 | }
32 |
33 | public boolean getCircleMode() {
34 |
35 | return mCircleMode;
36 | }
37 |
38 | /**
39 | * 获得中间的图片的位置(带有左边距的)
40 | * @return
41 | */
42 | private int getCenterOfCoverflow() {
43 |
44 | return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2 + getPaddingLeft();
45 | }
46 |
47 | /**
48 | * 获得view的中间位置
49 | * @param view
50 | * @return
51 | */
52 | private static int getCenterOfView(View view) {
53 |
54 | return view.getLeft() + view.getWidth() / 2;
55 | }
56 |
57 | protected boolean getChildStaticTransformation(View child, Transformation t) {
58 |
59 | final int childCenter = getCenterOfView(child);
60 | final int childWidth = child.getWidth();
61 | int rotationAngle = 0;
62 | t.clear();
63 | t.setTransformationType(Transformation.TYPE_MATRIX);
64 | if (childCenter == mCoveflowCenter) {
65 |
66 | transformImageBitmap((ImageView) child, t, 0);
67 | } else {
68 |
69 | rotationAngle = (int) (((float) (mCoveflowCenter - childCenter) / childWidth) * mMaxRotationAngle);
70 | if (Math.abs(rotationAngle) > mMaxRotationAngle) {
71 |
72 | rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle : mMaxRotationAngle;
73 | }
74 | transformImageBitmap((ImageView) child, t, rotationAngle);
75 | }
76 | return true;
77 | }
78 |
79 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
80 |
81 | mCoveflowCenter = getCenterOfCoverflow();
82 | super.onSizeChanged(w, h, oldw, oldh);
83 | }
84 |
85 | private void transformImageBitmap(ImageView child, Transformation t, int rotationAngle) {
86 |
87 | mCamera.save();
88 | final Matrix imageMatrix = t.getMatrix();
89 | final int imageHeight = child.getLayoutParams().height;
90 | final int imageWidth = child.getLayoutParams().width;
91 | final int rotation = Math.abs(rotationAngle);
92 | //平移变换,x,y,z三轴
93 | mCamera.translate(0.0f, 0.0f, 0.0f);
94 | // 如视图的角度变小,放大
95 | if (rotation <= mMaxRotationAngle) {
96 |
97 | float zoomAmount = (float) (mMaxZoom + (rotation * 1.5));
98 | mCamera.translate(0.0f, 0.0f, zoomAmount);
99 | if (mCircleMode) {//改变角度
100 |
101 | if (rotation < 40)
102 | mCamera.translate(0.0f, 155, 0.0f);
103 | else
104 | mCamera.translate(0.0f, (255 - rotation * 2.5f), 0.0f);
105 | }
106 | if (mAlphaMode) {//改变透明度
107 |
108 | ((ImageView) (child)).setAlpha((int) (255 - rotation * 2.5));
109 | }
110 | }
111 | mCamera.rotateY(rotationAngle);
112 | mCamera.getMatrix(imageMatrix);
113 | imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));
114 | imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));
115 | mCamera.restore();
116 | }
117 | }
--------------------------------------------------------------------------------
/src/com/demo/coverflow/ImageAdapter.java:
--------------------------------------------------------------------------------
1 | package com.demo.coverflow;
2 |
3 | import com.nostra13.universalimageloader.core.ImageLoader;
4 | import com.nostra13.universalimageloader.core.assist.FailReason;
5 | import com.nostra13.universalimageloader.core.assist.ImageLoadingListener;
6 |
7 | import android.content.Context;
8 | import android.graphics.Bitmap;
9 | import android.graphics.Bitmap.Config;
10 | import android.graphics.Canvas;
11 | import android.graphics.LinearGradient;
12 | import android.graphics.Matrix;
13 | import android.graphics.Paint;
14 | import android.graphics.PorterDuff.Mode;
15 | import android.graphics.PorterDuffXfermode;
16 | import android.graphics.Shader.TileMode;
17 | import android.graphics.drawable.BitmapDrawable;
18 | import android.view.View;
19 | import android.view.ViewGroup;
20 | import android.widget.BaseAdapter;
21 | import android.widget.ImageView;
22 |
23 |
24 | /**
25 | * CoverFlow的Adapter
26 | * @author Jack
27 | * @version 创建时间:2013-10-31 下午4:16:17
28 | */
29 | public class ImageAdapter extends BaseAdapter {
30 |
31 | int mGalleryItemBackground;
32 | private Context mContext;
33 | /*private Integer[] mImageIds = { R.drawable.a, R.drawable.b,
34 | R.drawable.c, R.drawable.d, R.drawable.e, R.drawable.f,
35 | R.drawable.g, R.drawable.h, R.drawable.i, R.drawable.j
36 | , R.drawable.k, R.drawable.l, R.drawable.m};*/
37 | private String[] mImageUrls = {"http://img0.pcgames.com.cn/pcgames/1408/02/4162655_IMG_9462.jpg",
38 | "http://img0.pcgames.com.cn/pcgames/1408/02/4162655_IMG_9466_thumb.jpg",
39 | "http://img0.pcgames.com.cn/pcgames/1408/02/4162655_IMG_9478_thumb.jpg",
40 | "http://img0.pcgames.com.cn/pcgames/1408/02/4162655_IMG_9504_thumb.jpg",
41 | "http://img0.pcgames.com.cn/pcgames/1408/02/4162655_IMG_9552_thumb.jpg",
42 | "http://img0.pcgames.com.cn/pcgames/1408/02/4162655_IMG_9581_thumb.jpg"};
43 |
44 | public ImageAdapter(Context c) {
45 | mContext = c;
46 | }
47 |
48 | @Override
49 | public int getCount() {
50 | return Integer.MAX_VALUE;
51 | }
52 |
53 | @Override
54 | public Object getItem(int position) {
55 | return position;
56 | }
57 |
58 | @Override
59 | public long getItemId(int position) {
60 | return position;
61 | }
62 |
63 | @Override
64 | public View getView(int position, View convertView, ViewGroup parent) {
65 | ImageView imageView = createReflectedImages(mContext, mImageUrls[position % mImageUrls.length]);
66 | imageView.setLayoutParams(new CoverFlow.LayoutParams(120, 100));
67 | imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
68 | return imageView;
69 | }
70 |
71 |
72 | /**
73 | * 倒影处理逻辑
74 | * @param mContext
75 | * @param imageUrl
76 | * @return
77 | */
78 | public ImageView createReflectedImages(Context mContext, String imageUrl) {
79 | ImageView imageView = new ImageView(mContext);
80 | ImageLoader.getInstance().displayImage(imageUrl, imageView, ImageLoaderUtils.getDefaultOptions(), new ImageLoadingListener() {
81 |
82 | @Override
83 | public void onLoadingStarted(String arg0, View arg1) {
84 |
85 | }
86 |
87 | @Override
88 | public void onLoadingFailed(String arg0, View arg1, FailReason arg2) {
89 |
90 | }
91 |
92 | @Override
93 | public void onLoadingComplete(String url, View imageView, Bitmap originalImage) {
94 | final int REFLECTIONGAP = 4;
95 | int width = originalImage.getWidth();
96 | int height = originalImage.getHeight();
97 |
98 | //Matrix 旋转、镜像处理的矩阵类
99 | Matrix matrix = new Matrix();
100 | matrix.preScale(1, -1);
101 | Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height / 2, width, height / 2, matrix, false);
102 | Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height / 2), Config.ARGB_8888);
103 | Canvas canvas = new Canvas(bitmapWithReflection);
104 | canvas.drawBitmap(originalImage, 0, 0, null);
105 | Paint deafaultPaint = new Paint();
106 | canvas.drawRect(0, height, width, height + REFLECTIONGAP, deafaultPaint);
107 | canvas.drawBitmap(reflectionImage, 0, height + REFLECTIONGAP, null);
108 | Paint paint = new Paint();
109 | //线性渐变
110 | LinearGradient shader = new LinearGradient(0,
111 | originalImage.getHeight(), 0, bitmapWithReflection.getHeight()
112 | + REFLECTIONGAP, 0x70ffffff, 0x00ffffff, TileMode.MIRROR);
113 | paint.setShader(shader);
114 | //设置两张图片相交时的模式 ,倒影图片隐藏一部分
115 | paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
116 | //按照设置绘制倒影图片
117 | canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + REFLECTIONGAP, paint);
118 | ((ImageView)imageView).setImageBitmap(bitmapWithReflection);
119 | // 设置的抗锯齿
120 | BitmapDrawable drawable = (BitmapDrawable) ((ImageView)imageView).getDrawable();
121 | drawable.setAntiAlias(true);
122 | }
123 |
124 | @Override
125 | public void onLoadingCancelled(String arg0, View arg1) {
126 | }
127 | });
128 | return imageView;
129 | }
130 | }
131 |
--------------------------------------------------------------------------------