Customize the gallery control to implement a simple 3D image browser

Source: Internet
Author: User

This article describes how to use a custom gallery control to implement the effect of a 3D image browser.

Let's talk about the effect first.


The above is a custom gallery control that achieves reflection and 3D imitation effects. The following is an image viewer. Click the small image above to view the large image below.

The following describes how to implement the image viewer.

1. Obtain the image path on the mobile phone

First, no matter how the image is displayed, if we want to implement the Image Viewer function, we need to first obtain the path information of all the images, we can view images.

We can use the following code to implement

private List<String> getImagesFromSD() {List<String> imageList = new ArrayList<String>();File f = Environment.getExternalStorageDirectory();if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {f = new File(Environment.getExternalStorageDirectory().toString());} else {Toast.makeText(MainActivity.this, R.string.sdcarderror, Toast.LENGTH_LONG).show();return imageList;}File[] files = f.listFiles();if (files == null || files.length == 0)return imageList;for (int i = 0; i < files.length; i++) {File file = files[i];if (isImageFile(file.getPath()))imageList.add(file.getPath());}return imageList;}

The function of the above method is to obtain the path of all files whose suffix names meet the suffix of the image in the SD card, and then put them in the list container for return.

The isimagefile method is implemented in this way.

private boolean isImageFile(String fName) {String end = fName.substring(fName.lastIndexOf(".") + 1, fName.length()).toLowerCase();if (end.equals("jpg") || end.equals("gif") || end.equals("png") || end.equals("jpeg") || end.equals("bmp")) {return true;}return false;}

2. After obtaining the image path, we need to display the 3D effects of small images on the custom gallery control above. In the current version, gallery controls are no longer recommended. viewpager and horizonalscrollview controls are replaced. The following describes the implementation of a custom gallery control.

/*** 3D effect gallery implementation ** @ time 9:10:47 on April 9, June 26, 2014 */@ suppresswarnings ("deprecation") public class galleryflow extends gallery {private camera mcamera = new camera (); // Maximum Rotation Angle of images on both sides: Private int mmaxrotationangle = 60; private int mmaxzoom =-120; 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);} // set the maximum rotation angle public void setmaxrotationangle (INT maxrotationangle) {mmaxrotationangle = maxrotationangle;} // obtain the central point of the current control. X axis position private int getcenterofcoverflow () {return (get Width ()-getpaddingleft ()-getpaddingright ()/2 + getpaddingleft ();} // obtain the Private Static int getcenterofview (view) {return view on the X axis of the View control. getleft () + view. getwidth ()/2;} // The default return value is false. If the city is set to true, this method is called every time the gallery generates a child control, so we can set the return value to true, and then complete the child rotation and other deformation operations protected Boolean getchildstatictransformation (view child, transformation T) {final int childcenter = getcenterofview (child); Final in T childwidth = child. getwidth (); int rotationangle = 0; T. clear (); T. settransformationtype (transformation. type_matrix); // if the child control is in the center, if (childcenter = mcoveflowcenter) {transformimagebitmap (imageview) Child, T, 0) is not rotated );} else {// otherwise, rotate the current Child control to an angle of rotationangle = (INT) (float) (mcoveflowcenter-childcenter)/childwidth) * mmaxrotationangle); If (math. ABS (rotationangle)> mmaxrotationangle ){ Rotationangle = (rotationangle <0 )? -Mmaxrotationangle: mmaxrotationangle;} transformimagebitmap (imageview) Child, T, rotationangle);} return true;} // recalculate the x-axis protected void onsizechanged (int w, int H, int oldw, int oldh) {mcoveflowcenter = getcenterofcoverflow (); super. onsizechanged (W, H, oldw, oldh);} // implement private void transformimagebitmap (imageview child, transformation T, int rotationangle) {mcamera. sav E (); 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 around. Mcamera. translate (0.0f, 0.0f, 100366f); 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); // restore the original status of the camera mcamera. restore ();}}
Through the custom gallery Control, we have now achieved that when the image in the gallery is swiped, the image on both sides will rotate at a certain angle, that is, the first part of the 3D effect is completed. Next, we need to modify the getview method in the gallery adapter to preview the reflection effect of the small image.
3. Implement the adapter to implement the reflected effect. To do the reflected effect, we need to process the imported image in the getview method. The specific code is as follows:
@ Suppresswarnings ({"deprecation", "UNUSED"}) public class imageadapter extends baseadapter {private context mcontext; // The path used to store images: Private list <string> imagefilelist; // original image private bitmap originalimage; // The reflected image. The height is half the height of the original image private bitmap reflectionimage; // It is used to store the processed image, the height is 1.5 times that of the original image private bitmap bitmapwithreflection; // the width and height of the image private int width; private int height; // matrix private matrix; // canvas private canvas; // The interval height between the original image and the reflected image final int reflectiongap = 4; // used for getview to return private imageview; // The Shadow blur effect of the reflection private lineargradient shader; public imageadapter (context c, list <string> _ imagefilelist) {mcontext = C; imagefilelist = _ imagefilelist; matrix = new matrix (); // It is set to X axis to flip matrix. prescale (1,-1) ;}@ overridepublic int getcount () {return imagefilelist. size () ;}@ overridepublic object getitem (INT position) {return position ;}@ overridepublic long getitemid (INT position) {return position ;} // return the processed imageview object @ overridepublic view getview (INT position, view convertview, viewgroup parent) {return createreflectedimages (imagefilelist. get (position);} // This is the most important method. It completes image mirroring. Public imageview createreflectedimages (string filepath) {// gets the original image originalimage = bitmapfactory. decodefile (filepath); width = originalimage. getwidth (); Height = originalimage. getheight (); // create a reflection image. The height is half of the original image, and the X axis is reversed using the matrix, that is, the reflection effect reflectionimage = bitmap. createbitmap (originalimage, 0, height/2, width, height/2, matrix, false); // initialize the bitmap object to store the processed image, the height is 1.5 times that of the original image. bitmapwithreflection = bitmap. createbitmap (width, (height + height/2), config. argb_8888); // creates a canvas = new canvas (bitmapwithreflection) based on the bitmapwithreflection object; // first draws the original image to the canvas. drawbitmap (originalimage, 0, 0, null); paint = new paint (); // draw a small gap between the original image and the reflected image. The height is reflectiongapcanvas. drawrect (0, height, width, height + reflectiongap, paint); // draw the reflection canvas. drawbitmap (reflectionimage, 0, height + reflectiongap, null); // set the shadow effect shader = new lineargradient (0, originalimage. getheight (), 0, bitmapwithreflection. getheight () + reflectiongap, 0x70ffffff, 0x00ffffff, tilemode. clamp); paint. setshader (shader); paint. setxfermode (New porterduduxfermode (mode. dst_in); // draw a rectangular canvas with a shadow paint brush on the reflection graph. drawrect (0, height, width, bitmapwithreflection. getheight () + reflectiongap, paint); // Initialize an imageview object imageview = new imageview (mcontext); // set the processed image to imageview. setimagebitmap (bitmapwithreflection); imageview. setlayoutparams (new gallery. layoutparams (120,160); imageview. setscaletype (scaletype. center_inside); Return imageview ;}}

The most important thing is to understand how to implement the reflection effect. The comment should be very detailed, but I will explain it more. 4. How to Use the custom gallery control to implement the final image Viewer? Let's take a look at how to use this control to achieve our final effect. Layout 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:background="#F9F900"    android:gravity="center_horizontal"    android:orientation="vertical" >    <com.examole.gallery.GalleryFlow        android:id="@+id/mygallery"        android:layout_width="match_parent"        android:layout_height="100dp"        android:layout_marginTop="20dp"        android:gravity="center_vertical" />    <ImageSwitcher        android:id="@+id/switcher"        android:layout_width="wrap_content"        android:layout_height="match_parent"        android:layout_gravity="center_horizontal" /></LinearLayout>
Here we use a very strange class, that is, imageswicher. Let's take a look at how to use it in activity.
Public class mainactivity extends activity implements adapterview. onitemselectedlistener, viewswitcher. viewfactory {private list <string> imagelist; private imageswitcher mswitcher; private gallery Gallery; @ overridepublic void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. activity_main); // obtain the image path imagelist = getimagesfromsd (); mswitcher = (imageswitcher) Findviewbyid (R. id. switcher); gallery = (Gallery) findviewbyid (R. id. mygallery); // The imageswitcher control must implement viewswitcher. viewfactory interface, and then in the makeview method, return the control we need to display to mswitcher. setfactory (this); // set the animation effect mswitcher for entering and leaving the image. setinanimation (animationutils. loadanimation (this, android. r. anim. slide_in_left); mswitcher. setoutanimation (animationutils. loadanimation (this, android. r. anim. slide_out_right); // sets gallery adaptation. Gallery. setadapter (New imageadapter (this, imagelist); Gallery. setonitemselectedlistener (this);} private list <string> getimagesfromsd () {list <string> imagelist = new arraylist <string> (); file F = environment. getexternalstoragedirectory (); If (environment. getexternalstoragestate (). equals (environment. media_mounted) {f = new file (environment. getexternalstoragedirectory (). tostring ();} else {toast. maket EXT (mainactivity. this, R. string. sdcarderror, toast. length_long ). show (); Return imagelist;} file [] files = f. listfiles (); If (Files = NULL | files. length = 0) return imagelist; For (INT I = 0; I <files. length; I ++) {file = files [I]; If (isimagefile (file. getpath () imagelist. add (file. getpath () ;}return imagelist ;}@ suppresslint ("defaultlocale") Private Boolean isimagefile (string fname) {string end = Fname. substring (fname. lastindexof (". ") + 1, fname. length ()). tolowercase (); If (end. equals ("jpg") | end. equals ("GIF") | end. equals ("PNG") | end. equals ("Jpeg") | end. equals ("BMP") {return true;} return false ;}@ overridepublic void onitemselected (adapterview <?> Parent, view, int position, long ID) {// when you click the small image above, obtain the absolute path of the image and set it to mswitcherstring photourl = imagelist. get (position); mswitcher. setimageuri (URI. parse (photourl) ;}@ overridepublic void onnothingselected (adapterview <?> Parent) {}@ overridepublic view makeview () {imageview I = new imageview (this); I. setbackgroundcolor (0x00000000); I. setscaletype (imageview. scaletype. center_inside); I. setlayoutparams (New imageswitcher. layoutparams (layoutparams. match_parent, layoutparams. match_parent); return I ;}}

In addition to the imageswitcher control, others should be familiar with it. After these steps, we finally achieved a simple image Viewer that imitates 3D effects.

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.