Fallery — A fully customizable media picker for android

https://github.com/mehdiyari/Fallery

Fallery is customizable media picker for android. Fallery is compatible with android API Level 14 to 30 and has a lot of cool features that you can see below.

Key features

1. Select media(photo, video) from android media store with custom offline gallery or custom online gallery.
2. Compatible with android API Level 14 to 30.
3. Content Observer.
4. Filter media based on types(Photos, videos, both).
5. Modern user interface with the capability to add new themes and languages.
6. Select media with a caption.
7. Taking photos from the camera with the intent.
8. Showing bucket list in two different UI(grid and linear) which user can switches between them in runtime.
9. Support setting max selectable media by user.
10. Support orientation.
11. Support custom edit text layout for caption(for emoji compatibility, etc).
12. Enable or disable media counts in fallery toolbar.
13. Support Vertical, Horizontal scrolling in showing media view-pager.
14. Support any view-pager transformer in media view-pager.
15. Support custom onClick for video toggle in the video preview screen.
16. Automatic grant external storage permissions.
17. Automatic grant shared storage permissions(only for android +10).
18. Easy to use.

Usage

How to add Fallery to android app ?

Gradle. Step 1. Add it in your root build.gradle at the end of repositories:

allprojects {
repositories {
maven { url 'https://jitpack.io' }
}
}

Step 2. Add the dependency

dependencies {
implementation 'com.github.mehdiyari:Fallery:{latest_version}'
}

Maven

<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependency>
<groupId>com.github.mehdiyari</groupId>
<artifactId>Fallery</artifactId>
<version>{latest_version}</version>
</dependency>

How to use Fallery for pick medias on device ?

Fallery designed to be used in java and kotlin. but before starting fallery you must set an image loader because fallery does not use any image loader libraries by default. for creating fallery image loader you must create ImageLoader and implement the FalleryImageLoader interface like this.

class GlideImageLoader : FalleryImageLoader {

override fun loadPhoto(
context: Context,
imageView: ImageView,
resizeDiminution: PhotoDiminution,
placeHolderColor: Int,
path: String
) {
Glide.with(imageView)
.asBitmap()
.placeholder(ColorDrawable(placeHolderColor))
.load(path)
.override(resizeDiminution.width, resizeDiminution.height)
.into(imageView)
}

override fun loadGif(
context: Context,
imageView: ImageView,
resizeDiminution: PhotoDiminution,
placeHolderColor: Int,
path: String
) {
Glide.with(imageView)
.asGif()
.placeholder(ColorDrawable(placeHolderColor))
.load(path)
.override(resizeDiminution.width, resizeDiminution.height)
.into(imageView)
}
}

And simply passing the new object of this class to FalleryBuilder. below you can see kotlin and java examples.

Kotlin

class MainActivity : AppCompatActivity(R.layout.activity_main) {

private val glideImageLoader by lazy { GlideImageLoader() }

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val falleryOptions = FalleryBuilder()
.setImageLoader(glideImageLoader)
.build()

falleryButton.setOnClickListener {
startFalleryWithOptions(requestCode = 1, falleryOptions = falleryOptions)
}
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 1 && resultCode == RESULT_OK && data != null) {
handleResultWithCaption(
result = data?.getFalleryResultMediasFromIntent(),
caption = data?.getFalleryCaptionFromIntent()
)
}
}

private fun handleResultWithCaption(result: Array<String>?, caption: String?) {
TODO("handle result and caption")
}
}

Java

public class MainActivity extends AppCompatActivity {

private Button button;
private GlideImageLoader glideImageLoader = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
glideImageLoader = New GlideImageLoader();

final FalleryOptions falleryOptions = new FalleryBuilder()
.setImageLoader(glideImageLoader)
.build();

this.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Fallery.startFalleryFromActivityWithOptions(
MainActivity.this, 1, falleryOptions
);
}
});
}

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == RESULT_OK && data != null) {
String[] result = Fallery.getResultMediasFromIntent(data);
String caption = Fallery.getCaptionFromIntent(data);
handleResultWithCaption(result, caption);
}
}

private void handleResultWithCaption(String[] result, String caption) {
// todo: handle result and caption
}
}

These examples show how to start fallery in java/kotlin activity. for fragments, in kotlin, you can start fallery with startFalleryWithOptions but for java, you must start fallery with Fallery.startFalleryFromFragmentWithOptions and override onActivityResult method for fragment and extract the result from input intent.

Create a custom offline/online gallery with Fallery

As an Android developer, in many scenarios, we need our app user to select media from the media’s on the mediastore, internet, assets, or cache dir. Fallery offers a solution to this problem.

What is fallery solution ?

Fallery fallery has two interface for providing data AbstractMediaBucketProviderandAbstractBucketContentProvider. You can create two classes and implement these interfaces like this

class CustomOnlineBucketProvider : AbstractMediaBucketProvider {

override suspend fun getMediaBuckets(bucketType: BucketType): List<MediaBucket> {
// get buckets list from any datasource
}
}
class CustomOnlineBucketContentProvider : AbstractBucketContentProvider {

override suspend fun getMediasOfBucket(
bucketId: Long,
bucketType: BucketType
): Flow<List<Media>> {
// get bucket content by bucketId from any datasource
}
}

And simply passing concreate classes to FalleryBuilder

FalleryBuilder()
.setImageLoader(glideImageLoader)
.setContentProviders(CustomOnlineBucketContentProvider(), CustomOnlineBucketProvider())
.setMediaObserverEnabled(false)
.setGrantExternalStoragePermission(false)
.build()

You can find out more examples in the fallery example app in Github.

Contribute

If you have free time I would very much appreciate your contributions.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store