RecyclerView+ImageLoader打造多选图库
来源:互联网 发布:台湾淘宝跟大陆一样吗 编辑:程序博客网 时间:2024/06/05 09:01
在上一篇博客《Universal-ImageLoader源码解析》中,我们从源码的角度分析了ImageLoader,这篇博客我们就开始结合RecyclerView和ImageLoader打造一个图片系统。
需求
在我的项目中有一个多图选择的需求,但是系统的图库只能选择一张图片,所以我们只能自己来做一个简单的图片。利用RecyclerView和ImageLoader可以很轻松的实现这个功能,下面我们先来看看效果吧。
Activity的实现
activity的实现很简单,我们先来看看代码,
public class GalleryActivity extends BaseActivity { private RecyclerView mRecyclerView; private GridLayoutManager mLayoutManager; private ArrayList<GalleryImage> mImages; // 所有图片 private ImageGalleryAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.gallery_layout); setupViews(); // 获取图片 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(); }}
首先我们看看setupViews,这里面find了RecyclerView,并且给他设置了一个GridLayoutManager,这样我们的RecyclerView显示出来就是一个网格的布局了,是不是很简单!new OpusBiz().getImages()是从通过系统数据库获取图片并回调,这里面的代码我们稍后再看,最后我们new了一个ImageGalleryAdapter,并且将这个Adapter设置给了RecyclerView。
接下来我们看看怎么获取的图片吧。
图片的获取
public class OpusBiz { /** * 从系统数据库中获取图库图片 * @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(); } /** * 从系统数据库中获取图库图片 * @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; } /** * 获取图库图片 */ public interface OnImagesListener { public void onResult(ArrayList<GalleryImage> images); }}
这里面开启了一个线程去查询系统数据库,获取图片的路径,然后然后一个ArrayList中,最后回调。
接下来我们继续看看Adapter怎么写的
ImageGalleryAdapter
public class ImageGalleryAdapter extends RecyclerView.Adapter<ImageGalleryAdapter.ImageViewHolder> { private RecyclerView mRecyclerView; private ArrayList<GalleryImage> mImages; private ArrayList<GalleryImage> mSelected; public ImageGalleryAdapter(RecyclerView recyclerView, ArrayList<GalleryImage> images) { mRecyclerView = recyclerView; mImages = images; mSelected = new ArrayList<GalleryImage>(UploadOpusActivity.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(isChecked) { // 则需要判断当前选择了几个 if(mSelected.size() >= UploadOpusActivity.MAX_COUNT) return; // 添加到选择的列表中 mSelected.add(image); }else { // 取消选择 mSelected.remove(image); } // 纯粹为了显示 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; } }}
也是一个简单的RecyclerView的adapter,主要看onBindViewHolder
里的代码,
ImageLoaderUtils.getInstance().displayImage(uri, holder.image);holder.item.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { boolean isChecked = !image.isChecked(); // 如果是选择状态 if(isChecked) { // 则需要判断当前选择了几个 if(mSelected.size() >= UploadOpusActivity.MAX_COUNT) return; // 添加到选择的列表中 mSelected.add(image); }else { // 取消选择 mSelected.remove(image); } // 纯粹为了显示 holder.cb.setChecked(isChecked); image.setChecked(isChecked); }});holder.cb.setChecked(image.isChecked());
首先通过ImageLoader加载了图片,然后监听了整个item的点击事件,如果是将要去选择,我们需要判断选择的最大数,如果大于我们允许的最大选择数则直接返回,否则,将选择的图片放到选择类别中,如果当前是选择状态,则就是要去取消选择,直接从选择列表中移除。最后,我们改变了CheckBox的选择状态。
最后的最后,附上对ImageLoader封装的代码,
public class ImageLoaderUtils { private static ImageLoaderUtils sInstance; private DisplayImageOptions mOptions; public synchronized static ImageLoaderUtils 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) // 2倍图 .considerExifParams(true) .displayer(new SimpleBitmapDisplayer()).build(); } /** * 设置默认的图标 * @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) // 2倍图 .considerExifParams(true) .displayer(new SimpleBitmapDisplayer()).build(); return sInstance; } /** * 获取图片 * @param url 图片url * @param l 回调 */ public void loadImage(final String url, final ImageLoaderListener l) { ImageLoader.getInstance().loadImage(url, mOptions, l); } /** * 显示圆形图片 * @param uri * @param imageView * @param radius 半径 */ public void displayRoundImage(String uri, ImageView imageView, int radius) { DisplayImageOptions options = 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) // 2倍图 .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(); // 恢复默认 } 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) { } }}
整体代码非常简单,实现了一个可多选图片的图库功能。
- RecyclerView+ImageLoader打造多选图库
- Recyclerview+okhttp+拦截器+ImageLoader
- Android 纯手工打造ImageLoader
- 为RecyclerView打造适配器
- RecyclerView:打造悬浮效果
- 打造RecyclerView的通用适配器
- 为RecyclerView打造万能适配器
- 打造 RecyclerView的 通用Adapter
- 为RecyclerView打造通用adapter
- 打造RecyclerView的万能适配器
- Android打造万能适配器--RecyclerView
- 为RecyclerView打造通用Adapter
- 为RecyclerView打造通用Adapter
- Diffutils打造不一样的recyclerview
- 【Android】RecyclerView:打造悬浮效果
- RecyclerView打造一个密码面板
- 用RecyclerView打造轮播图控件
- Databinding打造RecyclerView万能适配器
- 摄像头倒置怎么办?
- 英文论文中“such as, for example, e.g., i.e., etc., et al. ”的用法分析
- Android 可拖动进度条:SeekBar之自定义进度条
- 根文件系统的挂载过程 http://blog.sina.com.cn/s/blog_67e2ef6a0100s8kf.html
- tools:context=".MainActivity的作用
- RecyclerView+ImageLoader打造多选图库
- Fresco 源码分析(三) Fresco服务端处理(4) Producer处理体系的总结
- C++ 虚函数表解析
- Eclilpse导入maven项目,无法自动构建为java项目的问题
- C#中DllImport用法汇总
- addChildViewController等方法
- 打开MyEclipse10是时候提示:Could not create the view: An unexpected exception was thrown.
- ABAP ALV里日期类型的F4帮助
- 【哥德巴赫猜想】LightOJ Goldbach`s Conjecture 1259