Before a group of friends asked me, there is no local picture selection demo, similar to the effect of micro-letter, he said there is no online demo, asked me if I can write a demo on this effect, so I studied the next micro-letter of the local picture selection of the demo, The imitation of their own wrote the next share to everyone, Hope that there is such a demand for friends in the future a little help, the main use is ContentProvider scan the phone pictures, and the GridView to display the picture, about the GridView and ListView display pictures of the problem, has been a headache, Because our cell phone memory is limited, the mobile phone to each application allocated memory is also limited, so the picture is very easy to accompany the case of Oom, but now there are many open source picture display frame, to show a lot of pictures have been optimized, we are interested to understand, Today, I use this article LRUCache this class and to the image of the corresponding crop, so as possible to avoid the occurrence of oom, we first look at the effect of micro-letter
So let's get to the effect, first we create a new project, we name Imagescan.
First we look at the first interface bar, use the image of the phone to scan out, and then according to the image of the folder to classify it, and show the folder inside a picture and folder in the number of pictures, we based on the interface elements (folder name, folder picture number, A picture in a folder to encapsulate these three properties using an entity object Imagebean
Package Com.example.imagescan;
data object for each item of the/** * GridView * * @author len * * */public
class imagebean{
/**
* folder's first picture path
*
/private String Topimagepath;
/**
* Folder name
*
/private String folderName;
/**
* The number of pictures in the folder * *
private int imagecounts;
Public String Gettopimagepath () {return
topimagepath;
}
public void Settopimagepath (String topimagepath) {
this.topimagepath = Topimagepath;
}
Public String Getfoldername () {return
folderName;
}
public void Setfoldername (String folderName) {
this.foldername = folderName;
}
public int getimagecounts () {return
imagecounts;
}
public void setimagecounts (int imagecounts) {
this.imagecounts = imagecounts;
}
}
The next is the layout of the main interface, which I did not add to the navigation bar, only the following GridView, so that the main interface layout only a GridView
<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android"
xmlns:tools= "http:// Schemas.android.com/tools "
android:layout_width=" match_parent "
android:layout_height=" Match_parent " >
<gridview
android:id= "@+id/main_grid"
android:layout_width= "Match_parent"
android: layout_height= "Match_parent"
android:listselector= "@android: color/transparent"
android:cachecolorhint= "@android: Color/transparent"
android:stretchmode= "columnWidth"
android:horizontalspacing= "20dip"
android:gravity= "center"
android:verticalspacing= "20dip"
android:columnwidth= "90dip"
android:numcolumns= "2" >
</GridView>
</RelativeLayout>
Next is the GridView's item layout, look at the above picture also line you will think his effect is 2 pictures added effect, is not, the superposition effect behind is just a background picture, code first posted up
<?xml version= "1.0" encoding= "UTF-8"?> <relativelayout xmlns:android= "http://schemas.android.com/apk/res/" Android "Android:layout_width=" Fill_parent "android:layout_height=" wrap_content "> <framelayout andr Oid:id= "@+id/framelayout" android:layout_width= "fill_parent" android:layout_height= "wrap_content" > &L
T;com.example.imagescan.myimageview android:id= "@+id/group_image" android:background= "@drawable/albums_bg" android:src= "@drawable/friends_sends_pictures_no" android:paddingleft= "20dip" android:paddingright= "20 Dip "android:paddingtop=" 18dip "android:paddingbottom=" 30dip "android:scaletype=" Fitxy "Androi D:layout_width= "Fill_parent" android:layout_height= "150dip"/> <textview android:id= "@+id/group" _count "android:layout_width=" wrap_content "android:layout_height=" Wrap_content "android:background="
@drawable/ALBUMS_ICON_BG " android:gravity= "center" android:layout_marginbottom= "10dip" android:text= "5" Android:layout_gravi ty= "Bottom|center_horizontal"/> </FrameLayout> <textview android:id= "@+id/group_title" Andr Oid:layout_width= "Fill_parent" android:layout_height= "wrap_content" android:gravity= "center" android:layout _below= "@id/framelayout" android:layout_centerhorizontal= "true" android:ellipsize= "End" android:singleline=
"True" android:text= "Camera" android:textsize= "16sp"/> </RelativeLayout>
See the above layout code, also line you have found that the above is a custom myimageview, I will not say the role of the custom Myimageview, I'll tell you later, we continue to look at the code
The main code of the first interface
Package Com.example.imagescan;
Import Java.io.File;
Import java.util.ArrayList;
Import Java.util.HashMap;
Import Java.util.Iterator;
Import java.util.List;
Import Java.util.Map;
Import android.app.Activity;
Import Android.app.ProgressDialog;
Import Android.content.ContentResolver;
Import android.content.Intent;
Import Android.database.Cursor;
Import Android.net.Uri;
Import Android.os.Bundle;
Import Android.os.Handler;
Import Android.os.Message;
Import Android.provider.MediaStore;
Import Android.view.View;
Import Android.widget.AdapterView;
Import Android.widget.AdapterView.OnItemClickListener;
Import Android.widget.GridView; public class Mainactivity extends activity {private hashmap<string, list<string>> mgruopmap = new hashmap& Lt
String, list<string>> ();
Private list<imagebean> List = new arraylist<imagebean> ();
Private final static int scan_ok = 1;
Private ProgressDialog Mprogressdialog; Private GroupadapteR adapter;
Private GridView Mgroupgridview; Private Handler Mhandler = new Handler () {@Override public void Handlemessage (msg) {Super.hand
Lemessage (msg);
Switch (msg.what) {case SCAN_OK://Close progress bar Mprogressdialog.dismiss ();
adapter = new Groupadapter (mainactivity.this, list = Subgroupofimage (Mgruopmap), Mgroupgridview);
Mgroupgridview.setadapter (adapter);
Break
}
}
};
@Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (R.layout.activity_main);
Mgroupgridview = (GridView) Findviewbyid (R.id.main_grid);
GetImages (); Mgroupgridview.setonitemclicklistener (New Onitemclicklistener () {@Override public void Onitemclick (adapte Rview<?> Parent, view view, int position, long id) {list<string> childlist = MGRUOPMAP.get (List.get (position). Getfoldername ());
Intent mintent = new Intent (mainactivity.this, Showimageactivity.class);
Mintent.putstringarraylistextra ("Data", (arraylist<string>) childlist);
StartActivity (mintent);
}
});
}
/** * Using ContentProvider to scan pictures on mobile phones, this method is run in child threads/private void GetImages () {//Show progress bar Mprogressdialog
= Progressdialog.show (this, null, "Loading ..."); New Thread (New Runnable () {@Override public void run () {Uri Mimageuri = mediastore.images .
Media.external_content_uri;
Contentresolver mcontentresolver = MainActivity.this.getContentResolver (); Query only JPEG and png pictures Cursor mcursor = mcontentresolver.query (Mimageuri, NULL, MediaStore.Images.Media.MI Me_type + "=? or "+ MediaStore.Images.Media.MIME_TYPE +" =? ", new string[] {" Image/jpeg "," Image/png "},
MediaStore.Images.Media.DATE_MODIFIED);
if (mcursor = = null) {return; while (Mcursor.movetonext ()) {//Get the path of the picture String path = mcursor.getstring (Mcurso
R. Getcolumnindex (MediaStore.Images.Media.DATA)); Gets the parent path name of the picture String ParentName = new File (path). Getparentfile (). GetName (); Put the picture of the parent path name into Mgruopmap if (!mgruopmap.containskey (ParentName)) {list<string> chilelist =
New Arraylist<string> ();
Chilelist.add (path);
Mgruopmap.put (ParentName, chilelist);
else {mgruopmap.get (parentname). Add (path);
}//Notify handler scan picture complete mhandler.sendemptymessage (SCAN_OK);
Mcursor.close ();
}). Start ();
}
/** * Assemble the data source for the GridView of the packet interface, because when we scan the phone, we put the picture information in the HashMap * so we need to traverse hashmap to assemble the data into a list. * * @param mgruopmap * @return/private list<imagebean> subgroupofimage (hashmap<string, List
<String>> mgruopmap) {if (mgruopmap.size () = = 0) {return null;
} list<imagebean> List = new arraylist<imagebean> ();
Iterator<map.entry<string, list<string>>> it = Mgruopmap.entryset (). Iterator ();
while (It.hasnext ()) {map.entry<string, list<string>> Entry = It.next ();
Imagebean Mimagebean = new Imagebean ();
String key = Entry.getkey ();
list<string> value = Entry.getvalue ();
Mimagebean.setfoldername (key);
Mimagebean.setimagecounts (Value.size ());
Mimagebean.settopimagepath (value.get (0));//Get the first picture of the group List.add (Mimagebean);
} return list; }
}
First look at the GetImages () method, the method is to use ContentProvider to scan the image of the phone, I only scanned the phone's external storage of pictures, because the phone may have a lot of pictures, scanning pictures and more time-consuming, So here we have the child thread to get the picture, the scanned pictures are stored in the cursor, we first want to classify the pictures according to the folder, we use the HashMap to classify and store the result to Mgruopmap (key is the folder name, Value is the list of picture paths in the folder, the sorting is done, close cursor and use handler to inform the main thread
Then is the Subgroupofimage () method, the method is to assemble the MGRUOPMAP data into the list, in the list of the GridView in the data object of each item Imagebean, traversing the HashMap object, the specific logic to see the code, After that, set the adapter for the GridView.
Set Item Click event, click Folder to jump to show folder picture of activity, we need to pass a collection of the paths of the pictures in each folder
Before we look at the Groupadapter code, let's look at a more important class, the local picture loader Nativeimageloader
Package Com.example.imagescan;
Import Java.util.concurrent.ExecutorService;
Import java.util.concurrent.Executors;
Import Android.graphics.Bitmap;
Import Android.graphics.BitmapFactory;
Import Android.graphics.Point;
Import Android.os.Handler;
Import Android.os.Message;
Import Android.support.v4.util.LruCache; /** * Local picture loader, using the asynchronous resolution of the local picture, singleton mode using getinstance () Get nativeimageloader instance * Call Loadnativeimage () method to load local picture,
This class can be used as a tool class to load local pictures * * public class Nativeimageloader {private lrucache<string, bitmap> Mmemorycache;
private static Nativeimageloader minstance = new Nativeimageloader ();
Private Executorservice Mimagethreadpool = Executors.newfixedthreadpool (1); Private Nativeimageloader () {//Get the maximum memory for the application final int maxmemory = (int) (Runtime.getruntime (). MaxMemory ()/1024)
;
Store the picture with 1/4 of the maximum memory final int cacheSize = MAXMEMORY/4; Mmemorycache = new lrucache<string, bitmap> (cacheSize) {//Get the size of each picture @Override protected int sizeOf (String key, Bitmap Bitmap) {return bitmap.getrowbytes () * Bitmap.getheight ()
/1024;
}
};
/** * This method is used to obtain an instance of Nativeimageloader * @return/public static Nativeimageloader getinstance () {
return minstance;
}
/** * Load local picture, do not crop the picture * @param path * @param mcallback * @return * * Public Bitmap Loadnativeimag
E (Final String path, final Nativeimagecallback mcallback) {return this.loadnativeimage (path, NULL, mcallback); /** * This method to load the local picture, where the mpoint is used to encapsulate the width and height of the ImageView, we will crop the bitmap according to the size of the ImageView control if you do not want to crop the picture, call Loadnativeimage (f
Inal String Path, final nativeimagecallback mcallback) to load * @param path * @param mpoint * @param mcallback * @return/Public Bitmap loadnativeimage (final String path, final point Mpoint, final Nativeimagecallback mcallb
ACK) {//Get the Bitmap Bitmap in memory First Bitmap = Getbitmapfrommemcache (path); Final Handler Mhander = new Handler () {@Override public void Handlemessage (msg) {Super.h
Andlemessage (msg);
Mcallback.onimageloader ((Bitmap) msg.obj, path);
}
}; If the bitmap is not in the memory cache, enable the thread to load the local picture and add bitmap to the Mmemorycache if (bitmap = = null) {Mimagethreadpool.execute (new Runnable () {@Override public void run () { First get the thumbnail of the picture Bitmap Mbitmap = decodethumbbitmapforfile (path, mpoint = = null? 0:mpoint.x, mpoint = null ?
0:MPOINT.Y);
Message msg = Mhander.obtainmessage ();
Msg.obj = Mbitmap;
Mhander.sendmessage (msg);
Add a picture to the memory cache Addbitmaptomemorycache (path, mbitmap);
}
});
return bitmap; /** * Add bitmap * to the memory cache * * @param key * @param bitmap/private void Addbitmaptomemor Ycache (String key, Bitmap Bitmap) {if (Getbitmapfrommemcache (key) = = NULL && Bitmap!= null) {Mmemor
Ycache.put (key, bitmap); }/** * Based on key to get the picture in memory * @param key * @return/private Bitmap Getbitmapfrommemcache (String
Key) {return mmemorycache.get (key); /** * According to view (mainly imagEview) Width and height to obtain the thumbnail image of the picture * @param path * @param viewwidth * @param viewheight * @return * * Private BITMA P Decodethumbbitmapforfile (String path, int viewwidth, int viewheight) {bitmapfactory.options Options = new BITMAPFAC Tory.
Options ();
Set to True to resolve the bitmap object, which does not account for memory Options.injustdecodebounds = true;
Bitmapfactory.decodefile (path, options);
Set Scaling Scale options.insamplesize = Computescale (options, Viewwidth, viewheight);
Set to False to parse the bitmap object into memory Options.injustdecodebounds = false;
return Bitmapfactory.decodefile (path, options); /** * Calculates the bitmap scaling according to the width and height of the view (mainly ImageView). Default does not scale * @param options * @param width * @param height */private int Computescale (bitmapfactory.options
options, int viewwidth, int viewheight) {int insamplesize = 1;
if (Viewwidth = = 0 | | viewwidth = 0) {return insamplesize;
int bitmapwidth = Options.outwidth; int Bitmapheight = Options.outheight; If the width or height of the bitmap is greater than the view width of the picture we set, compute the scaling if (Bitmapwidth > Viewwidth | | bitmapheight > viewwidth) {int WI
Dthscale = Math.Round ((float) bitmapwidth/(float) viewwidth);
int heightscale = Math.Round ((float) bitmapheight/(float) viewwidth); In order to ensure that the image does not scale deformation, we take the Insamplesize = Widthscale < Heightscale, which is the smallest in width and height ratio?
Widthscale:heightscale;
return insamplesize;
/** * Load callback interface for local picture * * @author xiaanming */public interface nativeimagecallback{ /** * When the Strand Chengga the local picture, the bitmap and picture paths are recalled in this method * @param bitmap * @param path/public void Onimag
Eloader (Bitmap Bitmap, String path);
}
}
The class is a single instance class, provides a local picture loading, memory caching, cropping and other logic, the class in the loading of local pictures is the way to load, for large picture loading is also more time-consuming, so the way to use the child thread to load, the image of the caching mechanism used is lrucache, 1/4 of the memory allocated to the application by mobile phone is used to cache pictures, in addition to using LRUCache to cache pictures, the picture is cropped, for example, if our control size is 100 * 100, and our picture is 400* 400, we load such a large picture requires a lot of memory, so we used the picture clipping, according to the size of the control to determine the image of the crop ratio, so as to reduce memory consumption, improve the flow of the GridView glide, introduce some of the more important methods
Computescale () Calculate the proportion of the picture needs to be cropped, based on the size of the control and the size of the picture to determine the proportions, if the picture is larger than the control, we will be trimmed, otherwise do not need.
The Decodethumbbitmapforfile () method is to load the picture from the file after calculating the proportions of the picture cropping, we first set options.injustdecodebounds = True to indicate that the resolution does not occupy memory, But we can get the specific size of the picture, using Computescale () to calculate a good proportion, in the will Options.injustdecodebounds=false, again to parse the bitmap, this way on the picture has been cut.
Loadnativeimage (final String path, final point Mpoint, Final nativeimagecallback mcallback) we can get the bitmap object just by calling the method on the client , the specific logic inside is first to determine whether the memory cache LRUCache in the presence of the bitmap, does not exist to open the child thread to read, in order to facilitate the management of loading local picture thread, where the thread pool, the pool can only hold a thread, Read the local picture first add Bitmap to the LRUCache, save the key for the picture path, and then use the handler to inform the main thread picture loaded, and then Bitmap and path callback to method Onimageloader (Bitmap Bitmap, String path, the Mpoint of the method is used to encapsulate the width and height of the control's object
If you do not crop the picture directly this method's overloaded method Loadnativeimage (final String path, final nativeimagecallback mcallback) is OK, the logic is the same, It's just this way not to crop the picture
Next is the code for the adapter class of the GridView.
Package Com.example.imagescan;
Import java.util.List;
Import Android.content.Context;
Import Android.graphics.Bitmap;
Import Android.graphics.Point;
Import Android.view.LayoutInflater;
Import Android.view.View;
Import Android.view.ViewGroup;
Import Android.widget.BaseAdapter;
Import Android.widget.GridView;
Import Android.widget.ImageView;
Import Android.widget.TextView;
Import Com.example.imagescan.MyImageView.OnMeasureListener;
Import Com.example.imagescan.NativeImageLoader.NativeImageCallBack;
public class Groupadapter extends baseadapter{private list<imagebean> List;
Private point mpoint = new Point (0, 0);//to encapsulate ImageView and high object private GridView Mgridview;
protected Layoutinflater Minflater;
@Override public int GetCount () {return list.size ();
@Override public Object getitem (int position) {return list.get (position);
@Override public long getitemid (int position) {return position;
}
Public Groupadapter (Context context, list<imagebean> list, GridView mgridview) {this.list = list;
This.mgridview = Mgridview;
Minflater = Layoutinflater.from (context); @Override public view GetView (int position, View Convertview, ViewGroup parent) {Final Viewholder view
Holder;
Imagebean Mimagebean = list.get (position);
String path = Mimagebean.gettopimagepath ();
if (Convertview = = null) {Viewholder = new Viewholder ();
Convertview = minflater.inflate (R.layout.grid_group_item, NULL);
Viewholder.mimageview = (Myimageview) Convertview.findviewbyid (r.id.group_image);
Viewholder.mtextviewtitle = (TextView) Convertview.findviewbyid (r.id.group_title);
Viewholder.mtextviewcounts = (TextView) Convertview.findviewbyid (R.id.group_count); Used to monitor the width and height of the ImageView viewHolder.mImageView.setOnMeasureListener (new Onmeasurelistener () {@Overri De public void Onmeasuresize (int width, int height) {mpoint.set (width, height);
}
});
Convertview.settag (Viewholder);
}else{Viewholder = (viewholder) convertview.gettag ();
ViewHolder.mImageView.setImageResource (R.DRAWABLE.FRIENDS_SENDS_PICTURES_NO);
} viewHolder.mTextViewTitle.setText (Mimagebean.getfoldername ());
ViewHolder.mTextViewCounts.setText (Integer.tostring (Mimagebean.getimagecounts ()));
Set the path tag for ImageView, which is a small trick to load pictures asynchronously ViewHolder.mImageView.setTag (path); Load the local picture with the Nativeimageloader class Bitmap Bitmap = Nativeimageloader.getinstance (). Loadnativeimage (Path, mpoint, new Native Imagecallback () {@Override public void Onimageloader (Bitmap Bitmap, String path) {Imagevi
EW Mimageview = (imageview) mgridview.findviewwithtag (path);
if (bitmap!= null && mimageview!= null) {Mimageview.setimagebitmap (bitmap);
}
}
});
if (bitmap!= null) {ViewHolder.mImageView.setImageBitmap (bitmap);
}else{ViewHolder.mImageView.setImageResource (R.DRAWABLE.FRIENDS_SENDS_PICTURES_NO);
return convertview;
public static class viewholder{public Myimageview Mimageview;
Public TextView Mtextviewtitle;
Public TextView mtextviewcounts;
}
}
First we set the picture path of each item to the top of the ImageView, and then use Nativeimageloader to load the local picture, but the picture we show is wider and higher than the size of the Girdview item ImageView, So in order to save memory, we need to crop the picture, we need to crop the picture we use Loadnativeimage (final String path, final point Mpoint, final nativeimagecallback Mcallback) method, we have to get the width and height of the ImageView
But we want to get ImageView in the GetView () and the problem of the width and height, in the GetView () when the first display of the item in the use of imageview.getwidth () to get 0, why just start to get the width and height, Since we use Layoutinflater to Inflater () the XML layout file into view, view does not appear on the interface, indicating that the view is not onmeasure (), OnLayout (), OnDraw (), etc. You must wait until Retrue Convertview, indicating that the item's view has been drawn in the ListView position, then the item corresponding to the View Onmeasure (), OnLayout (), OnDraw () and other operations, At this time to get the width and height of the item, so I thought of the custom ImageView, in Onmeasure () using the callback mode to actively notify me imageview measurement width and height, but there is a small problem, is when the first item of the GridView is displayed, get the width and height or 0, the second can be normal access, the first width and height of 0, indicating that we do not cut the first picture, in the efficiency is no problem, do not know that there is no good method, can be in GetView () Gets the width and height of a control in the item.
Custom Myimageview Code, we only need to set Onmeasurelistener listening, when Myimageview measurement is completed, will be measured width and height of the correction to Onmeasuresize (), Then we can crop the picture based on the size of the Myimageview.
Package Com.example.imagescan;
Import Android.content.Context;
Import Android.util.AttributeSet;
Import Android.widget.ImageView;
public class Myimageview extends ImageView {private Onmeasurelistener onmeasurelistener;
public void Setonmeasurelistener (Onmeasurelistener onmeasurelistener) {this.onmeasurelistener = OnMeasureListener;
Public Myimageview (context, AttributeSet attrs) {Super (context, attrs);
Public Myimageview (context, AttributeSet attrs, int defstyle) {Super (context, attrs, Defstyle); @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (widthmeas
Urespec, Heightmeasurespec); Recalls the size of the picture measurement to the Onmeasuresize () method if (Onmeasurelistener!= null) {onmeasurelistener.onmeasuresize (Getmeasuredwidt
H (), Getmeasuredheight ());
} public interface onmeasurelistener{public void onmeasuresize (int width, int height); }
}
The above code completes the first interface function, next is to click the GridView item jump another interface to display all the pictures under the folder, the function is similar to the first interface, but also use the GridView to display the picture, the second interface layout code I will not post , and directly paste the interface code
package com.example.imagescan;
Import java.util.List;
Import android.app.Activity;
Import Android.os.Bundle;
Import Android.widget.GridView;
Import Android.widget.Toast;
public class Showimageactivity extends activity {private GridView Mgridview;
Private list<string> List;
Private Childadapter adapter;
@Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (r.layout.show_image_activity);
Mgridview = (GridView) Findviewbyid (R.id.child_grid);
List = Getintent (). Getstringarraylistextra ("Data");
adapter = new Childadapter (this, list, mgridview);
Mgridview.setadapter (adapter); @Override public void onbackpressed () {Toast.maketext (this, checked) + Adapter.getselectitems (). Size () + "it
Em ", Toast.length_long). Show ();
Super.onbackpressed (); }
}
The
GridView item above is a custom Myimageview to display the picture, and a checkbox to record our selection, adapter's code is as follows
Package Com.example.imagescan;
Import java.util.ArrayList;
Import Java.util.HashMap;
Import Java.util.Iterator;
Import java.util.List;
Import Java.util.Map;
Import Android.content.Context;
Import Android.graphics.Bitmap;
Import Android.graphics.Point;
Import Android.view.LayoutInflater;
Import Android.view.View;
Import Android.view.ViewGroup;
Import Android.widget.BaseAdapter;
Import Android.widget.CheckBox;
Import Android.widget.CompoundButton;
Import Android.widget.ImageView;
Import Android.widget.CompoundButton.OnCheckedChangeListener;
Import Android.widget.GridView;
Import Com.example.imagescan.MyImageView.OnMeasureListener;
Import Com.example.imagescan.NativeImageLoader.NativeImageCallBack;
Import Com.nineoldandroids.animation.AnimatorSet;
Import Com.nineoldandroids.animation.ObjectAnimator;
public class Childadapter extends Baseadapter {private point mpoint = new Point (0, 0);//to encapsulate ImageView width and Height objects/** * The selected case for storing Pictures/private HASHMAp<integer, boolean> mselectmap = new Hashmap<integer, boolean> ();
Private GridView Mgridview;
Private list<string> List;
protected Layoutinflater Minflater;
Public Childadapter (Context context, list<string> list, GridView mgridview) {this.list = list;
This.mgridview = Mgridview;
Minflater = Layoutinflater.from (context);
@Override public int GetCount () {return list.size ();
@Override public Object getitem (int position) {return list.get (position);
@Override public long getitemid (int position) {return position; @Override Public View getview (final int position, View Convertview, ViewGroup parent) {Final Viewholder
Viewholder;
String path = list.get (position);
if (Convertview = = null) {Convertview = minflater.inflate (R.layout.grid_child_item, NULL);
Viewholder = new Viewholder (); Viewholder.mimageview = (myimageview) convErtview.findviewbyid (R.id.child_image);
Viewholder.mcheckbox = (CheckBox) Convertview.findviewbyid (R.id.child_checkbox); Used to monitor the width and height of the ImageView viewHolder.mImageView.setOnMeasureListener (new Onmeasurelistener () {@Overri
De public void onmeasuresize (int width, int height) {mpoint.set (width, height);
}
});
Convertview.settag (Viewholder);
}else{Viewholder = (viewholder) convertview.gettag ();
ViewHolder.mImageView.setImageResource (R.DRAWABLE.FRIENDS_SENDS_PICTURES_NO);
} viewHolder.mImageView.setTag (path); ViewHolder.mCheckBox.setOnCheckedChangeListener (New Oncheckedchangelistener () {@Override public voi D oncheckedchanged (Compoundbutton Buttonview, Boolean ischecked) {//If the checkbox is unchecked, add an animation if (!mselectma P.containskey (position) | |
!mselectmap.get (position)) {addanimation (Viewholder.mcheckbox);
} Mselectmap.put (position, ischecked);
}
});
ViewHolder.mCheckBox.setChecked (Mselectmap.containskey (position)? Mselectmap.get (position): false); Load the local picture with the Nativeimageloader class Bitmap Bitmap = Nativeimageloader.getinstance (). Loadnativeimage (Path, mpoint, new Native Imagecallback () {@Override public void Onimageloader (Bitmap Bitmap, String path) {Imagevi
EW Mimageview = (imageview) mgridview.findviewwithtag (path);
if (bitmap!= null && mimageview!= null) {Mimageview.setimagebitmap (bitmap);
}
}
});
if (bitmap!= null) {ViewHolder.mImageView.setImageBitmap (bitmap);
}else{ViewHolder.mImageView.setImageResource (R.DRAWABLE.FRIENDS_SENDS_PICTURES_NO);
return convertview; /** * Add click Animation to checkbox, use open Source Library Nineoldandroids set Animation * @param view */private void addanimation (view view ) {float [] vaules = new FLoat[]{0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.25f, 1.2f, 1.15f, 1.1f, 1.0f};
Animatorset set = new Animatorset (); Set.playtogether (Objectanimator.offloat (View, "ScaleX", Vaules), objectanimator.offloat (view, "ScaleY", Vaules))
;
Set.setduration (150);
Set.start (); /** * Get the selected item position * @return * * public list<integer> Getselectitems () {LIST&L
t;integer> list = new arraylist<integer> (); For (Iterator<map.entry<integer, boolean>> it = Mselectmap.entryset (). iterator (); It.hasnext ();) {Map.En
Try<integer, boolean> entry = It.next ();
if (Entry.getvalue ()) {List.add (Entry.getkey ());
} return list;
public static class viewholder{public Myimageview Mimageview;
Public CheckBox Mcheckbox;
}
}
The second interface adapter with the first interface, nothing more than a checkbox to record the selection of pictures, we only need to set the checkbox Setoncheckedchangelistener monitoring, The checkbox has an animated effect after the selection of the micro-letter, so I use the Nineoldandroids animation library to add an animation effect to the checkbox, directly call the Addanimation () method can be added, Getselectitems () Method can get the position of our selected item, know the selected position, other information is known, micro-letter has a preview of the function of the picture, I do not add here, if there is this need to add, to recommend a https:// Github.com/chrisbanes/photoview
Run the project with the following effect
It looks good, the use of asynchronous reading pictures, the picture was cached and trimmed, so that in the display of local pictures more fluent, the GridView slide is quite smooth, but also effective to avoid the emergence of oom.