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) {        }    }}

整体代码非常简单,实现了一个可多选图片的图库功能。

1 0
原创粉丝点击