黑马程序员技术交流社区

标题: 【github项目分享】Gallery实现3D相册【Android】 [打印本页]

作者: Android_Robot    时间: 2016-5-5 15:13
标题: 【github项目分享】Gallery实现3D相册【Android】

因为要做一个设置开机画面的功能,主要是让用户可以设置自己的开机画面,应用层需要做让用户选择开机画面图片的功能。所以需要做一个简单的图片浏览选择程序。最后选用Gallery作为基本控件。加入了一些炫一点的元素,做成3D滑动效果。下面是Demo例子截图:



这个效果网上已经很多人做出来了,只是这次需要用到,所以自己也实践了一下(这里例子我也是根据网上一些资料编写)。特意找了几张美女图片给大家养养眼,O(∩_∩)O哈!下面针对一些关键代码进行简要说明,需要做这方面东西的朋友可以看看。这篇文章是实用性文章,理论分析不多。



1、重载Gallery类

因为需要加入倒影和3D切换的效果,因此我们需要重载Gallery类,其中有两个方法我们需要重写,一个是onSizeChanged(),另外一个是getChildStaticTransformation()。下面我们看看onSizeChanged()需要做的事情。


  1. <font color="#333333"><font face="Arial">@Override
  2.     protected void onSizeChanged(int w, int h, int oldw, int oldh)
  3.     {
  4.     //重写计算旋转的中心
  5.         mCoveflowCenter = getCenterOfCoverflow();
  6.         super.onSizeChanged(w, h, oldw, oldh);
  7.     }</font></font>
复制代码

上面主要做的事情就是在改变大小的时候,重新计算滑动切换时需要旋转变化的中心。下面计算图片位置时,会重新计算。


  1. <font color="#333333"><font face="Arial">protected boolean getChildStaticTransformation(View child, Transformation trans)
  2.     {
  3.      //图像的中心点和宽度
  4.         final int childCenter = getCenterOfView(child);
  5.         final int childWidth = child.getWidth();
  6.         int rotationAngle = 0;

  7.         trans.clear();
  8.         trans.setTransformationType(Transformation.TYPE_BOTH);        // alpha 和 matrix 都变换

  9.         if (childCenter == mCoveflowCenter)
  10.         {   
  11.         // 正中间的childView
  12.             transformImageBitmap((ImageView) child, trans, 0);   
  13.         }
  14.         else
  15.         {        
  16.         // 两侧的childView
  17.             rotationAngle = (int) ( ( (float) (mCoveflowCenter - childCenter) / childWidth ) * mMaxRotationAngle );
  18.             if (Math.abs(rotationAngle) > mMaxRotationAngle)
  19.             {
  20.                 rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle : mMaxRotationAngle;
  21.             }
  22.        //根据偏移角度对图片进行处理,看上去有3D的效果。
  23.             transformImageBitmap((ImageView) child, trans, rotationAngle);
  24.         }

  25.         return true;
  26.     }</font></font>
复制代码

上面就是重载Gallery的时候,需要注意处理的事情,其实主要就是做图形变化,效果图里面的图片斜着显示就是这里处理的结果,目的就是让人看上去有立体感。


2、编写Adapter适配器

我们使用很多控件都涉及适配器,就是用来绑定数据源和目标控件的一个中间件。这里我们需要重载BaseAdapter作为我们Gallery的适配器。主要是处理源图像,加入倒影,生成新的数据源图片。


  1. <font color="#333333"><font face="Arial"> public boolean createReflectedForAdapter()
  2.     {
  3.         final int reflectionGap = 4;
  4.         final int Height = 200;
  5.         int index = 0;
  6.         for (Map<String, Object> map : list)
  7.         {
  8.             Integer id = (Integer) map.get("image");
  9.             // 获取原始图片
  10.             Bitmap originalImage = BitmapFactory.decodeResource(mContext.getResources(), id);   
  11.             int width = originalImage.getWidth();
  12.             int height = originalImage.getHeight();
  13.             float scale = Height / (float)height;
  14.             
  15.             Matrix sMatrix = new Matrix();
  16.             sMatrix.postScale(scale, scale);
  17.             Bitmap miniBitmap = Bitmap.createBitmap(originalImage, 0, 0,
  18.                     originalImage.getWidth(), originalImage.getHeight(), sMatrix, true);
  19.             
  20.             //是否原图片数据,节省内存
  21.             originalImage.recycle();

  22.             int mwidth = miniBitmap.getWidth();
  23.             int mheight = miniBitmap.getHeight();
  24.             Matrix matrix = new Matrix();
  25.             // 图片矩阵变换(从低部向顶部的倒影)
  26.             matrix.preScale(1, -1);            
  27.             // 截取原图下半部分
  28.             Bitmap reflectionImage = Bitmap.createBitmap(miniBitmap, 0, mheight/2, mwidth, mheight/2, matrix, false);
  29.             // 创建倒影图片(高度为原图3/2)
  30.             Bitmap bitmapWithReflection = Bitmap.createBitmap(mwidth, (mheight + mheight / 2), Config.ARGB_8888);   
  31.             // 绘制倒影图(原图 + 间距 + 倒影)
  32.             Canvas canvas = new Canvas(bitmapWithReflection);   
  33.             // 绘制原图
  34.             canvas.drawBitmap(miniBitmap, 0, 0, null);        
  35.             Paint paint = new Paint();
  36.             // 绘制原图与倒影的间距
  37.             canvas.drawRect(0, mheight, mwidth, mheight + reflectionGap, paint);
  38.             // 绘制倒影图
  39.             canvas.drawBitmap(reflectionImage, 0, mheight + reflectionGap, null);   

  40.             paint = new Paint();
  41.             // 线性渐变效果
  42.             LinearGradient shader = new LinearGradient(0, miniBitmap.getHeight(), 0, bitmapWithReflection.getHeight()
  43.                     + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
  44.             paint.setShader(shader);   
  45.             // 倒影遮罩效果
  46.             paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));        
  47.             // 绘制倒影的阴影效果
  48.             canvas.drawRect(0, mheight, mwidth, bitmapWithReflection.getHeight() + reflectionGap, paint);        
  49.             ImageView imageView = new ImageView(mContext);
  50.         // 设置倒影图片
  51.             imageView.setImageBitmap(bitmapWithReflection);        
  52.             imageView.setLayoutParams(new GalleryView.LayoutParams((int)(width * scale),
  53.                     (int)(mheight * 3 / 2.0 + reflectionGap)));
  54.             imageView.setScaleType(ScaleType.MATRIX);
  55.             mImages[index++] = imageView;
  56.         }
  57.         return true;
  58.     }</font></font>
复制代码

上面其实就是一个图片处理过程,主要做的事情就是生成倒影,效果图里面底下是有倒影的。就是利用上面算法生成。我们在适配器添加图片的时候,会把适配器原生图片进行处理,加入倒影的效果。这个我们在图片初始化的时候就可以调用处理,具体代码可以查看Demo里面的代码关系。

具体图片滑动的过程,Gallery会帮我们处理好,我们要做的事情其实就是提供添加了特效的图片数据源,以及处理3D显示的变化效果,最后都会提供View作为显示图像给Gallery用来显示。

今天主要是说说如何实现Gallery的3D显示切换,Demo的代码很多是基于网上一些现成效果,感谢这些分享成果的开发者。下面是Demo的下载,不清楚的可以把Demo下载下来,运行看看效果然后分析一下代码。代码不多,也不是很复杂。

Gallery3D例子代码:Grallery3DTest2013-7-19.rar


其他精华资源推荐:
[持续更新]2016最新Android视频教程+源码+技巧/经验+软件+面试
【github项目分享】RecyclerView 列表控件漂亮时间线实现
慵懒又机智Android程序员都爱的绝美小工具,不服你来咬我~
Android之线程:后台异步任务AsyncTask







欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2