android之向Gallery中添加倒影3D效果

step1:新建项目MyGallery3D

                                                                


step2:设计应用的UI界面   /layout/gallery3d.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     android:gravity="center"  
  7.     >  
  8.     <cn.roco.gallery3d.MyGallery3D  
  9.         android:id="@+id/gallery3D"  
  10.         android:layout_width="fill_parent"  
  11.         android:layout_height="wrap_content"  
  12.         android:layout_centerInParent="true"  
  13.     />  
  14. </LinearLayout>  

step3:扩展Gallery,实现3D效果

MyGallery3D.java

  1. package cn.roco.gallery3d;  
  2. import android.content.Context;  
  3. import android.graphics.Camera;  
  4. import android.graphics.Matrix;  
  5. import android.util.AttributeSet;  
  6. import android.view.View;  
  7. import android.view.animation.Transformation;  
  8. import android.widget.Gallery;  
  9.   
  10. public class MyGallery3D extends Gallery  
  11. {  
  12.     /** 
  13.      * The camera class is used to 3D transformation matrix. 
  14.      * 相机类 
  15.      */  
  16.     private Camera mCamera = new Camera();  
  17.       
  18.     /** 
  19.      * The max rotation angle. 
  20.      * 最大转动角度 
  21.      */  
  22.     private int mMaxRotationAngle = 45;     
  23.       
  24.     /** 
  25.      * The max zoom value (Z axis). 
  26.      * 最大缩放值 
  27.      */  
  28.     private int mMaxZoom = -120;  
  29.       
  30.     /** 
  31.      * The center of the gallery. 
  32.      * 半径值 
  33.      */  
  34.     private int mCoveflowCenter = 0;  
  35.       
  36.     public MyGallery3D(Context context)  
  37.     {  
  38.         super(context);  
  39.         //支持转换 ,执行getChildStaticTransformation方法  
  40.         this.setStaticTransformationsEnabled(true);  
  41.     }  
  42.       
  43.     public MyGallery3D(Context context, AttributeSet attrs)  
  44.     {  
  45.         super(context,attrs);  
  46.         //支持转换 ,执行getChildStaticTransformation方法  
  47.         this.setStaticTransformationsEnabled(true);  
  48.     }  
  49.       
  50.     public MyGallery3D(Context context, AttributeSet attrs, int defStyle)  
  51.     {  
  52.         super(context, attrs, defStyle);  
  53.           
  54.         // Enable set transformation.  
  55.         this.setStaticTransformationsEnabled(true);  
  56.         // Enable set the children drawing order.  
  57.         this.setChildrenDrawingOrderEnabled(true);  
  58.     }  
  59.       
  60.     public int getMaxRotationAngle()  
  61.     {  
  62.         return mMaxRotationAngle;  
  63.     }  
  64.       
  65.     public void setMaxRotationAngle(int maxRotationAngle)  
  66.     {  
  67.         mMaxRotationAngle = maxRotationAngle;  
  68.     }  
  69.       
  70.     public int getMaxZoom()  
  71.     {  
  72.         return mMaxZoom;  
  73.     }  
  74.       
  75.     public void setMaxZoom(int maxZoom)  
  76.     {  
  77.         mMaxZoom = maxZoom;  
  78.     }  
  79.       
  80.     @Override  
  81.     protected int getChildDrawingOrder(int childCount, int i)  
  82.     {  
  83.         // Current selected index.  
  84.         int selectedIndex = getSelectedItemPosition() - getFirstVisiblePosition();  
  85.         if (selectedIndex < 0)   
  86.         {  
  87.             return i;  
  88.         }  
  89.           
  90.         if (i < selectedIndex)  
  91.         {  
  92.             return i;  
  93.         }  
  94.         else if (i >= selectedIndex)  
  95.         {  
  96.             return childCount - 1 - i + selectedIndex;  
  97.         }  
  98.         else  
  99.         {  
  100.             return i;  
  101.         }  
  102.     }  
  103.       
  104.     @Override  
  105.     protected void onSizeChanged(int w, int h, int oldw, int oldh)  
  106.     {  
  107.         mCoveflowCenter = getCenterOfCoverflow();  
  108.         super.onSizeChanged(w, h, oldw, oldh);  
  109.     }  
  110.       
  111.     private int getCenterOfView(View view)  
  112.     {  
  113.         return view.getLeft() + view.getWidth() / 2;  
  114.     }  
  115.     //控制gallery中每个图片的旋转(重写的gallery中方法)  
  116.     @Override  
  117.     protected boolean getChildStaticTransformation(View child, Transformation t)  
  118.     {  
  119. //        super.getChildStaticTransformation(child, t);  
  120.         //取得当前子view的半径值  
  121.         final int childCenter = getCenterOfView(child);  
  122.         final int childWidth  = child.getWidth();  
  123.         //旋转角度  
  124.         int rotationAngle = 0;  
  125.         //重置转换状态  
  126.         t.clear();  
  127.         //设置转换类型  
  128.         t.setTransformationType(Transformation.TYPE_MATRIX);  
  129.           
  130.         // If the child is in the center, we do not rotate it.  
  131.         //如果图片位于中心位置不需要进行旋转  
  132.         if (childCenter == mCoveflowCenter)  
  133.         {  
  134.             transformImageBitmap(child, t, 0);  
  135.         }  
  136.         else  
  137.         {  
  138.             // Calculate the rotation angle.  
  139.             //根据图片在gallery中的位置来计算图片的旋转角度  
  140.             rotationAngle = (int)(((float)(mCoveflowCenter - childCenter) / childWidth) * mMaxRotationAngle);  
  141.               
  142.             // Make the angle is not bigger than maximum.  
  143.             /*如果旋转角度绝对值大于最大旋转角度返回 
  144.                 (-mMaxRotationAngle或mMaxRotationAngle;)*/  
  145.             if (Math.abs(rotationAngle) > mMaxRotationAngle)  
  146.             {  
  147.                 rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle : mMaxRotationAngle;  
  148.             }  
  149.             transformImageBitmap(child, t, rotationAngle);  
  150.         }  
  151.         return true;  
  152.     }  
  153.       
  154.     private int getCenterOfCoverflow()  
  155.     {  
  156.         return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2 + getPaddingLeft();  
  157.     }  
  158.       
  159.     private void transformImageBitmap(View child, Transformation t, int rotationAngle)  
  160.     {  
  161.         //对效果进行保存  
  162.         mCamera.save();  
  163.           
  164.         final Matrix imageMatrix = t.getMatrix();  
  165.         //图片高度  
  166.         final int imageHeight = child.getLayoutParams().height;  
  167.         //图片宽度  
  168.         final int imageWidth  = child.getLayoutParams().width;  
  169.         //返回旋转角度的绝对值  
  170.         final int rotation    = Math.abs(rotationAngle);  
  171.           
  172.         // Zoom on Z axis.  
  173.         /** 
  174.          * 在Z轴上正向移动camera的视角,实际效果为放大图片。 
  175.                               如果在Y轴上移动,则图片上下移动;X轴上对应图片左右移动。 
  176.          */  
  177.         mCamera.translate(0.0f, 0.0f, 100.0f);  
  178.           
  179.         if (rotation < mMaxRotationAngle)  
  180.         {  
  181.             float zoomAmount = (float)(mMaxZoom + (rotation * 1.5f));  
  182.             mCamera.translate(0.0f, 0.0f, zoomAmount);  
  183.         }  
  184.           
  185.         // Rotate the camera on Y axis.  
  186.         /** 
  187.          * 在Y轴上旋转,对应图片竖向向里翻转。 
  188.                              如果在X轴上旋转,则对应图片横向向里翻转。 
  189.          */  
  190.         mCamera.rotateY(rotationAngle);  
  191.         // Get the matrix from the camera, in fact, the matrix is S (scale) transformation.  
  192.         mCamera.getMatrix(imageMatrix);  
  193.           
  194.         /*** 
  195.          *   第一,先在Z轴上平称,其实就是得到一个缩放矩阵变换,我这里简写为 S。 
  196.               第二,是利用camera这个类来生成matrix,其实mCamera.rotateY就是围绕Y轴旋转。 
  197.                    这里生成了一个旋转矩阵,记为 R 。经过这两步,此时调用mCamera.getMatrix(imageMatrix); 
  198.                   从Camera中得到matrix,此时这个矩阵中包含了S * R。 
  199.          * 第三 
  200.          * 由于这里涉及到旋转与缩放,缩放操作其实应该是针对Child中点进行了,这里就是作一个平衡操作, 
  201.          * 我们必须是先平移,再缩放,再平移回原来位置,所以,我们最终的矩阵变换应该是这样的: 
  202.            M = T * (S * R) * T1   (这里在T1表示与T相反)。 
  203.          */  
  204.         // The matrix final is T2 * S * T1, first translate the center point to (0, 0),   
  205.         // then scale, and then translate the center point to its original point.  
  206.         // T * S * T  
  207.          
  208.         // (T2 * S) * T1  
  209.         imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));  
  210.         // S * T1  
  211.         imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));  
  212.          
  213.         mCamera.restore();  
  214.     }  
  215. }  

step4:图片适配器    MyImageAdapter.java

  1. package cn.roco.gallery3d;  
  2.   
  3. import android.content.Context;  
  4. import android.content.res.Resources;  
  5. import android.graphics.Bitmap;  
  6. import android.graphics.Bitmap.Config;  
  7. import android.graphics.BitmapFactory;  
  8. import android.graphics.Canvas;  
  9. import android.graphics.LinearGradient;  
  10. import android.graphics.Matrix;  
  11. import android.graphics.Paint;  
  12. import android.graphics.PorterDuffXfermode;  
  13. import android.graphics.Shader.TileMode;  
  14. import android.view.View;  
  15. import android.view.ViewGroup;  
  16. import android.widget.BaseAdapter;  
  17. import android.widget.ImageView;  
  18.   
  19. public class MyImageAdapter extends BaseAdapter {  
  20.     int mGalleryItemBackground;  
  21.     private Context mContext;  
  22.     private Integer[] mImageIds;  
  23.     private ImageView[] mImages;  
  24.   
  25.     public MyImageAdapter(Context c, Integer[] ImageIds) {  
  26.         mContext = c;  
  27.         mImageIds = ImageIds;  
  28.         mImages = new ImageView[mImageIds.length];  
  29.     }  
  30.   
  31.     /** 
  32.      * 创建倒影效果 
  33.      *  
  34.      * @return 
  35.      */  
  36.     public boolean createReflectedImages() {  
  37.         // 倒影图和原图之间的距离  
  38.         final int reflectionGap = 4;  
  39.         int index = 0;  
  40.         for (int imageId : mImageIds) {  
  41.             // 返回原图解码之后的bitmap对象  
  42.             Bitmap originalImage = BitmapFactory.decodeResource(  
  43.                     mContext.getResources(), imageId);  
  44.             int width = originalImage.getWidth();  
  45.             int height = originalImage.getHeight();  
  46.             // 创建矩阵对象  
  47.             Matrix matrix = new Matrix();  
  48.   
  49.             // 指定一个角度以0,0为坐标进行旋转  
  50.             // matrix.setRotate(30);  
  51.   
  52.             // 指定矩阵(x轴不变,y轴相反)  
  53.             // 1表示放大比例,不放大也不缩小。    
  54.             // -1表示在y轴上相反,即旋转180度  
  55.             matrix.preScale(1, -1);  
  56.               
  57.             // 将矩阵应用到该原图之中,返回一个宽度不变,高度为原图1/2的倒影位图  
  58.             Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,  
  59.                     height / 2, width, height / 2, matrix, false);  
  60.   
  61.             //创建一个最终效果的图,即源图 + 间隙 + 倒影。  
  62.             Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height  
  63.                     + height / 2 + reflectionGap), Config.ARGB_8888);  
  64.   
  65.             // 将上面创建的位图初始化到画布  
  66.             Canvas canvas = new Canvas(bitmapWithReflection);  
  67.             canvas.drawBitmap(originalImage, 00null);  
  68.   
  69.             Paint deafaultPaint = new Paint();  
  70.             canvas.drawRect(0, height, width, height + reflectionGap,  
  71.                     deafaultPaint);  
  72.             canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);  
  73.   
  74.             Paint paint = new Paint();  
  75.             /**创建LinearGradient,从而给定一个由上到下的渐变色。 
  76.              * 参数一:为渐变起初点坐标x位置, 参数二:为y轴位置, 参数三和四:分辨对应渐变终点, 最后参数为平铺方式, 
  77.              * 这里设置为镜像Gradient是基于Shader类,所以我们通过Paint的setShader方法来设置这个渐变 
  78.              */  
  79.             LinearGradient shader = new LinearGradient(0,  
  80.                     originalImage.getHeight(), 0,  
  81.                     bitmapWithReflection.getHeight() + reflectionGap,  
  82.                     0x70ffffff0x00ffffff, TileMode.MIRROR);  
  83.             // 设置阴影  
  84.             paint.setShader(shader);  
  85.             paint.setXfermode(new PorterDuffXfermode(  
  86.                     android.graphics.PorterDuff.Mode.DST_IN));  
  87.             // 用已经定义好的画笔构建一个矩形阴影渐变效果  
  88.             canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()  
  89.                     + reflectionGap, paint);  
  90.   
  91.             // 创建一个ImageView用来显示已经画好的bitmapWithReflection  
  92.             ImageView imageView = new ImageView(mContext);  
  93.             imageView.setImageBitmap(bitmapWithReflection);  
  94.             // 设置imageView大小 ,也就是最终显示的图片大小  
  95.             imageView.setLayoutParams(new MyGallery3D.LayoutParams(300400));  
  96.             // imageView.setScaleType(ScaleType.MATRIX);  
  97.             mImages[index++] = imageView;  
  98.         }  
  99.         return true;  
  100.     }  
  101.   
  102.     @SuppressWarnings("unused")  
  103.     private Resources getResources() {  
  104.         return null;  
  105.     }  
  106.   
  107.     public int getCount() {  
  108.         return mImageIds.length;  
  109.     }  
  110.   
  111.     public Object getItem(int position) {  
  112.         return position;  
  113.     }  
  114.   
  115.     public long getItemId(int position) {  
  116.         return position;  
  117.     }  
  118.   
  119.     public View getView(int position, View convertView, ViewGroup parent) {  
  120.         return mImages[position];  
  121.     }  
  122.   
  123.     public float getScale(boolean focused, int offset) {  
  124.         return Math.max(01.0f / (float) Math.pow(2, Math.abs(offset)));  
  125.     }  
  126. }  

step5:MyGallery3DActivity.java

  1. package cn.roco.gallery3d;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.view.View;  
  6. import android.widget.AdapterView;  
  7. import android.widget.AdapterView.OnItemClickListener;  
  8. import android.widget.Toast;  
  9. import cn.roco.gallery3d.MyGallery3D;  
  10. import cn.roco.gallery3d.MyImageAdapter;  
  11.   
  12. public class MyGallery3DActivity extends Activity {  
  13.     public void onCreate(Bundle savedInstanceState) {  
  14.         super.onCreate(savedInstanceState);  
  15.   
  16.         setContentView(R.layout.gallery3d);  
  17.   
  18.         Integer[] images = { R.drawable.beautiful_000,  
  19.                 R.drawable.beautiful_001, R.drawable.beautiful_002,  
  20.                 R.drawable.beautiful_003, R.drawable.beautiful_004,  
  21.                 R.drawable.beautiful_005, R.drawable.beautiful_006,  
  22.                 R.drawable.beautiful_007, R.drawable.beautiful_008,  
  23.                 R.drawable.beautiful_009, R.drawable.beautiful_010, };  
  24.   
  25.         MyImageAdapter adapter = new MyImageAdapter(this, images);  
  26.         adapter.createReflectedImages();// 创建倒影效果  
  27.         MyGallery3D galleryFlow = (MyGallery3D) this  
  28.                 .findViewById(R.id.gallery3D);  
  29.         galleryFlow.setFadingEdgeLength(0);  
  30.         galleryFlow.setSpacing(-100); // 图片之间的间距  
  31.         galleryFlow.setAdapter(adapter);  
  32.   
  33.         galleryFlow.setOnItemClickListener(new OnItemClickListener() {  
  34.             public void onItemClick(AdapterView<?> parent, View view,  
  35.                     int position, long id) {  
  36.                 Toast.makeText(getApplicationContext(),  
  37.                         String.valueOf(position), Toast.LENGTH_SHORT).show();  
  38.             }  
  39.   
  40.         });  
  41.         galleryFlow.setSelection(1);  
  42.     }  
  43. }  

step6:AndroidManifest.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.       package="cn.roco.gallery3d"  
  4.       android:versionCode="1"  
  5.       android:versionName="1.0">  
  6.     <uses-sdk android:minSdkVersion="8" />  
  7.   
  8.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  9.         <activity android:name="MyGallery3DActivity"  
  10.                   android:label="@string/app_name">  
  11.             <intent-filter>  
  12.                 <action android:name="android.intent.action.MAIN" />  
  13.                 <category android:name="android.intent.category.LAUNCHER" />  
  14.             </intent-filter>  
  15.         </activity>  
  16.   
  17.     </application>  
  18. </manifest>  

step7:部署应用到模拟器,查看运行效果

             


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值