最近因为公司需求需要做一个自定义的相册,因为手机自带的相册没有这种可以选取多张图片的功能,先上gif图,看效果(功能可以看出来,不知道为什么gif这么稀烂。。。)
GIF.gif简单功能都实现了,主要点是对图片的查询,然后设置了两个popupWindow来显示小相册和点击放大的效果,比较简单。(代码里面会有一些简单的工具类,看名字可以看出来是干什么的)
查询手机中的图片路径
步骤:
1.查询图片的path
2.由图片path获取其他信息(该图片所在文件夹的路径,文件夹的名字,文 件夹下的图片个数)
3.定义一个图片Model,来保存及对图片信息的传递,以便展示出来
4.通过文件夹的list()方法,可以获取每一个小相册下的图片文件
上代码。。。
//获取图片的路径和父路径 及 图片size
private void getImages() {
if (!Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
ViewKit.shortToast("检测到没有内存卡");
return;
}
showLoading();
new Thread(new Runnable() {
@Override
public void run() {
Uri mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
ContentResolver mContentResolver = GalleryActivity.this.getContentResolver();
Cursor mCursor = mContentResolver.query(mImageUri, null,
MediaStore.Images.Media.MIME_TYPE + "=? or "+
MediaStore.Images.Media.MIME_TYPE + "=? or "+
MediaStore.Images.Media.MIME_TYPE + "=?",
new String[]{"image/jpeg", "image/png","image/jpg"},
MediaStore.Images.Media.DATE_TAKEN +" DESC");//获取图片的cursor,按照时间倒序(发现没卵用)
while (mCursor.moveToNext()) {
String path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DATA));// 1.获取图片的路径
File parentFile = new File(path).getParentFile();
if (parentFile == null)
continue;//不获取sd卡根目录下的图片
String parentPath = parentFile.getAbsolutePath();//2.获取图片的文件夹信息
String parentName = parentFile.getName();
ImageFloder imageFloder ;//自定义一个model,来保存图片的信息
//这个操作,可以提高查询的效率,将查询的每一个图片的文件夹的路径保存到集合中,
//如果存在,就直接查询下一个,避免对每一个文件夹进行查询操作
if (mDirPaths.contains(parentPath)) {
continue;
} else {
mDirPaths.add(parentPath);//将父路径添加到集合中
imageFloder = new ImageFloder();
imageFloder.setFirstImagePath(path);
imageFloder.setDir(parentPath);
imageFloder.setName(parentName);
}
List<String> strings = null;
try {
strings = Arrays.asList(parentFile.list(getFileterImage()));
} catch (Exception e) {
e.printStackTrace();
}
int picSize = strings.size();//获取每个文件夹下的图片个数
imageFloder.setCount(picSize);//传入每个相册的图片个数
mImageFloders.add(imageFloder);//添加每一个相册
//获取图片最多的文件夹信息(父目录对象和个数,使得刚开始显示的是最多图片的相册
if (picSize > mPicsSize) {
mPicsSize = picSize;
mImgDir = parentFile;
}
}
mCursor.close();
mDirPaths = null;
mHandler.sendEmptyMessage(1);
}
}).start();
}
这是Model类,贴出来,方便观看
public class ImageFloder {
private int count;//文件夹下的图片个数
private String firstImagePath;//第一张图片的路径 传这个给小相册图片显示
private String dir;//文件夹路径
private String name;//文件夹的名字
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public String getFirstImagePath() {
return firstImagePath;
}
public void setFirstImagePath(String firstImagePath) {
this.firstImagePath = firstImagePath;
}
public String getDir() {
return dir;
}
public void setDir(String dir) {
this.dir = dir;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
还记得上面的handler操作吗,查询图片是一个耗时的操作,为了更新ui,也为了方便观看,就使用了handler的方式,这样代码也比较整洁,下面这个小代码,就是接下来的步骤了
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
setAdapterData();//设置图片的显示
cancelLoading();//取消加载框
initListDirPopupWindw();//初始化小相册的popupWindow
initChekcBox();//初始化checkbox集合,防止checkBox的错乱
}
};
设置适配器(采用的RecycleVIew,自己做的封装)
//设置适配器数据
private void setAdapterData() {
if (mImgDir == null) {
ViewKit.shortToast("没有查询到图片");
return;
}
tv_pop_gallery.setText(mImgDir.getName());
try {
mImgs = Arrays.asList(mImgDir.list(getFileterImage()));//获取文件夹下的图片集合
}catch (Exception e){
e.printStackTrace();
}
//查询出来的图片是正序的,为了让图片按照时间倒序显示,对其倒序操作
Collections.sort(mImgs, new Comparator<String>() {
@Override
public int compare(String lhs, String rhs) {
return -1;
}
});
mAdapter = new GalleryAdapter(gallery_recycleView, mImgs, R.layout.item_gallery_camera);
gallery_recycleView.setLayoutManager(new GridLayoutManager(this, 3));
gallery_recycleView.addItemDecoration(new DividerGridItemDecoration(this));
gallery_recycleView.setAdapter(mAdapter);
}
适配器:
//适配器
private class GalleryAdapter extends BaseRecyclerAdapter<String> {
List<String> datas;
String picPath;
ImageView iv_gallery;
CheckBox cb_gallery;
public GalleryAdapter(RecyclerView v, List<String> datas, int itemLayoutId) {
super(v, datas, itemLayoutId);
this.datas = datas;
}
@Override
public void convert(final RecyclerHolder holder, String item, final int position) {
iv_gallery = holder.getView(R.id.iv_gallery);
cb_gallery = holder.getView(R.id.cb_gallery);
iv_gallery.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, DensityKit.getScreenW() / 3));
picPath = mImgDir.getAbsolutePath() + "/" + datas.get(position);
BitmapKit.loadLocalImage(iv_gallery, picPath);//这里采用的是Glide为ImageVIew加载图片,很方便,这里对Glide进行了工具类的封装
//显示大图
iv_gallery.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
initBigPicPopupWindw(mImgDir.getAbsolutePath() + "/" + datas.get(position));
}
});
//checkBox
cb_gallery.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
CheckBox checkBox = (CheckBox) v;
if (realCount >= 9 && !selectList.get(position)) {
ViewKit.shortToast("最多可以选择9张图片");
selectList.put(position, false);
} else{
selectList.put(position, !selectList.get(position));
}
for (Map.Entry<Integer, Boolean> entry : selectList.entrySet()) {
entry.getKey();
Boolean value = entry.getValue();
if (value) {
checkCount++;
}
}
tv_count_gallery.setText("(" + checkCount + ")");
tv_confirm_gallery.setVisibility(checkCount>0?View.VISIBLE:View.GONE);
realCount = checkCount;
checkCount = 0;
checkBox.setChecked(selectList.get(position));
}
});
if(selectList!=null)
cb_gallery.setChecked(selectList.get(position));
}
}
}
左侧popupWindow小相册的定义
//设置相册PopupWindow
private void initListDirPopupWindw() {
mListImageDirPopupWindow = new ListImageDirPopupWindow(this, mImageFloders);
mListImageDirPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
setToRightDrawable(R.drawable.arrow_bottom);
}
});
mListImageDirPopupWindow.setOnImageDirSelected(new ListImageDirPopupWindow.OnImageDirSelected() {
//点击item之后的回调
@Override
public void selected(ImageFloder floder) {
mListImageDirPopupWindow.showAtDropDownCenter(tv_confirm_gallery);
setToRightDrawable(R.drawable.arrow_bottom);
realCount = 0;
tv_pop_gallery.setText(floder.getName());
tv_count_gallery.setText("(0)");
tv_confirm_gallery.setVisibility(View.GONE);
File file = new File(floder.getDir());
List<String> picFileList = null;
try {
picFileList = Arrays.asList(file.list(getFileterImage()));
} catch (Exception e) {
e.printStackTrace();
}
Collections.sort(picFileList, new Comparator<String>() {
@Override
public int compare(String lhs, String rhs) {
return -1;
}
});
//重新设置数据和checkBox初始化
mImgDir = file;
mImgs = picFileList;
initChekcBox();
mAdapter = new GalleryAdapter(gallery_recycleView, picFileList, R.layout.item_gallery_camera);
gallery_recycleView.setAdapter(mAdapter);
}
});
}
相册PopupWIndow的代码:
public class ListImageDirPopupWindow extends PopupWindow {
RecyclerView recycl_camera_list;
public ListImageDirPopupWindow(Context context, List<ImageFloder> mImageFloders) {
View conentView = LayoutInflater.from(context).inflate(R.layout.view_dir_camera, null);
recycl_camera_list = (RecyclerView) conentView.findViewById(R.id.recycl_camera_list);
setContentView(conentView);
ListAdapter listAdapter = new ListAdapter(recycl_camera_list, mImageFloders, R.layout.item_list_camera);
recycl_camera_list.setLayoutManager(new LinearLayoutManager(context));//设置垂直
recycl_camera_list.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL));
recycl_camera_list.setAdapter(listAdapter);
listAdapter.setOnItemClickListener(new BaseRecyclerAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, Object data, int position) {
if (data instanceof ImageFloder) {
ImageFloder imageFloder = (ImageFloder) data;
onImageDirSelected.selected(imageFloder);
}
}
});
setAnimationStyle(R.style.popup_camera);
setFocusable(true);
setTouchable(true);
setOutsideTouchable(true);
ColorDrawable background = new ColorDrawable(0xffffff);
setBackgroundDrawable(background);
setWidth((int) (DensityKit.getScreenW()/2));
setHeight(DensityKit.getScreenH()/3);
}
class ListAdapter extends BaseRecyclerAdapter<ImageFloder> {
public ListAdapter(RecyclerView v, List<ImageFloder> datas, int itemLayoutId) {
super(v, datas, itemLayoutId);
}
@Override
public void convert(RecyclerHolder holder, final ImageFloder imageFloder, int position) {
ImageView iv_first_image = holder.getView(R.id.iv_first_image);
TextView tv_count_list = holder.getView(R.id.tv_count_list);
TextView tv_name_list = holder.getView(R.id.tv_name_list);
BitmapKit.loadLocalImage(iv_first_image, imageFloder.getFirstImagePath());
tv_count_list.setText("(" + imageFloder.getCount() + ")");
tv_name_list.setText(imageFloder.getName());
}
}
public void showAtDropDownCenter(View parent) {
if (!isShowing()) {
setAnimationStyle(R.style.popup_camera);
int[] location = new int[2];
parent.getLocationOnScreen(location);//获取以屏幕为原点的位置
showAtLocation(parent,Gravity.TOP|Gravity.LEFT,0,location[1]-getHeight());
// showAtLocation(parent,Gravity.TOP,(location[0]-getWidth())/2, location[1]-getHeight());
// showAtLocation(parent, Gravity.NO_GRAVITY, location[0], location[1]-getHeight()); 三种方式都可以 原理是一样的
} else {
dismiss();
}
}
//点击之后的接口回调
private OnImageDirSelected onImageDirSelected;
public void setOnImageDirSelected(OnImageDirSelected onImageDirSelected) {
this.onImageDirSelected = onImageDirSelected;
}
public interface OnImageDirSelected {
void selected(ImageFloder floder);
}
}
杂⑦杂⑧的代码,懒的搞了,都贴出来(都有小注释)
//设置大图片的PopupWindow
private void initBigPicPopupWindw(String path) {
BigImagePopup bigImagePopup = new BigImagePopup(this);
bigImagePopup.setUrl(path);
bigImagePopup.showAtDropDownCenter(tv_confirm_gallery);
}
//导航栏点击事件
@Override
public void onClick(View v) {
int i = v.getId();
if (i == R.id.tv_pop_gallery) {
setToRightDrawable(R.drawable.arrow_up);
mListImageDirPopupWindow.showAtDropDownCenter(tv_confirm_gallery);
} else if (i == R.id.tv_confirm_gallery) {
ArrayList<String> pathList = new ArrayList<>();
for (Map.Entry<Integer, Boolean> entry : selectList.entrySet()) {
Boolean isChecked = entry.getValue();
if (isChecked) {
Integer position = entry.getKey();
String checkPath = mImgDir.getAbsolutePath() + "/" + mImgs.get(position);
pathList.add(checkPath);
}
}
backUrl(pathList);
}
}
//intent
public static Intent createIntent(Context context) {
Intent intent = new Intent(context, GalleryActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
return intent;
}
//返回的图片路径集合
private void backUrl(ArrayList<String> pathList) {
Intent intent = new Intent();
intent.putStringArrayListExtra("imageUrl", pathList);
setResult(RESULT_OK, intent);
finish();
}
// 初始化 设置所有checkbox都为未选择
private void initChekcBox() {
selectList = new HashMap<Integer, Boolean>();
if (mImgs != null && mImgs.size() > 0) {
for (int i = 0; i < mImgs.size(); i++) {
selectList.put(i, false);
}
}
}
//动态改变text的toRightDrawable
private void setToRightDrawable(int drawalbeId){
Drawable drawable= getResources().getDrawable(drawalbeId);
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
tv_pop_gallery.setCompoundDrawables(null,null,drawable,null);
}
//设置popWindow的背景----不要设置 会透视。。。
public void setBg_popup() {
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.alpha = 1.0f;
getWindow().setAttributes(lp);
}
//图片筛选器,过滤无效图片
private FilenameFilter getFileterImage(){
FilenameFilter filenameFilter = new FilenameFilter() {
@Override
public boolean accept(File dir, String filename) {
if (filename.endsWith(".jpg")
|| filename.endsWith(".png")
|| filename.endsWith(".jpeg"))
return true;
return false;
}
};
return filenameFilter;
}
点击放大的popupWIndow
public class BigImagePopup extends PopupWindow {
ImageView iv_big_picture;
public BigImagePopup(Activity context) {
View conentView = LayoutInflater.from(context).inflate(R.layout.view_bigpic, null);
setContentView(conentView);
LinearLayout linearLayout = (LinearLayout) conentView.findViewById(R.id.ll_picture);
iv_big_picture = (ImageView) conentView.findViewById(R.id.iv_big_picture);
linearLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
iv_big_picture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
setAnimationStyle(R.style.big_popup_camera);
setFocusable(true);
setTouchable(true);
setOutsideTouchable(true);
ColorDrawable background = new ColorDrawable(0xffffff);
setBackgroundDrawable(background);
setWidth(LinearLayout.LayoutParams.MATCH_PARENT);
setHeight(LinearLayout.LayoutParams.MATCH_PARENT);
}
public void setUrl(String url){
BitmapKit.loadLocalImage(iv_big_picture, url);
}
public void showAtDropDownCenter(View parent) {
if (!isShowing()) {
setAnimationStyle(R.style.big_popup_camera);
showAtLocation(parent, Gravity.BOTTOM, 0, 0);
} else {
dismiss();
}
}
}
写个这样的博客都这么累。。。。。
网友评论