上篇介绍了使用Animation实现3D动画旋转翻页效果,现在介绍图片倒影实现,先看效果图

本示例主要通过自定义Gallery和ImageAdapter(继承自BaseAdapter)实现

1、倒影绘制

ImageAdapter继承自BaseAdapter,详细实现可见 Android 滑动效果入门篇(二)—— Gallery 这里重点介绍倒影原理及实现

倒影原理:

倒影效果是主要由原图+间距+倒影三部分组成,高度大约为原图的3/2(原图为1、倒影为1/2)

原图,就是我们看到了最开始的图片

间距,是原图与倒影之间的间隙,如:reflectionGap = 4;

倒影,是原图下半部分1/2高度,通过矩阵变换matrix.preScale(1, -1); 获取倒立图片,然后再加上线性遮罩和阴影实现

倒影实现:

  1. /** 反射倒影 */
  2. public boolean createReflectedImages() {
  3. final int reflectionGap = 4;
  4. int index = 0;
  5. for (Map<String, Object> map : list) {
  6. Integer id = (Integer) map.get("image");
  7. Bitmap originalImage = BitmapFactory.decodeResource(mContext.getResources(), id);   // 获取原始图片
  8. int width = originalImage.getWidth();
  9. int height = originalImage.getHeight();
  10. Matrix matrix = new Matrix();
  11. matrix.preScale(1, -1);         // 图片矩阵变换(从低部向顶部的倒影)
  12. Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height/2, width, height/2, matrix, false);   // 截取原图下半部分
  13. Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height / 2), Config.ARGB_8888);          // 创建倒影图片(高度为原图3/2)
  14. Canvas canvas = new Canvas(bitmapWithReflection);   // 绘制倒影图(原图 + 间距 + 倒影)
  15. canvas.drawBitmap(originalImage, 0, 0, null);       // 绘制原图
  16. Paint paint = new Paint();
  17. canvas.drawRect(0, height, width, height + reflectionGap, paint);       // 绘制原图与倒影的间距
  18. canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);    // 绘制倒影图
  19. paint = new Paint();
  20. LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0, bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
  21. paint.setShader(shader);    // 线性渐变效果
  22. paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));     // 倒影遮罩效果
  23. canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint);     // 绘制倒影的阴影效果
  24. ImageView imageView = new ImageView(mContext);
  25. imageView.setImageBitmap(bitmapWithReflection);     // 设置倒影图片
  26. imageView.setLayoutParams(new myGallery.LayoutParams(180, 240));
  27. imageView.setScaleType(ScaleType.MATRIX);
  28. mImages[index++] = imageView;
  29. }
  30. return true;
  31. }

2、myGallery

自定义Gallery来实现倒影图片的浏览与选择

  1. public class myGallery extends Gallery {
  2. private Camera mCamera = new Camera();
  3. private int mMaxRotationAngle = 60;     // 最大旋转角度 60
  4. private int mMaxZoom = -120;
  5. private int mCoveflowCenter;
  6. public myGallery(Context context) {
  7. super(context);
  8. this.setStaticTransformationsEnabled(true);
  9. }
  10. public myGallery(Context context, AttributeSet attrs) {
  11. super(context, attrs);
  12. this.setStaticTransformationsEnabled(true);
  13. }
  14. public myGallery(Context context, AttributeSet attrs, int defStyle) {
  15. super(context, attrs, defStyle);
  16. this.setStaticTransformationsEnabled(true);
  17. }
  18. public int getMaxRotationAngle() {
  19. return mMaxRotationAngle;
  20. }
  21. public void setMaxRotationAngle(int maxRotationAngle) {
  22. mMaxRotationAngle = maxRotationAngle;
  23. }
  24. public int getMaxZoom() {
  25. return mMaxZoom;
  26. }
  27. public void setMaxZoom(int maxZoom) {
  28. mMaxZoom = maxZoom;
  29. }
  30. /** 获取Gallery的中心x */
  31. private int getCenterOfCoverflow() {
  32. return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2 + getPaddingLeft();
  33. }
  34. /** 获取View的中心x */
  35. private static int getCenterOfView(View view) {
  36. return view.getLeft() + view.getWidth() / 2;
  37. }
  38. @Override
  39. protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  40. mCoveflowCenter = getCenterOfCoverflow();
  41. super.onSizeChanged(w, h, oldw, oldh);
  42. }
  43. @Override
  44. protected boolean getChildStaticTransformation(View child, Transformation trans) {
  45. final int childCenter = getCenterOfView(child);
  46. final int childWidth = child.getWidth();
  47. int rotationAngle = 0;
  48. trans.clear();
  49. trans.setTransformationType(Transformation.TYPE_BOTH);      // alpha 和 matrix 都变换
  50. if (childCenter == mCoveflowCenter) {   // 正中间的childView
  51. transformImageBitmap((ImageView) child, trans, 0);
  52. } else {        // 两侧的childView
  53. rotationAngle = (int) ( ( (float) (mCoveflowCenter - childCenter) / childWidth ) * mMaxRotationAngle );
  54. if (Math.abs(rotationAngle) > mMaxRotationAngle) {
  55. rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle : mMaxRotationAngle;
  56. }
  57. transformImageBitmap((ImageView) child, trans, rotationAngle);
  58. }
  59. return true;
  60. }
  61. private void transformImageBitmap(ImageView child, Transformation trans, int rotationAngle) {
  62. mCamera.save();
  63. final Matrix imageMatrix = trans.getMatrix();
  64. final int imageHeight = child.getLayoutParams().height;
  65. final int imageWidth = child.getLayoutParams().width;
  66. final int rotation = Math.abs(rotationAngle);
  67. // 在Z轴上正向移动camera的视角,实际效果为放大图片; 如果在Y轴上移动,则图片上下移动; X轴上对应图片左右移动。
  68. mCamera.translate(0.0f, 0.0f, 100.0f);
  69. // As the angle of the view gets less, zoom in
  70. if (rotation < mMaxRotationAngle) {
  71. float zoomAmount = (float) (mMaxZoom + (rotation * 1.5));
  72. mCamera.translate(0.0f, 0.0f, zoomAmount);
  73. }
  74. mCamera.rotateY(rotationAngle);     // rotationAngle 为正,沿y轴向内旋转; 为负,沿y轴向外旋转
  75. mCamera.getMatrix(imageMatrix);
  76. imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));
  77. imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));
  78. mCamera.restore();
  79. }
  80. }

3、Activity

Activity中,主要实现自定义Gallery的图片填充ImageAdapter、myGallery选择事件监听、点击事件监听

  1. private void initRes(){
  2. tvTitle = (TextView) findViewById(R.id.tvTitle);
  3. gallery = (myGallery) findViewById(R.id.mygallery);     // 获取自定义的myGallery控件
  4. adapter = new ImageAdapter(this);
  5. adapter.createReflectedImages();    // 创建倒影效果
  6. gallery.setAdapter(adapter);
  7. gallery.setOnItemSelectedListener(new OnItemSelectedListener() {    // 设置选择事件监听
  8. @Override
  9. public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
  10. tvTitle.setText(adapter.titles[position]);
  11. }
  12. @Override
  13. public void onNothingSelected(AdapterView<?> parent) {
  14. }
  15. });
  16. gallery.setOnItemClickListener(new OnItemClickListener() {          // 设置点击事件监听
  17. @Override
  18. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  19. Toast.makeText(Main.this, "img " + (position+1) + " selected", Toast.LENGTH_SHORT).show();
  20. }
  21. });
  22. }

main.xml布局文件中,通过实现自定义的myGallery,来显示图片集合

    1. <?xml version="1.0" encoding="utf-8"?>
    2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3. android:layout_width="fill_parent"
    4. android:layout_height="fill_parent"
    5. android:orientation="vertical" >
    6. <TextView
    7. android:id="@+id/tvTitle"
    8. android:layout_width="wrap_content"
    9. android:layout_height="wrap_content"
    10. android:layout_centerHorizontal="true"
    11. android:textSize="16sp" />
    12. <com.homer.reflect.myGallery
    13. android:id="@+id/mygallery"
    14. android:layout_width="fill_parent"
    15. android:layout_height="wrap_content"
    16. android:layout_below="@id/tvTitle"
    17. android:layout_marginTop="10dip" />
    18. </RelativeLayout>

Android 滑动效果进阶篇(六)—— 倒影效果的更多相关文章

  1. Android 滑动效果进阶篇(五)—— 3D旋转

    前面介绍了利用Android自带的控件,进行滑动翻页制作效果,现在我们通过代码实现一些滑动翻页的动画效果. Animation实现动画有两个方式:帧动画(frame-by-frame animatio ...

  2. Android 滑动效果入门篇(二)—— Gallery

    Gallery 是Android官方提供的一个View容器类,继承于AbsSpinner类,用于实现页面滑动效果. 从上面的继承关系可以看出,AbsSpinner类继承自AdapterView,因此我 ...

  3. Android 滑动效果入门篇(一)—— ViewFlipper

    ViewFilpper 是Android官方提供的一个View容器类,继承于ViewAnimator类,用于实现页面切换,也可以设定时间间隔,让它自动播放.又ViewAnimator继承至于Frame ...

  4. Android 滑动效果高级篇(八)—— 自定义控件

    自定义控件,较常用View.ViewGroup.Scroller三个类,其继承关系如下: 本示例自定义控件,实现一个Gallery效果,并添加了一个显示View个数和位置的bar条,效果图: 自定义控 ...

  5. Android 滑动效果基础篇(四)—— Gallery + GridView

    Android系统自带一个GridView和Gallery两个控件,GridView网格显示,Gallery单个浏览,两者结合起来可以真正实现Gallery浏览图片效果. 本示例通过GridView和 ...

  6. Android 滑动效果基础篇(三)—— Gallery仿图像集浏览

    Android系统自带一个Gallery浏览图片的应用,通过手指拖动时能够非常流畅的显示图片,用户交互和体验都很好. 本示例就是通过Gallery和自定义的View,模仿实现一个仿Gallery图像集 ...

  7. Android 滑动效果高级篇(七)—— 华丽翻页效果

    By 何明桂(http://blog.csdn.net/hmg25) 转载请注明出处 之前看到像ipad上的ibook的模拟书籍翻页的特效感觉很炫,在android上也有像laputa和ireader ...

  8. 十六、Android 滑动效果汇总

    Android 滑动效果入门篇(一)—— ViewFlipper Android 滑动效果入门篇(二)—— Gallery Android 滑动效果基础篇(三)—— Gallery仿图像集浏览 And ...

  9. Android 滑动效果汇总

    Android 滑动效果入门篇(一)—— ViewFlipper Android 滑动效果入门篇(二)—— Gallery Android 滑动效果基础篇(三)—— Gallery仿图像集浏览 And ...

随机推荐

  1. 一个很全的VTK实例网址

    https://cmake.org/Wiki/VTK/Examples/Cxx#Visualization

  2. openlayers 3 简书

    1. 简书http://www.jianshu.com/p/6785e755fa0d 2. 文档 http://anzhihun.coding.me/ol3-primer/ch03/03-02.htm ...

  3. Linux中postfix邮件服务器的搭建

    postfix是Wietse Venema在IBM的GPL协议之下开发的MTA(邮件传输代理)软件.postfix是Wietse Venema想要为使用最广泛的sendmail提供替代品的一个尝试.在 ...

  4. 内存缓存机制and垃圾回收机制

    一.内存缓存机制 var_dump(memory_get_usage(true)); $a="laruence"; var_dump(memory_get_usage(true)) ...

  5. MAC OS设置JDK小结

    开始折腾mac pro,在网上找了些资料,自己也尝试了一下,特在这里做个小结. mac中JDK的位置 OSX默认的JDK /System/Library/Frameworks/JavaVM.frame ...

  6. eBay 使用ReviseInventoryStatusCall调整库存和价格

        1.简介   针对Fixed-Price的Item,其Inventory Revise和Price Revise可以使用接口ReviseInventoryStatusCall来完成. 其使用非 ...

  7. EF的join用法

    var customers = DB.Customer.Join(DB.Commission, cst => cst.CommissionId,                          ...

  8. OpenCL中的half与float的转换

    在kernel中使用half类型可以在牺牲一定精度的代价下来提升运算速度. 在kernel中, 可以比较方便的对half数据进行计算, 但在host上的, 对half的使用就没那么方便了. 查看cl_ ...

  9. js读取解析JSON类型数据【申明:来源于网络】

    js读取解析JSON类型数据[申明:来源于网络] 地址:http://blog.csdn.net/sunhuaqiang1/article/details/47026841

  10. https单向认证服务端发送到客户端到底会不会加密?

    最近向大神请教了CA认证单向认证和双向认证的问题,有一点不太明白,单向认证的时候,为什么服务端发送到客户端的东西也是加密的?