RecyclerView + ImageLoader create multi-choice Image Library, recyclerview multiple choice
In the previous blog "Universal-ImageLoader source code parsing", we analyzed ImageLoader from the perspective of source code. This blog begins to combine RecyclerView and ImageLoader to create an image system.
Requirement
In my project, there is a need to select multiple images, but the system's image library can only select one image, so we can only make a simple image by ourselves. You can use RecyclerView and ImageLoader to easily implement this function. Let's take a look at the effect.
Implementation of Activity
The implementation of activity is very simple. Let's take a look at the code first,
Public class GalleryActivity extends BaseActivity {private RecyclerView attributes; private GridLayoutManager mLayoutManager; private ArrayList <GalleryImage> mImages; // All images are private and mAdapter; @ Override protected void onCreate (Bundle attributes) {super. onCreate (savedInstanceState); setContentView (R. layout. gallery_layout); setupViews (); // get the image new OpusBiz (). getImages (new OnImagesListener () {@ Override public void onResult (ArrayList <GalleryImage> images) {if (images = null | images. isEmpty () return; mImages = images; setAdapter () ;}}) ;}@ Override protected void setupViews () {super. setupViews (); setNormalTitle (R. string. select_image_text); mTitleBar. setRightText (R. string. OK); mRecyclerView = (RecyclerView) findViewById (R. id. rv_gallery); mLayoutManager = new GridLayoutManager (this, 4, GridLayoutManager. HORIZONTAL, false); mRecyclerView. setLayoutManager (mLayoutManager); mRecyclerView. setItemAnimator (new DefaultItemAnimator ();} private void setAdapter () {mAdapter = new ImageGalleryAdapter (mRecyclerView, mImages); mRecyclerView. setAdapter (mAdapter) ;}@ Override protected void onRightClick () {ArrayList <GalleryImage> images = mAdapter. getSelected (); Intent intent = getIntent (); intent. putExtra (Constants. EXTRA_GALLERY_IMAGE, images); setResult (RESULT_ OK, intent); onLeftClick ();}}
First, let's take a look at setupViews, which finds the RecyclerView and setsGridLayoutManagerIn this way, our RecyclerView shows a grid layout. Isn't it easy! New OpusBiz (). getImages () obtains the image from the system database and calls back the image. The code here will be available later. Finally, we have a new ImageGalleryAdapter and set this Adapter to RecyclerView.
Next, let's take a look at how to obtain the image.
Image Acquisition
Public class OpusBiz {/*** get the image library image from the system database * @ param li */public void getImages (final OnImagesListener li) {final Handler handler = new Handler () {@ Override public void handleMessage (Message msg) {if (msg. what = Constants. MSG_SUCCESS) li. onResult (ArrayList <GalleryImage>) msg. obj) ;}}; new Thread (new Runnable () {@ Override public void run () {handler. obtainMessage (Constants. MSG_SUCCESS, getImages ()). sendToTarget ();}}). start ();}/*** obtain the image library image from the system database * @ return */private ArrayList <GalleryImage> getImages () {ArrayList <GalleryImage> images = new ArrayList <GalleryImage> (); GalleryImage image; final String [] columns = {MediaStore. images. media. DATA, MediaStore. images. media. _ ID}; final String orderBy = MediaStore. images. media. DATE_TAKEN; Cursor imagecursor = App. getInstance (). getContentResolver (). query (MediaStore. images. media. EXTERNAL_CONTENT_URI, columns, null, null, orderBy + "DESC"); for (int I = 0; I <imagecursor. getCount (); I ++) {imagecursor. moveToPosition (I); int dataColumnIndex = imagecursor. getColumnIndex (MediaStore. images. media. DATA); image = new GalleryImage (); image. setUri (imagecursor. getString (dataColumnIndex); images. add (image);} return images;}/*** get image library */public interface OnImagesListener {public void onResult (ArrayList <GalleryImage> images );}}
Here, a thread is enabled to query the database, obtain the image path, and then call back in an ArrayList.
Next, let's continue to see how the Adapter is written.
ImageGalleryAdapter
Public class ImageGalleryAdapter extends RecyclerView. adapter <ImageGalleryAdapter. imageViewHolder> {private RecyclerView overview; private ArrayList <GalleryImage> mImages; private ArrayList <GalleryImage> mSelected; public Preview (optional RecyclerView, ArrayList <GalleryImage> images) {response = recyclerView; mImages = images; mSelected = new ArrayList <GalleryImage> (Uplo AdOpusActivity. MAX_COUNT);} public ArrayList <GalleryImage> getSelected () {return mSelected;} @ Override public int getItemCount () {return mImages. size () ;}@ Override public void onBindViewHolder (final ImageViewHolder holder, int position) {final GalleryImage image = mImages. get (holder. getLayoutPosition (); String uri = image. getUri (); if (! Uri. startsWith ("file: //") uri = "file: //" + image. getUri (); ImageLoaderUtils. getInstance (). displayImage (uri, holder. image); holder. item. setOnClickListener (new OnClickListener () {@ Override public void onClick (View v) {boolean isChecked =! Image. isChecked (); // if the select status is if (isChecked) {// you need to determine the number of if (mSelected. size ()> = UploadOpusActivity. MAX_COUNT) return; // Add mSelected to the selected list. add (image);} else {// deselect mSelected. remove (image);} // purely for displaying holder. cb. setChecked (isChecked); image. setChecked (isChecked) ;}}); holder. cb. setChecked (image. isChecked ();} @ Override public ImageViewHolder onCreateViewHolder (ViewGroup parent, int position) {View view = LayoutInflater. from (parent. getContext ()). inflate (R. layout. gallery_item, parent, false); return new ImageViewHolder (view);} class ImageViewHolder extends RecyclerView. viewHolder {View item; ImageView image; CheckBox cb; public ImageViewHolder (View view) {super (view); item = view; image = (ImageView) view. findViewById (R. id. iv_gallery_item_image); cb = (CheckBox) view. findViewById (R. id. cb_gallery_item_check); int size = mRecyclerView. getMeasuredHeight ()/4; LayoutParams p = image. getLayoutParams (); p. width = size; p. height = size ;}}}
It is also a simple adapter for RecyclerView.onBindViewHolder
Code in,
ImageLoaderUtils. getInstance (). displayImage (uri, holder. image); holder. item. setOnClickListener (new OnClickListener () {@ Override public void onClick (View v) {boolean isChecked =! Image. isChecked (); // if the select status is if (isChecked) {// you need to determine the number of if (mSelected. size ()> = UploadOpusActivity. MAX_COUNT) return; // Add mSelected to the selected list. add (image);} else {// deselect mSelected. remove (image);} // purely for displaying holder. cb. setChecked (isChecked); image. setChecked (isChecked) ;}}); holder. cb. setChecked (image. isChecked ());
First, the image is loaded through ImageLoader, and then the Click Event of the entire item is monitored. If you want to select the image, we need to determine the maximum number of items selected, if it is greater than the maximum number of options we allow, the system returns the result directly. Otherwise, the selected image is placed in the selected category. If it is in the selected status, the system cancels the selection, directly remove from the selection list. Finally, we changed the CheckBox selection status.
Finally, the Code encapsulated by ImageLoader is attached,
Public class ImageLoaderUtils {private static ImageLoaderUtils sInstance; private DisplayImageOptions mOptions; public synchronized static attributes getInstance () {if (sInstance = null) sInstance = new ImageLoaderUtils (); return sInstance ;} private ImageLoaderUtils () {setDefault ();} private void setDefault () {mOptions = new DisplayImageOptions. builder (). showImageOnLoading (R. drawable. default_icon ). showImageForEmptyUri (R. drawable. default_icon ). showImageOnFail (R. drawable. default_icon ). cacheInMemory (true ). cacheOnDisk (true ). bitmapConfig (Config. RGB_565) // 2x graph. considerExifParams (true ). displayer (new SimpleBitmapDisplayer ()). build ();}/*** set the default icon * @ param res * @ return */public ImageLoaderUtils defaultIcon (int res) {mOptions = new DisplayImageOptions. builder (). showImageOnLoading (res ). showImageForEmptyUri (res ). showImageOnFail (res ). cacheInMemory (true ). cacheOnDisk (true ). bitmapConfig (Config. RGB_565) // 2x graph. considerExifParams (true ). displayer (new SimpleBitmapDisplayer ()). build (); return sInstance;}/*** get image * @ param url image url * @ param l callback */public void loadImage (final String url, final ImageLoaderListener l) {ImageLoader. getInstance (). loadImage (url, mOptions, l);}/*** show circular image * @ param uri * @ param imageView * @ param radius */public void displayRoundImage (String uri, imageView imageView, int radius) {DisplayImageOptions = new DisplayImageOptions. builder (). showImageOnLoading (R. drawable. default_icon ). showImageForEmptyUri (R. drawable. default_icon ). showImageOnFail (R. drawable. default_icon ). cacheInMemory (true ). cacheOnDisk (true ). considerExifParams (true ). bitmapConfig (Config. RGB_565) // 2x graph. displayer (new RoundedBitmapDisplayer (radius )). build (); displayImage (uri, imageView, options);} public void displayImage (String uri, ImageView imageView) {displayImage (uri, imageView, mOptions); // ImageLoader. getInstance (). displayImage (uri, imageView, mOptions); setDefault (); // Restore Default} private void displayImage (String uri, ImageView imageView, DisplayImageOptions options) {if (uri = null) return; ImageLoader. getInstance (). displayImage (uri, imageView, options);} public static abstract class ImageLoaderListener implements ImageLoadingListener {@ Override public void onLoadingStarted (String imageUri, View view) {}@ Override public void onLoadingFailed (String imageUri, View view, FailReason failReason) {}@ Override public void onLoadingCancelled (String imageUri, View view ){}}}
The overall code is very simple and implements a multi-choice image library function.
Copyright Disclaimer: This article is from the Loader's Blog and cannot be reproduced without the permission of the blogger.