Android programming implementation of the cool image browser _android

Source: Internet
Author: User
Tags abs reflection

This article is an example of the Android programming implementation of the awesome image browser. Share to everyone for your reference, specific as follows:

Anyone who has ever used Android's own gallery components knows that the effect of gallery is to drag and browse a group of pictures, which is obviously less than the iphone's Coverflow for dragging and browsing pictures. In fact, by extending gallery, the Coverflow effect can be realized by pseudo 3D transformation. This article through the source code to parse this function realization. Specific code action can refer to annotations.

The final results are as follows:

To use gallery, we must first assign a adapter to it. Here, we implement a custom imageadapter to create a reflection effect on the image.

The incoming parameter is an array of picture IDs in the context and within the drawable of the program. The Createreflectedimages () method is then invoked to create each image's reflection effect, generate the corresponding ImageView array, and finally return in GetView ().

Copyright (C) is Neil Davies * * Licensed under the Apache License, Version 2.0 (the "License"); 
* You could not use this file, except in compliance with the License. * Obtain a copy of the License at * * [url]http://www.apache.org/licenses/license-2.0[/url] * * unless require  
D by applicable or agreed into writing, software * Distributed under the License is distributed on ' as is ' basis, 
* Without warranties or CONDITIONS of any KIND, either express or implied. 
* The License for the specific language governing permissions and * limitations under the License.  * * This code are base on the Android Gallery widget and being Created * by Neil Davies neild001 ' in ' gmail dot com to be a Coverflow Widget * * @author Neil Davies * * public class Imageadapter extends Baseadapter {int Mgalleryitembackgrou 
nd 
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 r 
Eflectiongap = 4; 
int index = 0; 
for (int imageid:mimageids) {Bitmap originalimage = Bitmapfactory.decoderesource (Mcontext.getresources (), imageId); 
int width = originalimage.getwidth (); 
int height = originalimage.getheight (); 
This is not scale but'll flip on the Y axis 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 for//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 are a linear gradient that covers the//reflection Paint Paint = new Paint (); LinearGradient shader = new LinearGradient (0, Originalimage.getheight (), 0, Bitmapwithreflection.getheight () + reflecti 
Ongap, 0x70ffffff, 0X00FFFFFF, Tilemode.clamp); 
Set the paint to use this shader (linear gradient) paint.setshader (shader); 
Set the Transfer mode to is Porter Duff and destination in Paint.setxfermode (new Porterduffxfermode (mode.dst_in)); Draw a rectangle using the paint with our linear gradient canvas.drawrect (0, height, width, bitmapwithreflection.geth Eight () + ReflectiOngap, paint); 
ImageView 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 Reso 
urces * * 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 jaggies * 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 the * ' offset ' to the center.  * * Public Float Getscale (boolean focused, int offset) {/* Formula:1/(2 ^ offset)/Returnmath.max (0,1.0f/(float) 
Math.pow (2, Math.Abs (offset));

 } 
} 
}

The

Only realizes the image's reflection effect is not enough, because in the coverflow the picture switch has the rotation and the scaling effect, but has not realized in the gallery which brings. Therefore, we extend our own gallery and realize our own galleryflow. In the original gallery class, a method Getchildstatictransformation () is provided to implement the transform to the picture. By covering this method and invoking the custom Transformimagebitmap ("Distance per picture from Gallery Center"), we can rotate and scale each picture accordingly. The camera and matrix are used for view transformations. You can refer to code comments specifically.

public class Galleryflow Extendsgallery {/** * Graphics Camera used for transforming the matrix of Imageviews 
  * * Privatecamera Mcamera = Newcamera (); 
  /** * The maximum angle the child imageview would be rotated by/* Privateint = 60; 
  /** * The maximum zoom on the Centre child * * Privateint =-120; 
  /** * The Centre of the Coverflow * * Privateint mcoveflowcenter; 
    Publicgalleryflow (context) {super (context); 
  This.setstatictransformationsenabled (TRUE); 
    } publicgalleryflow (context, AttributeSet attrs) {Super (context, attrs); 
  This.setstatictransformationsenabled (TRUE); 
    } publicgalleryflow (Context, AttributeSet attrs, int defstyle) {Super (context, attrs, Defstyle); 
  This.setstatictransformationsenabled (TRUE); /** * Get the max rotational angle of the image * * @return the Mmaxrotationangle/Publicint get MaxrotatioNangle () {returnmmaxrotationangle; }/** * Set the max rotational angle of each image * * @param maxrotationangle * the Mmaxrotationangl 
  E to set */Publicvoid Setmaxrotationangle (intmaxrotationangle) {mmaxrotationangle = Maxrotationangle; 
    /** * Get the Max zoom of the centre image * * @return the mmaxzoom * * Publicint getmaxzoom () { 
  Returnmmaxzoom; /** * Set the max zoom of the centre image * * @param maxzoom * The mmaxzoom to Set * * * publi 
  Cvoid Setmaxzoom (intmaxzoom) {mmaxzoom = Maxzoom; 
   /** * Get the Centre of the Coverflow * * @return The Centre of this coverflow. * * Privateint Getcenterofcoverflow () {return (GetWidth ()-Getpaddingleft ()-getpaddingright ())/2 + GE 
  Tpaddingleft (); 
   /** * Get the Centre of the view * * @return The Centre of the given view. */privatestatic int Getcenterofview (view view) { 
    Returnview.getleft () + view.getwidth ()/2; }/** * {@inheritDoc} * * @see #setStaticTransformationsEnabled (Boolean)/Protectedboolean Getchil 
    Dstatictransformation (View Child, Transformation t) {Finalint childcenter = Getcenterofview (child); 
    Finalint childwidth = Child.getwidth (); 
    Introtationangle = 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); 
  } returntrue; }/** * This are called during layout when the size of this view has changed. If * yOu were just added to the view hierarchy, "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 * view. 
    * * Protectedvoid onsizechanged (intw, 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 whic H to rotate the Bitmap * * privatevoid Transformimagebitmap (ImageView child, transformation T, Introtationang 
    Le) {mcamera.save (); 
    Finalmatrix Imagematrix = T.getmatrix (); 
    Finalint imageheight = Child.getlayoutparams (). Height; Finalint imagewidth = Child.getLayoutparams (). width; 
    Finalint rotation = Math.Abs (rotationangle); 
    The perspective of the forward moving camera on the z-axis, the actual effect is to enlarge the picture. 
    If you move on the y-axis, the picture moves up and down, and the corresponding picture moves around the x-axis. 
    Mcamera.translate (0.0f,0.0f, 100.0f);  As the angle of the view gets less, zoom in if (Rotation < Mmaxrotationangle) {Floatzoomamount = (float) 
      (Mmaxzoom + (rotation *1.5)); 
    Mcamera.translate (0.0f,0.0f, Zoomamount); 
    //rotate on the y-axis and flip the picture vertically inward. 
    If you rotate on the x-axis, the corresponding picture is flipped sideways. 
    Mcamera.rotatey (RotationAngle); 
    Mcamera.getmatrix (Imagematrix); 
    Imagematrix.pretranslate (-(IMAGEWIDTH/2),-(IMAGEHEIGHT/2)); 
    Imagematrix.posttranslate ((IMAGEWIDTH/2), (IMAGEHEIGHT/2)); 
  Mcamera.restore ();

 } 
}

The code is over here. If you are interested, you can adjust the parameters inside to achieve more and more dazzling effect.
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.img0100, r.drawable.img0130, r.drawable.img0200, 
      r.drawable.img0230, r.drawable.img0300, r.drawable.img0330, 
      r.drawable.img0354}; 
    Imageadapter Adapter =new Imageadapter (this, images); 
    Adapter.createreflectedimages (); 
    Galleryflow Galleryflow = (galleryflow) Findviewbyid (r.id.gallery_flow); 
    Galleryflow.setadapter (adapter); 
}

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);

Then use Iv.setimagedrawable (BD);
Instead of Iv.setimagebitmap (bitmapwithreflection);
can basically eliminate sawtooth.

PS2:

Imageadapter to determine the memoryleak problem, the seemingly bitmap decode method will cause ML, the use of imageadapter when a number of rotation screen will appear after oom. It is now possible to get some improvement by calling the Recycle () method and setting null and calling System.GC () in a timely manner by bimap the finished use, but the problem is not obvious.
Celebrating essence and recommendation, adding 3 ps~

PS3 on PS1:

Why the anti-aliasing is not apparent after opening. The answer is that the sawtooth can not be completely eliminated, but it will improve greatly after opening anti-aliasing.
In addition to why Android does not default on Sawtooth, here are a few of my thoughts:
Interpolation is what I now know antialiasing algorithm, that is, the calculation of the correlation between pixels to insert intermediate pixels to achieve smooth edge of the image. But it will certainly cost a lot of computing.
Although I have not been tested, I suspect that graphics performance will drop by at least 30% after using AntiAlias.
Of course, there are no complex graphics operations involved, so opening anti-aliasing does not have a noticeable performance impact, but if you test on a simulator or a low-end model you will find a problem.

PS4:

Someone asked what the two words in Transformimagebitmap () meant:

Imagematrix.pretranslate (-(IMAGEWIDTH/2),-(IMAGEHEIGHT/2));
Imagematrix.posttranslate ((IMAGEWIDTH/2), (IMAGEHEIGHT/2));

The personal understanding is as follows:

Pretranslate is equivalent to pretranslate,posttranslate the image before any matrix transformation, and performs all transformations before executing the posttranlate.
Before making any transformations, the whole image is moved from the center point of the image to the origin ((0,0) point), and then the image is moved from the origin to the center point before the transformation is completed.
If you do not add these two sentences, any transformation will take the original point of the image as the transformation center point, after added, any transformation will take the center point of the image as the transformation Center point.
For example, to rotate an image requires two parameters: one is the angle of rotation and the other is the coordinate of the center of rotation. The coordinates of the center of rotation affect the effect of rotation. Can you understand that? It is not the same that you take a stick and rotate it in the middle of the stick with one end of the stick. Pretranslate and Posttranslate do not have an effect on the image itself, affecting the rotation axis when the image is transformed.
Say so much a bit around, in fact, is the knowledge of matrix transformation.

PS5 on PS2:

This issue has been well discussed under Google Group and appears to exist only in debug mode. Now that I'm using this code, there's no oom problem.

I hope this article will help you with the Android program.

Related Article

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.