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

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值