Android中仿微信选择图片并展示在RecyclerView中

 Android图片选择

大家都知道网上有很多第三方的图片选择器,但是到了自己真正的项目中,可能会有不同的需求,需要自己去修改。因此我自己根据鸿洋大神的慕课网视频写了一个图片选择器,又对代码进行了修改,方便大家进行使用。

本项目主要设计思路就是:一个图片加载类(单例)+利用ContentProvider扫描手机的图片+GridView显示图片 +RecyclerView在界面上显示图片。

本项目的主要步骤有以下几步:

1.图片加载类

2.扫描手机中的图片

3.选择图片展示在recyclerview中

当然最重要的是:

1.尽可能的去避免内存溢出
2.用户操作UI控件必须充分的流畅
3.用户预期显示的图片尽可能的快(图片的加载策略的选择)LIFO

本项目的主要功能:

1.扫描手机中的图片,默认显示图片最多的文件夹,在底部显示文件夹的名字以及图片的数量。

2.点击底部,弹出popupWindow,此popupWindow显示所有包含图片的文件夹以及文件夹的名字。

3.选择文件夹,进入图片选择界面,点击选择图片,再次点击取消。

4.点击右上方的“选择”按钮,将选择的图片呈现在recyclerView中。

展示一下效果:


代码展示及讲解

1.图片加载类 ImageLoader(核心类)

本类是图片选择器的核心类,该类为单例,可以设置图片加载打方式:
1.FIFO(先进先加载)
2.LILO(后进先加载)。 
调用该方法:ImageLoader.getInstance(最大图片加载并发数,ImageLoader.Type.FIFO(图片加载的方式)) 

.LoadImage(图片的本地存放路径(绝对路径), 要显示图片的ImageView布局);

public class ImageLoader {
    private static ImageLoader mInStance;

    //图片缓存的核心对象
    private LruCache<String,Bitmap> mLruCache;

    //线程池
    private ExecutorService mThreadPool;
    private  static  final  int DEAFULT_THREAD_COUNT=1;
    //队列的调度方式
    private  Type mType=Type.LIFO;
    //任务队列
    private LinkedList<Runnable> mTaskQueue;
    //后台轮询线程
    private  Thread mPoolThread;
    private Handler mPoolThreadHandler;
    //UI线程中的Handler
    private Handler mUIHandler;
    private Semaphore  mSemaphorePoolThreadHandler=new Semaphore(0);
    private Semaphore  mSemaphoreThreadPool;
    public  enum  Type{
        FIFO,LIFO;
    }

    public ImageLoader(int threadCount,Type type) {
          init(threadCount,type);
    }

    /**
     * 初始化
     * @param threadCount
     * @param type
     */
    private void init(int threadCount, Type type) {
        //后台轮询线程
        mPoolThread=new Thread(){
            @Override
            public void run() {
                Looper.prepare();
                mPoolThreadHandler=new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        //线程池取出一个任务进行执行
                        mThreadPool.execute(getTask());
                        try {
                            mSemaphoreThreadPool.acquire();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                };
                //释放一个信号量
                mSemaphorePoolThreadHandler.release();
                Looper.loop();
            }
        };
        mPoolThread.start();
        //获取我们应用的最大可用内存
        int maxMemory= (int) Runtime.getRuntime().maxMemory();
        int cacheMemory = maxMemory / 8;
        mLruCache=new LruCache<String,Bitmap>(cacheMemory){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes()*value.getHeight();
            }
        };
            mThreadPool= Executors.newFixedThreadPool(threadCount);
            mTaskQueue=new LinkedList<>();
            mType=type==null?Type.LIFO:type;
            mSemaphoreThreadPool=new Semaphore(threadCount);

    }

    /**
     * 从任务队列取出一个方法
     * @return
     */
    private Runnable getTask() {
        if (mType==Type.FIFO){
            return mTaskQueue.removeFirst();
        }else if (mType==Type.LIFO){
            return mTaskQueue.removeLast();
        }
        return  null;
    }

    public  static  ImageLoader getInStance(){
        if (mInStance==null){
            synchronized (ImageLoader.class){
                if (mInStance==null){
                    mInStance=new ImageLoader(DEAFULT_THREAD_COUNT,Type.LIFO);
                }
            }
        }
        return  mInStance;
    }
    public  static  ImageLoader getInStance(int threadCount,Type type){
        if (mInStance==null){
            synchronized (ImageLoader.class){
                if (mInStance==null){
                    mInStance=new ImageLoader(threadCount,type);
                }
            }
        }
        return  mInStance;
    }

    /**
     * 根据path为imageview设置图片
     * @param path
     * @param imageView
     */
    public  void loadImage(final String path, final ImageView imageView){
        imageView.setTag(path);
        if (mUIHandler==null){
            mUIHandler=new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    //获取得到的图片,为imageview回调设置图片
                    ImgBeanHolder holder= (ImgBeanHolder) msg.obj;
                    Bitmap bitmap = holder.bitmap;
                    ImageView imageview= holder.imageView;
                    String path = holder.path;
                    if (imageview.getTag().toString().equals( path)){
                        imageview.setImageBitmap(bitmap);
                    }
                }
            };
        }
        //根据path在缓存中获取bitmap
        Bitmap bm=getBitmapFromLruCache(path);
        if (bm!=null){
            refreshBitmap(bm, path, imageView);
        }else{
            addTask(new Runnable(){
                @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
                @Override
                public void run() {
                    //加载图片
                    //图片的压缩
                    //1.获得图片需要显示的大小
                  ImageSize imageSize=  getImageViewSize(imageView);
                    //压缩图片
                    Bitmap bm=decodeSampledBitmapFromPath(imageSize.width,imageSize.height,path);
                    //把图片加入到缓存
                    addBitmapToLruCache(path,bm);
                    //
                    refreshBitmap(bm, path, imageView);
                    mSemaphoreThreadPool.release();
                }
            });
        }

    }

    private void refreshBitmap(Bitmap bm, String path, ImageView imageView) {
        Message message = Message.obtain();
        ImgBeanHolder holder=new ImgBeanHolder();
        holder.bitmap=bm;
        holder.path=path;
        holder.imageView=imageView;
        message.obj=holder;
        mUIHandler.sendMessage(message);
    }

    /**
     * 将图片加入到LruCache
     * @param path
     * @param bm
     */
    private void addBitmapToLruCache(String path, Bitmap bm) {
        if (getBitmapFromLruCache(path)==null){
            if (bm!=null){
                mLruCache.put(path,bm);
            }
        }
    }

    /**
     * 根据图片需要显示的宽和高进行压缩
     * @param width
     * @param height
     * @param path
     * @return
     */
    private Bitmap decodeSampledBitmapFromPath(int width, int height, String path) {
       //获得图片的宽和高,并不把图片加载到内存中
        BitmapFactory.Options options=new BitmapFactory.Options();
        options.inJustDecodeBounds=true;
        BitmapFactory.decodeFile(path,options);

        options.inSampleSize=caculateInSampleSize(options,width,height);

        //使用获得到的InSampleSize再次解析图片
        options.inJustDecodeBounds=false;
        Bitmap bitmap=BitmapFactory.decodeFile(path,options);
        return  bitmap;

    }

    /**
     * 根据需求的宽和高以及图片实际的宽和高计算SampleSize
     * @param options
     * @param width
     * @param height
     * @return
     */
    private int caculateInSampleSize(BitmapFactory.Options options, int width, int height) {
        int outWidth = options.outWidth;
        int outHeight = options.outHeight;
        int inSampleSize=1;
        if (outWidth>width||outHeight>height){
            int widthRadio=Math.round(outWidth*1.0f/width);
            int heightRadio=Math.round(outHeight*1.0f/height);
            inSampleSize=Math.max(widthRadio,heightRadio);
        }

        return inSampleSize;
    }

    /**
     *根据ImageView获得适当的压缩的宽和高
     * @param imageView
     */
    private ImageSize getImageViewSize(ImageView imageView) {
        ImageSize imageSize=new ImageSize();

        DisplayMetrics displayMetrics = imageView.getContext().getResources().getDisplayMetrics();
        ViewGroup.LayoutParams lp = imageView.getLayoutParams();
     //  int width=(lp.width== ViewGroup.LayoutParams.WRAP_CONTENT?0:imageView.getWidth());
       int width = imageView.getWidth();//获取imageview的实际宽度
        if (width <=0){
            width=lp.width;//获取imageview再layout声明的宽度
        }
        if (width<=0){
            width= getImageViewFieldValue(imageView,"mMaxWidth");//检查最大值
        }
        if (width<=0){
            width=displayMetrics.widthPixels;
        }
        //int height = lp.height == ViewGroup.LayoutParams.WRAP_CONTENT ? 0 : imageView.getHeight();
        int height = imageView.getHeight();//获取imageview的实际高度

        if (height <=0){
            height=lp.height;//获取imageview再layout声明的高度
        }
        if (height<=0){
            height=getImageViewFieldValue(imageView,"mMaxHeight");;//检查最大值
        }
        if (height<=0){
            height=displayMetrics.heightPixels;
        }
        imageSize.width=width;
        imageSize.height=height;
        return imageSize;
    }

    /**
     * 通过反射获得imageView的某个属性值
     * @return
     */
    private  static  int getImageViewFieldValue(Object object,String fieldName){
        int value=0;

        try {
            Field field=ImageView.class.getDeclaredField(fieldName);
            field.setAccessible(true);
            int fieldValue = field.getInt(object);
            if (fieldValue>0&&fieldValue<Integer.MAX_VALUE){
                value=fieldValue;
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return  value;
    }
    private  synchronized void addTask(Runnable runnable)  {
        mTaskQueue.add(runnable);
        try {
            if (mPoolThreadHandler==null){
                mSemaphorePoolThreadHandler.acquire();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        mPoolThreadHandler.sendEmptyMessage(0x110);
    }

    /**
     * 根据path为imageview设置图片
     * @param key
     * @return
     */
    private Bitmap getBitmapFromLruCache(String key) {
         return mLruCache.get(key);
    }
   private  class  ImageSize{
       int width;
       int height;
   }
    private class ImgBeanHolder{
        Bitmap bitmap;
        ImageView imageView;
        String path;
    }
}

2.图片的列表

首先扫描手机上的所有图片信息,拿到图片数量最多的文件夹,直接显示在GridView上;并且扫描结束,得到一个所有包含图片的文件夹信息的List;

对于文件夹信息,我们单独创建了一个Bean: 

public class FolderBean {
    private String dir;//当前文件夹路径
    private String firstImamgPath;//第一张图片的路径
    private String name;//文件夹的名字
    private int count; //图片数量

    public String getDir() {
        return dir;
    }

    public void setDir(String dir) {
        this.dir = dir;
        int indexOf = this.dir.lastIndexOf("/")+1;
        this.name=this.dir.substring(indexOf);
    }

    public String getFirstImamgPath() {
        return firstImamgPath;
    }

    public void setFirstImamgPath(String firstImamgPath) {
        this.firstImamgPath = firstImamgPath;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

其次是扫描手机中的图片:

注意:在6.0系统以上,要手动开启读取内存卡的权限,否则程序是运行不起来的。

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
    if (ContextCompat.checkSelfPermission(SelectPhotoActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(SelectPhotoActivity.this, new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
    }else{
        aboutScanPhoto();//未开启权限,先开启权限。以开启权限后,直接扫描图片
    }
}else{
    aboutScanPhoto();//扫描图片的方法
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode){
        case 1:
            if(grantResults.length>0 &&grantResults[0] == PackageManager.PERMISSION_GRANTED){
                aboutScanPhoto();
            }else {
                Toast.makeText(this, "请打开权限!", Toast.LENGTH_SHORT).show();
            }
            break;
        default:
    }
}

扫描图片的方法

if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
    Toast.makeText(this,"当前存储卡不可用!",Toast.LENGTH_LONG);
    return;
}
mProgressDialog= ProgressDialog.show(this,null,"正在加载。。。");
new Thread(){
    @Override
    public void run() {
        Uri mImgUri= MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        ContentResolver cr=SelectPhotoActivity.this.getContentResolver();
        Cursor mCursor = cr.query(mImgUri, null,
                MediaStore.Images.Media.MIME_TYPE + "=? or "
                        + MediaStore.Images.Media.MIME_TYPE + "=?",
                new String[] { "image/jpeg", "image/png" },
                MediaStore.Images.Media.DATE_MODIFIED);
        Set<String> mDirPaths=new HashSet<String>();
        while (mCursor.moveToNext()){
            String path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DATA));
            File parentFile=new File(path).getParentFile();
            if (parentFile==null) {
                continue;
            }
            String dirPath = parentFile.getAbsolutePath();
            FolderBean folderBean=null;
            if (mDirPaths.contains(dirPath)){
                continue;
            }else{
                mDirPaths.add(dirPath);
                folderBean=new FolderBean();
                folderBean.setDir(dirPath);
                folderBean.setFirstImamgPath(path);
            }

            if (parentFile.list()==null){
                continue;
            }
            int picSize=parentFile.list(new FilenameFilter() {
                @Override
                public boolean accept(File dir, String name) {
                    if (name.endsWith(".jpg")||name.endsWith("jpeg")||name.endsWith("png")){
                        return  true;
                    }
                    return false;
                }
            }).length;
            folderBean.setCount(picSize);
            mFolderBeans.add(folderBean);

            if (picSize>mMaxCount){
                mMaxCount=picSize;
                mCurrentDir=parentFile;
            }
        }
        mCursor.close();
        handler.sendEmptyMessage(0x110);

    }
}.start();

然后我们通过handler发送消息,在handleMessage里面:

1、创建GridView的适配器,为我们的GridView设置适配器,显示图片;

2、创建我们的popupWindow了

private Handler handler=new Handler(){
    @Override
    public void handleMessage(Message msg) {
        if (msg.what==0x110){
            mProgressDialog.dismiss();
            dataToView();
            initPopupWindow();
        }
    }
};

dataToView()就是我们为view设置数据

private void dataToView() {
    if (mCurrentDir==null){
        Toast.makeText(this,"未扫描到任何图片",Toast.LENGTH_LONG).show();
        return;
    }
    mImgs= Arrays.asList(mCurrentDir.list());
    adapter = new ImageAdapter(this,mImgs,mCurrentDir.getAbsolutePath());
    mGridView.setAdapter(adapter);
    mTvDirName.setText(mCurrentDir.getName());
    mTvDirCount.setText(mMaxCount+"");
}

我们还用到了一个GridView的adapter

public  class ImageAdapter extends BaseAdapter {
    private  String mDirPath;
    private List<String> mImgPaths;
    private LayoutInflater mInflater;
    private static List<String> mSelectImg=new LinkedList<>();
    public ImageAdapter(Context context, List<String> mDatas, String dirPath) {
        this.mDirPath=dirPath;
        this.mImgPaths=mDatas;
        mInflater=LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return mImgPaths.size();
    }

    @Override
    public Object getItem(int position) {
        return mImgPaths.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder vh=null;
        if (convertView==null){
            convertView=  mInflater.inflate(R.layout.item,parent,false);
            vh=new ViewHolder();
            vh.mImg=convertView.findViewById(R.id.iv_item);
            vh.mSelect=convertView.findViewById(R.id.ib_select);
            convertView.setTag(vh);
        }else {
            vh = (ViewHolder) convertView.getTag();
        }
        vh.mImg.setImageResource(R.mipmap.default_error);
        vh.mSelect.setImageResource(R.mipmap.btn_unselected);
        vh.mImg.setColorFilter(null);
        final String filePath=mDirPath+"/"+mImgPaths.get(position);
        //   new  ImageLoader(3, ImageLoader.Type.LIFO).loadImage(mDirPath + "/" + mImgPaths.get(position),vh.mImg);
        ImageLoader.getInStance(3, ImageLoader.Type.LIFO).loadImage(mDirPath+"/"+mImgPaths.get(position),vh.mImg);
        final ViewHolder finalVh = vh;
        vh.mImg.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //已经被选择
                if (mSelectImg.contains(filePath)){
                    mSelectImg.remove(filePath);
                    finalVh.mImg.setColorFilter(null);
                    finalVh.mSelect.setImageResource(R.mipmap.btn_unselected);
                }else{
                    //未被选中
                    mSelectImg.add(filePath);
                    finalVh.mImg.setColorFilter(Color.parseColor("#77000000"));
                    finalVh.mSelect.setImageResource(R.mipmap.btn_selected);
                }

            }
        });
        if (mSelectImg.contains(filePath)){
            vh.mImg.setColorFilter(Color.parseColor("#77000000"));
            vh.mSelect.setImageResource(R.mipmap.btn_selected);
        }
        return convertView;
    }



    public List<String> selectPhoto(){
        if (!mSelectImg.isEmpty()){
            return mSelectImg;
        }
        return null;
    }
    private  class  ViewHolder{
        ImageView mImg;
        ImageButton mSelect;
    }
}
3.到这一步图片就已经显示在GridView中,下一步就是我们的popupWindow

要实现的效果是:点击底部的布局弹出我们的文件夹选择框,并且我们弹出框后面的Activity要变暗;

首先我们创建了一个popupWindow使用的类,和Activity类似:

public class ListImageDirPopupWindow extends PopupWindow {
    private  int mWidth;
    private int mHeight;
    private View mConvertView;
    private List<FolderBean> mDatas;
    private ListView mListView;

    public  interface  OnDirSelectedListener{
        void onSelected(FolderBean folderBean);
    }
    public  OnDirSelectedListener mListener;

    public void setOnDirSelectedListener(OnDirSelectedListener mListener) {
        this.mListener = mListener;
    }

    public ListImageDirPopupWindow(Context context, List<FolderBean> datas) {
       calWidthAndHeight(context);
        mConvertView= LayoutInflater.from(context).inflate(R.layout.popup_main,null);
        mDatas=datas;
        setContentView(mConvertView);
        setWidth(mWidth);
        setHeight(mHeight);
        setFocusable(true);
        setTouchable(true);
        setOutsideTouchable(true);
        setBackgroundDrawable(new BitmapDrawable());

        setTouchInterceptor(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                if (event.getAction()==MotionEvent.ACTION_OUTSIDE){
                    dismiss();
                    return true;
                }
                return false;
            }
        });
        initViews(context);
        initEvent();
    }

    private void initViews(Context context) {
        mListView=  mConvertView.findViewById(R.id.lv_dir);
        mListView.setAdapter(new ListDirAdapter(context,mDatas));
    }

    private void initEvent() {
       mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
           @Override
           public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
               if (mListener!=null){
                   mListener.onSelected(mDatas.get(position));
               }
           }
       });
    }

    /**
     * 计算popupWindow的宽度和高度
     * @param context
     */
    private void calWidthAndHeight(Context context) {

        WindowManager wm= (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics=new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        mWidth= outMetrics.widthPixels;
        mHeight= (int) (outMetrics.heightPixels*0.7);

    }
    private class  ListDirAdapter extends ArrayAdapter<FolderBean>{

        private  LayoutInflater mInflater;
        private  List<FolderBean> mDatas;

        public ListDirAdapter(@NonNull Context context, List<FolderBean> datas) {
            super(context, 0, datas);
            mInflater= LayoutInflater.from(context);
        }

        @NonNull
        @Override
        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
            ViewHolder vh=null;
            if (convertView==null){
                vh=new ViewHolder();
                convertView=  mInflater.inflate(R.layout.popup_item,parent,false);
                vh.mDirName=(TextView) convertView.findViewById(R.id.tv_dir_item_name);
                vh.mDirCount=(TextView) convertView.findViewById(R.id.tv_dir_item_count);
                vh.mImg= (ImageView) convertView.findViewById(R.id.iv_dir_image);
                convertView.setTag(vh);
            }else{
                vh= (ViewHolder) convertView.getTag();
            }
            FolderBean bean = getItem(position);
            //重置
            vh.mImg.setImageResource(R.mipmap.default_error);

            ImageLoader.getInStance(3, ImageLoader.Type.LIFO).loadImage(bean.getFirstImamgPath(),vh.mImg);
            vh.mDirName.setText(bean.getName());
            vh.mDirCount.setText(bean.getCount()+"");
            return convertView;
        }

        private  class  ViewHolder{
            ImageView mImg;
            TextView mDirName;
            TextView mDirCount;
        }
    }
}
然后我们需要和Activity交互,当我们点击某个文件夹的时候,外层的Activity需要改变它GridView的数据源,展示我们点击文件夹的图片。在这里我们创建一个接口OnDirSelectedListener ,对Activity设置回调

mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        if (mListener!=null){
            mListener.onSelected(mDatas.get(position));
        }
    }
});

4.选择不同的文件夹

前面我们handleMessage中初始化调用popupWindow,通过activity的回调,实现选择文件夹显示图片

mImageDirPopupWindow=new ListImageDirPopupWindow(this,mFolderBeans);
mImageDirPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
    @Override
    public void onDismiss() {
        lightOn();
    }
});
mImageDirPopupWindow.setOnDirSelectedListener(new ListImageDirPopupWindow.OnDirSelectedListener() {
    @Override
    public void onSelected(FolderBean folderBean) {
        mCurrentDir=new File(folderBean.getDir());
       mImgs= Arrays.asList(mCurrentDir.list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                if (name.endsWith(".jpg")||name.endsWith("jpeg")||name.endsWith("png")){
                    return  true;
                }
                return false;
            }
        }));
        adapter=new ImageAdapter(SelectPhotoActivity.this,mImgs,mCurrentDir.getAbsolutePath());
        mGridView.setAdapter(adapter);
        mTvDirCount.setText(mImgs.size()+"");
        mTvDirName.setText(folderBean.getName());
        mImageDirPopupWindow.dismiss();
    }
});

5.图片展示在RecyclerView中

在ImageAdapter中定义了一个方法,获得选择图片的路径,点击“选择”按钮的时候,把这个路径的集合传过去

public List<String> selectPhoto(){
    if (!mSelectImg.isEmpty()){
        return mSelectImg;
    }
    return null;
}

然后通过ImageLoader这个类将图片展示出来,我们在recyclerview设置图片展示方式为网格方式。

ImageLoader.getInStance(3, ImageLoader.Type.LIFO).loadImage(mDatas.get(position),holder.iv);

if (photoSelect!=null) {
    final SimpleAdapter mAdapter = new SimpleAdapter(this, photoSelect);
    mListView.setAdapter(mAdapter);
    mListView.setLayoutManager(new GridLayoutManager(this,3));
}

其中涉及到了一个adapter,是recyclerview所需要的

public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.MyViewHolder> {

    private LayoutInflater mInflater;
    private Context mContext;
    protected List<String> mDatas;

    public SimpleAdapter(Context mContext, List<String> mDatas) {
        this.mContext = mContext;
        this.mDatas = mDatas;
        mInflater=LayoutInflater.from(mContext);
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = mInflater.inflate(R.layout.list_item, parent, false);
        MyViewHolder viewHolder=new MyViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {
        ImageLoader.getInStance(3, ImageLoader.Type.LIFO).loadImage(mDatas.get(position),holder.iv);
    }

    @Override
    public int getItemCount() {
        return mDatas.size();
    }

    class  MyViewHolder extends RecyclerView.ViewHolder {
        ImageView iv;
        public MyViewHolder(View itemView) {
            super(itemView);
            iv=  itemView.findViewById(R.id.iv_photo);
        }
    }
}

如果大家想学习RecyclerView的使用,可以看一下我的博客

https://blog.csdn.net/wen_haha/article/details/80775056

总结:本项目的主要代码基本已经贴出来了,感兴趣的朋友可以去下载本人的项目,最后,如有不对的地方,请多多指教.

Demo

CSDN地址:

https://download.csdn.net/download/wen_haha/10499827

Github地址:

https://github.com/kongkongdaren/SelectPhotoDemo

猜你喜欢

转载自blog.csdn.net/wen_haha/article/details/80813202