Android开发教程:镜像倒影特效Gallery


本文档将介绍在Android上如何实现一个倒影效果的Gallery。

为了达到上图所示的效果,

首先,是需要有一个自定义的gallery,实现了对Gallery的继承,通过重写getChildStaticTransformation方法来控制,每个子view有不同的缩放比例,形成阶梯状的展示。这个gallery是在坤庭的代码基础上实现的,我这里就不再重复介绍。

接下来,gallery中的每个view,都是一个自定义的MirrorView,由它来实现了画原图及画倒影。新的算法解决了性能问题,下面就重点说一下这部分内容:

镜像特效最近还蛮流行的,尤其在HTC 的Sense 介面上,常常都可以见到。大家可以看到,加了个镜像特效后,那感觉就很立体,感觉上好像是这些图片摆立在一个玻璃桌面上。

在Android 上要帮图片加上镜像特效,会不会很麻烦?一点也不麻烦,只要几行代码,就可以搞定。

效果展示如下:

Android开发教程:镜像倒影特效Gallery

因此,在开始看答案之前,我会建议你要先有Photoshop 的使用经验。想想,如果用Photoshop 要帮图片加上镜像特效,要如何做?我想一般不外乎是先复制个图片,并将其垂直翻转,接着再对这翻转的图片,加个由灰到黑的渐层mask 即可。

好了,让我们来看一下答案。底下就是帮图片加上镜像特效的程式范例。

  1. public  class  MirrorView extends  View {   
  2.   
  3. Paint m_paint;   
  4.   
  5. int m_nShadowH;   
  6.   
  7. Drawable m_dw;   
  8.   
  9. Bitmap m_bitmap;   
  10.   
  11. Matrix mMatrix;   
  12.   
  13. int shadowHeight;   
  14.   
  15. public MirrorView(Context context, Bitmap bitmap) {   
  16.   
  17. super (context);   
  18.   
  19. m_bitmap = bitmap;   
  20.   
  21. _Init();   
  22.   
  23. }   
  24.   
  25. private void _Init() {   
  26.   
  27. //m_dw = new BitmapDrawable(BitmapFactory.decodeResource(getResources(),  R.drawable.icon));   
  28.   
  29. m_dw = new BitmapDrawable(m_bitmap);   
  30.   
  31. m_dw.setBounds(0,0,m_dw.getIntrinsicWidth(),m_dw.getIntrinsicHeight());   
  32.   
  33. m_nShadowH = m_dw.getIntrinsicHeight()/1;   
  34.   
  35. m_paint = new Paint(Paint.ANTI_ALIAS_FLAG );   
  36.   
  37. LinearGradient lg = new LinearGradient(000, m_nShadowH, 0xB0FFFFFF0×00000000, Shader.TileMode.CLAMP );   
  38.   
  39. m_paint.setShader(lg);   
  40.   
  41. m_paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY ));   
  42.   
  43. mMatrix = new Matrix();   
  44.   
  45. }   
  46.   
  47. @Override  
  48.   
  49. public void onDraw(Canvas canvas) {   
  50.   
  51. super .onDraw(canvas);   
  52.   
  53. int nX = 0;   
  54.   
  55. int nY = 0;   
  56.   
  57. _DrawNormalImg(canvas, nX, nY);   
  58.   
  59. _DrawMirror(canvas, nX, nY);   
  60.   
  61. }   
  62.   
  63. private void _DrawNormalImg(Canvas canvas, int nX, int nY) {   
  64.   
  65. canvas.save(Canvas.MATRIX_SAVE_FLAG );   
  66.   
  67. canvas.translate(nX, nY);   
  68.   
  69. m_dw.draw(canvas);   
  70.   
  71. canvas.restore();   
  72.   
  73. }   
  74.   
  75. private void _DrawMirror(Canvas canvas, int nX, int nY) {   
  76.   
  77. int nW = m_dw.getIntrinsicWidth();   
  78.   
  79. int nH = m_dw.getIntrinsicHeight();   
  80.   
  81. shadowHeight=nH/2;   
  82.   
  83. float [] src={0, nH, nW, nH, nW,nH – m_nShadowH, 0, nH – m_nShadowH};   
  84.   
  85. float [] dst={ 0, nH, nW, nH,nW, shadowHeight, 0, shadowHeight };   
  86.   
  87. canvas.save();   
  88.   
  89. mMatrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1);   
  90.   
  91. canvas.concat(mMatrix);   
  92.   
  93. //draw mirror image   
  94.   
  95. canvas.save(Canvas.MATRIX_SAVE_FLAG );   
  96.   
  97. canvas.scale(1.0f, -1.0f);   
  98.   
  99. canvas.translate(nX, -(nY + nH * 2));   
  100.   
  101. canvas.clipRect(0, nH, nW, nH – m_nShadowH);   
  102.   
  103. m_dw.draw(canvas);   
  104.   
  105. canvas.restore();   
  106.   
  107. //draw mask   
  108.   
  109. canvas.save();   
  110.   
  111. canvas.translate(nX, nY + nH);   
  112.   
  113. canvas.drawRect(00, nW, m_nShadowH, m_paint);   
  114.   
  115. canvas.restore();   
  116.   
  117. canvas.restore();   
  118.   
  119. }   
  120.   
  121. }  

_DrawMirror() 方法是关键。用Photoshop 要如何做出镜像特效?第一步是先画出垂直翻转的图片。

Android 绘图座标体系预设的原点在左上角,X 轴往右是越来越大的正值,而Y 轴往下,则是越来越大的正值。要画出垂直翻转的图片,其实也就是要垂直翻转整个绘图座标体系。在 Android 中,要如何做?答案就是 canvas.scale(1.0f, -1.0f)。很简单吧,没想到给scale() 函式一个负值,就可以翻转相对应的轴。

在Photoshop 中,做镜像特效的第二步是要对这翻转的图片,加个由灰到黑的渐层mask。

在Android 中,要画渐层色,那就一定得用LinearGradient 这个类别。至于要对背景图加上个mask,就请参考一下Paint 的setXfermode() 函式。 _Init() 这个函式,就是负责生成一个由灰到黑渐层mask 的m_paint 物件。

这个控件我测试过,200张图片加入adapter,在大数据量情况下性能也没有问题。

相关内容