Custom superb gallery with reflection and deflection

Source: Internet
Author: User

The blog I wrote last night is gone, so I had to re-write it today and study it again. First of all, let's look at it:


Let's take a look at the main class code:

Public class gallerydemoactivity extends activity {/** called when the activity is first created. * // @ override public void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); requestwindowfeature (window. feature_no_title); setcontentview (R. layout. main); integer [] images = {R. drawable. image01, R. drawable. image02, R. drawable. image03, R. drawable. image04, R. drawable. image05}; IMA Geadapter adapter = new imageadapter (this, images); adapter. createreflectedimages (); // create the ing effect galleryflow = (galleryflow) This. findviewbyid (R. id. gallery); galleryflow. setfadingedgelength (0); galleryflow. setspacing (10); // the padding between images. galleryflow. setadapter (adapter); galleryflow. setonitemclicklistener (New onitemclicklistener () {public void onitemclick (adapterview <?> Parent, view, int position, long ID) {toast. maketext (getapplicationcontext (), String. valueof (position), toast. length_short ). show () ;}}); galleryflow. setselection (4 );}

It is relatively simple. First, let's look at how the reflection effect is implemented. Find the createreflectedimages () method in the imageadapter class:

/*** Create a reflection effect ** @ return */Public Boolean createreflectedimages () {// The final int reflectiongap = 4; int Index = 0; for (INT imageid: mimageids) {// returns the bitmap object bitmap originalimage = bitmapfactory after the source image is decoded. decoderesource (mcontext. getresources (), imageid); int width = originalimage. getwidth (); int Height = originalimage. getheight (); // create a matrix object matrix = new matrix (); // specify an angle to rotate at 0 to 0. // matrix. setrotate (30); // specify the matrix (X axis unchanged, Y axis opposite) matrix. prescale (1,-1); // apply the Matrix to the source image, and return a bitmap reflectionimage = bitmap with the same width and 1/2 height as the source image. createbitmap (originalimage, 0, height/2, width, height/2, matrix, false); // create a width that remains unchanged, bitmap bitmapwithreflection = bitmap. createbitmap (width, (height + height/2), config. argb_8888); // initialize the previously created bitmap to canvas = new canvas (bitmapwithreflection); canvas. drawbitmap (originalimage, 0, 0, null); paint deafaultpaint = new paint (); deafaultpaint. setantialias (false); // canvas. drawrect (0, height, width, height + reflectiongap, deafaultpaint); canvas. drawbitmap (reflectionimage, 0, height + reflectiongap, null); paint = new paint (); paint. setantialias (false);/*** parameter 1: indicates the X position of the initial point coordinate of the gradient. * parameter 2: indicates the Y axis. * parameter 3 and 4: determine the end point of the gradient, * The final parameter is the tile mode. * The image gradient is set based on the shader class. Therefore, we use the setshader method of painting to set the gradient */lineargradient shader = new lineargradient (0, originalimage. getheight (), 0, bitmapwithreflection. getheight () + reflectiongap, 0x70ffffff, 0x00ffffff, tilemode. mirror); // sets the shadow paint. setshader (shader); paint. setxfermode (New porterduduxfermode (Android. graphics. porterduff. mode. dst_in); // use a defined paint brush to build a canvas with a rectangular shadow gradient effect. drawrect (0, height, width, bitmapwithreflection. getheight () + reflectiongap, paint); // create an imageview to display the painted bitmapwithreflection imageview = new imageview (mcontext); imageview. setimagebitmap (bitmapwithreflection); // sets the imageview size, that is, the final image size. setlayoutparams (New galleryflow. layoutparams (200,300); // imageview. setscaletype (scaletype. matrix); mimages [index ++] = imageview;} return true ;}

First obtain the reflection, and then combine the reflection and the original photo into an image. The static method createbitmap () of bitmap is used in it. See the official documentation:

public static Bitmap createBitmap (Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)Since: API Level 1Returns an immutable bitmap from subset of the source bitmap, transformed by the optional matrix. It is initialized with the same density as the original bitmap.ParameterssourceThe bitmap we are subsettingxThe x coordinate of the first pixel in sourceyThe y coordinate of the first pixel in sourcewidthThe number of pixels in each rowheightThe number of rowsmOptional matrix to be applied to the pixelsfiltertrue if the source should be filtered. Only applies if the matrix contains more than just translation.ReturnsA bitmap that represents the specified subset of sourceThrowsIllegalArgumentExceptionif the x, y, width, height values are outside of the dimensions of the source bitmap.

The X and Y parameters are the starting coordinates of the source image copy, that is, the coordinate point of the source image copy, the width of the copy, and the height of the copy.

Because the comments in the Code are more detailed, I will not talk about them here.

The following code sets the gradient effect:

/*** Parameter 1: It is the coordinate X position at the beginning of the gradient, * parameter 2: It is the Y axis, * parameter 3 and 4: The corresponding gradient end point is identified, * the final parameter is the tile mode, * The image gradient is set here based on the shader class, so we use the setshader method of painting to set this gradient */lineargradient shader = new lineargradient (0, originalimage. getheight (), 0, bitmapwithreflection. getheight () + reflectiongap, 0x70ffffff, 0x00ffffff, tilemode. mirror );

After reading the reflection, let's take a look at the deflection in the main. xml file:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical"    >    <nsouth.jonas.android.GalleryFlow     android:layout_width="match_parent"    android:layout_height="match_parent"    android:gravity="center_vertical"    android:id="@+id/gallery" /></LinearLayout>

There is only one custom galleryflow. Let's take a look at its code:

Public class galleryflow extends gallery {private camera mcamera = new camera (); // camera class private int mmaxrotationangle = 60; // Maximum Rotation Angle private int mmaxzoom =-280; /// maximum zoom value private int mcoveflowcenter; // radius value public galleryflow (context) {super (context); // supports conversion and executes the getchildstatictransformation method this. setstatictransformationsenabled (true);} public galleryflow (context, attributeset attrs) {s Uper (context, attrs); this. setstatictransformationsenabled (true);} public galleryflow (context, attributeset attrs, int defstyle) {super (context, attrs, defstyle); this. setstatictransformationsenabled (true);}/*** get the Maximum Rotation Angle * @ return */Public int getmaxrotationangle () {return mmaxrotationangle ;} /*** set the maximum rotation angle * @ Param maxrotationangle */Public void setmaxrotationangle (INT maxrotatio Nangle) {mmaxrotationangle = maxrotationangle;}/*** get the maximum zoom value * @ return */Public int getmaxzoom () {return mmaxzoom ;} /*** set the maximum zoom value * @ Param maxzoom */Public void setmaxzoom (INT maxzoom) {mmaxzoom = maxzoom ;} /*** get the radius value * @ return */private int getcenterofcoverflow () {return (getwidth ()-getpaddingleft ()-getpaddingright ()/2 + getpaddingleft ();} /*** @ Param view * @ return */privat E static int getcenterofview (view) {return view. getleft () + view. getwidth ()/2;} // controls the rotation of each image in the Gallery (the method in the rewritten Gallery) protected Boolean getchildstatictransformation (view child, transformation T) {// obtain the final int childcenter = getcenterofview (child); Final int childwidth = child. getwidth (); // Rotation Angle int rotationangle = 0; // reset the conversion status T. clear (); // set the conversion type T. settransformationtype (Transform Ation. type_matrix); // if the image is in the center, it does not need to be rotated if (childcenter = mcoveflowcenter) {transformimagebitmap (imageview) Child, T, 0 );} else {// calculate the Image Rotation Angle Based on the image's position in the gallery. rotationangle = (INT) (float) (mcoveflowcenter-childcenter)/childwidth) * mmaxrotationangle); system. out. println ("rotationangle:" + rotationangle); // if the absolute value of the rotation angle is greater than the maximum rotation angle, return (-mmaxrotationangle or mmaxrotationangle;) if (math. ABS (rotationan GLE)> mmaxrotationangle) {rotationangle = (rotationangle <0 )? -Mmaxrotationangle: mmaxrotationangle;} transformimagebitmap (imageview) Child, T, rotationangle);} return true;}/***/protected void onsizechanged (int w, int H, int oldw, int oldh) {mcoveflowcenter = getcenterofcoverflow (); super. onsizechanged (W, H, oldw, oldh);} private void transformimagebitmap (imageview child, transformation T, int rotationangle) {// save mcamera. save (); Final mat Rix imagematrix = T. getmatrix (); // Image Height final int imageheight = child. getlayoutparams (). height; // Image Width final int imagewidth = child. getlayoutparams (). width; // returns the absolute value of the rotation angle 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, 1001_f); // 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 ();}}

The main method is:

// Controls the rotation of each image in the Gallery (override the method in the gallery) protected Boolean getchildstatictransformation (view child, transformation T) {// obtain the final int childcenter = getcenterofview (child); Final int childwidth = child. getwidth (); // Rotation Angle int rotationangle = 0; // reset the conversion status T. clear (); // set the conversion type T. settransformationtype (transformation. type_matrix); // if the image is in the center, it does not need to be rotated if (childcenter = mcoveflowcenter) {transformima Gebitmap (imageview) Child, T, 0);} else {// calculate the Rotation Angle of the Image Based on the position of the image in Gallery rotationangle = (INT) (float) (mcoveflowcenter-childcenter)/childwidth) * mmaxrotationangle); system. out. println ("rotationangle:" + rotationangle); // if the absolute value of the rotation angle is greater than the maximum rotation angle, return (-mmaxrotationangle or mmaxrotationangle;) if (math. ABS (rotationangle)> mmaxrotationangle) {rotationangle = (rotationangle <0 )? -Mmaxrotationangle: mmaxrotationangle;} transformimagebitmap (imageview) Child, T, rotationangle);} return true ;}

Calculate the Rotation Angle Based on the position of the image, and then rotate the image:

// Calculate the Rotation Angle of the Image Based on the position of the image in the gallery. rotationangle = (INT) (float) (mcoveflowcenter-childcenter)/childwidth) * mmaxrotationangle); system. out. println ("rotationangle:" + rotationangle); // if the absolute value of the rotation angle is greater than the maximum rotation angle, return (-mmaxrotationangle or mmaxrotationangle;) if (math. ABS (rotationangle)> mmaxrotationangle) {rotationangle = (rotationangle <0 )? -Mmaxrotationangle: mmaxrotationangle;} transformimagebitmap (imageview) Child, T, rotationangle );

The main function is implemented in the transformimagebitmap () method:

Private void transformimagebitmap (imageview child, transformation T, int rotationangle) {// Save the mcamera effect. save (); Final matrix imagematrix = T. getmatrix (); // Image Height final int imageheight = child. getlayoutparams (). height; // Image Width final int imagewidth = child. getlayoutparams (). width; // returns the absolute value of the rotation angle 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, 1001_f); // 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 ();}

It mainly performs flip operations.

The onfling method needs to be rewritten to modify the sliding speed. If you want to slide only one image at a time, you can try the following method:

Private Boolean locate (motionevent E1, motionevent E2) {return e2.getx ()> e1.getx () ;}@ override public Boolean onfling (motionevent E1, motionevent E2, float velocityx, float velocityy) {// E1 is the pressed event, and E2 is the raised event int keycode; If (isscrollingleft (E1, E2) {keycode = keyevent. keycode_dpad_left;} else {keycode = keyevent. keycode_dpad_right;} onkeydown (keycode, null); Return true ;}

It simply converts the slide in onfling to clicking the left and right arrow keys of the physical.

Note: The code is down from the Internet. I just used it for analysis and learning. I didn't want to cheat the world or steal my name.

Last,: http://download.csdn.net/detail/aomandeshangxiao/4211424


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.