├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── creative │ │ └── multiimagepicker │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── creative │ │ │ └── multiimagepicker │ │ │ └── MainActivity.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ └── test │ └── java │ └── com │ └── creative │ └── multiimagepicker │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jitpack.yml ├── multiimagepicker ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── creativechintak │ │ └── multiimagepicker │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── creativechintak │ │ │ └── multiimagepicker │ │ │ ├── Constants.kt │ │ │ ├── GalleryActivity.kt │ │ │ ├── StartImagePickerActivity.kt │ │ │ ├── adapter │ │ │ └── ImagesAdapter.kt │ │ │ ├── builder │ │ │ └── MultiImagePicker.kt │ │ │ ├── helper │ │ │ └── FileUtils.kt │ │ │ └── model │ │ │ └── ImageModel.kt │ └── res │ │ ├── drawable │ │ ├── border_image.xml │ │ ├── icon_header_back.xml │ │ └── icon_item_selected.xml │ │ ├── layout │ │ ├── activity_gallery.xml │ │ ├── layout_gallery_picker_toolbar.xml │ │ └── layout_image_item.xml │ │ ├── values-land │ │ └── integers.xml │ │ ├── values-large-land │ │ └── integers.xml │ │ ├── values-large │ │ └── integers.xml │ │ └── values │ │ ├── colors.xml │ │ ├── integers.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── creativechintak │ └── multiimagepicker │ └── ExampleUnitTest.kt ├── sampleimages └── multiimagepicker-demo.gif └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MultiImagePicker 2 | [![](https://jitpack.io/v/chintan369/MultiImagePicker.svg)](https://jitpack.io/#chintan369/MultiImagePicker) 3 | 4 | This library allows to select multiple image selection option in Android to select device images rather than selecting a single image from Gallery intent. 5 | 6 | This library provides a simple implementation to call Gallery intent for multiple image selection as well as easy to get the result in Uri list. You can also request the absolute filepath instead of Uri in response. 7 | 8 | Demo and Features with Explaination: [https://youtu.be/stjLSTfnDVo](https://youtu.be/stjLSTfnDVo) 9 | 10 | ## Add Dependency 11 | Use Gradle: 12 | 13 | **Step 1:** Add it in your root _`build.gradle`_ at the end of repositories: 14 | ```gradle 15 | allprojects { 16 | repositories { 17 | ... 18 | maven { url 'https://jitpack.io' } 19 | } 20 | } 21 | ``` 22 | 23 | **Note:** In New Android studio updates, now `allProjects` block has been removed from root `build.gradle` file. So you must add this repository to your root _`settings.gradle`_ as below: 24 | ```gradle 25 | dependencyResolutionManagement { 26 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 27 | repositories { 28 | ... 29 | maven { url "https://jitpack.io" } 30 | } 31 | } 32 | ``` 33 | 34 | **Step 2:** Add the dependency in your module's (e.g. app or any other) _`build.gradle`_ file: 35 | ```gradle 36 | dependencies { 37 | ... 38 | implementation 'com.github.chintan369:MultiImagePicker:' 39 | } 40 | ``` 41 | 42 | or use Maven: 43 | ```xml 44 | 45 | 46 | jitpack.io 47 | https://jitpack.io 48 | 49 | 50 | 51 | 52 | com.github.chintan369 53 | MultiImagePicker 54 | latest-version 55 | 56 | ``` 57 | 58 | ## How do I use MultiImagePicker? 59 | In your `Activity` or `Fragment`, wherever you want to call the multiple image selection, call `MultiImagePicker` as below with your selection limit configuration: 60 | 61 | ### Requesting to select images 62 | Using Java / Kotlin: 63 | ```kotlin 64 | MultiImagePicker.with(this) // `this` refers to activity or fragment 65 | .setSelectionLimit(10) // The number of max image selection you want from user at a time, MAX is 30 66 | .open() // This will open image selection activity to select images 67 | ``` 68 | 69 | **Note:** Even if you will set selection limit to `< 1` or `> 30`, MultiImagePicker will set the limit to `30` by default and continue. 70 | 71 | ### Handle Result after images selection 72 | When user has completed with images selection and clicks `Done`, MultiImagePicker will come back to the calling `Activity` or `Fragment` and returns the result in `onActivityResult` method. 73 | 74 | In `onActivityResult(requestCode, resultCode, data)` method, handle the result and get the selected image list either in Uri list or in absolute filepath list: 75 | 76 | Using Kotlin: 77 | ```kotlin 78 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { 79 | super.onActivityResult(requestCode, resultCode, data) 80 | ... 81 | if (requestCode == MultiImagePicker.REQUEST_PICK_MULTI_IMAGES && resultCode == RESULT_OK) { 82 | val result = MultiImagePicker.Result(data) 83 | if (result.isSuccess()) { 84 | val imageListInUri = result.getImageList() // List os selected images as content Uri format 85 | //You can also request list as absolute filepath instead of Uri as below 86 | val imageListInAbsFilePath = result.getImageListAsAbsolutePath(context) 87 | 88 | //do your stuff from the selected images list received 89 | } 90 | } 91 | } 92 | ``` 93 | 94 | or using Java: 95 | ```java 96 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 97 | super.onActivityResult(requestCode, resultCode, data) 98 | ... 99 | if (requestCode == MultiImagePicker.REQUEST_PICK_MULTI_IMAGES && resultCode == RESULT_OK) { 100 | MultiImagePicker.Result result = new MultiImagePicker.Result(data) 101 | if (result.isSuccess()) { 102 | ArrayList imageListInUri = result.getImageList() // List os selected images as content Uri format 103 | //You can also request list as absolute filepath instead of Uri as below 104 | ArrayList imageListInAbsFilePath = result.getImageListAsAbsolutePath(context) 105 | 106 | //do your stuff from the selected images list received 107 | } 108 | } 109 | } 110 | ``` 111 | 112 | ## Demo 113 | 114 | 115 | 116 | That's pretty simple to use and enjoy the library! 117 | 118 | If you requires more features and customization on this library, Create an issue with title prefix - "Requires feature/customization - ". 119 | 120 | Also for my work, if you liked it, then you can Buy me a Coffee from here: 121 | 122 | Buy Me A Coffee 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'kotlin-android' 4 | } 5 | 6 | android { 7 | compileSdk 33 8 | 9 | defaultConfig { 10 | applicationId "com.creative.multiimagepicker" 11 | minSdk 21 12 | targetSdk 33 13 | versionCode 1 14 | versionName "1.0" 15 | 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | } 18 | 19 | buildFeatures { 20 | viewBinding = true 21 | } 22 | 23 | buildTypes { 24 | release { 25 | minifyEnabled false 26 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 27 | } 28 | } 29 | compileOptions { 30 | sourceCompatibility JavaVersion.VERSION_11 31 | targetCompatibility JavaVersion.VERSION_11 32 | } 33 | kotlinOptions { 34 | jvmTarget = '11' 35 | } 36 | } 37 | 38 | dependencies { 39 | 40 | implementation 'androidx.core:core-ktx:1.6.0' 41 | implementation 'androidx.appcompat:appcompat:1.3.1' 42 | implementation 'com.google.android.material:material:1.4.0' 43 | implementation 'androidx.constraintlayout:constraintlayout:2.1.1' 44 | testImplementation 'junit:junit:4.+' 45 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 46 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 47 | 48 | implementation project(':multiimagepicker') 49 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/creative/multiimagepicker/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.creative.multiimagepicker 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.creative.multiimagepicker", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/creative/multiimagepicker/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.creative.multiimagepicker 2 | 3 | import android.content.Intent 4 | import androidx.appcompat.app.AppCompatActivity 5 | import android.os.Bundle 6 | import android.util.Log 7 | import com.creative.multiimagepicker.databinding.ActivityMainBinding 8 | import com.creativechintak.multiimagepicker.builder.MultiImagePicker 9 | 10 | class MainActivity : AppCompatActivity() { 11 | 12 | private lateinit var binding: ActivityMainBinding 13 | 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | super.onCreate(savedInstanceState) 16 | binding = ActivityMainBinding.inflate(layoutInflater) 17 | val view = binding.root 18 | setContentView(view) 19 | 20 | binding.btnPickImage.setOnClickListener { 21 | openImagePicker() 22 | } 23 | } 24 | 25 | private fun openImagePicker() { 26 | MultiImagePicker.with(this) 27 | .setSelectionLimit(10) 28 | .open() 29 | } 30 | 31 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { 32 | super.onActivityResult(requestCode, resultCode, data) 33 | 34 | if(requestCode == MultiImagePicker.REQUEST_PICK_MULTI_IMAGES && resultCode == RESULT_OK){ 35 | val result = MultiImagePicker.Result(data) 36 | if(result.isSuccess()){ 37 | val imageList = result.getImageList() 38 | 39 | imageList.forEach { 40 | Log.e("Image Uri ->",it.toString()) 41 | } 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 |