Android Custom Picture Selector Simple Edition

  • 2021-08-21 21:27:12
  • OfStack

Picture selector is basically a necessary thing for every App, and it is also possible to use a recognized third party, but it is convenient to change it and use it conveniently. Moreover, it is difficult to think about it before it is done, but it is very simple to operate it in practice. This time, the main process is written first, and the details of specific optimization are written later.

Difficulties: The most confusing problem before starting work is how to get all the pictures in the mobile phone. After getting them, they are displayed and the processing logic is simple.

Step 1: Apply for permissions dynamically


private boolean permissionOpen() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
        PackageManager.PERMISSION_GRANTED) {// Dynamic application for read-write permission 
      ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
          101);
    } else {
      getImages();// If you have permission, go directly to get the mobile phone picture 
      return true;
    }
    return false;
  }

@Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    if (requestCode == 101) {
      if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        getImages();// After applying for permission successfully, get the mobile phone picture 
      } else {
        Toast.makeText(this, " Permission application failed ", Toast.LENGTH_LONG).show();
      }
      return;
    }
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  }

Step 2: Make a model for mobile phone pictures. My idea is to make a model for every folder where pictures are placed. To put it more popularly, there are three pictures under the A folder. There are two pictures under the c. jpg, d. jhpg, e. jpg, and I will make a model for such folders as A and B


public class PictureBean {// My idea is to use every 1 The folder for putting pictures is 1 Model 

  private String name;// The name of the folder will be used later. For specific purposes, you can first open the picture selector of WeChat, click the video and picture in the lower left corner, and pop up 1 A popupwindow , every 1 A item Have both 1 A name , he this name It should be the file name of the parent directory of the picture, and my this name That's what it means, but this blog should not be used for the time being 
  private int number;// The number of pictures in this folder 
  private String firstImageUrl;// The number under this folder 1 A picture 
  private List<String> imageList;// Collection of pictures under this folder 
  private String parentPath;// The absolute path to this folder 

  public String getParentPath() {
    return parentPath;
  }

  public void setParentPath(String parentPath) {
    this.parentPath = parentPath;
  }

  public String getName() {
    return name;
  }

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

  public int getNumber() {
    return number;
  }

  public void setNumber(int number) {
    this.number = number;
  }

  public String getFirstImageUrl() {
    return firstImageUrl;
  }

  public void setFirstImageUrl(String firstImageUrl) {
    this.firstImageUrl = firstImageUrl;
  }

  public List<String> getImageList() {
    return imageList;
  }

  public void setImageList(List<String> imageList) {
    this.imageList = imageList;
  }

}

Step 3: Declare variables such as list first, so as to avoid that 1 will look at the code and don't know how a variable comes from

private List < PictureBean > beanList; //Finally, we will put all the folder models here. If you ask where are the pictures? Of course it's in imageList of PictureBean

Step 4: Look at the getImages () method


private void getImages() {
    new Thread(new Runnable() {//查询图片什么的,肯定要开1个线程就不解释了
      @Override
      public void run() {
        Uri imageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;//这个Uri代表要查询的数据库名称加上表的名称
        ContentResolver contentResolver = context.getContentResolver();//这个用的少不知道该怎么表达,反正就是对外共享数据呗,提供手机里的各种数据(视频,图片,文件)

        Cursor cursor = contentResolver.query(imageUri, null, MediaStore.Images.Media.MIME_TYPE//这个就是查询操作了吧(cursor,游标,听起来很熟悉,老师绝对讲过,不过原谅我数据库这1块渣到爆炸)
            + "=? or " + MediaStore.Images.Media.MIME_TYPE + "=?", new String[]{"image/jpeg"}, MediaStore.Images.Media.DATE_MODIFIED);

        if (cursor == null) {
          return;
        }

        List<String> pathList = new ArrayList<>();//同1个文件夹下的图片的集合
        String mParentPath = "";//所在文件夹的绝对路径
        while (cursor.moveToNext()) {
          String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));//图片的绝对路径
          File file = new File(path).getParentFile();
          String parentPath = file.getAbsolutePath();//文件夹的绝对路径

          if (cursor.isFirst()) {//如果是第1个图片
            pathList.add(path);//直接加到图片集合里
            mParentPath = parentPath;//文件夹的绝对路径 等于 我们获取到的这张图片的 文件夹的绝对路径
          } else if (mParentPath.equals(parentPath)) {//如果 新的图片的文件夹的绝对路径 跟上1张图片的文件夹的绝对路径相同, 说明两张图片在同1个文件夹下
            pathList.add(path);//继续填到集合里
          } else {//说明 新的图片跟 上1张图片不在同1个文件夹 下
            List<String> list = new ArrayList<>(); 
            list.addAll(pathList); //用1个新的list 加载 之前1个文件夹下的所有图片(这里暂时想不到更好的办法了)
            pathList.clear(); 
            pathList.add(path); //旧的list 清空之后呢, 开始加载 新的文件夹下的 第1张图片(仔细看1看就知道逻辑了,代码写的确实比较烂,哈哈哈)
            PictureBean bean = new PictureBean();//我们之前写好的模型
            bean.setNumber(list.size()); //数量就是list的数量
            bean.setFirstImageUrl(list.get(0)); //第1张图片
            bean.setImageList(list);//图片集合
            bean.setParentPath(mParentPath);//所在文件夹的绝对路径
            beanList.add(bean);//把模型放到步骤3定义好的list
            mParentPath = parentPath; //文件夹绝对路径 变成了 新的文件夹路径
          }
        }
         //到此为止,喜大普奔,所有的图片都已经获取到了,接下来直接显示出来(想做复杂的呢可以参考微信,我正在参考中...)
        handler.sendEmptyMessage(1);
      }
    }).start();
  }

Step 5: Because we are a simple version this time, since we have all the picture data, we will simply show it 1.


Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      final List<String> list = new ArrayList<>();
         // Because it is a simple version, I will save all the pictures directly to 1 A list Used to show the 
      for (PictureBean pictureBean : beanList) {
        for (String s : pictureBean.getImageList()) {
          list.add(s);
        }
      }
      adapter.setList(list);
      adapter.notifyDataSetChanged();
      adapter.setmOnClick(new ItemAdapter.onClick() {
        @Override
        public void itemOnClick(int position) {// Click event is to return the absolute path of the clicked picture 
          Intent intent = new Intent();
          intent.putExtra("image", list.get(position));
          setResult(RESULT_OK, intent);
          finish();
        }
      });
    }
  };

At this point, even if the difficulties mentioned at the beginning are settled, the adapter code is very simple and will not be posted, and the most important step is Step 4.


Related articles: