转载请注明出处:http://blog.csdn.net/l1028386804/article/details/48052709

如今,Android开发已经成为移动互联开发领域中一支不可或缺的力量,那么Android中要实现3D的效果那也就是合情合理的事情了。那么,如何在Android中实现像IOS中那样的3D图片浏览效果呢?下面,鄙人将重磅推出今天的重点博文,和大家一起在Android中实现酷炫的3D图片浏览效果。

一、原理

老规矩,还是要来啰嗦下原理的东西。

整体实现是以手机屏幕的正中间位置为对称轴,位于正中间的图片显示最大,也最亮,同时左右两边的图片以最中间位置为对称轴,分别旋转对应的角度,同时亮度调整为适当的比例,已达到对称的效果。具体的3D浏览图片效果,我是通过自定义Gallery来实现的,创建一个类GalleryFlow,继承Gallery,在这个类中进行图像的旋转、缩放,亮度设置等操作。同时,在这个类中,我创建了一个相机对象camera来设置图像的变化效果;同时自定义一个图像的适配器类ImageAdapter,这个类继承BaseAdapter,主要是实现界面图片的显示,以及创建带有倒影的图片。

原理啰嗦完了,那就让我们一起来实现这个酷炫的3D效果吧。

二、实现

1、自定义适配器ImageAdapter

显示图片的适配器,这个类继承BaseAdapter,完成图像的基本显示,同时将原有图片生成带有倒影的图片进行显示。具体的实现为,在构造方法中将界面中的上下文信息,和存放图片id的数组传递过来,通过传递的图片id数组生成对应的ImageView数组,用来存放带有图片信息的ImageView对象。在createRefectedBitmap()方法中将原有图片处理成带有倒影效果的图片存放在ImageView对象中,然后将ImageView对象存放在ImageView数组中。

具体实现的代码如下:

package com.lyz.gallery.activity;import android.content.Context;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.graphics.drawable.BitmapDrawable;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;/** * 自定义图片显示的适配器ImageAdapter * @author liuyazhuang * */public class ImageAdapter extends BaseAdapter {private Context context;private int[] imageIds;private ImageView[] images;//构造方法public ImageAdapter(Context context, int[] imageIds) {this.context = context;this.imageIds = imageIds;//存放图片的数组images = new ImageView[imageIds.length];}@Overridepublic int getCount() {return images.length;}@Overridepublic Object getItem(int position) {return images[position];}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {return images[position];}/** * 创建带有倒影的图片 */public void createRefectedBitmap() {//原图片与倒影图片之间的距离int refectionGap = 4;//向图片数组中加入图片for(int i = 0; i < imageIds.length; i++){int imageId = imageIds[i];//原图片Bitmap resourceBitmap = BitmapFactory.decodeResource(context.getResources(), imageId);int width = resourceBitmap.getWidth();int height = resourceBitmap.getHeight();//倒影图片//reource:原图片//x,y:生成倒影图片的起始位置//width,heiht:生成倒影图片宽和高//Matrix m:用来设置图片的样式(倒影)Matrix m = new Matrix();//x:水平翻转;y:垂直翻转   1支持; -1翻转m.setScale(1, -1);Bitmap refrectionBitmap = Bitmap.createBitmap(resourceBitmap, 0, height / 2, width, height / 2,m, false);//合成的带有倒影的图片Bitmap bitmap = Bitmap.createBitmap(width, height + height/2, Config.ARGB_8888);//创建画布Canvas canvas = new Canvas(bitmap);//绘制原图片canvas.drawBitmap(resourceBitmap, 0, 0, null);//绘制原图片与倒影之间的间隔Paint defaultPaint = new Paint();canvas.drawRect(0, height, width, height + refectionGap, defaultPaint);//绘制倒影图片canvas.drawBitmap(refrectionBitmap, 0, height + refectionGap, null);//ps中的渐变和遮罩效果Paint paint = new Paint();//设置遮罩效果paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));//设置渐变效果//设置着色器为遮罩着色LinearGradient shader = new LinearGradient(0, height, 0, bitmap.getHeight(), 0x70ffffff, 0x00ffffff, TileMode.CLAMP);paint.setShader(shader);canvas.drawRect(0, height, width, bitmap.getHeight(), paint);//创建BitmapDrawable图片BitmapDrawable bd = new BitmapDrawable(bitmap);//消除图片锯齿效果,使图片平滑bd.setAntiAlias(true);ImageView imageView = new ImageView(context);imageView.setImageDrawable(bd);//设置图片大小imageView.setLayoutParams(new GalleryFlow.LayoutParams(160, 240));//将图片放置在images数组中images[i] = imageView;}}}

2、自定义Gallery类GalleryFlow

这个类中我们主要实现的是图片的缩放、旋转、亮度调整等操作,下面我们分解来看这个类。

1)成员变量

这里的成员变量主要是:最大的旋转角度、最大缩放值、记录中间点的位置、相机对象

具体实现代码如下:

//最大的旋转角度private int maxRotateAngle = 50;//最大缩放值private int maxZoom = -250;//记录中间点的位置private int currentOfGallery;//创建相机对象private Camera camera = new Camera();

2)构造方法

我在这里复写了Gallery的三个构造方法,并在每个构造方法中分别调用了setStaticTransformationsEnabled(true);方法,这个方法的作用是:指定图形是否变化 false:否 true:是。当我们调用了setStaticTransformationsEnabled方法时,Android就会回调下面的getChildStaticTransformation方法

具体实现代码如下:

public GalleryFlow(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);setStaticTransformationsEnabled(true);}public GalleryFlow(Context context, AttributeSet attrs) {super(context, attrs);//指定图形是否变化 false:否  true:是setStaticTransformationsEnabled(true);}public GalleryFlow(Context context) {super(context);setStaticTransformationsEnabled(true);}

3)getChildStaticTransformation方法

这个方法是调用了setStaticTransformationsEnabled时,Android会回调的一个方法,我在这个方法中完成的操作主要是:计算图像的旋转角度,设置图片的变形样式,同时调用图片变形的放方法transformationBitmap来达到图片变形的效果。

具体实现的代码如下:

@Overrideprotected boolean getChildStaticTransformation(View child, Transformation t) {//得到图片的中心点int currentOfChild = getCurrentOfView(child);int width = child.getLayoutParams().width;int height = child.getLayoutParams().height;//旋转的角度int rotateAngle = 0;t.clear();//设置图片变形样式t.setTransformationType(Transformation.TYPE_MATRIX);//位置中心点位置if(currentOfChild == currentOfGallery){transformationBitmap((ImageView)child, t, 0);}else{//不是中心位置rotateAngle = (int) ((float)(currentOfGallery - currentOfChild) / width * maxRotateAngle);if(Math.abs(rotateAngle) > maxRotateAngle){rotateAngle = rotateAngle < 0 ? -maxRotateAngle : maxRotateAngle;}//图片变形transformationBitmap((ImageView)child, t, rotateAngle);}return true;}

4)图片变形方法transformationBitmap

这个方法主要完成的操作就是通过相机对象来完成对图像的变形操作。

具体实现代码如下:

/** * 图片变形 * @param child * @param t * @param i */private void transformationBitmap(ImageView child, Transformation t, int rotateAngle) {//保存图像变化的效果camera.save();Matrix imageMatrix = t.getMatrix();int rotate = Math.abs(rotateAngle);int imageWidth = child.getWidth();int imageHeight = child.getHeight();//z:正数:图片变大//x:水平移动//y:垂直移动camera.translate(0.0f, 0.0f, 100.0f);//当前旋转角度小于最大旋转角度if(rotate < maxRotateAngle){float zoom = (float) ((rotate * 1.5) + maxZoom);camera.translate(0.0f, 0.0f, zoom);//设置图片渐变效果child.setAlpha((int) (255 - rotate * 2.5));}//图片向展示中心进行垂直角度旋转camera.rotateY(rotateAngle);camera.getMatrix(imageMatrix);imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));imageMatrix.postTranslate(imageWidth / 2, imageHeight / 2);//还原图像变化的效果camera.restore();}

5)获取Gallery展示图片的中心点方法

具体实现代码如下:

/** * 获取Gallery展示图片的中心点 * @return */public int getCurrentOfGallery(){return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2 + getPaddingLeft();}

6)获取图片中心点方法

具体实现代码如下:

/** * 获取图片中心点 * @param view * @return */public int getCurrentOfView(View view){return view.getLeft() + view.getWidth() / 2;}

7)onSizeChanged方法

这个方法是当屏幕大小变化的时候,Android自动回调的方法,我在这个方法中的操作就是将获取到的Gallery展示图片的中心点赋值给成员变量currentOfGallery。

具体代码如下:

@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {currentOfGallery = getCurrentOfGallery();super.onSizeChanged(w, h, oldw, oldh);}

8)完整代码如下:

package com.lyz.gallery.activity;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;/** * 自定义Gallery * @author liuyazhuang * */public class GalleryFlow extends Gallery {//最大的旋转角度private int maxRotateAngle = 50;//最大缩放值private int maxZoom = -250;//记录中间点的位置private int currentOfGallery;//创建相机对象private Camera camera = new Camera();public GalleryFlow(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);setStaticTransformationsEnabled(true);}public GalleryFlow(Context context, AttributeSet attrs) {super(context, attrs);//指定图形是否变化 false:否  true:是setStaticTransformationsEnabled(true);}public GalleryFlow(Context context) {super(context);setStaticTransformationsEnabled(true);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {currentOfGallery = getCurrentOfGallery();super.onSizeChanged(w, h, oldw, oldh);}@Overrideprotected boolean getChildStaticTransformation(View child, Transformation t) {//得到图片的中心点int currentOfChild = getCurrentOfView(child);int width = child.getLayoutParams().width;int height = child.getLayoutParams().height;//旋转的角度int rotateAngle = 0;t.clear();//设置图片变形样式t.setTransformationType(Transformation.TYPE_MATRIX);//位置中心点位置if(currentOfChild == currentOfGallery){transformationBitmap((ImageView)child, t, 0);}else{//不是中心位置rotateAngle = (int) ((float)(currentOfGallery - currentOfChild) / width * maxRotateAngle);if(Math.abs(rotateAngle) > maxRotateAngle){rotateAngle = rotateAngle < 0 ? -maxRotateAngle : maxRotateAngle;}//图片变形transformationBitmap((ImageView)child, t, rotateAngle);}return true;}/** * 图片变形 * @param child * @param t * @param i */private void transformationBitmap(ImageView child, Transformation t, int rotateAngle) {//保存图像变化的效果camera.save();Matrix imageMatrix = t.getMatrix();int rotate = Math.abs(rotateAngle);int imageWidth = child.getWidth();int imageHeight = child.getHeight();//z:正数:图片变大//x:水平移动//y:垂直移动camera.translate(0.0f, 0.0f, 100.0f);//当前旋转角度小于最大旋转角度if(rotate < maxRotateAngle){float zoom = (float) ((rotate * 1.5) + maxZoom);camera.translate(0.0f, 0.0f, zoom);//设置图片渐变效果child.setAlpha((int) (255 - rotate * 2.5));}//图片向展示中心进行垂直角度旋转camera.rotateY(rotateAngle);camera.getMatrix(imageMatrix);imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));imageMatrix.postTranslate(imageWidth / 2, imageHeight / 2);//还原图像变化的效果camera.restore();}/** * 获取Gallery展示图片的中心点 * @return */public int getCurrentOfGallery(){return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2 + getPaddingLeft();}/** * 获取图片中心点 * @param view * @return */public int getCurrentOfView(View view){return view.getLeft() + view.getWidth() / 2;}}

3、MainActivity

这个类主要实现的功能是加载布局文件,构造要显示的图片的id数组,调用ImageAdapter方法实现图片的显示操作。

具体实现的代码如下:

package com.lyz.gallery.activity;import android.os.Bundle;import android.app.Activity;import android.view.Menu;/** * 程序主入口 * @author liuyazhuang * */public class MainActivity extends Activity {private GalleryFlow gallery_flow;//存放图片id的数组private int[] imageIds;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//构造存放图片id的数组imageIds = new int[]{R.drawable.photo1,R.drawable.photo2,R.drawable.photo3,R.drawable.photo4,R.drawable.photo5,R.drawable.photo6,R.drawable.photo7,R.drawable.photo8};gallery_flow = (GalleryFlow) findViewById(R.id.gallery_flow);//实例化ImageAdapter对象ImageAdapter adapter = new ImageAdapter(this, imageIds);//向图片数组中加载图片adapter.createRefectedBitmap();gallery_flow.setAdapter(adapter);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}}

4、布局文件activity_main.xml

这个布局文件很简单,就是放置了一个我们自己定义的GalleryFlow控件。

具体实现代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="@android:color/black">    <com.lyz.gallery.activity.GalleryFlow        android:id="@+id/gallery_flow"        android:layout_width="match_parent"        android:layout_height="match_parent"/></RelativeLayout>

5、AndroidManifest.xml

这个文件中没有做任何操作,都是Android自动生成的内容。

具体实现代码如下:

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.lyz.gallery.activity"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="8"        android:targetSdkVersion="18" />    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name="com.lyz.gallery.activity.MainActivity"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>

三、运行效果


四、温馨提示

大家可以到链接http://download.csdn.net/detail/l1028386804/9058447下载Android实现3D图片浏览效果示例完整源代码

本实例中,为了方面,我把一些文字直接写在了布局文件中和相关的类中,大家在真实的项目中要把这些文字写在string.xml文件中,在外部引用这些资源,切记,这是作为一个Android程序员最基本的开发常识和规范,我在这里只是为了方便直接写在了类和布局文件中。

更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. Python list sort方法的具体使用
  3. python list.sort()根据多个关键字排序的方法实现
  4. Android高手进阶教程(十九)---Android中几种图像特效处理的集锦!
  5. Android中使用Handler机制更新UI的三种解决方案
  6. Android(安卓)Framework启动流程浅析
  7. Android逆向之旅---Android中的sharedUserId属性详解
  8. Android中AsyncTask的简单用法
  9. android游戏引擎初探

随机推荐

  1. Android(安卓)Listview多次调用相同的add
  2. Android(安卓)studio的安装、环境配置和
  3. android SDK启动的错误
  4. 46.Android(安卓)自定义Dialog
  5. 移植Android(安卓)GingerBread 2.3.4系统
  6. Android(安卓)Activity class and static
  7. 自定义平滑滑动页面的组件:DragableSpace
  8. 获取联系人信息和删除联系人
  9. android中的保存数据方法
  10. Android访问权限总结