上篇介绍了使用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. 1、ListView自定义控件下拉刷新(一)

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layo ...

  2. 用VBS脚本发邮件

    需求是这样的:针对账号的管理,如果发现该账号的管理员给账号加了批注,(比如要过期,修改密码,完善资料等),就需要找到这样的账号及其管理的邮件,然后发邮件给他们的管理员同时抄送给账号以达到提醒的目的.那 ...

  3. Webdriver API (三)- actions

    Actions类主要定义了一些模拟用户的鼠标mouse,键盘keyboard操作.对于这些操作,使用perform()方法进行执行. actions类可以完成单一的操作,也可以完成几个操作的组合. 有 ...

  4. 一个可序列化的C#对象,如何转成一个XML格式的文件或字符串【转】

    原文:http://blog.csdn.net/otong/article/details/7894059 序列化或反序列化成一个字符串: 方法一: 序列化: public static string ...

  5. css3 javascript 实现菜单按钮特效

    一个菜单按钮特效案例,简单的实现了动态效果. 代码效果预览地址: http://code.w3ctech.com/detail/2504 <div class="bar" i ...

  6. 根据关键词获取进程ID然后杀掉进程

    例如需要杀掉监听进程,如下: [oracle@kel ~]$ ps -ef|grep lsnr oracle 4973 1 1 19:40 ? 00:00:00 /home/oracle/produc ...

  7. Polymer——Template

    Polymer Template 一.Ta的简介 template是polymer element中一个重要的组成部分,主要有两种使用目的,一是构建Shadow Dom,二是用于数据绑定和视图渲染. ...

  8. 关于如果修改 ie 浏览器 文本模式

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/html4/stric ...

  9. Unity3d自定义脚本模板

    这是一个小技巧,打开Unity安装目录,如: C:\Program Files (x86)\Unity\Editor\Data\Resources\ScriptTemplates /* * * Tit ...

  10. 记录一次Android交叉编译ffmpeg排查错误

    Android版本手机直播引擎中,引用了libvlc开源库.项目接过来,发现编译脚本中使用了很多用户名下的绝对路径.项目相关人离职,导致这个脚本实际上已经废掉.而且不知道相关路径下有没有其他文件和第三 ...