BSImagePicker
An image picker that extends BottomSheetDialogFragment. Camera and gallery all in one dialog. Single or Multi Selection.
Why this library?
When your app needs user to pick one or more images from their device, it is still quite painful in Android.
Without any customization, you first need to ask user whether he/she wants to take a picture using camera, or select one from a Gallery app.
Then you have to write quite some code to launch a Camera intent.
Not to mention that you cannot even let user select multiple images.
So an image picker that solve all these pains is almost present in every app.
And this library does the below:
- Without the need to ask user whether to take photo or select from gallery, these options are all in one dialog;
- Works for both single and multiple selections;
- Handle asking permissions for you;
- You just need to show this dialog, and register callbacks that give you a
Uri
orList<Uri>
.
The UI design of this library is referenced from TedBottomPicker.
I like the design of his library! And in fact I have used his library in 2 production apps already.
But there are still some defects that annoyed me:
- You need to handle permissions by yourself; but as a
Fragment
, it is a perfect place to handle by itself; - I don't like the design of his multiple selection mode;
- He query media files on the Main Thread. If you query all images in the device, that will absolutely block your app's response! I implemented using CursorLoader instead;
- He does not handle fragment lifecycle correctly. Quite some number of crashes due to referencing a null
Context
has been reported from my production apps, and his library cannot survive configuration change (e.g. device rotation); - He is still using Glide v3 instead of v4.
- He hard-coded to use his own
FileProvider
, which will crash if your app has your ownFileProvider
.
But note that BSImagePicker
does not allow selection from camera and gallery when in multi selection mode, which is possible in TedBottomPicker
, due to the difference in UIUX.
Also, a recent release of TedBottomPicker
also supports selecting vidoes. This is not supported by BSImagePicker
as well.
How to Use
Minimum SDK: 16
Add to Project
First make sure jcenter()
is included as a repository in your project's build.gradle:
And then add the below to your app's build.gradle:
You also need to make sure you have included 'com.android.support:support-v4:{supportLibraryVersion}
in your dependencies.
Step 1: Create your own FileProvider
Just follow the guide from Official Android Document.
Step 2: Create a BSImagePicker using a builder
After you have defined your own FileProvider
, pass the authority String to the constructor of BSImagePicker.Builder
.
The below code snippet also shows all configurables, with some description.
Single Selection:
Multiple Selection:
Step 3: Register callbacks
In order to survive configuration change, I cannot let you simply pass an anonymous interface to the builder. That callback will become null when device orientation changes.
So, your caller Activity or Fragment must implements OnSingleImageSelectedListener
or OnMultiImageSelectedListener
.
Step 4: Show the picker, which is essentially just a DialogFragment
Customization of layouts
You can easily customize various layouts and string resources by simply overriding the original resource I defined in the library.
Customize layout of camera tile or gallery tile
Define your own R.layout.item_picker_camera_tile.xml
or R.layout.item_picker_gallery_tile.xml
. But make sure the root ViewGroup is a FitWidthRelativeLayout
with app:view_aspectRatio="1"
.
You do not need to specify any View id.
Customize String resources of the bottom bar of multi-selection
Define below String resources with the same ID in your own app:
IMPORTANT: Your string resources must match the number of replaceables (%d) with the original resources above.
You ask why don't I use plurals? See this post.
Limitations
- You cannot filter the images showing in the picker, e.g. From only a specific folder.
- Since the customization of layouts are done by resource overriding, it is impossible to set different style for different pickers in the same app. I consider this as an edge case.
Release notes
v1.0.1
First Release.