Android实现简单图库辅助器
写在前面
实际开发经常会遇到读取相册或者拍照功能,网上也很非常多图库框架,都各有风格,也因此与自己的项目格格不入。再者,框架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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 红薯与豆浆这样做最美味,快手早餐速成教材
下一篇: 古时候的妃嫔下场如何 白绫一条是最幸运的