上篇介绍了使用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. [转] C# 中的static静态变量

    logitechyan原文关于C#中static静态变量 C#静态变量使用static 修饰符进行声明,在类被实例化时创建,通过类进行访问不带有 static 修饰符声明的变量称做非静态变量,在对象被 ...

  2. redis配置实例及redis.conf详细说明

    一.配置实例 1.redis修改持久化路径.日志路径.清缓存 redis修改持久化路径和日志路径 vim  redis.conf logfile /data/redis_cache/logs/redi ...

  3. storm入门教程 第一章 前言[转]

    1.1   实时流计算 互联网从诞生的第一时间起,对世界的最大的改变就是让信息能够实时交互,从而大大加速了各个环节的效率.正因为大家对信息实时响应.实时交互的需求,软件行业除了个人操作系统之外,数据库 ...

  4. UI控件之 ScrollView垂直滚动控件 和 HorizontalScrollView水平滚动控件的使用

    1. ScrollView 垂直滚动控件的使用 ScrollView控件只是支持垂直滚动,而且在ScrollView中只能包含一个控件,通常是在< ScrollView >标签中定义了一个 ...

  5. 网站sqlserver提权操作

    在入侵过程中,得到SQLserver的权限,想进一步得到system权限的方法总结 *************************** 利用xp_cmdshell **************** ...

  6. webdriver(python)学习笔记七——多层框架定位与智能等待

    多层框架或窗口定位: switch_to_frame() switch_to_window() 智能等待: implicitly_wait() 现在web应用中经常会遇到框架如(frame)或窗口(w ...

  7. poj 3311 Hie with the Pie

    floyd,旅游问题每个点都要到,可重复,最后回来,dp http://poj.org/problem?id=3311 Hie with the Pie Time Limit: 2000MS   Me ...

  8. 查看系统或者Jmeter的Properties

    工作台-非测试元件-Property Display,可以显示系统或者Jmeter的Properties

  9. C++ 为什么要用覆盖(学习笔记)

    长篇大论这里就不说了,举个例子class fruit{public: void func() { printf("fruit\n"); } virtual void vfunc() ...

  10. aggregation(2):adaptive Boosting (AdaBoost)

    给你这些水果图片,告诉你哪些是苹果.那么现在,让你总结一下哪些是苹果? 1)苹果都是圆的.我们发现,有些苹果不是圆的.有些水果是圆的但不是苹果, 2)其中到这些违反"苹果都是圆的" ...