一個簡單的Android相冊App

分類:技術 時間:2017-01-13

本文文字稍多,源碼下載地址在最后。

01 效果圖

主頁.png

選擇相冊.png

圖片預覽.png

02 用到的技術點

LoaderManager、Glide圖片加載框架、ButterKnife注解、easypermissions、RecyclerView、PopupWindow、ViewPager

03 一小部分關鍵代碼

圖片預覽的ViewPager
public class PreviewViewPager extends ViewPager {
    private boolean mScrolling;
    private float touchDownY;
    private int mTouchSlop;

    public PreviewViewPager(Context context) {
        this(context, null);
    }

    public PreviewViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
    }

    // 由于ViewPager Adapter的Item都有添加點擊事件,為了避免上下滑動和點擊事件的沖突做如下處理。
    // 上下滑動時攔截事件,只有真正的點擊時才執行Item的點擊事件。
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean isBeingDragged = super.onInterceptTouchEvent(ev);

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touchDownY = ev.getY();
                mScrolling = false;
                break;
            case MotionEvent.ACTION_MOVE:
                if (Math.abs(touchDownY - ev.getY()) gt;= mTouchSlop) {
                    mScrolling = true;
                }
                else{
                    mScrolling = false;
                }
                break;

            case MotionEvent.ACTION_UP:
                mScrolling = false;
                break;
        }
        return isBeingDragged ? isBeingDragged : mScrolling;
    }
}
相冊主頁的Fragment
public class AlbumFragment extends BaseFragment implements ImageLoaderListener, View.OnClickListener, BaseRecyclerAdapter.OnItemClickListener{
    @BindView(R.id.rv_image) RecyclerView mContentView;
    @BindView(R.id.btn_title_select) Button mSelectFolderView;
    @BindView(R.id.iv_title_select) ImageView mSelectFolderIcon;
    @BindView(R.id.toolbar) View mToolbar;

    private LoaderListener mCursorLoader;
    private ImageFolderAdapter mImageFolderAdapter;
    private ImageAdapter mImageAdapter;
    private ImageFolderPopupWindow mFolderPopupWindow;
    private String[] mImageSources;

    @Override
    protected int getLayoutId() {
        return R.layout.fragment_select_image;
    }

    @Override
    protected void initWidget(View root) {
        super.initWidget(root);
        mContentView.setLayoutManager(new GridLayoutManager(getActivity(), 4));
        mContentView.addItemDecoration(new SpaceGridItemDecoration((int) DeviceUtil.dipToPx(getResources(), 1)));
        mImageAdapter = new ImageAdapter(getContext(), this);
        mImageFolderAdapter = new ImageFolderAdapter(getContext(), this);
        mContentView.setAdapter(mImageAdapter);
        mContentView.setItemAnimator(null);
        mImageAdapter.setOnItemClickListener(this);
    }

    @Override
    protected void initData() {
        super.initData();
        mCursorLoader = new LoaderListener();
        getLoaderManager().initLoader(0, null, mCursorLoader);
    }

    @Override
    public void displayImage(ImageView iv, String path) {
        // Load image
        getImgLoader().load(path)
                .asBitmap()
                .centerCrop()
                .error(R.mipmap.ic_split_graph)
                .into(iv);
    }

    @OnClick({R.id.btn_title_select})
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_title_select:
                showPopupFolderList();
                break;
        }
    }

    /**
     * 創建彈出的相冊
     */
    private void showPopupFolderList() {
        if (mFolderPopupWindow == null) {
            ImageFolderPopupWindow popupWindow = new ImageFolderPopupWindow(getContext(), new ImageFolderPopupWindow.Callback() {
                @Override
                public void onSelect(ImageFolder imageFolder) {
                    addImagesToAdapter(imageFolder.getImages());
                }

                @Override
                public void onDismiss() {
                    mSelectFolderIcon.setImageResource(R.mipmap.ic_arrow_bottom);
                }

                @Override
                public void onShow() {
                    mSelectFolderIcon.setImageResource(R.mipmap.ic_arrow_top);
                }
            });
            popupWindow.setAdapter(mImageFolderAdapter);
            mFolderPopupWindow = popupWindow;
        }
        mFolderPopupWindow.showAsDropDown(mToolbar);
    }

    @Override
    public void onItemClick(int position) {
        ImageGalleryActivity.show(getContext(), mImageSources, position);
    }

    private class LoaderListener implements LoaderManager.LoaderCallbackslt;Cursorgt; {
        private final String[] IMAGE_PROJECTION = {
                MediaStore.Images.Media.DATA,
                MediaStore.Images.Media.DISPLAY_NAME,
                MediaStore.Images.Media.DATE_ADDED,
                MediaStore.Images.Media._ID,
                MediaStore.Images.Media.MINI_THUMB_MAGIC,
                MediaStore.Images.Media.BUCKET_DISPLAY_NAME};

        @Override
        public Loaderlt;Cursorgt; onCreateLoader(int id, Bundle args) {
            if (id == 0) {
                //數據庫光標加載器
                return new CursorLoader(getContext(),
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION,
                        null, null, IMAGE_PROJECTION[2]   quot; DESCquot;);
            }
            return null;
        }

        @Override
        public void onLoadFinished(Loaderlt;Cursorgt; loader, Cursor data) {
            if (data != null) {
                final ArrayListlt;Imagegt; images = new ArrayListlt;gt;();
                final Listlt;ImageFoldergt; imageFolders = new ArrayListlt;gt;();

                final ImageFolder defaultFolder = new ImageFolder();
                defaultFolder.setName(quot;全部照片quot;);
                defaultFolder.setPath(quot;quot;);
                imageFolders.add(defaultFolder);

                int count = data.getCount();
                if (count gt; 0) {
                    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]));
                        int id = data.getInt(data.getColumnIndexOrThrow(IMAGE_PROJECTION[3]));
                        String thumbPath = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[4]));
                        String bucket = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[5]));

                        Image image = new Image();
                        image.setPath(path);
                        image.setName(name);
                        image.setDate(dateTime);
                        image.setId(id);
                        image.setThumbPath(thumbPath);
                        image.setFolderName(bucket);

                        images.add(image);

                        File imageFile = new File(path);
                        File folderFile = imageFile.getParentFile();
                        ImageFolder folder = new ImageFolder();
                        folder.setName(folderFile.getName());
                        folder.setPath(folderFile.getAbsolutePath());
                        if (!imageFolders.contains(folder)) {
                            folder.getImages().add(image);
                            folder.setAlbumPath(image.getPath());//默認相冊封面
                            imageFolders.add(folder);
                        } else {
                            // 更新
                            ImageFolder f = imageFolders.get(imageFolders.indexOf(folder));
                            f.getImages().add(image);
                        }
                    } while (data.moveToNext());
                }

                addImagesToAdapter(images);
                defaultFolder.getImages().addAll(images);
                defaultFolder.setAlbumPath(images.size() gt; 0 ? images.get(0).getPath() : null);
                mImageFolderAdapter.resetItem(imageFolders);
            }
        }

        @Override
        public void onLoaderReset(Loaderlt;Cursorgt; loader) {
        }
    }

    private void addImagesToAdapter(ArrayListlt;Imagegt; images) {
        mImageAdapter.resetItem(images);
        mImageSources = toArray(images);
    }

    private static String[] toArray(Listlt;Imagegt; images) {
        if (images == null)
            return null;
        int len = images.size();
        if (len == 0)
            return null;

        String[] strings = new String[len];
        int i = 0;
        for (Image image : images) {
            strings[i] = image.getPath();
            i  ;
        }
        return strings;
    }
}
圖片文件夾選擇(PopupWindow)
public class ImageFolderPopupWindow extends PopupWindow implements View.OnAttachStateChangeListener, BaseRecyclerAdapter.OnItemClickListener{
    private ImageFolderAdapter mAdapter;
    private RecyclerView mFolderView;

    private Callback mCallback;

    public ImageFolderPopupWindow(Context context, Callback callback) {
        super(LayoutInflater.from(context).inflate(R.layout.popup_window_folder, null),
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);

        mCallback = callback;

        // init
        setAnimationStyle(R.style.popup_anim_style_alpha);
        setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        setOutsideTouchable(true);
        setFocusable(true);

        // content
        View content = getContentView();
        content.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
            }
        });

        content.addOnAttachStateChangeListener(this);

        mFolderView = (RecyclerView) content.findViewById(R.id.rv_popup_folder);
        mFolderView.setLayoutManager(new LinearLayoutManager(context));
    }

    public void setAdapter(ImageFolderAdapter adapter) {
        this.mAdapter = adapter;
        mFolderView.setAdapter(adapter);
        mAdapter.setOnItemClickListener(this);
    }

    @Override
    public void onItemClick(int position) {
        if (mCallback != null) mCallback.onSelect(mAdapter.getItem(position));
        dismiss();
    }

    @Override
    public void onViewAttachedToWindow(View v) {
        if(mCallback != null) mCallback.onShow();
    }

    @Override
    public void onViewDetachedFromWindow(View v) {
        if(mCallback != null) mCallback.onDismiss();
    }

    public interface Callback {
        void onSelect(ImageFolder imageFolder);
        void onDismiss();
        void onShow();
    }
}

04 源碼

源碼 下載地址

05 PhotoAlbum apk

PhotoAlbum apk 下載地址


Tags: 安卓開發

文章來源:http://www.jianshu.com/p/aba7e513dfa4


ads
ads

相關文章
ads

相關文章

ad