Coverflow is implemented using the android built-in gallery component, source code + Parsing

Source: Internet
Author: User

First, declare that the source code is reprinted from Neil Davies outside China and the Open Source protocol apache2.0 is used. Please use the source code to consciously abide by the Protocol content.
This article is original in kearnel. For more information, see the source.

The following is the text:

Anyone who has used Android's own gallery component knows that the effect of gallery is to drag and browse a group of images, which is obviously inferior to coverflow used to drag and browse images on the iPhone. In fact, you can extend gallery and basically implement coverflow through pseudo 3D transformation. This article uses source code parsing to implement this function. For specific code functions, see annotations.

The final implementation result is as follows:

To use gallery, we must first specify an adapter for it. Here, we implement a custom imageadapter to create a reflection effect for the image.
The input parameter is the image ID array in context and drawable in the program. Then, call the createreflectedimages () method to create the reflection effect of each image, generate the corresponding imageview array, and finally return it in getview.

  1. /*
  2. * Copyright (c) 2010 Neil Davies
  3. *
  4. * Licensed under the Apache license, version 2.0 (the "License ");
  5. * You may not use this file before t in compliance with the license.
  6. * You may obtain a copy of the license
  7. *
  8. * Http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * Distributed under the license is distributed on an "as is" basis,
  12. * Without warranties or conditions of any kind, either express or implied.
  13. * See the license for the specific language governing permissions and
  14. * Limitations under the license.
  15. *
  16. * This code is base on the android gallery widget and was created
  17. * By Neil Davies neild001 'at' gmail dot com To Be A coverflow widget
  18. *
  19. * @ Author Neil Davies
  20. */
  21. Public class imageadapter extends baseadapter {
  22. Int mgalleryitembackground;
  23. Private context mcontext;
  24. Private integer [] mimageids;
  25. Private imageview [] mimages;
  26. Public imageadapter (context c, int [] imageids ){
  27. Mcontext = C;
  28. Mimageids = imageids;
  29. Mimages = new imageview [mimageids. Length];
  30. }
  31. Public Boolean createreflectedimages (){
  32. // The gap we want between the reflection and the original image
  33. Final int reflectiongap = 4;
  34. Int Index = 0;
  35. For (INT imageid: mimageids ){
  36. Bitmap originalimage = bitmapfactory. decoderesource (
  37. Mcontext. getresources (), imageid );
  38. Int width = originalimage. getwidth ();
  39. Int Height = originalimage. getheight ();
  40. // This will not scale but will flip on the Y axis
  41. Matrix matrix = new matrix ();
  42. Matrix. prescale (1,-1 );
  43. // Create a bitmap with the flip matrix applied to it.
  44. // We only want the bottom half of the image
  45. Bitmap reflectionimage = bitmap. createbitmap (originalimage, 0,
  46. Height/2, width, height/2, matrix, false );
  47. // Create a new bitmap with same width but taller to fit
  48. // Reflection
  49. Bitmap bitmapwithreflection = bitmap. createbitmap (width,
  50. (Height + height/2), config. argb_8888 );
  51. // Create a new canvas with the bitmap that's big enough
  52. // The image plus gap plus reflection
  53. Canvas canvas = new canvas (bitmapwithreflection );
  54. // Draw in the original image
  55. Canvas. drawbitmap (originalimage, 0, 0, null );
  56. // Draw in the gap
  57. Paint deafaultpaint = new paint ();
  58. Canvas. drawrect (0, height, width, height + reflectiongap,
  59. Deafaultpaint );
  60. // Draw in the reflection
  61. Canvas. drawbitmap (reflectionimage, 0, height + reflectiongap,
  62. Null );
  63. // Create a shader that is a linear gradient that covers
  64. // Reflection
  65. Paint paint = new paint ();
  66. Lineargradient shader = new lineargradient (0,
  67. Originalimage. getheight (), 0,
  68. Bitmapwithreflection. getheight () + reflectiongap,
  69. 0x70ffffff, 0x00ffffff, tilemode. Clamp );
  70. // Set the paint to use this shader (linear gradient)
  71. Paint. setshader (shader );
  72. // Set the transfer mode to be Porter Duff and destination in
  73. Paint. setxfermode (New porterduxfermode (mode. dst_in ));
  74. // Draw a rectangle using the paint with our linear gradient
  75. Canvas. drawrect (0, height, width,
  76. Bitmapwithreflection. getheight () + reflectiongap, paint );
  77. Imageview = new imageview (mcontext );
  78. Imageview. setimagebitmap (bitmapwithreflection );
  79. Imageview
  80. . Setlayoutparams (New galleryflow. layoutparams (160,240 ));
  81. // Imageview. setscaletype (scaletype. Matrix );
  82. Mimages [index ++] = imageview;
  83. }
  84. Return true;
  85. }
  86. Public int getcount (){
  87. Return mimageids. length;
  88. }
  89. Public object getitem (INT position ){
  90. Return position;
  91. }
  92. Public long getitemid (INT position ){
  93. Return position;
  94. }
  95. Public View getview (INT position, view convertview, viewgroup parent ){
  96. // Use this code if you want to load from resources
  97. /*
  98. * Imageview I = new imageview (mcontext );
  99. * I. setimageresource (mimageids [position]); I. setlayoutparams (New
  100. * Coverflow. layoutparams (350,350 ));
  101. * I. setscaletype (imageview. scaletype. center_inside );
  102. *
  103. * // Make sure we set anti-aliasing otherwise we get jargies
  104. * Bitmapdrawable drawable = (bitmapdrawable) I. getdrawable ();
  105. * Drawable. setantialias (true); return I;
  106. */
  107. Return mimages [position];
  108. }
  109. /**
  110. * Returns the size (0.0f to 1.0f) of the views depending on
  111. * 'Offset' to the center.
  112. */
  113. Public float getscale (Boolean focused, int offset ){
  114. /* Formula: 1/(2 ^ offset )*/
  115. Return math. Max (0, 1.0f/(float) math. Pow (2, math. Abs (offset )));
  116. }
  117. }
  118. }

Copy code

It is not enough to achieve only the image reflection effect, because in coverflow, image switching has the rotation and scaling effects, but not in the built-in Gallery. Therefore, we can extend our own gallery to implement our own galleryflow. In the original gallery class, a method getchildstatictransformation () is provided to transform the image. By overwriting this method and calling the custom transformimagebitmap ("the distance between each image and the gallery center") method, we can rotate and scale each image accordingly. Camera and matrix are used for view transformation. For more information, see code comments.

  1. Public class galleryflow extends gallery {
  2. /**
  3. * Graphics camera used for transforming the matrix of imageviews
  4. */
  5. Private camera mcamera = new camera ();
  6. /**
  7. * The maximum angle the child imageview will be rotated
  8. */
  9. Private int mmaxrotationangle = 60;
  10. /**
  11. * The maximum zoom on the center child
  12. */
  13. Private int mmaxzoom =-120;
  14. /**
  15. * The centre of the coverflow
  16. */
  17. Private int mcoveflowcenter;
  18. Public galleryflow (context ){
  19. Super (context );
  20. This. setstatictransformationsenabled (true );
  21. }
  22. Public galleryflow (context, attributeset attrs ){
  23. Super (context, attrs );
  24. This. setstatictransformationsenabled (true );
  25. }
  26. Public galleryflow (context, attributeset attrs, int defstyle ){
  27. Super (context, attrs, defstyle );
  28. This. setstatictransformationsenabled (true );
  29. }
  30. /**
  31. * Get the max rotational angle of the image
  32. *
  33. * @ Return the mmaxrotationangle
  34. */
  35. Public int getmaxrotationangle (){
  36. Return mmaxrotationangle;
  37. }
  38. /**
  39. * Set the max rotational angle of each image
  40. *
  41. * @ Param maxrotationangle
  42. * The mmaxrotationangle to set
  43. */
  44. Public void setmaxrotationangle (INT maxrotationangle ){
  45. Mmaxrotationangle = maxrotationangle;
  46. }
  47. /**
  48. * Get the max zoom of the center Image
  49. *
  50. * @ Return the mmaxzoom
  51. */
  52. Public int getmaxzoom (){
  53. Return mmaxzoom;
  54. }
  55. /**
  56. * Set the max zoom of the center Image
  57. *
  58. * @ Param maxzoom
  59. * The mmaxzoom to set
  60. */
  61. Public void setmaxzoom (INT maxzoom ){
  62. Mmaxzoom = maxzoom;
  63. }
  64. /**
  65. * Get the centre of the coverflow
  66. *
  67. * @ Return the center of this coverflow.
  68. */
  69. Private int getcenterofcoverflow (){
  70. Return (getwidth ()-getpaddingleft ()-getpaddingright ()/2
  71. + Getpaddingleft ();
  72. }
  73. /**
  74. * Get the centre OF THE VIEW
  75. *
  76. * @ Return the center of the given view.
  77. */
  78. Private Static int getcenterofview (view ){
  79. Return view. getleft () + view. getwidth ()/2;
  80. }
  81. /**
  82. * {@ Inheritdoc}
  83. *
  84. * @ See # setstatictransformationsenabled (Boolean)
  85. */
  86. Protected Boolean getchildstatictransformation (view child, transformation T ){
  87. Final int childcenter = getcenterofview (child );
  88. Final int childwidth = Child. getwidth ();
  89. Int rotationangle = 0;
  90. T. Clear ();
  91. T. settransformationtype (transformation. type_matrix );
  92. If (childcenter = mcoveflowcenter ){
  93. Transformimagebitmap (imageview) Child, T, 0 );
  94. } Else {
  95. Rotationangle = (INT) (float) (mcoveflowcenter-childcenter)/childwidth) * mmaxrotationangle );
  96. If (math. Abs (rotationangle)> mmaxrotationangle ){
  97. Rotationangle = (rotationangle <0 )? -Mmaxrotationangle
  98. : Mmaxrotationangle;
  99. }
  100. Transformimagebitmap (imageview) Child, T, rotationangle );
  101. }
  102. Return true;
  103. }
  104. /**
  105. * This is called during layout when the size of this view has changed. If
  106. * You were just added to the view hierarchy, you're called with the old
  107. * Values of 0.
  108. *
  109. * @ Param W
  110. * Current width of this view.
  111. * @ Param H
  112. * Current height of this view.
  113. * @ Param oldw
  114. * Old width of this view.
  115. * @ Param oldh
  116. * Old height of this view.
  117. */
  118. Protected void onsizechanged (int w, int H, int oldw, int oldh ){
  119. Mcoveflowcenter = getcenterofcoverflow ();
  120. Super. onsizechanged (W, H, oldw, oldh );
  121. }
  122. /**
  123. * Transform the image bitmap by the angle passed
  124. *
  125. * @ Param imageview
  126. * Imageview the imageview whose bitmap we want to rotate
  127. * @ Param t
  128. * Transformation
  129. * @ Param rotationangle
  130. * The angle by which to rotate the bitmap
  131. */
  132. Private void transformimagebitmap (imageview child, transformation T,
  133. Int rotationangle ){
  134. Mcamera. Save ();
  135. Final matrix imagematrix = T. getmatrix ();
  136. Final int imageheight = Child. getlayoutparams (). height;
  137. Final int imagewidth = Child. getlayoutparams (). width;
  138. Final int rotation = math. Abs (rotationangle );
  139. // Forward the camera angle on the Z axis. The actual effect is to enlarge the image.
  140. // If the image is moved on the Y axis, the image is moved up and down; on the X axis, the image is moved left and right.
  141. Mcamera. Translate (0.0f, 0.0f, 100366f );
  142. // As the angle of the view gets less, zoom in
  143. If (rotation <mmaxrotationangle ){
  144. Float zoomamount = (float) (mmaxzoom + (rotation * 1.5 ));
  145. Mcamera. Translate (0.0f, 0.0f, zoomamount );
  146. }
  147. // Rotate on the Y axis, and flip the corresponding image vertically to the inside.
  148. // If the image is rotated on the X axis, the image is reversed horizontally.
  149. Mcamera. rotatey (rotationangle );
  150. Mcamera. getmatrix (imagematrix );
  151. Imagematrix. pretranslate (-(imagewidth/2),-(imageheight/2 ));
  152. Imagematrix. posttranslate (imagewidth/2), (imageheight/2 ));
  153. Mcamera. Restore ();
  154. }
  155. }

Copy code

The Code ends here. If you are interested, you can adjust the parameters to achieve more and more dazzling results.
The following is an example of a call:

  1. Public void oncreate (bundle savedinstancestate ){
  2. Super. oncreate (savedinstancestate );
  3. Setcontentview (R. layout. layout_gallery );
  4. Integer [] images = {R. drawable. img0001, R. drawable. img0030,
  5. R. drawable. im0000100, R. drawable. img0130, R. drawable. im0000200,
  6. R. drawable. img0230, R. drawable. im0000300, R. drawable. img0330,
  7. R. drawable. im1_354 };
  8. Imageadapter adapter = new imageadapter (this, images );
  9. Adapter. createreflectedimages ();
  10. Galleryflow = (galleryflow) findviewbyid (R. Id. gallery_flow );
  11. Galleryflow. setadapter (adapter );
  12. }

Copy code

PS1:
It can be seen that this implementation of the gallery sawtooth problem is more serious. You can use the following code in createreflectedimages:

  1. Bitmapdrawable BD = new bitmapdrawable (bitmapwithreflection );
  2. BD. setantialias = true;
  3. ...

Copy code

Then use IV. setimagedrawable (BD );
Replace IV. setimagebitmap (bitmapwithreflection );
You can basically eliminate the Sawtooth.

PS2:
The memoryleak problem to be determined by the imageadapter. The decode method of Bitmap may cause ml. OOM may appear after multiple screen rotation when imageadapter is used. Currently, you can call the recycle () method and set null and call system. GC () in time by calling the completed bimap, but the problem is not obvious.

 

 

 

Well, the original code does have a small problem. I made some minor changes and now it's okay.
In addition, you should not reference Gallery in the layout XML file, but use the custom com. Gallery. galleryflow. Otherwise, the error CCE may occur.
See the appendix for the project.Gallery.rar(737.16 KB)
This is:

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.