您的位置:首页 > 移动开发 > Android开发

Android3D画廊总结整理

2016-07-08 19:34 351 查看
/**

* 在网上看到好多的3D画廊的效果,最常见就是Gallery,但是在API16的时候就已经废弃了,现在推荐使用ViewPager和HorizontalScrollView来实现这种效果,下面就在这里对其进行整理一下,代码更多的是借鉴了好多网上的,勿喷!!!!


*/

Gallery实现






步骤:

1、为Gallery设置Adapter

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView iv;
if (convertView != null) {
iv = (ImageView) convertView;
} else {
iv = new ImageView(MainActivity.this);
}
//通过调用BitmapUtils的getBitmap方法来得到生成倒影效果的图片
Bitmap bitmap = BitmapUtils.getImageBitmap(getResources(), res[position]);
BitmapDrawable bd = new BitmapDrawable(bitmap);
bd.setAntiAlias(true);//为Bitmap设置抗锯齿效果
iv.setImageDrawable(bd);
Gallery.LayoutParams params = new Gallery.LayoutParams(160, 400);
iv.setLayoutParams(params);//为ImageView设置宽高
return iv;
}

2、设置图片倒影效果
public static Bitmap getBitmap(Resources res, int drawableId) {
Bitmap src_bitmap = BitmapFactory.decodeResource(res, drawableId);//原图
//1、生成倒影图片
Matrix matrix = new Matrix();
matrix.setScale(1, -1);// 让图形按照矩阵进行垂直反转
Bitmap inverted_Bitmap = Bitmap.createBitmap(src_bitmap, 0, (int) (src_bitmap.getHeight() * 0.5), src_bitmap.getWidth(), src_bitmap.getHeight() / 2, matrix, true);
//2、得到合成的图片
Bitmap result = Bitmap.createBitmap(src_bitmap.getWidth(), (int) (src_bitmap.getHeight() * 1.5 + 10), Bitmap.Config.ARGB_8888);
//将原图和倒影图画到合成图上
Canvas canvas = new Canvas(result);
canvas.drawBitmap(src_bitmap, 0, 0, null);
canvas.drawBitmap(inverted_Bitmap, 0, src_bitmap.getHeight() + 10, null);
//3、设置遮罩效果
Paint paint = new Paint();
// 设置颜色
LinearGradient lg = new LinearGradient(0, (int) (src_bitmap.getHeight() + 10), 0, result.getHeight(), 0x70ffffff, 0x00ffffff, Shader.TileMode.CLAMP);
paint.setShader(lg);
// 设置模式为: 遮罩, 是取交集
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawRect(0, (int) (src_bitmap.getHeight() + 5), src_bitmap.getWidth(), result.getHeight(), paint);
src_bitmap.recycle();
inverted_Bitmap.recycle();
return result;
}
xfermode的讲解请移步:http://blog.csdn.net/weiwozhiyi/article/details/50749622

3、自定义Gallery

为了实现3D的效果需要覆盖protected boolean getChildStaticTransformation(View child, Transformation t)方法,通过为transformation设置动画来实现图片3D的浏览效果。

t.clear();// 设置变换效果之前, 需要把Transformation中的上一个item的变换效果清楚
t.setTransformationType(Transformation.TYPE_MATRIX);// 设置变换效果的类型为矩阵类型
接下来通过使用camera来为图片设置放大、透明度、旋转的效果

private void startTransformation(ImageView child, int rotateAngle, Transformation t) {
camera.save();// 保存状态
int absRotateAngle = Math.abs(rotateAngle);	// 取旋转角度的绝对值
//1、放大效果(中间的图片要比两边的图片要大)
camera.translate(0, 0, 100);
int zoom = -250 + absRotateAngle*2 ;
camera.translate(0, 0, zoom);

//2、 透明度(中间的图片是完全显示, 两边有一定的透明度)
int alpha = 255 - 3 * absRotateAngle;
child.setAlpha(alpha);// 透明度取值范围: 0 ~ 255, 0 就是完全隐藏, 255 完全显示

//3、旋转(在中间的图片没有旋转角度, 只要不在中间就有旋转角度)
camera.rotateY(rotateAngle);
Matrix matrix = t.getMatrix();
// 给matrix赋值
camera.getMatrix(matrix);// 把matrix矩阵给camera对象, camera对象就会把上面添加的效果转换成矩阵添加到matrix对象中

凡是大量用到Bitmap的地方都有可能发生OOM异常,为了解决OOM异常这里应用软引用来对图片进行缓存处理

强引用:
String s = "abc";
list.add(s);

软引用:
如果若引用对象回收完之后,内存还是报警,继续回收软引用对象,还是继续内存报警,
OOM outOfMemoryException内存溢出异常
SoftReference<Bitmap> softReference = new SoftReference<Bitmap>(bitmap);

弱引用:
如果虚引用对象回收完之后,内存还是报警,继续回收弱引用对象

虚引用:
虚拟机的内存不够使用,开始报警,这时候垃圾回收机制开始执行System.gc();
String a = "a";(定义了之后没有用这个对象则回收它)
如果没有对象回收了,回收虚引用的对象
当然你如果不想自己去写这么多代码,github提供了3DGallery的库https://github.com/davidschreiber/FancyCoverFlow

使用步骤:

1、布局文件引用

<at.technikum.mti.fancycoverflow.FancyCoverFlow
android:id="@+id/fancy_converflow"
android:layout_width="match_parent"
android:layout_height="match_parent">

</at.technikum.mti.fancycoverflow.FancyCoverFlow>
2、对自定义控件进行设置

/**
* 当然你也可以在xml进行设置
*fcf:maxRotation="45"
*fcf:unselectedAlpha="0.3"
*fcf:unselectedSaturation="0.0"
*fcf:unselectedScale="0.4"
*fcf:scaleDownGravity="0.5"
*/
fancy_converflow.setUnselectedAlpha(1.0f);//未选择的Item透明度
fancy_converflow.setUnselectedSaturation(0.0f);//未选中的饱和度
fancy_converflow.setUnselectedScale(0.5f);//未选中的缩放
fancy_converflow.setSpacing(20);//设置Item之间间隙
fancy_converflow.setMaxRotation(45);//设置最大的旋转角
fancy_converflow.setScaleDownGravity(0.5f);//从哪个位置进行缩放
fancy_converflow.setReflectionEnabled(true);
fancy_converflow.setReflectionRatio(0.3f);//倒影的比例
fancy_converflow.setReflectionGap(10);//倒影和原图的间距
fancy_converflow.setActionDistance(FancyCoverFlow.ACTION_DISTANCE_AUTO);



ViewPager实现

滑动ViewPager页面显示动画效果,你需要去实现ViewPager.PageTransform类,重写public void transformPage(View page, float position) {方法

在Android官方文档提供了两种:ZoomOutPageTransformer、DepthPageTransformer

1、ZoomOutPageTransformer



代码

public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();

if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);

} else if (position <= 1) { // [-1,1]
// Modify the default slide transition to shrink the page as well
float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
float vertMargin = pageHeight * (1 - scaleFactor) / 2;
float horzMargin = pageWidth * (1 - scaleFactor) / 2;
if (position < 0) {
view.setTranslationX(horzMargin - vertMargin / 2);
} else {
view.setTranslationX(-horzMargin + vertMargin / 2);
}

// Scale the page down (between MIN_SCALE and 1)
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);

// Fade the page relative to its size.
view.setAlpha(MIN_ALPHA +
(scaleFactor - MIN_SCALE) /
(1 - MIN_SCALE) * (1 - MIN_ALPHA));

} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}


2、DepthPageTransformer

代码


public void transformPage(View view, float position) {
int pageWidth = view.getWidth();

if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);

} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(1);
view.setTranslationX(0);
view.setScaleX(1);
view.setScaleY(1);

} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1 - position);

// Counteract the default slide transition
view.setTranslationX(pageWidth * -position);

// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);

} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
更多关于ViewPager的内容请看鸿洋大神的:http://blog.csdn.net/lmj623565791/article/details/40411921/

效果



在一个屏幕显示多个Page

//页面宽度所占ViewPager的宽度的比例,默认为1
@Override
public float getPageWidth(int position) {
return 0.4f;
}
为每个Page添加间距

vp.setPageMargin(30);
代码如下:

public class CustomTransform implements ViewPager.PageTransformer {
private static final float MIN_SCALE=0.65f;
private int MAX_ROTATION = 40;
@Override
public void transformPage(View page, float position) {
float scaleFactor=Math.max(MIN_SCALE,1-Math.abs(position));
float rotate=20*Math.abs(position);
if (position<-1){
// This page is way off-screen to the left.
}else if (position <= 1){
// Modify the default slide transition to shrink the page as well
page.setScaleX(scaleFactor);
page.setScaleY(scaleFactor);
page.setRotationY(rotate);
}else if (position>1) {
// This page is way off-screen to the right.
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: