Gallery是一个内部元素可以水平滚动,并且可以把当前选择的子元素定位在它中心的布局组件。下面是一个实现3D画廊的小demo
MainActivity.class
package com.czh.gallery3d;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Gallery.LayoutParams;
import android.widget.ImageView;
public class MainActivity extends Activity {
private int[] imgageResIDs;
private int width;
private int height;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CustomGallery mGallery = (CustomGallery) findViewById(R.id.customergallery);
width = getWindowManager().getDefaultDisplay().getWidth();
height = getWindowManager().getDefaultDisplay().getHeight();
imgageResIDs = new int[] { R.drawable.pic_1, R.drawable.pic_2,
R.drawable.pic_3, R.drawable.pic_4, R.drawable.pic_5,
R.drawable.pic_6, R.drawable.pic_7, R.drawable.pic_8,
R.drawable.pic_1, R.drawable.pic_2, R.drawable.pic_3,
R.drawable.pic_4, R.drawable.pic_5, R.drawable.pic_6,
R.drawable.pic_7, R.drawable.pic_8, R.drawable.pic_1,
R.drawable.pic_2, R.drawable.pic_3, R.drawable.pic_4,
R.drawable.pic_5, R.drawable.pic_6, R.drawable.pic_7,
R.drawable.pic_8, R.drawable.pic_1, R.drawable.pic_2,
R.drawable.pic_3, R.drawable.pic_4, R.drawable.pic_5,
R.drawable.pic_6, R.drawable.pic_7, R.drawable.pic_8 };
mGallery.setAdapter(new MyAdapter());
}
class MyAdapter extends BaseAdapter {
@Override
public int getCount() {
return imgageResIDs.length;
}
@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) {
ImageView iv = null;
if (convertView == null) {
iv = new ImageView(MainActivity.this);
} else {
iv = (ImageView) convertView;
}
Bitmap bitmap = ImageUtils.getImageBitmap(
MainActivity.this.getResources(), imgageResIDs[position]);
BitmapDrawable bd = new BitmapDrawable(bitmap);
bd.setAntiAlias(true);// 消除锯齿
iv.setImageBitmap(bitmap);
LayoutParams params = new LayoutParams(width / 2, height / 2);
iv.setLayoutParams(params);
return iv;
}
}
}
ImageUtils.class
package com.czh.gallery3d;
import java.lang.ref.SoftReference;
import java.util.Hashtable;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
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.util.Log;
public class ImageUtils {
private static Hashtable<Integer, SoftReference<Bitmap>> mCacheHashtable = new Hashtable<Integer, SoftReference<Bitmap>>();// 缓存集合
/**
* 根据id返回一个处理后的图片
*
* @param res
* @param imageID
* @return
*/
public static Bitmap getImageBitmap(Resources res, int imageID) {
// 先去集合中去当前imageID 是否已经拿过图片,如果集合中有,说明已经拿过,直接使用结合中的图片返回
SoftReference<Bitmap> softReference = mCacheHashtable.get(imageID);
if (softReference != null) {
Bitmap bitmap = softReference.get();
if (bitmap != null) {
// 从内存中取
Log.i("Log", "从内存中取");
return bitmap;
}
}
// 如果集合中没有,就调用getInvertImage得到一个图片,需要向集合中保留一张,最后返回当前图片
Log.i("Log", "重新加载");
Bitmap invertImage = getInvertImage(res, imageID);
// 在集合中存一份,便于下次再取的时候直接去集合中取
mCacheHashtable.put(imageID, new SoftReference<Bitmap>(invertImage));
return invertImage;
}
/**
*
* @param imageID
* @return
*/
public static Bitmap getInvertImage(Resources res, int imageID) {
// 获取原图
Bitmap sourdeBitmap = BitmapFactory.decodeResource(res, imageID);
// 生成倒影图片
Matrix m = new Matrix();// 图形矩阵
m.setScale(1f, -1f);// 让图形按照矩阵进行垂直反转
// float[] values = {
// 1.0f,0f,0f,
// 0f,-1.0f,0f,
// 0f,0f,1.0f
// };
// m.setValues(values);
Bitmap inVertBitmap = Bitmap.createBitmap(sourdeBitmap, 0,
sourdeBitmap.getHeight() / 2, sourdeBitmap.getWidth(),
sourdeBitmap.getHeight() / 2, m, false);
// 把两张图片合成一张
Bitmap resultBitmap = Bitmap.createBitmap(sourdeBitmap.getWidth(),
(int) (sourdeBitmap.getHeight() * 1.5 + 5), Config.ARGB_8888);
Canvas canvas = new Canvas(resultBitmap);// 指定画板画在合成图片上
canvas.drawBitmap(sourdeBitmap, 0, 0, null);
canvas.drawBitmap(inVertBitmap, 0, sourdeBitmap.getHeight() + 5, null);//
// 添加遮罩效果
Paint paint = new Paint();
// 设置颜色
LinearGradient shader = new LinearGradient(0,
sourdeBitmap.getHeight() + 5, 0, resultBitmap.getHeight(),
0x70ffffff, 0x00ffffff, TileMode.CLAMP);
paint.setShader(shader);
// 设置模式为遮罩,去交集
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawRect(0, sourdeBitmap.getHeight() + 5,
sourdeBitmap.getWidth(), resultBitmap.getHeight(), paint);
return resultBitmap;
}
}
CustomGallery.class
package com.czh.gallery3d;
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;
public class CustomGallery extends Gallery {
private int galleryCenterPoint = 0;// gallery的中心点
private Camera camera;
public CustomGallery(Context context, AttributeSet attrs) {
super(context, attrs);
// 启用getChildStaticTransformstin()被调用
setStaticTransformationsEnabled(true);
camera = new Camera();
}
/**
* 当gallery空间大的宽和高改变时回调此方法,第一次计算出gallery的宽和高
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
super.onSizeChanged(w, h, oldw, oldh);
galleryCenterPoint = getGalleryCentPoint();
}
/**
* 返回gallery的item的子图形变换效果
*/
@Override
protected boolean getChildStaticTransformation(View child, Transformation t) {
// TODO Auto-generated method stub
int viewCenterPoint = getviewCenterPoint(child);// item的中心点
int rotateAngle = 0;// 默认旋转角度为0
// 如果当前的View的中心点不等于gallery的中心点,就是两边的图片,需要计算旋转角度
if (viewCenterPoint != galleryCenterPoint) {
// gallery中心点 - 图片中心点 = 差值
int diff = galleryCenterPoint - viewCenterPoint;
// 差值/图片的宽度 = 比值
float scale = (float) diff / (float) child.getWidth();
// 比值 * 最大旋转角度 = 最终的旋转角度
rotateAngle = (int) (scale * 50);
if (Math.abs(rotateAngle) > 50) {// 当前角度超过了50,需要赋值到50或者-50
rotateAngle = rotateAngle > 0 ? 50 : -50;
}
}
// 设置变换效果之前,需要把Transformation中的上一个item的变换效果清除
t.clear();
t.setTransformationType(Transformation.TYPE_MATRIX);// 设置变换效果的类型为矩阵类型
startTransformationItem((ImageView) child, rotateAngle, t);
return true;
}
/**
* 设置变换效果
*
* @param iv
* gallery的item
* @param rotateAngle
* 旋转的角度
* @param t
* 变换的对象
*/
private void startTransformationItem(ImageView iv, int rotateAngle,
Transformation t) {
camera.save();// 保存状态
int absRotateAngle = Math.abs(rotateAngle);// 取旋转角度的绝对值
// 3、放大效果
camera.translate(0, 0, 100f);// 给摄像机定位
int zoom = -250 + (absRotateAngle * 2);
camera.translate(0, 0, zoom);
// 2、透明度
int alpha = (int) (255 - (absRotateAngle * 2.5));
iv.setAlpha(alpha);// 透明度取值范围0~255 0完全透明 255完全显示
// 1、旋转
camera.rotateY(rotateAngle);
Matrix matrix = t.getMatrix();//变换的矩阵,需要把变幻的效果添加到矩阵中
camera.getMatrix(matrix);//把matrix矩阵给camera对象,camera对象就会把上面添加的效果转换成矩阵添加到matrix对象中
//矩阵前乘
matrix.preTranslate(-iv.getWidth()/2, -iv.getHeight()/2);
//矩阵后乘
matrix.postTranslate(iv.getWidth()/2, iv.getHeight()/2);
camera.restore();// 恢复到之前保存的状态
}
/**
* 获取gallery的中心点
*
* @return
*/
private int getGalleryCentPoint() {
return this.getWidth() / 2;
}
/**
* 获得view的中心点
*
* @return
*/
private int getviewCenterPoint(View v) {
return v.getWidth() / 2 + v.getLeft();
}
}
下面来看布局文件
activity_main.zml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="#000000"
android:layout_height="match_parent" >
<com.czh.gallery3d.CustomGallery
android:id="@+id/customergallery"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
到这里一个小小的Gallery实现3D画廊效果的小demo就实现了