上篇介绍了使用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. 22、TTS技术

    Android对TTS技术的支持 Android 1.6开始支持TTS(Text To Speech)技术,通过该技术可以将文本转换成语音. TTS技术的核心是android.speech.tts.T ...

  2. Delphi 使用串口模拟工具进行串口程序开发调试

      版权声明:本文为博主原创文章,如需转载请注明出处及作者. 本文由小李专栏原创,转载需注明出处:[http://blog.csdn.net/softwave/article/details/8907 ...

  3. ASP.NET单点登录(代码)

    [p=25, null, left]由于某些原因,在我们的应用中会遇到一个用户只能在一个地方登录的情况,也就是我们通常所说的单点登录.在ASP.NET中实现单点登录其实很简单,下面就把主要的方法和全部 ...

  4. 通过gdb跟踪进程调度分析进程切换的过程

    作者:吴乐 山东师范大学 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 本实验目的:通过gdb在lin ...

  5. netty的入门

    netty是什么? netty是一个基于NIO的通信框架,对于传统计算机,系统的瓶颈一直在输入输出设备上,计算速度超过IO速度,所以对于i o的性能提高异常重要. 什么是NIO? 非阻塞IO,N表示n ...

  6. HDU5807 Keep In Touch DP

    // HDU5807 Keep In Touch DP // 思路:直接暴力是O(n^6).所以要优化一下 // dp[i][j][k][0]:当前点i j k的方案数 // dp[i][j][k][ ...

  7. 瞬间从IT屌丝变大神——命名规则

    为了避免命名冲突,命名规则如下: 公共组件因为高度重用,,命名从简,不要加前缀. 各栏目的相应代码,需加前缀,前缀为工程师姓名拼音的首字母,例如:海子前缀为“hz_”,分隔符为下划线"_&q ...

  8. SQL Server 执行计划

    当一个查询被提交时,发生了什么? 向SQL Server提交一个查询时,sever上的许多进程会在这个查询上开始工作. 这些进程的目标就是管理这个系统,使得这个查询可以选择,插入,更新,删除数据. 每 ...

  9. 文本分类之特征描述vsm和bow

    当我们尝试使用统计机器学习方法解决文本的有关问题时,第一个需要的解决的问题是,如果在计算机中表示出一个文本样本.一种经典而且被广泛运用的文本表示方法,即向量空间模型(VSM),俗称“词袋模型”. 我们 ...

  10. linux - 怎么自动填写有交互的shell脚本 - SegmentFault

    linux - 怎么自动填写有交互的shell脚本 - SegmentFault TCL/Expect交互式自动化测试概要 - - ITeye技术网站 expect是一种基于TCL,能与交互式程序进行 ...