Android 使用Gallery实现3D相册(附效果图+Demo源码)

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

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

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


代码如下:

protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
    //重写计算旋转的中心
        mCoveflowCenter = getCenterOfCoverflow();
        super.onSizeChanged(w, h, oldw, oldh);
    }

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


代码如下:

protected boolean getChildStaticTransformation(View child, Transformation trans)
    {
     //图像的中心点和宽度
        final int childCenter = getCenterOfView(child);
        final int childWidth = child.getWidth();
        int rotationAngle = 0;

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

if (childCenter == mCoveflowCenter)
        {   
        // 正中间的childView
            transformImageBitmap((ImageView) child, trans, 0);   
        }
        else
        {       
        // 两侧的childView
            rotationAngle = (int) ( ( (float) (mCoveflowCenter - childCenter) / childWidth ) * mMaxRotationAngle );
            if (Math.abs(rotationAngle) > mMaxRotationAngle)
            {
                rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle : mMaxRotationAngle;
            }
       //根据偏移角度对图片进行处理,看上去有3D的效果。
            transformImageBitmap((ImageView) child, trans, rotationAngle);
        }

return true;
    }

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

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


代码如下:

public boolean createReflectedForAdapter()
    {
        final int reflectionGap = 4;
        final int Height = 200;
        int index = 0;
        for (Map<String, Object> map : list)
        {
            Integer id = (Integer) map.get("image");
            // 获取原始图片
            Bitmap originalImage = BitmapFactory.decodeResource(mContext.getResources(), id);   
            int width = originalImage.getWidth();
            int height = originalImage.getHeight();
            float scale = Height / (float)height;

Matrix sMatrix = new Matrix();
            sMatrix.postScale(scale, scale);
            Bitmap miniBitmap = Bitmap.createBitmap(originalImage, 0, 0,
                    originalImage.getWidth(), originalImage.getHeight(), sMatrix, true);

//是否原图片数据,节省内存
            originalImage.recycle();

int mwidth = miniBitmap.getWidth();
            int mheight = miniBitmap.getHeight();
            Matrix matrix = new Matrix();
            // 图片矩阵变换(从低部向顶部的倒影)
            matrix.preScale(1, -1);           
            // 截取原图下半部分
            Bitmap reflectionImage = Bitmap.createBitmap(miniBitmap, 0, mheight/2, mwidth, mheight/2, matrix, false);
            // 创建倒影图片(高度为原图3/2)
            Bitmap bitmapWithReflection = Bitmap.createBitmap(mwidth, (mheight + mheight / 2), Config.ARGB_8888);   
            // 绘制倒影图(原图 + 间距 + 倒影)
            Canvas canvas = new Canvas(bitmapWithReflection);   
            // 绘制原图
            canvas.drawBitmap(miniBitmap, 0, 0, null);       
            Paint paint = new Paint();
            // 绘制原图与倒影的间距
            canvas.drawRect(0, mheight, mwidth, mheight + reflectionGap, paint);
            // 绘制倒影图
            canvas.drawBitmap(reflectionImage, 0, mheight + reflectionGap, null);

paint = new Paint();
            // 线性渐变效果
            LinearGradient shader = new LinearGradient(0, miniBitmap.getHeight(), 0, bitmapWithReflection.getHeight()
                    + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
            paint.setShader(shader);   
            // 倒影遮罩效果
            paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));       
            // 绘制倒影的阴影效果
            canvas.drawRect(0, mheight, mwidth, bitmapWithReflection.getHeight() + reflectionGap, paint);       
            ImageView imageView = new ImageView(mContext);
        // 设置倒影图片
            imageView.setImageBitmap(bitmapWithReflection);       
            imageView.setLayoutParams(new GalleryView.LayoutParams((int)(width * scale),
                    (int)(mheight * 3 / 2.0 + reflectionGap)));
            imageView.setScaleType(ScaleType.MATRIX);
            mImages[index++] = imageView;
        }
        return true;
    }

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

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

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

Gallery3D例子代码:点击下载

(0)

相关推荐

  • Android ViewPager相册横向移动的实现方法

    当我们第一次下载QQ并且打开的时候,会有一个新手引导,引导是几张图片,再加上一些文字说明,向右滑动,直到结束,今天一大早起来研究了一下关于此种效果的实现之ViewPager控件. 下面这个例子将用ViewPager实现横向移动相册,ViewPager有一个对应的PagerAdapter,用于绑定数据:我们需要继承此类并实现自己的功能. 1.首先定义一个显示项所需要使用的数据对象ImageItem 复制代码 代码如下: public class ImageItem { private int id

  • 基于Android实现保存图片到本地并可以在相册中显示出来

    App应用越来越人性化,不仅界面优美而且服务也很多样化,操作也非常方便.比如我们在用app的时候,发现上面有比较的图片想保存到手机,只要点一点app上提供的保存按钮就可以了.那这个图片保存到本地怎么实现的呢? 保存图片很简单,方法如下: /** 首先默认个文件保存路径 */ private static final String SAVE_PIC_PATH=Environment.getExternalStorageState().equalsIgnoreCase(Environment.MED

  • 自己动手写一个java版简单云相册

    动手写一个java版简单云相册,实现的功能是: 用户可以一次上传一个至多个文件. 用户可以下载其他人上传的图片. 用户可以查看其他所有人的图片. 用户只能删除通过自己IP上传的图片. 用到的技术: 文件上传下载.设计模式.Dom4j.xPath等. 先看下2个页面: 源代码: web.xml: <?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns=

  • javaWEB实现相册管理的简单功能

    这仅仅只是一个小小的相册管理,主要实现的功能:能够实现对图片的上传,统一浏览,单个下载,单个删除,只能删除自己上传的文件. 现在对每个功能进行单个的解释: 图片的上传  图片的上传在之前的文章中写的很清楚了,点击打开链接:<JavaEE实现前后台交互的文件上传与下载> . 在这个相册管理中,就不是单一的文件传了,还需要涉及到很多参数供其他功能模块的使用 <span style="font-size:24px;">//上传文件一般采用外面的 apache的上传工具

  • 精致小巧的java相册制作方法

    本文实例为大家分享了java相册制作方法,供大家参考,具体内容如下 注: 1)html上的图片是静态指定的.当更新了新的图片时必须手工更新.所以使用Servlet读取本地images中的所有图片,动态显示给用户. 2)如果存在中文名的图片,由于get方式无法直接传递中文,会导致出错. 主页面–index.jsp <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"

  • 相册管理系统(Java表单+xml数据库存储)

    功能文件的上传,下载和管理 技术:1.用xml当做数据库存储信息(dom4j,xpath) 2.Java表单的文件上传和下载 3.文件目录的打散 ( Hash目录是一种优化文件存储性能的方法) 需要的jar包: commons-fileupload-1.2.2.jar.commons-io-2.1.jar.dom4j-1.6.1.jar和jaxen-1.1-beta-6.jar -----------------------------------------------------------

  • Android拍照保存在系统相册不显示的问题解决方法

    可能大家都知道我们保存相册到Android手机的时候,然后去打开系统图库找不到我们想要的那张图片,那是因为我们插入的图片还没有更新的缘故,先讲解下插入系统图库的方法吧,很简单,一句代码就能实现 复制代码 代码如下: MediaStore.Images.Media.insertImage(getContentResolver(), mBitmap, "", ""); 通过上面的那句代码就能插入到系统图库,这时候有一个问题,就是我们不能指定插入照片的名字,而是系统给了我

  • Android相册效果(使用C#和Java分别实现)

    运行效果 C#实现 using Android.App; using Android.OS; using Android.Widget; namespace ImageDemo { [Activity(Label = "@string/ApplicationName", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : Activity { private Galle

  • Android实现读取相机(相册)图片并进行剪裁

    我们先说一下思路,在android系统中就自带了图片剪切的应用,所以,我们只需要将我们获取到的相片传给图片剪切应用,再将剪切好的相片返回到我们自己的界面显示就ok了 在开发一些APP的过程中,我们可能涉及到头像的处理,比如从手机或者相册获取头像,剪裁成自己需要的头像,设置或上传头像等.网上一些相关的资料也是多不胜数,但在实际应用中往往会存在各种问题,没有一个完美的解决方案.由于近期项目的需求,就研究了一下,目前看来还没有什么问题. 这里我们只讨论获取.剪裁与设置,上传流程根据自己的业务需求添加.

  • android照相、相册获取图片剪裁报错的解决方法

    这是调用相机 public static File getImageFromCamer(Context context, File cameraFile, int REQUE_CODE_CAMERA, Intent intent) { intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File fileDir = HelpUtil.getFile(context, "/Tour/user_photos"); cameraFile

随机推荐