ImagePicker Libraries and Examples
In this article we will explore some awesome android gallery imagepicker libraries. These are libraries designed to pick images from the gallery or filesystem. This tutorial is seperate from one where we'd looked at libraries that allow us to both capture and pick images. You can find that tutorial here.
Example 1: Kotlin Standard ImagePicker with Runtime Permissions
In the first example we will show you how to pick an image from the gallery in kotlin android without any third party library. Then you wil proceed to check out how to do it using third party libraries.
Step 1: Create Project
Start by creating an empty Android Studio
project.
Step 2: Dependencies
No external dependency is used in this example.
Step 3: Add Permission
We need to pick an image from the gallery. Those images may be stored in the external storage. So we need to declare the external storage permission in our AndroidManifest.xml
:
Step 4: Design Layout
The picked image will be shown in the ImageView. We will show a button and an imageView in our layout. The user presses the button then the imagepicker is launched. We pick an image and it gets shown in the ImageView.
Design your layout as follows:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<ImageView
android:id="@+id/image_view"
android:layout_width="300dp"
android:layout_height="300dp"
android:src="@drawable/ic_image_black_24dp"/>
<Button
android:id="@+id/btn"
android:layout_marginTop="20dp"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:text="Select Image"
android:textColor="@android:color/white"
android:textSize="20sp"/>
</LinearLayout>
Step 5: Pick and Show Image
We will do these by writing code. Go to your MainActivity.kt
and declare the following imports:
import android.Manifest
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*
Extend the AppCompatActivity
, the initialize two integers as instance fields:
class MainActivity : AppCompatActivity() {
private val GALLERY = 100
private val GALLERY_PERMISSION_CODE = 101
Here is how you initiate or show the ImagePicker using Intent:
fun pickupImageFromGallery()
{
val intent = Intent(Intent.ACTION_PICK)
intent.type = "image/*"
startActivityForResult(intent, GALLERY)
}
When our button is clicked we will check runtime permissions then show our imagepicker, if the permission is granted:
btn.setOnClickListener {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED)
{
//permission denied
val permission = arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE)
//show popup to request runtime permission
requestPermissions(permission, GALLERY_PERMISSION_CODE)
}
else
{
//permission already granted
pickupImageFromGallery()
}
}
else
{
//system os is < Marshmallow
pickupImageFromGallery()
}
}
Here's the full code:
MainActivity.kt
import android.Manifest
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private val GALLERY = 100
private val GALLERY_PERMISSION_CODE = 101
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn.setOnClickListener {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED)
{
//permission denied
val permission = arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE)
//show popup to request runtime permission
requestPermissions(permission, GALLERY_PERMISSION_CODE)
}
else
{
//permission already granted
pickupImageFromGallery()
}
}
else
{
//system os is < Marshmallow
pickupImageFromGallery()
}
}
}
fun pickupImageFromGallery()
{
val intent = Intent(Intent.ACTION_PICK)
intent.type = "image/*"
startActivityForResult(intent, GALLERY)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray)
{
when(requestCode)
{
GALLERY_PERMISSION_CODE ->
{
if (grantResults.size >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
//permission from popup granted
pickupImageFromGallery()
}
else
{
//permission from popup denied
Toast.makeText(this,"permission denied",Toast.LENGTH_SHORT).show()
}
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && requestCode == GALLERY)
{
image_view.setImageURI(data?.data)
}
}
}
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |
3. | Code: Apache 2.0 License |
Example 2: Kotlin Android Take Picture with Camera - No Library
The second example will look at how to capture an image from the camera in Kotlin Android. In this case we do not use any third party library. However later on we will see how to both capture and pick images using third party libraries.
Step 1: Create Project
Start by creating an empty Android Studio
project.
Step 2: Dependencies
No third party dependency is needed for this project.
Step 3: Add Permissions
We do need two permissions: to write to external storage and to access camera. The access camera permission will allow us launch the camera to capture our image. However after we've captured the image we need the write-to-external storage permission so that we can save and render the image.
Add these two permissions in your android manifest file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
Step 4: Design Layout
Add a button and imageview to your xml layout. The button will launch the camera while the imageview will render the captured image:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<ImageView
android:id="@+id/image_view"
android:layout_width="300dp"
android:layout_height="300dp"
android:src="@drawable/ic_image_black_24dp"/>
<Button
android:id="@+id/btn"
android:layout_marginTop="20dp"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:background="@color/colorAccent"
android:textSize="20dp"
android:text="Take Picture"
android:textColor="@android:color/white"/>
</LinearLayout>
Step 5: Capture Image and render it
Here is the code for opening the camera and capturing the image:
fun openCamera()
{
val values = ContentValues()
values.put(MediaStore.Images.Media.TITLE, "New Picture")
values.put(MediaStore.Images.Media.DESCRIPTION, "From the Camera")
image_uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri)
startActivityForResult(cameraIntent, CAMERA)
}
Here is the code for rendering the captured image in an imageview using the setImageUri
inside the onActivityResult()
callback:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK)
{
//set image capture to image view
image_view.setImageURI(image_uri)
}
}
Here is the code for checking the runtime permissions before invoking the camera:
btn.setOnClickListener {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED ||
checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED)
{
//permission was not enabled
val permission = arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
//show popup to request permission
requestPermissions(permission, CAMERA_PERMISSION_CODE)
}
else
{
//permission already granted
openCamera()
}
}
else
{
//system os is < marshmallow
openCamera()
}
}
Here is the full code:
MainActivity.kt
import android.Manifest
import android.app.Activity
import android.content.ContentValues
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.MediaStore
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private val CAMERA = 100
private val CAMERA_PERMISSION_CODE = 101
var image_uri : Uri? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn.setOnClickListener {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED ||
checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED)
{
//permission was not enabled
val permission = arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
//show popup to request permission
requestPermissions(permission, CAMERA_PERMISSION_CODE)
}
else
{
//permission already granted
openCamera()
}
}
else
{
//system os is < marshmallow
openCamera()
}
}
}
fun openCamera()
{
val values = ContentValues()
values.put(MediaStore.Images.Media.TITLE, "New Picture")
values.put(MediaStore.Images.Media.DESCRIPTION, "From the Camera")
image_uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri)
startActivityForResult(cameraIntent, CAMERA)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray)
{
when(requestCode)
{
CAMERA_PERMISSION_CODE ->
{
if (grantResults.size >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
//permission from popu granted
openCamera()
}
else
{
//permission from popup denied
Toast.makeText(this,"permission denied", Toast.LENGTH_SHORT).show()
}
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK)
{
//set image capture to image view
image_view.setImageURI(image_uri)
}
}
}
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |
3. | Code: Apache 2.0 License |
Let us now see how to use third party libraries to capture or pick.
(a). TedBottomPicker
TedBottomPicker is simple image picker using bottom sheet.
Bottom sheets slide up from the bottom of the screen to reveal more content.
If you want pick image from gallery or take picture, this library can help easily. TedBottomPicker provide 3 options:
- Take a picture by camera(using
MediaStore.ACTION_IMAGE_CAPTURE
intent) - Get image from gallery(using
Intent.ACTION_PICK
intent) - Get image from recent image(using
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
cursor)
TedBottomPicker is simple image picker using bottom sheet.
Step 1: Install TedBottomPicker
In your app level add the implementation statement for this library:
dependencies {
implementation 'gun0912.ted:tedbottompicker:x.y.z'
//implementation 'gun0912.ted:tedbottompicker:2.0.1'
}
Step 2: Check Permission
You have to grant WRITE_EXTERNAL_STORAGE
permission from user. If your targetSDK version is 23+, you have to check permission and request permission to user. Because after Marshmallow(6.0), you have to not only declare permissions in AndroidManifest.xml
but also request permissions at runtime.
Step 3: Start TedBottomPicker
This library supports two styles:
- RxJava
- Listener
For RxJava, here is how you pick a single image:
TedRxBottomPicker.with(MainActivity.this)
.show()
.subscribe(uri ->
// here is selected image uri
}, Throwable::printStackTrace);
and multuple images:
TedRxBottomPicker.with(MainActivity.this)
//.setPeekHeight(getResources().getDisplayMetrics().heightPixels/2)
.setPeekHeight(1600)
.showTitle(false)
.setCompleteButtonText("Done")
.setEmptySelectionText("No Select")
.setSelectedUriList(selectedUriList)
.showMultiImage()
.subscribe(uris -> {
// here is selected image uri list
}, Throwable::printStackTrace);
As for the listener style, here is how you pick a single image:
TedBottomPicker.with(MainActivity.this)
.show(new TedBottomSheetDialogFragment.OnImageSelectedListener() {
@Override
public void onImageSelected(Uri uri) {
// here is selected image uri
}
});
and multiple images:
TedBottomPicker.with(MainActivity.this)
.setPeekHeight(1600)
.showTitle(false)
.setCompleteButtonText("Done")
.setEmptySelectionText("No Select")
.setSelectedUriList(selectedUriList)
.showMultiImage(new TedBottomSheetDialogFragment.OnMultiImageSelectedListener() {
@Override
public void onImagesSelected(List<Uri> uriList) {
// here is selected image uri list
}
});
Full Example
Here is a full example. You wil be able to download:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private ImageView iv_image;
private List<Uri> selectedUriList;
private Uri selectedUri;
private Disposable singleImageDisposable;
private Disposable multiImageDisposable;
private ViewGroup mSelectedImagesContainer;
private RequestManager requestManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv_image = findViewById(R.id.iv_image);
mSelectedImagesContainer = findViewById(R.id.selected_photos_container);
requestManager = Glide.with(this);
setSingleShowButton();
setMultiShowButton();
setRxSingleShowButton();
setRxMultiShowButton();
}
private void setSingleShowButton() {
Button btnSingleShow = findViewById(R.id.btn_single_show);
btnSingleShow.setOnClickListener(view -> {
PermissionListener permissionlistener = new PermissionListener() {
@Override
public void onPermissionGranted() {
TedBottomPicker.with(MainActivity.this)
//.setPeekHeight(getResources().getDisplayMetrics().heightPixels/2)
.setSelectedUri(selectedUri)
//.showVideoMedia()
.setPeekHeight(1200)
.show(uri -> {
Log.d("ted", "uri: " + uri);
Log.d("ted", "uri.getPath(): " + uri.getPath());
selectedUri = uri;
iv_image.setVisibility(View.VISIBLE);
mSelectedImagesContainer.setVisibility(View.GONE);
requestManager
.load(uri)
.into(iv_image);
});
}
@Override
public void onPermissionDenied(ArrayList<String> deniedPermissions) {
Toast.makeText(MainActivity.this, "Permission Denied\n" + deniedPermissions.toString(), Toast.LENGTH_SHORT).show();
}
};
checkPermission(permissionlistener);
});
}
private void setMultiShowButton() {
Button btnMultiShow = findViewById(R.id.btn_multi_show);
btnMultiShow.setOnClickListener(view -> {
PermissionListener permissionlistener = new PermissionListener() {
@Override
public void onPermissionGranted() {
TedBottomPicker.with(MainActivity.this)
//.setPeekHeight(getResources().getDisplayMetrics().heightPixels/2)
.setPeekHeight(1600)
.showTitle(false)
.setCompleteButtonText("Done")
.setEmptySelectionText("No Select")
.setSelectedUriList(selectedUriList)
.showMultiImage(uriList -> {
selectedUriList = uriList;
showUriList(uriList);
});
}
@Override
public void onPermissionDenied(ArrayList<String> deniedPermissions) {
Toast.makeText(MainActivity.this, "Permission Denied\n" + deniedPermissions.toString(), Toast.LENGTH_SHORT).show();
}
};
checkPermission(permissionlistener);
});
}
private void setRxSingleShowButton() {
Button btnSingleShow = findViewById(R.id.btn_rx_single_show);
btnSingleShow.setOnClickListener(view -> {
PermissionListener permissionlistener = new PermissionListener() {
@Override
public void onPermissionGranted() {
singleImageDisposable = TedRxBottomPicker.with(MainActivity.this)
//.setPeekHeight(getResources().getDisplayMetrics().heightPixels/2)
.setSelectedUri(selectedUri)
//.showVideoMedia()
.setPeekHeight(1200)
.show()
.subscribe(uri -> {
selectedUri = uri;
iv_image.setVisibility(View.VISIBLE);
mSelectedImagesContainer.setVisibility(View.GONE);
requestManager
.load(uri)
.into(iv_image);
}, Throwable::printStackTrace);
}
@Override
public void onPermissionDenied(ArrayList<String> deniedPermissions) {
Toast.makeText(MainActivity.this, "Permission Denied\n" + deniedPermissions.toString(), Toast.LENGTH_SHORT).show();
}
};
checkPermission(permissionlistener);
});
}
private void setRxMultiShowButton() {
Button btnRxMultiShow = findViewById(R.id.btn_rx_multi_show);
btnRxMultiShow.setOnClickListener(view -> {
PermissionListener permissionlistener = new PermissionListener() {
@Override
public void onPermissionGranted() {
multiImageDisposable = TedRxBottomPicker.with(MainActivity.this)
//.setPeekHeight(getResources().getDisplayMetrics().heightPixels/2)
.setPeekHeight(1600)
.showTitle(false)
.setCompleteButtonText("Done")
.setEmptySelectionText("No Select")
.setSelectedUriList(selectedUriList)
.showMultiImage()
.subscribe(uris -> {
selectedUriList = uris;
showUriList(uris);
}, Throwable::printStackTrace);
}
@Override
public void onPermissionDenied(ArrayList<String> deniedPermissions) {
Toast.makeText(MainActivity.this, "Permission Denied\n" + deniedPermissions.toString(), Toast.LENGTH_SHORT).show();
}
};
checkPermission(permissionlistener);
});
}
private void checkPermission(PermissionListener permissionlistener) {
TedPermission.with(MainActivity.this)
.setPermissionListener(permissionlistener)
.setDeniedMessage("If you reject permission,you can not use this service\n\nPlease turn on permissions at [Setting] > [Permission]")
.setPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE)
.check();
}
private void showUriList(List<Uri> uriList) {
// Remove all views before
// adding the new ones.
mSelectedImagesContainer.removeAllViews();
iv_image.setVisibility(View.GONE);
mSelectedImagesContainer.setVisibility(View.VISIBLE);
int widthPixel = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());
int heightPixel = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());
for (Uri uri : uriList) {
View imageHolder = LayoutInflater.from(this).inflate(R.layout.image_item, null);
ImageView thumbnail = imageHolder.findViewById(R.id.media_image);
requestManager
.load(uri.toString())
.apply(new RequestOptions().fitCenter())
.into(thumbnail);
mSelectedImagesContainer.addView(imageHolder);
thumbnail.setLayoutParams(new FrameLayout.LayoutParams(widthPixel, heightPixel));
}
}
@Override
protected void onDestroy() {
if (singleImageDisposable != null && !singleImageDisposable.isDisposed()) {
singleImageDisposable.dispose();
}
if (multiImageDisposable != null && !multiImageDisposable.isDisposed()) {
multiImageDisposable.dispose();
}
super.onDestroy();
}
}
Reference
Here are the download links:
No. | Link |
---|---|
1. | Download example |
2. | Read more |
(b). TedImagePicker
TedImagePicker is simple/beautiful/smart image picker.
- Support Image/Video
- Support Single/Multi select
- Support more configuration option
Step 1: Install TedImagePicker
Start by installing the library from maven central:
repositories {
google()
mavenCentral()
}
dependencies {
implementation 'io.github.ParkSangGwon:tedimagepicker:x.y.z'
//implementation 'io.github.ParkSangGwon:tedimagepicker:1.1.10'
}
Step 2: Enable DataBinding
Enable data binding since TedImagePicker uses data binding:
Step 3: Pick Image
You can use the RxJava approach or listener approach. If you use listener approach, you can pick a single image this way:
or multiple images:
And if you use the RxJava approach, you can pick a single image this way:
Or multiple images:
TedRxImagePicker.with(this)
.startMultiImage()
.subscribe({ uriList ->
}, Throwable::printStackTrace)
Full Example
Here is a full example:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private var selectedUriList: List<Uri>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
setNormalSingleButton()
setNormalMultiButton()
setRxSingleButton()
setRxMultiButton()
setRxMultiDropDown()
}
private fun setNormalSingleButton() {
binding.btnNormalSingle.setOnClickListener {
TedImagePicker.with(this)
.start { uri -> showSingleImage(uri) }
}
}
private fun setNormalMultiButton() {
binding.btnNormalMulti.setOnClickListener {
TedImagePicker.with(this)
//.mediaType(MediaType.IMAGE)
//.scrollIndicatorDateFormat("YYYYMMDD")
//.buttonGravity(ButtonGravity.BOTTOM)
//.buttonBackground(R.drawable.btn_sample_done_button)
//.buttonTextColor(R.color.sample_yellow)
.errorListener { message -> Log.d("ted", "message: $message") }
.selectedUri(selectedUriList)
.startMultiImage { list: List<Uri> -> showMultiImage(list) }
}
}
private fun setRxSingleButton() {
binding.btnRxSingle.setOnClickListener {
TedRxImagePicker.with(this)
.start()
.subscribe(this::showSingleImage, Throwable::printStackTrace)
}
}
private fun setRxMultiButton() {
binding.btnRxMulti.setOnClickListener {
TedRxImagePicker.with(this)
.startMultiImage()
.subscribe(this::showMultiImage, Throwable::printStackTrace)
}
}
private fun setRxMultiDropDown() {
binding.btnRxMultiDropDown.setOnClickListener {
TedRxImagePicker.with(this)
.dropDownAlbum()
.imageCountTextFormat("%s장")
.startMultiImage()
.subscribe(this::showMultiImage, Throwable::printStackTrace)
}
}
private fun showSingleImage(uri: Uri) {
binding.ivImage.visibility = View.VISIBLE
binding.containerSelectedPhotos.visibility = View.GONE
Glide.with(this).load(uri).into(binding.ivImage)
}
private fun showMultiImage(uriList: List<Uri>) {
this.selectedUriList = uriList
Log.d("ted", "uriList: $uriList")
binding.ivImage.visibility = View.GONE
binding.containerSelectedPhotos.visibility = View.VISIBLE
binding.containerSelectedPhotos.removeAllViews()
val viewSize =
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100f, resources.displayMetrics)
.toInt()
uriList.forEach {
val itemImageBinding = ItemImageBinding.inflate(LayoutInflater.from(this))
Glide.with(this)
.load(it)
.apply(RequestOptions().fitCenter())
.into(itemImageBinding.ivMedia)
itemImageBinding.root.layoutParams = FrameLayout.LayoutParams(viewSize, viewSize)
binding.containerSelectedPhotos.addView(itemImageBinding.root)
}
}
}
You can download the code below.
Reference
Here are the download links:
No. | Link |
---|---|
1. | Download example |
2. | Read more |
(c). Louvre
A small customizable library useful to handle an gallery image pick action built-in your app.
Here's the demo:
This library requires API 19+.
Step 1: Install Louvre
The library is hosted in jitpack. So you need to register jitpack as a maven url in your project level build.gradle file:
Then specify the implementation statement in your dependencies in the app level build.gradle file:
Step 2: Add Necessary Permission
That necessary permission is the external storage permission. You add in your android manifest file:
Step 3: Choose Louvre theme
Choose one of the Louvre themes to use in GalleryActivity
and override it to define your app color palette.
<style name="AppTheme.Louvre.Light.DarkActionBar" parent="Louvre.Theme.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.Louvre.Dark" parent="Louvre.Theme.Dark">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.Louvre.Light" parent="Louvre.Theme.Light">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
For PreviewActivity
you just need to define the accent color.
<style name="AppTheme.Louvre.Preview" parent="Louvre.Theme.Preview">
<item name="colorAccent">@color/colorAccent</item>
</style
Step 4: Register Louvre Activities
Register the activities in the android manifest:
<activity
android:name="com.andremion.louvre.home.GalleryActivity"
android:theme="@style/AppTheme.Louvre.Light.DarkActionBar" />
<activity
android:name="com.andremion.louvre.preview.PreviewActivity"
android:theme="@style/AppTheme.Louvre.Preview" />
Step 5: Write Kotlin/Java Code
Your now go on and write your code either in activity, to initialize Louvre:
or in fragment:
You can configure the number of items you want to picked in the gallery:
Example
Here's an example:
package com.andremion.louvre.sample;
import android.app.Dialog;
import android.content.DialogInterface;
import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentManager;
import androidx.appcompat.app.AlertDialog;
import android.util.SparseBooleanArray;
import com.andremion.louvre.Louvre;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import static android.content.ContentValues.TAG;
public class MediaTypeFilterDialog extends DialogFragment implements DialogInterface.OnMultiChoiceClickListener, DialogInterface.OnClickListener {
private static final String ARG_REQUEST_CODE = "request_code_arg";
private static final String ARG_MAX_SELECTION = "max_selection_arg";
private static final String ARG_SELECTION = "selection_arg";
public static void show(@NonNull FragmentManager fragmentManager, int requestCode, int maxSelection, @Nullable List<Uri> selection) {
MediaTypeFilterDialog dialog = new MediaTypeFilterDialog();
Bundle args = new Bundle();
args.putInt(ARG_REQUEST_CODE, requestCode);
args.putInt(ARG_MAX_SELECTION, maxSelection);
if (selection != null) {
args.putSerializable(ARG_SELECTION, new LinkedList<>(selection));
}
dialog.setArguments(args);
dialog.show(fragmentManager, TAG);
}
private final SparseBooleanArray mSelectedTypes;
public MediaTypeFilterDialog() {
mSelectedTypes = new SparseBooleanArray();
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getContext())
.setTitle(R.string.media_type_prompt)
.setMultiChoiceItems(Louvre.IMAGE_TYPES, null, this)
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, null)
.show();
}
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
if (isChecked) {
mSelectedTypes.put(which, true);
} else {
mSelectedTypes.put(which, false);
}
}
@Override
public void onClick(DialogInterface dialog, int which) {
//noinspection WrongConstant,ConstantConditions,unchecked
Louvre.init(getActivity())
.setRequestCode(getArguments().getInt(ARG_REQUEST_CODE))
.setMaxSelection(getArguments().getInt(ARG_MAX_SELECTION))
.setSelection((List<Uri>) getArguments().get(ARG_SELECTION))
.setMediaTypeFilter(parseToArray(mSelectedTypes))
.open();
}
@NonNull
private String[] parseToArray(@NonNull SparseBooleanArray selectedTypes) {
List<String> selectedTypeList = new ArrayList<>();
for (int i = 0; i < selectedTypes.size(); i++) {
int key = selectedTypes.keyAt(i);
if (selectedTypes.get(key, false)) {
selectedTypeList.add(Louvre.IMAGE_TYPES[key]);
}
}
String[] array = new String[selectedTypeList.size()];
selectedTypeList.toArray(array);
return array;
}
}
Find full exmaple here.
Reference
Find source code reference here.
Dhaval2404/ImagePicker
An Easy to use and configurable library to Pick an image from the Gallery or Capture image using Camera.
It also allows to Crop and Compresses the Image based on Aspect Ratio, Resolution and Image Size.
Here are its main features:
- Pick Gallery Image
- Pick Image from Google Drive
- Capture Camera Image
- Crop Image (Crop image based on provided aspect ratio or let user choose one)
- Compress Image (Compress image based on provided resolution and size)
- Retrieve Image Result as Uri object (Retrieve as File object feature is removed in v2.0 to support scope storage)
- Handle runtime permission for camera
- Does not require storage permission to pick gallery image or capture new image.
Here is the demo image:
Step 1: Install it
- Gradle dependency:
If you are yet to Migrate on AndroidX, Use support build artifact:
- The ImagePicker configuration is created using the builder pattern.
Kotlin
ImagePicker.with(this)
.crop() //Crop image(Optional), Check Customization for more option
.compress(1024) //Final image size will be less than 1 MB(Optional)
.maxResultSize(1080, 1080) //Final image resolution will be less than 1080 x 1080(Optional)
.start()
```
**Java**
```java
ImagePicker.with(this)
.crop() //Crop image(Optional), Check Customization for more option
.compress(1024) //Final image size will be less than 1 MB(Optional)
.maxResultSize(1080, 1080) //Final image resolution will be less than 1080 x 1080(Optional)
.start()
- Handling results
Override
onActivityResult
method and handle ImagePicker result.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
//Image Uri will not be null for RESULT_OK
val uri: Uri = data?.data!!
// Use Uri object instead of File to avoid storage permissions
imgProfile.setImageURI(fileUri)
} else if (resultCode == ImagePicker.RESULT_ERROR) {
Toast.makeText(this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this, "Task Cancelled", Toast.LENGTH_SHORT).show()
}
}
Inline method (with registerForActivityResult, Only Works with FragmentActivity and AppCompatActivity)
i. Add required dependency for registerForActivityResult API
groovy
implementation "androidx.activity:activity-ktx:1.2.3"
implementation "androidx.fragment:fragment-ktx:1.3.3"
ii. Declare this method inside fragment or activity class
```kotlin private val startForProfileImageResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult -> val resultCode = result.resultCode val data = result.data
if (resultCode == Activity.RESULT_OK) {
//Image Uri will not be null for RESULT_OK
val fileUri = data?.data!!
mProfileUri = fileUri
imgProfile.setImageURI(fileUri)
} else if (resultCode == ImagePicker.RESULT_ERROR) {
Toast.makeText(this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this, "Task Cancelled", Toast.LENGTH_SHORT).show()
}
}
```
iii. Create ImagePicker instance and launch intent
ImagePicker.with(this)
.compress(1024) //Final image size will be less than 1 MB(Optional)
.maxResultSize(1080, 1080) //Final image resolution will be less than 1080 x 1080(Optional)
.createIntent { intent ->
startForProfileImageResult.launch(intent)
}
Customization
- Pick image using Gallery
ImagePicker.with(this)
.galleryOnly() //User can only select image from Gallery
.start() //Default Request Code is ImagePicker.REQUEST_CODE
- Capture image using Camera
- Crop square image(e.g for profile)
ImagePicker.with(this)
.maxResultSize(620, 620) //Final image resolution will be less than 620 x 620
.start()
ImagePicker.with(this)
.setImageProviderInterceptor { imageProvider -> //Intercept ImageProvider
Log.d("ImagePicker", "Selected ImageProvider: "+imageProvider.name)
}
.start()
ImagePicker.with(this)
.setDismissListener {
// Handle dismiss event
Log.d("ImagePicker", "onDismiss");
}
.start()
- Specify Directory to store captured, cropped or compressed images. Do not use external public storage directory (i.e. Environment.getExternalStorageDirectory())
ImagePicker.with(this)
/// Provide directory path to save images, Added example saveDir method. You can choose directory as per your need.
// Path: /storage/sdcard0/Android/data/package/files
.saveDir(getExternalFilesDir(null)!!)
// Path: /storage/sdcard0/Android/data/package/files/DCIM
.saveDir(getExternalFilesDir(Environment.DIRECTORY_DCIM)!!)
// Path: /storage/sdcard0/Android/data/package/files/Download
.saveDir(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)!!)
// Path: /storage/sdcard0/Android/data/package/files/Pictures
.saveDir(getExternalFilesDir(Environment.DIRECTORY_PICTURES)!!)
// Path: /storage/sdcard0/Android/data/package/files/Pictures/ImagePicker
.saveDir(File(getExternalFilesDir(Environment.DIRECTORY_PICTURES)!!, "ImagePicker"))
// Path: /storage/sdcard0/Android/data/package/files/ImagePicker
.saveDir(getExternalFilesDir("ImagePicker")!!)
// Path: /storage/sdcard0/Android/data/package/cache/ImagePicker
.saveDir(File(getExternalCacheDir(), "ImagePicker"))
// Path: /data/data/package/cache/ImagePicker
.saveDir(File(getCacheDir(), "ImagePicker"))
// Path: /data/data/package/files/ImagePicker
.saveDir(File(getFilesDir(), "ImagePicker"))
// Below saveDir path will not work, So do not use it
// Path: /storage/sdcard0/DCIM
// .saveDir(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM))
// Path: /storage/sdcard0/Pictures
// .saveDir(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES))
// Path: /storage/sdcard0/ImagePicker
// .saveDir(File(Environment.getExternalStorageDirectory(), "ImagePicker"))
.start()
- Limit MIME types while choosing a gallery image
ImagePicker.with(this)
.galleryMimeTypes( //Exclude gif images
mimeTypes = arrayOf(
"image/png",
"image/jpg",
"image/jpeg"
)
)
.start()
- You can also specify the request code with ImagePicker
ImagePicker.with(this)
.maxResultSize(620, 620)
.start(101) //Here 101 is request code, you may use this in onActivityResult
- Add Following parameters in your colors.xml file, If you want to customize uCrop Activity.
<resources>
<!-- Here you can add color of your choice -->
<color name="ucrop_color_toolbar">@color/teal_500</color>
<color name="ucrop_color_statusbar">@color/teal_700</color>
<color name="ucrop_color_widget_active">@color/teal_500</color>
</resources>
Reference
Read more here.