您的位置:首页 > 移动开发 > 微信开发

android 仿微信多图选择器(带预览、照相功能)

2016-07-21 16:04 537 查看
实现了单选、多选 、拍照 、预览 等功能;
先上图:


 

 

 

 


代码结构

 下面不如正题:

一、添加依赖、权限

1)添加以下依赖

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.squareup.picasso:picasso:2.4.0'
compile 'com.nineoldandroids:library:2.4.0'

}


2) 在 AndroidManifest.xml 添加权限,并注册相关Activity

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

二、主要代码

1)设置参数

2)在图片选择的MultiImageSelectorFragment中添加接口,用于选择图片回调

public interface Callback {
void onSingleImageSelected(String path);

void onImageSelected(String path);

void onImageUnselected(String path);

void onCameraShot(File imageFile);
}


3)扫描手机相册图片

private LoaderManager.LoaderCallbacks<Cursor> mLoaderCallback = new LoaderManager.LoaderCallbacks<Cursor>() {

private final String[] IMAGE_PROJECTION = {
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.DATE_ADDED,
MediaStore.Images.Media.MIME_TYPE,
MediaStore.Images.Media.SIZE,
MediaStore.Images.Media._ID};

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
if (id == LOADER_ALL) {
CursorLoader cursorLoader = new CursorLoader(getActivity(),
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION,
IMAGE_PROJECTION[4] + ">0 AND " + IMAGE_PROJECTION[3] + "=? OR " + IMAGE_PROJECTION[3] + "=? ",
new String[]{"image/jpeg", "image/png"}, IMAGE_PROJECTION[2] + " DESC");
return cursorLoader;
} else if (id == LOADER_CATEGORY) {
CursorLoader cursorLoader = new CursorLoader(getActivity(),
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION,
IMAGE_PROJECTION[4] + ">0 AND " + IMAGE_PROJECTION[0] + " like '%" + args.getString("path") +
"%'", null, IMAGE_PROJECTION[2] + " DESC");
return cursorLoader;
}

return null;
}

private boolean fileExist(String path) {
if (!TextUtils.isEmpty(path)) {
return new File(path).exists();
}
return false;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (data != null) {
if (data.getCount() > 0) {
List<Image> images = new ArrayList<>();
data.moveToFirst();
do {
String path = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[0]));
String name = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[1]));
long dateTime = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]));
Image image = null;
if (fileExist(path)) {
image = new Image(path, name, dateTime);
images.add(image);
}
if (!hasFolderGened) {
// 获取文件夹名称
File folderFile = new File(path).getParentFile();
if (folderFile != null && folderFile.exists()) {
String fp = folderFile.getAbsolutePath();
Folder f = getFolderByPath(fp);
if (f == null) {
Folder folder = new Folder();
folder.name = folderFile.getName();
folder.path = fp;
folder.cover = image;
List<Image> imageList = new ArrayList<>();
imageList.add(image);
folder.images = imageList;
mResultFolder.add(folder);
} else {
f.images.add(image);
}
}
}

} while (data.moveToNext());

mImageAdapter.setData(images);
// 设定默认选择
if (resultList != null && resultList.size() > 0) {
mImageAdapter.setDefaultSelected(resultList);
}
final List<Image> imagesMode = images;
mImageAdapter.setOnItemClickListerner(new OnItemClickListerner() {
@Override
public void onPhotoClick(View view, int position) {
List<String> mImgUrls = new ArrayList<>();
for (int i = 0; i < imagesMode.size(); i++) {
mImgUrls.add(imagesMode.get(i).path);
}
int[] screenLocation = new int[2];
view.getLocationOnScreen(screenLocation);
MultiImageSelectorPagerFragment fragment = MultiImageSelectorPagerFragment
.newInstance(mImgUrls, position, mDesireImageCount, screenLocation,
view.getWidth(), view.getHeight());
((MultiImageSelectorActivity) getActivity()).addPhotoPagerFragment(fragment);
}

@Override
public void onMarkClick(Image image, int mode) {
selectImageFromGrid(image, mode);
}
});

if (!hasFolderGened) {
if (mDirPopupWindow != null) {
mDirPopupWindow.setDatas(mResultFolder);
hasFolderGened = true;
}
}

}
}
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {

}
};

private Folder getFolderByPath(String path) {
if (mResultFolder != null) {
for (Folder folder : mResultFolder) {
if (TextUtils.equals(folder.path, path)) {
return folder;
}
}
}
return null;
}


4)选择图片

private void selectImageFromGrid(Image image, int mode) {
Log.e(TAG, "resultList = " + resultList.size());
if (image != null) {
// 多选模式
if (mode == MODE_MULTI) {
if (resultList.contains(image.path)) {
resultList.remove(image.path);
if (resultList.size() != 0) {
mPreviewBtn.setEnabled(true);
mPreviewBtn.setText(String.format("%s(%d)", getResources().getString(R.string.preview),
resultList.size()));
} else {
mPreviewBtn.setEnabled(false);
mPreviewBtn.setText(R.string.preview);
}
if (mCallback != null) {
mCallback.onImageUnselected(image.path);
}
} else {
// 判断选择数量问题
if (mDesireImageCount == resultList.size()) {
Toast.makeText(getActivity(), R.string.msg_amount_limit, Toast.LENGTH_SHORT).show();
return;
}

resultList.add(image.path);
mPreviewBtn.setEnabled(true);
mPreviewBtn.setText(String.format("%s(%d)", getResources().getString(R.string.preview),
resultList.size()));
if (mCallback != null) {
mCallback.onImageSelected(image.path);
}
}
mImageAdapter.select(image);
} else if (mode == MODE_SINGLE) {
// 单选模式
if (mCallback != null) {
mCallback.onSingleImageSelected(image.path);
}
}
}
}


5)展现文件夹的PopupWindow

private void initListDirPopupWindow() {
//屏幕高度
int mScreenHeight = getScreenHeight();
Log.e(TAG, "mResultFolder = " + mResultFolder.size() + ", mScreenHeight = " + mScreenHeight);
mDirPopupWindow = new ListImageDirPopupWindow(ViewGroup.LayoutParams.MATCH_PARENT,
(int) (0.7 * mScreenHeight), mResultFolder, LayoutInflater.from(getActivity())
.inflate(R.layout.list_folder, null));
mDirPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
//设置背景颜色变暗
WindowManager.LayoutParams lp = getActivity().getWindow().getAttributes();
lp.alpha = 1.0f;
getActivity().getWindow().setAttributes(lp);
}
});
//设置选择文件夹的回调
mDirPopupWindow.setOnPhotoDirSelected(new ListImageDirPopupWindow.OnPhotoDirSelected() {
@Override
public void onSelected(List<Folder> datas, int position) {
SharedPreferencesUtils.setParam(getActivity(), "FolderSelectIndex", position);
if (position == 0) {
getActivity().getSupportLoaderManager().restartLoader(LOADER_ALL, null, mLoaderCallback);
mCategoryText.setText(R.string.folder_all);
if (mIsShowCamera) {
mImageAdapter.setShowCamera(true);
} else {
mImageAdapter.setShowCamera(false);
}
} else {
final Folder folder = datas.get(position);
if (null != folder) {
mImageAdapter.setData(folder.images);
mCategoryText.setText(folder.name);
// 设定默认选择
if (resultList != null && resultList.size() > 0) {
mImageAdapter.setDefaultSelected(resultList);
}
mImageAdapter.setOnItemClickListerner(new OnItemClickListerner() {
@Override
public void onPhotoClick(View view, int position) {
List<String> mImgUrls = new ArrayList<>();
for (int i = 0; i < folder.images.size(); i++) {
mImgUrls.add(folder.images.get(i).path);
}
int[] screenLocation = new int[2];
view.getLocationOnScreen(screenLocation);
MultiImageSelectorPagerFragment fragment = MultiImageSelectorPagerFragment
.newInstance(mImgUrls, position, mDesireImageCount, screenLocation,
view.getWidth(), view.getHeight());
((MultiImageSelectorActivity) getActivity()).addPhotoPagerFragment(fragment);
}

@Override
public void onMarkClick(Image image, int mode) {
selectImageFromGrid(image, mode);
}
});
}
mImageAdapter.setShowCamera(false);
}
mGridView.smoothScrollToPosition(0);
mDirPopupWindow.dismiss();
}
});
}


好了,到此结束;整篇由于篇幅原因没有贴任何布局文件,大家自己通过源码查看;

在此希望大家可以通过该案例,能够去其糟粕,取其精华,学习其中值得借鉴的代码风格,不要真的当作一个例子去学习~~

备注:源码中还存在部分异常未处理:如

1)点击预览后,文件夹数量会翻倍,解决方案

2)切换文件夹目录gridview未滑动回顶部

虽然设置了mGridView.smoothScrollToPosition(0),但是也没有效果;网上查到的结果是gridview焦点获取不到,然后就没有然后了。。(本人未去证实),希望有解决方案的朋友留个言,谢谢!

...........................................................................

如有不足之处,望指正!谢谢!

源码地址

转载请注明:http://blog.csdn.net/qq_27305737/article/details/51983796
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息