图片选择器ImageEditContainer
1. 简介
本次demo中一共封装了两个组件:ImageEditButton 和 ImageEditContainer。其中ImageEditContainer 是在 ImageEditButton,两个组件可单独使用。
在demo中,实现了 图片选择(拍照+本地),裁剪,压缩,保存本地 以及对已选择图片的删除操作(如果有修改需求,也可以使用对应方法进行操作,该方法已添加);
还有就是 针对 6.0权限的处理问题,本次使用了第三方库 rxpermissions 进行权限的处理。
2.项目主目录结构

3. 功能介绍
MainActivity.java 界面效果图:


ImageEditContainer 组件初始化:
layImageContainer = (ImageEditContainer) findViewById(R.id.lay_image_container);
layImageContainer.setEditListener(this);
layImageContainer.setBtnImageResource(R.drawable.icon_picture_photograph);
layImageContainer.setTotalImageQuantity(3);
如上代码,设置组件的监听,添加按钮展示图,以及最多选择图片个数。
implements ImageEditContainer.ImageEditContainerListener 的实现
@Override
public void doAddImage() {
PopupWindow mCameraPop = SelectPicturePopupWindowUtils.showSelectPicturePopupWindow(this);
if (mCameraPop != null)
mCameraPop.showAtLocation(layImageContainer, Gravity.BOTTOM, 0, 0);
} @Override
public void doEditLocalImage(ImageItem imageItem) {
if (imageItem != null) {
layImageContainer.updateEditedImageItem(imageItem);
}
} @Override
public void doEditRemoteImage(RemoteImageItem remoteImageItem) {
if (remoteImageItem != null) {
if (remoteImageItem.isDeleted) {
layImageContainer.removeRemoteImageItem(remoteImageItem);
} else {
layImageContainer.updateRemoteImageItem(remoteImageItem);
}
}
}
当图片选择数量达到最大个数时,添加按钮会消失。效果图如下所示:

图片裁剪 效果图如下所示:
图片可拖拽,缩放

图片选择好后,进行图片压缩:
private void compressImage(String path) {
if (TextUtils.isEmpty(path)) {
return;
}
compressImage = compressImage + 1;
ImageItem imageItem = new ImageItem();
imageItem.storedPath = path;
File file = new File(FilePathUtils.getImageSavePath());
if (!file.exists()) {
file.mkdirs();
}
String filePath = FilePathUtils.getImageSavePath() + System.currentTimeMillis() + ".jpg";
new Thread(new MyThread(imageItem, path, filePath)).start();
List<String> imagePaths = new ArrayList<>();
imagePaths.add(path);
layImageContainer.addNewImageItem(imageItem);
}
图片压缩比较慢,要开启个 线程进行压缩:
public class MyThread implements Runnable {
private String imgPath;
private String outPath;
private ImageItem imageItem;
public MyThread(ImageItem imageItem, String imgPath, String outPath) {
this.imageItem = imageItem;
this.imgPath = imgPath;
this.outPath = outPath;
}
public void run() {
try {
BitmapUtil.compressAndGenImage(imgPath, outPath, 500, false);
compressImage = compressImage - 1;
imageItem.storedPath = outPath;
} catch (IOException e) {
compressImage = compressImage - 1;
e.printStackTrace();
}
}
}
使用的压缩方法:
/**
* Compress by quality, and generate image to the path specified
*
* @param imgPath
* @param outPath
* @param maxSize target will be compressed to be smaller than this size.(kb)
* @param needsDelete Whether delete original file after compress
* @throws IOException
*/
public static void compressAndGenImage(String imgPath, String outPath, int maxSize, boolean needsDelete) throws IOException {
compressAndGenImage(getBitmap(imgPath), outPath, maxSize); // Delete original file
if (needsDelete) {
File file = new File(imgPath);
if (file.exists()) {
file.delete();
}
}
}
组件 ImageEditContainer 添加图片方法介绍:
可添加本地和网络图片
/**
* 添加本地图片
* List<String> storePaths 本地图片路径数组
*/
public void addNewImages(List<String> storePaths) { } /**
* 添加本地图片
*/
public void addNewImageItem(ImageItem imageItem) { } /**
* 添加网络图片
*/
public void addRemoteImageItem(RemoteImageItem remoteImageItem) { }
组件 ImageEditContainer 其他方法介绍:
/**
* 设置组件中 选择按钮的宽高
*/
public void setImvHeightAndWidth(int height, int width) { }
/**
* 设置图片最大数量
*/
public void setTotalImageQuantity(int totalImageQuantity) { }
/**
* 设置图片展示图
*/
public void setBtnImageResource(int resid) { }
/**
* 获取组件中所有图片对象(本地+网络)
*/
public List<Object> getAllImageItems() { } public void updateEditedImageItem(ImageItem imageItem) { } /**
* 更新网络图片
*/
public void updateRemoteImageItem(RemoteImageItem remoteImageItem) {
} /**
* 删除网络图片
*/
public void removeRemoteImageItem(RemoteImageItem remoteImageItem) {
}
4. 组件代码
1.ImageEditButton.java
/**
* Created by dingzuoqiang on 2017/6/20.
* Email: 530858106@qq.com
*/
public class ImageEditButton extends RelativeLayout { private final static String TAG = "ImageEditButton"; private ImageView imvAddImage;
private ImageView imvEdit; private int imvHeight;
private int imvWidth;
public ImageEditButtonListener editButtonListener; public ImageEditButton(Context context) {
this(context, null);
} public ImageEditButton(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.image_edit_button_view, this, true);
imvHeight = CommonUtil.dip2px(getContext(), 70);
imvWidth = imvHeight;
imvAddImage = (ImageView) findViewById(R.id.imv_add_image);
imvEdit = (ImageView) findViewById(R.id.imv_edit);
setImvHeightAndWidth(imvHeight, imvWidth);
imvAddImage.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
doEditImage();
}
});
imvEdit.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
doEditImage2();
}
});
} public void setImvHeightAndWidth(int height, int width) {
this.imvHeight = height;
this.imvWidth = width;
ViewGroup.LayoutParams layoutParams = imvAddImage.getLayoutParams();
layoutParams.width = imvHeight;
layoutParams.height = imvWidth;
imvAddImage.setLayoutParams(layoutParams);
} public int getImvHeight() {
return imvHeight;
} public int getImvWidth() {
return imvWidth;
} public void setPadding2(int left, int top, int right, int bottom) {
this.setPadding(left, top, right, bottom);
} public void setBtnImageResource(int resid) {
imvAddImage.setImageResource(resid);
// ImageLoaderUtils.loadImageFromDrawable(resid, imvAddImage, null);
} public void reset() {
imvEdit.setVisibility(GONE);
} public void setEditButtonListener(ImageEditButtonListener editButtonListener) {
this.editButtonListener = editButtonListener;
} public BaseImageItem getImageItem() {
Object object = this.getTag();
if (object instanceof BaseImageItem) return (BaseImageItem) object;
return null;
} public void displayUI() {
//
Object object = this.getTag();
if (object == null) return;
if (object instanceof ImageItem) {
ImageItem imageItem = (ImageItem) object; if (TextUtils.isEmpty(imageItem.storedPath))
return;
File file = new File(imageItem.storedPath);
if (file.exists()) {
// 其实Glide加载本地图片和加载网络图片调用的方法是一样的,唯一的区别是说加载SD卡的图片需要SD卡的权限,加载网络需要网络权限
Glide.with(getContext()).load(file).crossFade().into(imvAddImage);
}
} else if (object instanceof RemoteImageItem) {
// 如果是 remoteImageItem 则需要从读取图片,同时不可以裁剪
RemoteImageItem remoteImageItem = (RemoteImageItem) object;
Glide.with(getContext()).load(remoteImageItem.thumbUrl).centerCrop().crossFade().into(imvAddImage);
} // TODO
BaseImageItem baseImageItem = (BaseImageItem) object;
displayNoteIcons(baseImageItem);
} private void displayNoteIcons(BaseImageItem baseImageItem) {
imvEdit.setVisibility(VISIBLE);
} private void doEditImage() {
if (editButtonListener == null) return; Object object = this.getTag();
if (object == null) {
// add image
editButtonListener.doAddImage();
} else {
//
if (object instanceof ImageItem) {
editButtonListener.doEditLocalImage((ImageItem) object);
} else if (object instanceof RemoteImageItem) {
editButtonListener.doEditRemoteImage((RemoteImageItem) object);
}
} } private void doEditImage2() {
if (editButtonListener == null) return; Object object = this.getTag();
if (object != null) {
//
if (object instanceof ImageItem) {
ImageItem imageItem = (ImageItem) object;
imageItem.isDeleted = true;
editButtonListener.doEditLocalImage(imageItem);
} else if (object instanceof RemoteImageItem) {
RemoteImageItem remoteImageItem = (RemoteImageItem) object;
remoteImageItem.isDeleted = true;
editButtonListener.doEditRemoteImage(remoteImageItem);
}
} } public interface ImageEditButtonListener { public void doAddImage(); public void doEditLocalImage(ImageItem imageItem1); public void doEditRemoteImage(RemoteImageItem remoteImageItem);
} }
2.ImageEditContainer.java
/**
* Created by dingzuoqiang on 2017/6/20.
* Email: 530858106@qq.com
*/
public class ImageEditContainer extends HorizontalScrollView implements ImageEditButton.ImageEditButtonListener { private final static String TAG = "ImageEditContainer";
public ImageEditContainerListener mEditListener;
private int idValue = 0;
ImageEditButton imbAddImage;
ViewGroup buttonsContainer; private int totalImageQuantity = 3;// 总添加数量
private int mBtnBgResid = 0; public ImageEditContainer(Context context) {
//super(context);
this(context, null);
} public ImageEditContainer(Context context, AttributeSet attrs) {
super(context, attrs);
//
LayoutInflater.from(context).inflate(R.layout.image_edit_container, this, true); imbAddImage = (ImageEditButton) findViewById(R.id.imb_add_image);
imbAddImage.setEditButtonListener(this);
//
buttonsContainer = (ViewGroup) findViewById(R.id.lay_container);
setHorizontalScrollBarEnabled(false);
setHorizontalFadingEdgeEnabled(false); } public void setImvHeightAndWidth(int height, int width) {
for (int i = 0; i < buttonsContainer.getChildCount(); i++) {
ImageEditButton imageEditButton = (ImageEditButton) buttonsContainer.getChildAt(i);
if (imageEditButton == null) continue;
imageEditButton.setImvHeightAndWidth(height, width);
}
} public void setTotalImageQuantity(int totalImageQuantity) {
if (totalImageQuantity > 0)
this.totalImageQuantity = totalImageQuantity;
} public void setBtnImageResource(int resid) {
mBtnBgResid = resid;
imbAddImage.setBtnImageResource(mBtnBgResid);
} public List<Object> getAllImageItems() {
List<Object> allItems = new ArrayList<>();
for (int i = 0; i < buttonsContainer.getChildCount(); i++) {
ImageEditButton imageEditButton = (ImageEditButton) buttonsContainer.getChildAt(i);
if (imageEditButton == null) continue;
if (imageEditButton.getTag() == null) continue;
allItems.add(imageEditButton.getTag());
}
return allItems;
} /**
* 添加本地图片
*/
public void addNewImages(List<String> storePaths) { for (int i = 0; i < storePaths.size(); i++) {
String path = storePaths.get(i);
ImageItem imageItem = new ImageItem();
imageItem.storedPath = path;
imageItem.id = idValue++;
Log.i(TAG, "index=" + i + " id=" + imageItem.id);
imageItem.index = (buttonsContainer.getChildCount() - 1);
addBaseImageItemToContainer(imageItem); }
} /**
* 添加本地图片
*/
public void addNewImageItem(ImageItem imageItem) {
if (imageItem == null) return;
imageItem.id = idValue++;
imageItem.index = (buttonsContainer.getChildCount() - 1);
addBaseImageItemToContainer(imageItem);
} public void updateEditedImageItem(ImageItem imageItem) {
ImageEditButton imageEditButton = getImageEditButtonForImageItemById(imageItem);
if (imageEditButton == null) {
return;
} Object originObj = imageEditButton.getTag();
if (!(originObj instanceof ImageItem)) {
if (originObj instanceof RemoteImageItem) {
RemoteImageItem remoteItem = (RemoteImageItem) originObj;
if (remoteItem.index == imageItem.index) {
imageEditButton.setTag(imageItem);
imageEditButton.displayUI();
return;
}
reorderForImageItem(imageItem);
}
return;
} ImageItem originImageItem = (ImageItem) originObj;
if (imageItem.isDeleted) {
removeButtonContainImageItem(imageItem);
resetImageItemIndex();
return;
} else { if (originImageItem.index == imageItem.index) {
imageEditButton.setTag(imageItem);
imageEditButton.displayUI();
return;
}
reorderForImageItem(imageItem);
}
} /**
* 添加网络图片
*/
public void addRemoteImageItem(RemoteImageItem remoteImageItem) {
addBaseImageItemToContainer(remoteImageItem);
} /**
* 更新网络图片
*/
public void updateRemoteImageItem(RemoteImageItem remoteImageItem) { ImageEditButton imageEditButton = getImageEditButtonForImageItemById(remoteImageItem);
if (imageEditButton == null) {
if (getAllImageItems().size() > 0) {
List<Object> objectList = getAllImageItems();
for (int i = 0; i < objectList.size(); i++) {
BaseImageItem baseImageItem = (BaseImageItem) objectList.get(i);
removeButtonContainImageItem(baseImageItem);
}
//
objectList.add(0, remoteImageItem); for (int i = 0; i < objectList.size(); i++) {
addRemoteImageItem((RemoteImageItem) objectList.get(i));
}
//
} else {
addRemoteImageItem(remoteImageItem);
} return;
}
BaseImageItem baseImageItem = (BaseImageItem) imageEditButton.getTag();
if (baseImageItem instanceof ImageItem) return;
RemoteImageItem originRemoteItem = (RemoteImageItem) baseImageItem; if (remoteImageItem.index == originRemoteItem.index) {
// index 相同 只是update
imageEditButton.setTag(remoteImageItem);
imageEditButton.displayUI();
return;
}
reorderForImageItem(remoteImageItem);
} /**
* 删除网络图片
*/
public void removeRemoteImageItem(RemoteImageItem remoteImageItem) { ImageEditButton imageEditButton = getImageEditButtonForImageItemById(remoteImageItem);
if (null != imageEditButton && null != imageEditButton.getTag()) {
BaseImageItem baseImageItem = (BaseImageItem) imageEditButton.getTag();
if (baseImageItem instanceof ImageItem) return;
RemoteImageItem originRemoteItem = (RemoteImageItem) baseImageItem;
removeButtonContainImageItem(remoteImageItem);
resetImageItemIndex();
}
} private void reorderForImageItem(BaseImageItem imageItem) {
removeButtonContainImageItem(imageItem);
List<BaseImageItem> imageItems = new ArrayList<>();
imageItems.add(imageItem);
int count = buttonsContainer.getChildCount();
for (int i = imageItem.index; i < count; i++) {
ImageEditButton button = (ImageEditButton) buttonsContainer.getChildAt(i);
if (button == null) continue;
BaseImageItem imageItem1 = (BaseImageItem) button.getTag();
if (imageItem1 == null) continue;
imageItems.add(imageItem1);
}
for (int i = 0; i < imageItems.size(); i++) {
BaseImageItem item = imageItems.get(i);
removeButtonContainImageItem(item);
}
//
for (int i = 0; i < imageItems.size(); i++) {
addBaseImageItemToContainer(imageItems.get(i));
} } private void resetImageItemIndex() {
for (int i = 0; i < buttonsContainer.getChildCount(); i++) { try {
ImageEditButton button = (ImageEditButton) buttonsContainer.getChildAt(i);
if (button == null) continue;
BaseImageItem imageItem = (BaseImageItem) button.getTag();
if (imageItem == null) continue;
imageItem.index = i; } catch (Exception ignored) { }
}
} private ImageEditButton getImageEditButtonForImageItemById(BaseImageItem imageItem) {
for (int i = 0; i < buttonsContainer.getChildCount(); i++) {
ImageEditButton imageEditButton = (ImageEditButton) buttonsContainer.getChildAt(i);
if (imageEditButton == null) continue;
if (imageEditButton.getImageItem() == null) continue;
BaseImageItem searchedImageItem = imageEditButton.getImageItem();
if (imageItem.id.longValue() == searchedImageItem.id.longValue()) {
return imageEditButton;
}
}
return null;
} /*
删除一个 ImageItem
*/
private void removeButtonContainImageItem(BaseImageItem imageItem) { ImageEditButton imageEditButton = getImageEditButtonForImageItemById(imageItem);
if (imageEditButton == null) return;
buttonsContainer.removeView(imageEditButton);
resetImageItemIndex();
imbAddImage.setVisibility(buttonsContainer.getChildCount() <= totalImageQuantity ? VISIBLE : GONE);
} private void addBaseImageItemToContainer(BaseImageItem imageItem) {
buttonsContainer.removeView(imbAddImage); ImageEditButton imageEditButton = new ImageEditButton(getContext());
if (mBtnBgResid != 0)
imageEditButton.setBtnImageResource(mBtnBgResid);
imageEditButton.setTag(imageItem);
imageEditButton.setEditButtonListener(this);
// buttonsContainer.addView(imageEditButton, buttonsContainer.getChildCount(), new RelativeLayout.LayoutParams(nSize, imbAddImage.getHeight()));
buttonsContainer.addView(imageEditButton, buttonsContainer.getChildCount());
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) imageEditButton.getLayoutParams();
layoutParams.rightMargin = CommonUtil.dip2px(getContext(), 5);
imageEditButton.setLayoutParams(layoutParams);
imageEditButton.setImvHeightAndWidth(imbAddImage.getImvHeight(), imbAddImage.getImvWidth());
imageEditButton.displayUI();
//
buttonsContainer.addView(imbAddImage, buttonsContainer.getChildCount());
//
imbAddImage.setVisibility(buttonsContainer.getChildCount() <= totalImageQuantity ? VISIBLE : GONE); resetImageItemIndex(); } /*
ImageEditButton listener
*/ public void doAddImage() {
if (mEditListener != null) {
mEditListener.doAddImage();
}
} public void doEditLocalImage(ImageItem imageItem) {
if (mEditListener != null) {
mEditListener.doEditLocalImage(imageItem);
} } public void doEditRemoteImage(RemoteImageItem remoteImageItem) {
if (mEditListener != null) {
mEditListener.doEditRemoteImage(remoteImageItem);
} }
// ----- public void setEditListener(ImageEditContainerListener editListener) {
this.mEditListener = editListener;
} // public interface ImageEditContainerListener {
public void doAddImage(); public void doEditLocalImage(ImageItem imageItem1); public void doEditRemoteImage(RemoteImageItem remoteImageItem);
}
图片选择器ImageEditContainer的更多相关文章
- Android之仿微信图片选择器
先上效果图.第一张图显示的是“相机”文件夹中的所有图片:通过点击多张图片可以到第二张图所示的效果(被选择的图片会变暗,同时选择按钮变亮):点击最下面的那一栏可以到第三张图所示的效果(显示手机中所有包含 ...
- Android图片选择器
1.概述 应公司项目需求,要做一个图片选择器,网上搜索了一些源码,我在别人的基础上进行了修改,另外页面也进行了重整,我的是先加载图片文件夹列表,然后再进入选择图片. 参考博客地址 ...
- paip.提升用户体验--radio图片选择器 easyui 实现..
#paip.提升用户体验--radio图片选择器 easyui 实现.. =================================== ##原因... ------------------- ...
- [转]Android 超高仿微信图片选择器 图片该这么加载
快速加载本地图片缩略图的方法: 原文地址:Android 超高仿微信图片选择器 图片该这么加载 其示例代码下载: 仿微信图片选择器 ImageLoader
- 仿照微信的效果,实现了一个支持多选、选原图和视频的图片选择器,适配了iOS6-9系统,3行代码即可集成.
提示:如果你发现了Bug,请尝试更新到最新版.目前最新版是1.6.4,此前的版本或多或少存在一些bug的~如果你已经是最新版了,请留一条评论,我看到了会尽快处理和修复哈~ 关于升级iOS10和Xcdo ...
- 一个iOS图片选择器的DEMO(实现图片添加,宫格排列,图片长按删除,以及图片替换等功能)
在开发中,经常用到选择多张图片进行上传或作其他处理等等,以下DEMO满足了此功能中的大部分功能,可直接使用到项目中. 主要功能如下: 1,图片九宫格排列(可自动设置) 2,图片长按抖动(仿苹果软件删除 ...
- Android 高级UI设计笔记06:仿微信图片选择器(转载)
仿微信图片选择器: 一.项目整体分析: 1. Android加载图片的3个目标: (1)尽可能的去避免内存溢出. a. 根据图片的显示大小去压缩图片 b. 使用缓存对我们图片进行管理(LruCache ...
- Android图片选择器--仿QQ
当做一款APP,需要选择本地图片时,首先考虑的无疑是系统相册,但是Android手机五花八门,再者手机像素的提升,大图无法返回等异常因数,导致适配机型比较困难,微信.QQ都相继的在自己的APP里集成了 ...
- Android 图片选择器
图片选择器,遍历系统所有图片并显示,点击查看大图,长按选中,并将结果返回 字体颜色res/color建立text_selecor.xml <selector xmlns:android=&quo ...
随机推荐
- IOS开发之简单计算器
用Object-C写的一个简单的计算机程序,主要学习按钮的action动作. 以下是主界面: 以下代码时界面按钮和ViewController.h连接的地方: - (IBAction)button_0 ...
- NYOJ 题目42 一笔画问题(欧拉图)
一笔画问题 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描写叙述 zyc从小就比較喜欢玩一些小游戏.当中就包含画一笔画.他想请你帮他写一个程序.推断一个图是否可以用一笔画下 ...
- android:“新版飞机大战”源码开源啦!
今天10.24,为了纪念程序猿的节日,把之前写过的一个"飞机大战"的一个源码开源了. 源码地址:https://github.com/nuptboyzhb/newplanegame ...
- bzoj 1266 [AHOI2006] 上学路线 route 题解
转载请注明:http://blog.csdn.net/jiangshibiao/article/details/23989499 [原题] 1266: [AHOI2006]上学路线route Time ...
- 使用OpenCV读、操作、写图像并与bash合作对某个文件夹下全部图像进行相似处理
我门要对某个文件夹下全部图像文件进行统一处理,假设图像的数量过多.那么手动地一张张处理就会显得有些麻烦.本文使用OpenCV和bash来完毕我们指定的任务. 任务 将文件夹A下的全部统一格式的jpg图 ...
- HDU2577 How to Type【DP】
题目链接: pid=2577">http://acm.hdu.edu.cn/showproblem.php? pid=2577 题目大意: 给你一个仅仅包括大写和小写字母的字符串,如今 ...
- ubuntu14.04 的ibus不能卸载(安装fcitx输入法框架时可能有这个需求)。出现无system setting有用程序
每年的ubuntu新版本号公布,都会吸引一大批热血青年. 关注越多也让ubuntu越来越好了. 使用ubuntu的人都会在安装系统之后马上安装顺手的输入法,也可能不会.看人. 安装输入法,对于中文输入 ...
- String,StringBuffer,StringBuilder三者有什么异同?
相同点: 1.三者都是Java平台提供的三种类型得到字符串,它们可以储存和操作字符串. 不同点: 1.String是final修饰的,也就意味着String引用的字符串内容是不能被改变的.而Strin ...
- sql compare options
sql compare project's options Add object existence checks Use DROP and CREATE instead of ALTER Ignor ...
- 【T^T】【周赛】第一周周赛——欢迎16级的新同学
借光光,YZC的福气(今天拿到Rank1),本来还可以更好的,前面吃M去了,ABC都很晚切,而且异常兴奋,结果WA了好多发,但还是由于水题看题不清,分析不清导致的 A Home W的数学 Descri ...