上篇介绍了使用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. MyBatis的association示例——MyBatis学习笔记之三

    前两篇博文介绍的都是单表映射,而实际上很多时候我们需要用到较复杂的映射.今天学会的association的用法,就是一例,现写出来和大家分享(为简洁起见,ant工程中各文件.目录的布局,以及其它与前面 ...

  2. HTMLayout使用心得

    1.关闭按钮 采用CSS!提供的behavior实现窗口关闭功能,不需要在C++代码中处理关闭事件 div {      behavior: sys-ctl;      -sys-ctl-pos: c ...

  3. SQL你必须知道的-查询聚合分组排序

    use MySchoolTwo    -- 简单查询    select * from Student    -- 话说这种查询的效率要比 * 要高级点    select sId , sName , ...

  4. A Blind Watermarking for 3-D Dynamic Mesh Model Using Distribution of Temporal Wavelet Coefficients

    这周看了一篇动态网格序列水印的论文,由于目前在网格序列上做水印的工作特别少,加之我所看的这篇论文中的叙述相对简洁,理解起来颇为困难.好在请教了博士师兄,思路明朗了许多,也就把这思路整理在此了. 论文作 ...

  5. python 入门实践之网页数据抓取

    这个不错.正好入门学习使用. 1.其中用到 feedparser: 技巧:使用 Universal Feed Parser 驾驭 RSS http://www.ibm.com/developerwor ...

  6. 瞬间从IT屌丝变大神——HTML规范

    HTML规范包含以下内容: DTD统一用<!DOCTYPE HTML PUBLIC "_//W3C//DTD XHTML 1.0 Transitional//EN"" ...

  7. 在阿里云linux下使用SVN访问VisualSVN出错:SSL handshake failed: SSL error: Key usage violation in certificate has been detected

    Subversion clients receive the following error message when attempting to connect to VisualSVN Serve ...

  8. 恒天云单节点部署指南--OpenStack H版本虚拟机单节点部署解决方案

    本帖是openstack单节点在虚拟机上部署的实践.想要玩玩和学习openstack的小伙伴都看过来,尤其是那些部署openstack失败的小伙伴.本帖可以让你先领略一下openstack的魅力.本I ...

  9. web.py处理文件上传

    #coding=utf8 import web urls = ('/','Home', '/upload', 'Upload') app = web.application(urls, globals ...

  10. [转]sublime 使用技巧总结

    原文链接:http://www.cnblogs.com/yingzi/archive/2012/04/24/2469056.html 对于用惯了editplus的人来说,突然接触到sublime有点无 ...