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.
- /*
- * Copyright (c) 2010 Neil Davies
- *
- * Licensed under the Apache license, version 2.0 (the "License ");
- * You may not use this file before t in compliance with the license.
- * You may obtain a copy of the license
- *
- * Http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * Distributed under the license is distributed on an "as is" basis,
- * Without warranties or conditions of any kind, either express or implied.
- * See the license for the specific language governing permissions and
- * Limitations under the license.
- *
- * This code is base on the android gallery widget and was created
- * By Neil Davies neild001 'at' gmail dot com To Be A coverflow widget
- *
- * @ Author Neil Davies
- */
- Public class imageadapter extends baseadapter {
- Int mgalleryitembackground;
- Private context mcontext;
- Private integer [] mimageids;
- Private imageview [] mimages;
- Public imageadapter (context c, int [] imageids ){
- Mcontext = C;
- Mimageids = imageids;
- Mimages = new imageview [mimageids. Length];
- }
- Public Boolean createreflectedimages (){
- // The gap we want between the reflection and the original image
- Final int reflectiongap = 4;
- Int Index = 0;
- For (INT imageid: mimageids ){
- Bitmap originalimage = bitmapfactory. decoderesource (
- Mcontext. getresources (), imageid );
- Int width = originalimage. getwidth ();
- Int Height = originalimage. getheight ();
- // This will not scale but will flip on the Y axis
- Matrix matrix = new matrix ();
- Matrix. prescale (1,-1 );
- // Create a bitmap with the flip matrix applied to it.
- // We only want the bottom half of the image
- Bitmap reflectionimage = bitmap. createbitmap (originalimage, 0,
- Height/2, width, height/2, matrix, false );
- // Create a new bitmap with same width but taller to fit
- // Reflection
- Bitmap bitmapwithreflection = bitmap. createbitmap (width,
- (Height + height/2), config. argb_8888 );
- // Create a new canvas with the bitmap that's big enough
- // The image plus gap plus reflection
- Canvas canvas = new canvas (bitmapwithreflection );
- // Draw in the original image
- Canvas. drawbitmap (originalimage, 0, 0, null );
- // Draw in the gap
- Paint deafaultpaint = new paint ();
- Canvas. drawrect (0, height, width, height + reflectiongap,
- Deafaultpaint );
- // Draw in the reflection
- Canvas. drawbitmap (reflectionimage, 0, height + reflectiongap,
- Null );
- // Create a shader that is a linear gradient that covers
- // Reflection
- Paint paint = new paint ();
- Lineargradient shader = new lineargradient (0,
- Originalimage. getheight (), 0,
- Bitmapwithreflection. getheight () + reflectiongap,
- 0x70ffffff, 0x00ffffff, tilemode. Clamp );
- // Set the paint to use this shader (linear gradient)
- Paint. setshader (shader );
- // Set the transfer mode to be Porter Duff and destination in
- Paint. setxfermode (New porterduxfermode (mode. dst_in ));
- // Draw a rectangle using the paint with our linear gradient
- Canvas. drawrect (0, height, width,
- Bitmapwithreflection. getheight () + reflectiongap, paint );
- Imageview = new imageview (mcontext );
- Imageview. setimagebitmap (bitmapwithreflection );
- Imageview
- . Setlayoutparams (New galleryflow. layoutparams (160,240 ));
- // Imageview. setscaletype (scaletype. Matrix );
- Mimages [index ++] = imageview;
- }
- Return true;
- }
- Public int getcount (){
- Return mimageids. length;
- }
- Public object getitem (INT position ){
- Return position;
- }
- Public long getitemid (INT position ){
- Return position;
- }
- Public View getview (INT position, view convertview, viewgroup parent ){
- // Use this code if you want to load from resources
- /*
- * Imageview I = new imageview (mcontext );
- * I. setimageresource (mimageids [position]); I. setlayoutparams (New
- * Coverflow. layoutparams (350,350 ));
- * I. setscaletype (imageview. scaletype. center_inside );
- *
- * // Make sure we set anti-aliasing otherwise we get jargies
- * Bitmapdrawable drawable = (bitmapdrawable) I. getdrawable ();
- * Drawable. setantialias (true); return I;
- */
- Return mimages [position];
- }
- /**
- * Returns the size (0.0f to 1.0f) of the views depending on
- * 'Offset' to the center.
- */
- Public float getscale (Boolean focused, int offset ){
- /* Formula: 1/(2 ^ offset )*/
- Return math. Max (0, 1.0f/(float) math. Pow (2, math. Abs (offset )));
- }
- }
- }
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.
- Public class galleryflow extends gallery {
- /**
- * Graphics camera used for transforming the matrix of imageviews
- */
- Private camera mcamera = new camera ();
- /**
- * The maximum angle the child imageview will be rotated
- */
- Private int mmaxrotationangle = 60;
- /**
- * The maximum zoom on the center child
- */
- Private int mmaxzoom =-120;
- /**
- * The centre of the coverflow
- */
- Private int mcoveflowcenter;
- Public galleryflow (context ){
- Super (context );
- This. setstatictransformationsenabled (true );
- }
- Public galleryflow (context, attributeset attrs ){
- Super (context, attrs );
- This. setstatictransformationsenabled (true );
- }
- Public galleryflow (context, attributeset attrs, int defstyle ){
- Super (context, attrs, defstyle );
- This. setstatictransformationsenabled (true );
- }
- /**
- * Get the max rotational angle of the image
- *
- * @ Return the mmaxrotationangle
- */
- Public int getmaxrotationangle (){
- Return mmaxrotationangle;
- }
- /**
- * Set the max rotational angle of each image
- *
- * @ Param maxrotationangle
- * The mmaxrotationangle to set
- */
- Public void setmaxrotationangle (INT maxrotationangle ){
- Mmaxrotationangle = maxrotationangle;
- }
- /**
- * Get the max zoom of the center Image
- *
- * @ Return the mmaxzoom
- */
- Public int getmaxzoom (){
- Return mmaxzoom;
- }
- /**
- * Set the max zoom of the center Image
- *
- * @ Param maxzoom
- * The mmaxzoom to set
- */
- Public void setmaxzoom (INT maxzoom ){
- Mmaxzoom = maxzoom;
- }
- /**
- * Get the centre of the coverflow
- *
- * @ Return the center of this coverflow.
- */
- Private int getcenterofcoverflow (){
- Return (getwidth ()-getpaddingleft ()-getpaddingright ()/2
- + Getpaddingleft ();
- }
- /**
- * Get the centre OF THE VIEW
- *
- * @ Return the center of the given view.
- */
- Private Static int getcenterofview (view ){
- Return view. getleft () + view. getwidth ()/2;
- }
- /**
- * {@ Inheritdoc}
- *
- * @ See # setstatictransformationsenabled (Boolean)
- */
- Protected Boolean getchildstatictransformation (view child, transformation T ){
- Final int childcenter = getcenterofview (child );
- Final int childwidth = Child. getwidth ();
- Int rotationangle = 0;
- T. Clear ();
- T. settransformationtype (transformation. type_matrix );
- If (childcenter = mcoveflowcenter ){
- Transformimagebitmap (imageview) Child, T, 0 );
- } Else {
- Rotationangle = (INT) (float) (mcoveflowcenter-childcenter)/childwidth) * mmaxrotationangle );
- If (math. Abs (rotationangle)> mmaxrotationangle ){
- Rotationangle = (rotationangle <0 )? -Mmaxrotationangle
- : Mmaxrotationangle;
- }
- Transformimagebitmap (imageview) Child, T, rotationangle );
- }
- Return true;
- }
- /**
- * This is called during layout when the size of this view has changed. If
- * You were just added to the view hierarchy, you're called with the old
- * Values of 0.
- *
- * @ Param W
- * Current width of this view.
- * @ Param H
- * Current height of this view.
- * @ Param oldw
- * Old width of this view.
- * @ Param oldh
- * Old height of this view.
- */
- Protected void onsizechanged (int w, int H, int oldw, int oldh ){
- Mcoveflowcenter = getcenterofcoverflow ();
- Super. onsizechanged (W, H, oldw, oldh );
- }
- /**
- * Transform the image bitmap by the angle passed
- *
- * @ Param imageview
- * Imageview the imageview whose bitmap we want to rotate
- * @ Param t
- * Transformation
- * @ Param rotationangle
- * The angle by which to rotate the bitmap
- */
- Private void transformimagebitmap (imageview child, transformation T,
- Int rotationangle ){
- Mcamera. Save ();
- Final matrix imagematrix = T. getmatrix ();
- Final int imageheight = Child. getlayoutparams (). height;
- Final int imagewidth = Child. getlayoutparams (). width;
- Final int rotation = math. Abs (rotationangle );
- // Forward the camera angle on the Z axis. The actual effect is to enlarge the image.
- // 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.
- Mcamera. Translate (0.0f, 0.0f, 100366f );
- // As the angle of the view gets less, zoom in
- If (rotation <mmaxrotationangle ){
- Float zoomamount = (float) (mmaxzoom + (rotation * 1.5 ));
- Mcamera. Translate (0.0f, 0.0f, zoomamount );
- }
- // Rotate on the Y axis, and flip the corresponding image vertically to the inside.
- // If the image is rotated on the X axis, the image is reversed horizontally.
- Mcamera. rotatey (rotationangle );
- Mcamera. getmatrix (imagematrix );
- Imagematrix. pretranslate (-(imagewidth/2),-(imageheight/2 ));
- Imagematrix. posttranslate (imagewidth/2), (imageheight/2 ));
- Mcamera. Restore ();
- }
- }
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:
- Public void oncreate (bundle savedinstancestate ){
- Super. oncreate (savedinstancestate );
- Setcontentview (R. layout. layout_gallery );
- Integer [] images = {R. drawable. img0001, R. drawable. img0030,
- R. drawable. im0000100, R. drawable. img0130, R. drawable. im0000200,
- R. drawable. img0230, R. drawable. im0000300, R. drawable. img0330,
- R. drawable. im1_354 };
- Imageadapter adapter = new imageadapter (this, images );
- Adapter. createreflectedimages ();
- Galleryflow = (galleryflow) findviewbyid (R. Id. gallery_flow );
- Galleryflow. setadapter (adapter );
- }
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:
- Bitmapdrawable BD = new bitmapdrawable (bitmapwithreflection );
- BD. setantialias = true;
- ...
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: