欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android实现简单图库辅助器

程序员文章站 2023-01-21 10:47:16
写在前面 实际开发经常会遇到读取相册或者拍照功能,网上也很非常多图库框架,都各有风格,也因此与自己的项目格格不入。再者,框架api太多,需要的配置太多,还要吃力研究。所以...

写在前面

实际开发经常会遇到读取相册或者拍照功能,网上也很非常多图库框架,都各有风格,也因此与自己的项目格格不入。再者,框架api太多,需要的配置太多,还要吃力研究。所以,本人摸索大多图库框架,提炼核心,写一个只提供核心的辅助类,剩下的就可以自行玩耍。

实现步骤

第一步,创建辅助类,使用弱引用持有activity,防止内存溢出。

  public class galleryhelper{

    private activity mactivity;

    public galleryhelper(activity activity) {
      mactivity = new weakreference<>(activity).get();
    }
  }

第二步,创建文件夹实体类,代表文件夹数据。paths集合是文件夹下的所有路径。

public final class folderentity {

  private int num;
  private string name;
  private list<string> paths = new arraylist<>();

  public int getnum() {
    return paths.size();
  }

  public list<string> getpaths() {
    return paths;
  }

  public void setname(string name) {
    this.name = name;
  }
}

第三步,首先获取手机所有的图片,在activity里有getloadermanager方法获取一个loadermanager实例,该类用于异步加载手机内数据监测,这里不做多分析。我们调用它的initloader方法,前两个参数这里不需要,只要实现loadercallbacks接口,并且指定cursor类型。loadercallbacks接口有三个覆盖方法,我们需要用到的是oncreateloader方法和onloadfinished方法,前者是初始化loader,后者是加载完成后的回调。

  mactivity.getloadermanager().initloader(0, null, new loadermanager.loadercallbacks<cursor>() {
      @override
      public loader<cursor> oncreateloader(int i, bundle bundle) {
      }

      @override
      public void onloadfinished(loader<cursor> loader, cursor cursor) {
      }

      @override
      public void onloaderreset(loader<cursor> loader) {

      }
    });

在oncreateloader方法里,初始化cursorloader,参数跟cursor类下的query一样,第一个参数指定外部村粗多媒体uri;第二个参数是查找结果字段,这里只要了路径;第三个参数和第四个参数是搜索条件,条件为搜索jpeg格式和png格式,最后一个是按时间倒序搜索。

  public loader<cursor> oncreateloader(int i, bundle bundle) {
     return new cursorloader(mactivity,
         mediastore.images.media.external_content_uri,
         new string[]{mediastore.images.media.data},
         mediastore.images.media.mime_type + "=? or "
             + mediastore.images.media.mime_type + "=?",
         new string[]{"image/jpeg", "image/png"},
         mediastore.images.media.date_added + " desc");
   }

cursorloader初始化完成之后,搜索的结果会回调在onloadfinished方法。这时就可以处理搜索出来的图片路径。因为图片路径是没有分类,这里采用hashmap分类,以文件夹路径为key,具体文件夹folderentity类为value,如果当前图片路径的文件夹不存在则创建folderentity并且放入hashmap,存在则获取folderentity。

  public void onloadfinished(loader<cursor> loader, cursor cursor) {
     hashmap<string, folderentity> folderentityhashmap = new hashmap<string, folderentity>();
      if (cursor != null) {
        while (cursor.movetonext()) {
          //图片路径
          string path = cursor.getstring(
          cursor.getcolumnindex(mediastore.images.media.data));

          // 路径不存在或者文件不存在就跳过
          file file = new file(path);
          if (textutils.isempty(path) || !file.exists()) {
            continue;
          }
          string folerpath = file.getparent();
          folderentity folderentity;
          if (folderentityhashmap.containskey(folerpath)) {
            folderentity = folderentityhashmap.get(folerpath);
          } else {
            folderentity = new folderentity();
            folderentityhashmap.put(file.getparentfile().getname(), folderentity);
          }
          folderentity.getpaths().add(path);
        }
        cursor.close();
      }

    }

但是数据是要提供给外部的,hashmap就显得很麻烦,所以要转换arraylist,并且按数量大小进行顺序。

    private arraylist<folderentity> map2list(hashmap<string, folderentity> mediabeanmap) {
      iterator<folderentity> iterator = mediabeanmap.values().iterator();
      arraylist<folderentity> list = new arraylist<folderentity>();
      while (iterator.hasnext()) {
        list.add(iterator.next());
      }
      collections.sort(list, new comparator<folderentity>() {
        @override
        public int compare(folderentity lhs, folderentity rhs) {
          return lhs.getnum() > rhs.getnum() ? 1 : -1;
        }
      });
      return list;
    }

使用接口将数据提供给外部。

  public interface gallerycallback {
    void complete(list<folderentity> list);
  }

  callback.complete(map2list(folderentityhashmap));

第四步是实现拍照功能,这里实现是创建文件再启动拍照功能。

  file imagestoredir = new file(environment.getexternalstoragedirectory(),
      "/dcim/" + mactivity.getresources().getstring(r.string.app_name));
  if (!imagestoredir.exists()) {
    imagestoredir.mkdir();
  }
  intent captureintent = new intent(mediastore.action_image_capture);
  if (captureintent.resolveactivity(mactivity.getpackagemanager()) != null) {
    simpledateformat dateformat = new simpledateformat("yyyymmddhhmmss", locale.china);
    string filename = string.format("img%s", dateformat.format(new date()));
    imagepath = new file(imagestoredir, filename).getabsolutepath();
    captureintent.putextra(mediastore.extra_output, uri.fromfile(new file(imagepath)));
    mactivity.startactivityforresult(new intent(
        mediastore.action_image_capture), request_code);
  }

定义回调接口,接收activit的onactivityresult方法,表示回调成功把上面创建好的文件路径提供外部。

  public interface cameracallback {
    void complete(string path);
  }

  public void onactivityresult(int requestcode, int resultcode) {
    if (activity.result_ok == resultcode && request_code == requestcode) {
      if (cameracallback != null) {
        cameracallback.complete(imagepath);
      }
    }
  }

外部调用

  galleryhelper = new galleryhelper(this);
    galleryhelper.loadimages(new galleryhelper.gallerycallback() {
      @override
      public void complete(list<folderentity> list) {
        //加载本地图片返回结果
      }
    });

 findviewbyid(r.id.btn_camera).setonclicklistener(new view.onclicklistener() {
     @override
     public void onclick(view v) {
       galleryhelper.opencamera(new galleryhelper.cameracallback() {
         @override
         public void complete(string path) {
         //拍照返回结果
         }
       });
     }
   });

  @override
  protected void onactivityresult(int requestcode, int resultcode, intent data) {
    super.onactivityresult(requestcode, resultcode, data);
    //使用拍照,必须接收activity的onactivityresult方法
    galleryhelper.onactivityresult(requestcode, resultcode);
  }

别忘了加权限,这里为了简单实现,我把targetsdkversion设置23以下,23和23以上的需要自行加上动态权限。

  <uses-permission android:name="android.permission.read_external_storage" />
  <uses-permission android:name="android.permission.write_external_storage" />
  <uses-permission android:name="android.permission.camera" />
  <uses-permission android:name="android.permission.mount_unmount_filesystems" />

整体就完成了,使用非常方便,有了这图库辅助器就可以自定义风格,再也不用受约束。网上大多开源图片选择器的搜索图片都是如此,但这例子难免有bug,不足之处望指教。

github地址:https://github.com/tanxinye/galleryhelper

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。