1. 简介

PhotoPicker, 是一款开源的图片选择器。效果上和微信相似。

2. 使用方法

2.1 添加依赖

dependencies {
compile 'me.iwf.photopicker:PhotoPicker:0.9.5@aar' compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:recyclerview-v7:23.4.0'
compile 'com.android.support:design:23.4.0'
compile 'com.nineoldandroids:library:2.4.0'
compile 'com.github.bumptech.glide:glide:3.7.0'
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • appcompat-v7version >= 23.0.0

或者使用download源码,然后使用module依赖,我平时使用是这种方式。

dependencies {
...
compile project(':PhotoPicker')
...
}
  • 1
  • 2
  • 3
  • 4
  • 5

2.2 代码集成

如下内容来自Github介绍

  • Pick Photo
PhotoPicker.builder()
.setPhotoCount(9)
.setShowCamera(true)
.setShowGif(true)
.setPreviewEnabled(false)
.start(this, PhotoPicker.REQUEST_CODE);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • Preview Photo
ArrayList<String> photoPaths = ...;

PhotoPreview.builder()
.setPhotos(selectedPhotos)
.setCurrentItem(position)
.setShowDeleteButton(false)
.start(MainActivity.this);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • onActivityResult
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK && requestCode == PhotoPicker.REQUEST_CODE) {
if (data != null) {
ArrayList<String> photos =
data.getStringArrayListExtra(PhotoPicker.KEY_SELECTED_PHOTOS);
}
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
>
<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" />
<application
...
>
... <activity android:name="me.iwf.photopicker.PhotoPickerActivity"
android:theme="@style/Theme.AppCompat.NoActionBar"
/> <activity android:name="me.iwf.photopicker.PhotoPagerActivity"
android:theme="@style/Theme.AppCompat.NoActionBar"/> </application>
</manifest>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • Custom Style
<style name="actionBarTheme" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
<item name="android:textColorPrimary">@android:color/primary_text_light</item>
<item name="actionBarSize">@dimen/actionBarSize</item>
</style> <style name="customTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="actionBarTheme">@style/actionBarTheme</item>
<item name="colorPrimary">#FFA500</item>
<item name="actionBarSize">@dimen/actionBarSize</item>
<item name="colorPrimaryDark">#CCa500</item>
</style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • ProGuard
# Glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
# nineoldandroids
-keep interface com.nineoldandroids.view.** { *; }
-dontwarn com.nineoldandroids.**
-keep class com.nineoldandroids.** { *; }
# support-v7-appcompat
-keep public class android.support.v7.widget.** { *; }
-keep public class android.support.v7.internal.widget.** { *; }
-keep public class android.support.v7.internal.view.menu.** { *; }
-keep public class * extends android.support.v4.view.ActionProvider {
public <init>(android.content.Context);
}
# support-design
-dontwarn android.support.design.**
-keep class android.support.design.** { *; }
-keep interface android.support.design.** { *; }
-keep public class android.support.design.R$* { *; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

3. 源码分析

3.1 代码结构

  • 类说明(按照功能)
类名 描述
PhotoPicker 内部类PhotoPickerBuilder是关键,设置图片选择参数,启动PhotoPickerActivity均在此
PhotoPickerActivity 图片选择界面,两个Fragment:PhotoPickerFragment,ImagePagerFragment,一个用来图片选择,一个用来预览图片
PhotoPagerActivity 图片预览界面,和PhotoPickerActivity使用同样的布局文件,但是只有一个Fragment,ImagePagerFragment
PhotoPreview 内部类PhotoPreviewBuilder是关键,设置预览参数,启动PhotoPagerActivity均在此
PhotoPickerFragment 图片选择Fragment,在PhotoPickerActivity中使用到,Toolbar + RecyclerView + ListPopupWindow
ImagePagerFragment 图片预览Framgment,在PhotoPickerActivity中如果支持预览,点击图片后就会切换到此Fragment,单独使用PhotoPreview自然也是用的ImagePagerFragment
ImageCaptureManager 拍照管理类,当PhotoPicker中setShowCamera设为true后,点击拍照项,会调用系统相机拍照,相关方法实现均在ImageCaptureManager
PhotoGridAdapter 图片选择界面RecyclerView的 Adapter,瀑布流,主要因为它继承SelectableAdapter,平时开发有相同需求可以借鉴一些这个实现
PopupDirectoryListAdapter 底部图片分类文件夹ListPopupWindow的Adapter
MediaStoreHelper 图片数据查找Helper类,单独拿出来看,Loader的使用
SelectableAdapter 自定义用于选择的RecyclerView.Adapter,支持toggleSelection
Selectable Selectable接口,支持toggleSelection
PhotoPagerAdapter ImagePagerFragment中用于预览的ViewPager的Adapter
PhotoDirectory 图片目录对象,在PopupDirectoryListAdapter中使用到
Photo 图片对象,存放id和Path,分别对应数据库中图片_ID字段和DATA字段
OnItemCheckListener 图片选择框的点击事件接口
OnPhotoClickListener 图片点击事件接口,应该只有在图片选择器支持预览的情况下使用
AndroidLifecycleUtils 判断是否可以加载图片
FileUtils 文件处理工具类,只有一个判断文件是否存在的方法
PermissionsConstant 关于权限请求的部分常量
PermissionsUtils 权限请求工具类
PhotoDirectoryLoader 继承CursorLoader,从数据库中读取数据
SquareItemLayout 图片选择器Item布局
TouchImageView 预览图片自定义元件

3.2 源码设计思路

从代码结构和使用方法上来看,PhotoPicker是将图片选择作为一个单独的功能模块解耦出来,以Activity的形式进行PhotoPicker或者是PhotoPreview,在合适的位置创建Intent显示启动PhotoPagerAcitivty(预览)或者是PhotoPickerActivity(选择图片)。针对图片选择的场景,通过onActivityResult得到所选图片的Path。


  • PhotoPicker
方法 参数 描述
setPhotoCount(int photoCount) EXTRA_MAX_COUNT(“MAX_COUNT”) 设置可选的最大图片数量
setShowCamera(boolean showCamera) EXTRA_SHOW_CAMERA(“SHOW_CAMERA”) 是否显示拍照
setShowGif(boolean showGif) EXTRA_SHOW_GIF(“SHOW_GIF”) 是否显示gif图
setGridColumnCount(int columnCount) EXTRA_GRID_COLUMN(“column”) 设置图片选择网格的列数
setSelected(ArrayList< String> imagesUri) EXTRA_ORIGINAL_PHOTOS(“ORIGINAL_PHOTOS”) 已选照片
setPreviewEnabled(boolean previewEnabled) EXTRA_PREVIEW_ENABLED(“PREVIEW_ENABLED”) 图片网格视图中是否支持预览
参数 描述
KEY_SELECTED_PHOTOS(“SELECTED_PHOTOS”) 所选图片Path 列表

  • PhotoPreview
方法 参数 描述
setCurrentItem(int currentItem) EXTRA_CURRENT_ITEM(“current_item”) 设置预览界面当前显示图片序号
setPhotos(ArrayList< String> photoPaths) EXTRA_PHOTOS(“photos”) 设置预览图片列表,图片Path的ArrayList
setShowDeleteButton(boolean showDeleteButton) EXTRA_SHOW_DELETE(“show_delete”) 是否显示删除按钮

  • Build设计模式 
    PhotoPicker和PhotoPreview都是采用的Build设计模式。利用构建者模式,可以清晰的管理参数,层次清晰,增加代码的可读性,Android源码系统中也有此模式的大量使用,如AlertDialog.Builder等等。 
    PhotoPickerBuilder和PhotoPreviewBuilder正式采用的这种设计模式。

  • Loader机制 
    loader机制,包括LoaderManager,Loader,LoaderCallbacks三部分, 
    LoaderManager 来管理我们的laoder实例,获取来初始化,重启一个loader, 
    Loader 来执行我们的异步操作,有开始,完成,后台等接口实现 
    LoaderCallbacks 来执行我们的loader回调,主要是绑定分发Loader,完成加载,重置数据等 
    MediaStoreHelper中只有一个方法getPhotoDirs,方法中使用 
    activity.getSupportLoaderManager() 
    .initLoader(0, args, 
    new PhotoDirLoaderCallbacks(activity, resultCallback)); 
    的方式初始化Loader,然后在 
    PhotoDirLoaderCallbacks实现 
    LoaderManager.LoaderCallbacks< Cursor>接口。onCreateLoader方法中创建PhotoDirectoryLoader并传入参数,onLoadFinished返回后台数据库查询结果。

4. 备注

PhotoPicker,可以满足日常开发需求,代码结构非常清晰,可以直接根据自己的需求在源码上进行定制修改。感谢大神的开源精神。

<Android 开源库> PhotoPicker 从头到脚的更多相关文章

  1. PhotoPicker 从头到脚

    1. 简介 PhotoPicker, 是一款开源的图片选择器.效果上和微信相似. 2. 使用方法 2.1 添加依赖 dependencies { compile 'me.iwf.photopicker ...

  2. 1.设计模式第一步-《设计模式从头到脚舔一遍-使用C#实现》

    更新记录: 完成第一次编辑:2022年4月23日20:29:33. 加入小黄人歌曲:2022年4月23日21:45:36. 1.1 设计模式(Design Pattern)是什么 设计模式是理论.是前 ...

  3. mysql的从头到脚优化之数据库引擎的选择(转载)

    一. Mysql常用的存储引擎包括Innodb和Myisam以及memory引擎,但是最常用的莫过于Innodb引擎和MyISAM引擎,下边分别做下记录和比较: 下面思考下这几个问题: 你的数据库需要 ...

  4. mysql的从头到脚优化之服务器参数的调优

    一. 说到mysql的调优,有许多的点可以让我们去做,因此梳理下,一些调优的策略,今天只是总结下服务器参数的调优  其实说到,参数的调优,我的理解就是无非两点: 如果是Innodb的数据库,innod ...

  5. 并发编程(一):从头到脚解读synchronized

    一.目录 1.多线程启动方式 2.synchronized的基本用法 3.深度解析synchronized 4.同步方法与非同步方法是否能同时调用? 5.同步锁是否可重入(可重入锁)? 6.异常是否会 ...

  6. Struts2从头到脚--学习笔记(自认为比较重要的)

    一. Struts2框架介绍 Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与 ...

  7. 【Android开源库】 PagerSlidingTabStrip从头到脚

    简介 PagerSlidingTabStrip,是我个人经常使用到的一个和ViewPager配合的页面指示器,可以满足开发过程中常用的需求,如类似于今日头条的首页新闻内容导航栏等等,之前自己开发的Ju ...

  8. <Android 基础(三十四)> TabLayout 从头到脚

    1. 简介 1.TabLayout给我们提供的是一排横向的标签页 2.#newTab()这个方法来创建新的标签页,然后用过#setText()和#setIcon方法分别修改标签页的文本和图标,创建完成 ...

  9. <Android开源库> PagerSlidingTabStrip从头到脚

    简介 PagerSlidingTabStrip,是我个人经常使用到的一个和ViewPager配合的页面指示器,可以满足开发过程中常用的需求,如类似于今日头条的首页新闻内容导航栏等等,之前自己开发的Ju ...

随机推荐

  1. elasticsearch6.7 04.API规范

    API Conventions elasticsearch的REST的API是使用HTTP的JSON格式暴露的. 除非另有说明,本章中列出的约定可以在整个REST API中应用. 多索引 索引名称支持 ...

  2. 深入理解Java虚拟机--阅读笔记二

    垃圾收集器与内存分配策略 一.判断对象是否已死 1.垃圾收集器在对堆进行回收前,要先判断对象是否已死.而判断的算法有引用计数算法和可达性分析算法: 2.引用计数算法是给对象添加引用计数器,有地方引用就 ...

  3. linux上,mysql使用聚合函数group by 时报错:SELECT list is not in GROUP BY clause and contains nonaggre的问题

    之前在windows上测试是可以正常使用的,但是上传到Linux上后,就报错: Expression # of SELECT list is not in GROUP BY clause and co ...

  4. JSON 解析与封装

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.解析: var str = '{"name":"huangxiaojian&qu ...

  5. 第一章 深入.NET框架

    一. .NET的过人之处 1..NET框架提高了软件的可重复行 ,可扩展性,可维护行和灵活性. 2.对web应用的强大支撑. 3.对Web Service(Web服务)的支持. 4.实现SOA,支持云 ...

  6. 论各类BI工具的“大数据”特性!

    市面上的BI工具形形色色,功能性能包装得十分亮丽,但实际应用中我们往往更关注的是朴实的技术特性和解决方案.对于大数据,未来的应用趋势不可抵挡,很多企业也正存在大数据分析处理展现的需求,以下我们列举市面 ...

  7. 用ContentProvider获取通讯录联系人

    手机中的联系人数据实际是保存在数据库中的,但Android并没有让我们通过操作数据库去读取数据,而是通过一个ContractProvider这个应用提供了一个ContentProvider访问接口. ...

  8. Centos7 用yum命令安装LAMP环境(php+Apache+Mysql)以及php扩展

    1.yum -y update    // 更新系统 1.1)yum -y install gcc g++ gcc-c++ make kernel-devel kernel-headers 1.2)v ...

  9. python if 判断

    #!/usr/bin/env python# -*- conding:utf-8 -*- if 条件: 执行1 执行2else: 执行3 if else 后面需要加: python严格缩进,内容1和内 ...

  10. Oracle EBS INV 创建物料搬运单

    Create or Replace PROCEDURE ProcessMoveOrder AS -- Common Declarations l_api_version NUMBER := 1.0; ...