1. 程式人生 > >android 仿微信多圖選擇器(帶預覽、照相功能)

android 仿微信多圖選擇器(帶預覽、照相功能)

  • 實現了單選、多選 、拍照 、預覽 等功能;
先上圖:

    

程式碼結構


 下面不如正題:

一、新增依賴、許可權

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