android 选择器 简书,私人订制Android本地图片选择器

效果图

fd5ebfc4725e

效果图

需求分析

网格布局显示本地图片

支持图片多选

支持选中的图片预览

未选择图片时不可预览

由已选多图变为无图时可退出图片选择页面

图片已选达到上限后依然可以跳转图片选择页面

第三方框架使用

实现目标

应用并修改第三方框架GalleryFinal源码,实现效果图的样式。

具体实现

导入GalleryFinal源码

从GalleryFinal的Github仓库中拷贝仓库地址,使用git指令cloneGalleryFinal源代码到本地:

git clone https://github.com/pengjianbo/GalleryFinal.git

选择Android Studio菜单栏File->New->import Module...,导入GalleryFinal源代码到Android Studio:

fd5ebfc4725e

导入GalleryFinal源码

详情参考:

【Mac流派】程序猿修炼之道(6)-技能篇之git指令

Android Studio导入第三方库的三种方法

写一个GridView

这里声明一下,选择图片的Activity是GalleryFinal自带的,所以我们这里要写的GridView是用来显示选中并返回的图片,这里的代码就不放出来了,效果图如下:

fd5ebfc4725e

未选择时

fd5ebfc4725e

选择图片时

本人实现的可支持最大图片数量是5,在图片选满的时候依然显示“+”,用以跳转图片选择页面选择其他图片。

初始化GalleryFinal配置

通过代码设置图片选择器的标题栏背景颜色,标题文本颜色,浮动按钮颜色;

通过监听事件,达到滚动时不加载图片,停下来时加载图片,实现优化;

初始化功能配置;

为防止代码分开查看导致逻辑的混乱,将上述配置代码一齐贴上,下面的代码可放在跳转图片选择界面的按钮点击事件中。这里强调一下:mThemeConfig = new ThemeConfig.Builder() .setTitleBarBgColor等方法传参是整型,但是其传入的是颜色值而非资源文件的id。

代码注释较详细,其他不做过多讲解:

// ------- 声明 -------

// 主题配置

private ThemeConfig mThemeConfig;

// 图片加载器

private cn.finalteam.galleryfinal.ImageLoader mGlidImgLoader;

// 滚动监听事件

private PauseOnScrollListener mPauseOnScrollListener;

// 功能配置

private FunctionConfig mFunctionConfig;

// 核心配置

private CoreConfig mCoreConfig;

// ------- 实现 -------

// 获取标题栏背景颜色

int colorTitleBarBg = ContextCompat.getColor(Activity.this, R.color.titleBarBgColor);

// 标题栏文字颜色

int colorTitleBarText = ContextCompat.getColor(Activity.this, R.color.titleBarTextColor);

// 浮动按钮常规颜色

int colorFabNormal = ContextCompat.getColor(Activity.this, R.color.color_ffaa2a);

// 浮动按钮点击颜色

int colorFabPressed = ContextCompat.getColor(Activity.this, R.color.color_e29428);

// 标题栏按钮颜色

int colorTitleBarIcon = ContextCompat.getColor(MainActivity.this, R.color.colorTitleBarIcon);

// 设置主题

mThemeConfig = new ThemeConfig.Builder()

.setTitleBarBgColor(colorTitleBarBg) // 设置标题栏背景颜色

.setTitleBarTextColor(colorTitleBarText) // 设置标题栏文字颜色

.setFabNormalColor(colorFabNormal) // 设置浮动按钮常规颜色

.setFabPressedColor(colorFabPressed) // 设置浮动按钮点击颜色

.setCheckSelectedColor(colorFabNormal) // 设置选中标记(对勾)的颜色和按钮的颜色相同

.setTitleBarIconColor(colorTitleBarIcon) // 设置标题栏按钮颜色

.setIconBack(R.drawable.ic_back) // 设置返回按钮

.build();

// 初始化图片加载器

mGlidImgLoader = new GlideImageLoader();

// 初始化监听事件

mPauseOnScrollListener = new GlidePauseOnScrollListener(false, true);

// 初始化功能配置

FunctionConfig.Builder funConBuilder = new FunctionConfig.Builder();

// 设置最多可选择5张照图片

funConBuilder.setMutiSelectMaxSize(5);

// 设置图片不可编辑

funConBuilder.setEnableEdit(false);

// 设置图片不可旋转

funConBuilder.setEnableRotate(false);

// 设置图片不可裁剪

funConBuilder.setEnableCrop(false);

// 设置不可通过照相选择照片

funConBuilder.setEnableCamera(false);

// 设置添加过滤集合,过滤掉之前选中的图片

// funConBuilder.setFilter(mPhotoList);

// 不过滤图片,而是将之前选中的图片设置为选中状态

funConBuilder.setSelected(mPhotoList);

// 设置可预览

funConBuilder.setEnablePreview(true);

// 功能配置

mFunctionConfig = funConBuilder.build();

// 初始化核心配置

mCoreConfig = new CoreConfig.Builder(ReportActivity.this, mGlidImgLoader, mThemeConfig)

.setFunctionConfig(mFunctionConfig) // 添加功能配置

.setPauseOnScrollListener(mPauseOnScrollListener) // 滑动停止加载事件

.setNoAnimcation(true) // 无特效动画

.build();

// 实例化

GalleryFinalGalleryFinal.init(mCoreConfig);

// 多图片选择打开相册

GalleryFinal.openGalleryMuti(Constants.REQUEST_CODE_GALLERY, mFunctionConfig,

mOnHandlerResultCallback);

// 初始化图片加载器

initImageLoader(ReportActivity.this);

/**

* 初始化图片加载器

*

* @param context

*/

private void initImageLoader(Context context) {

// 图片加载器配置

ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(this);

// 设置线程优先级

config.threadPriority(Thread.NORM_PRIORITY - 2);

// 禁止内存缓存

config.denyCacheImageMultipleSizesInMemory();

// 设置磁盘缓存文件名生成器

config.diskCacheFileNameGenerator(new Md5FileNameGenerator());

// 设置磁盘缓存大小

config.diskCacheSize(20 * 1024 * 1024);

// 设置任务进程执行顺序:先进后出

config.tasksProcessingOrder(QueueProcessingType.LIFO);

// 调试使用,若是发布版,需要移除代码

config.writeDebugLogs();

// 初始化图片加载器

ImageLoader.getInstance().init(config.build());

}

选择图片返回的回调实现

/**

* 回调处理

*/

private GalleryFinal.OnHanlderResultCallback mOnHandlerResultCallback = new GalleryFinal.OnHanlderResultCallback() {

@Override

public void onHanlderSuccess(int reqeustCode, List resultList) {

// 清除原来列表中的图片

mPhotoList.clear();

// 返回图片列表

mPhotoList.addAll(resultList);

// 刷新页面

mPhotoAdapter.notifyDataSetChanged();

}

@Override

public void onHanlderFailure(int requestCode, String errorMsg) {

// 错误提示

Toast.makeText(Activity.this, errorMsg, Toast.LENGTH_SHORT).show();

}

};

基于上述代码,可得到效果图如下:

fd5ebfc4725e

初步效果图

修改源码

通过运行调试,发现框架中有些功能与需求不一致,因此我产生了修改源码的想法,总结需要更改的原功能点如下:

选择完达到上限数量的图片后,无法重新回到图片选择页面

fd5ebfc4725e

选择图片数量达到上限时无法进入图片选择页面

无图片选择时,无法点击浮动按钮进行返回

fd5ebfc4725e

无图片时无法返回

无图片选择时,预览按钮依然存在

fd5ebfc4725e

无图片选择时预览按钮依然存在并可以点击

针对以上需要修改的功能,源码修改如下:

选择图片到达上限依然可以返回图片选择页面

因图片选择页面的跳转在openGalleryMuti方法里实现:

// 多图片选择打开相册

GalleryFinal.openGalleryMuti(Constants.REQUEST_CODE_GALLERY, mFunctionConfig,

mOnHandlerResultCallback);

所以我们来看看openGalleryMuti方法的源码:

fd5ebfc4725e

openGalleryMuti方法源码

可以发现,源码中有这么一个判断逻辑:

if (config.getSelectedList() != null && config.getSelectedList().size() > config.getMaxSize()) {

if(callback != null){

callback.onHanlderFailure(requestCode, mCoreConfig.getContext().getString(R.string.select_max_tips));

}

return;

}

其作用是当选中的图片数量超过最大值时,返回打开本地图片选择器失败的提示信息。之前我们提到,需求中我们实际多显示了一张图片:

fd5ebfc4725e

“添加”图片

且在配置的时候传入的是添加了一张图片以后的图片列表:

// 不过滤图片,而是将之前选中的图片设置为选中状态

funConBuilder.setSelected(mPhotoList);

所以会导致界面无法跳转,我们有三个策略:

1.将多添加的图片放到adapter里面处理,adapter外部保持选中图片数量与选择页面传入图片的数量一致

2.setSelected传入图片列表之前将mPhotoList移除多出的图片

3.注释掉源码中对图片数量上限的判断

无图选择时,点击浮动按钮可以返回

可能有人不解,为何不点击标题栏的返回按钮返回而要点击浮动按钮返回?其原因是,若之前我选择好图片,但是想想,现在我不想要选择的图片了,这时候我们想把图片清空掉,这时候需要点击浮动按钮,来更新选中图片的列表。

想到这是浮动按钮的点击事件,所以我们到源码的GallerySelectActivity中浮动按钮的事件回调方法中:

fd5ebfc4725e

浮动按钮点击事件

这段代码仅仅在选中图片的数量大于0的时候才执行操作,所以我们添加一个条件,修改后的代码如下:

if (mSelectPhotoList.size() > 0) {

if (!GalleryFinal.getFunctionConfig().isEditPhoto()) {

resultData(mSelectPhotoList);

} else {

toPhotoEdit();

}

} else {

// 添加的代码,使未选中图片时也可返回

resultData(mSelectPhotoList);

}

fd5ebfc4725e

mSelectPhotoList初始化

考虑到选中图片的列表在声明时已经初始化,所以不用担心图片返回的回调事件传入空指针对象。

未选择图片时不显示预览按钮

通过布局的id——iv_preview在PhotoSelectActivity中查找,在refreshSelectCount方法里找到了对预览按钮可见性的设置:

fd5ebfc4725e

refreshSelectCount方法源码

从源码中可以看到,预览按钮的可见性判断逻辑仅仅与isEnablePreview有关,而没有和选中的图片数量进行关联,所以我们修改代码如下:

public void refreshSelectCount() {

mTvChooseCount.setText(getString(R.string.selected, mSelectPhotoList.size(), GalleryFinal.getFunctionConfig().getMaxSize()));

if (mSelectPhotoList.size() > 0 && GalleryFinal.getFunctionConfig().isMutiSelect()) {

mIvClear.setVisibility(View.VISIBLE);

if (GalleryFinal.getFunctionConfig().isEnablePreview()) {

mIvPreView.setVisibility(View.VISIBLE);

}

} else {

mIvClear.setVisibility(View.GONE);

mIvPreView.setVisibility(View.GONE);

}

}

当选中图片列表大小为0的时候,隐藏预览按钮;大于0的时候再根据isEnablePreview()来判断是否显示预览按钮。

修改布局和代码逻辑

布局和代码逻辑的修改,其思路与上一节修改源码一样,因需求的效果图功能与GalleryFinal的功能基本一致,逻辑上并不需要做很多的修改,而布局的修改仅涉及到ImageButton变成Button,ImageView变成TextView以及控件位置的调整,在关联控件上和点击事件根据id来判断事件处理上做相应修改即可,在此不做赘述。

总结

使用GalleryFinal订制属于自己的图片选择器并不难,只需要循着需求的功能点,按照代码的逻辑一点点追踪源码并进行修改订制即可。诚恳地说,GalleryFinal框架的可移植性确实很强,在此推荐大家了解一下!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值