Skip to content

Commit

Permalink
feat: long press to preview image
Browse files Browse the repository at this point in the history
  • Loading branch information
nguyenhoanglam committed Nov 24, 2023
1 parent 12346c1 commit 90d5a9d
Show file tree
Hide file tree
Showing 53 changed files with 426 additions and 130 deletions.
151 changes: 79 additions & 72 deletions README.md
Expand Up @@ -4,15 +4,14 @@ An Android library that allows you to select images from the device library or c

## Preview

<img src="https://i.imgur.com/ZM09aU3.png" height="652" width="350"> <img src="https://i.imgur.com/d3O0VFN.png" height="652" width="350">
<img src="https://i.imgur.com/35eH442.png" height="650" width="351"> <img src="https://i.imgur.com/T0cOGy0.png" height="650" width="351">

## Changelog

- Fix camera permission bug: [#148](https://github.com/nguyenhoanglam/ImagePicker/issues/148), [#155](https://github.com/nguyenhoanglam/ImagePicker/issues/155)
- Allow to set custom colors, drawables, texts and messages.
- Add select and unselect all feature.
- Add, remove and rename some options.
- Upgrade gradle and dependencies version.
- Display preview mode when long pressing an image.
- Fix bugs [#153](https://github.com/nguyenhoanglam/ImagePicker/issues/153), [#157](https://github.com/nguyenhoanglam/ImagePicker/issues/157)
- Add ```imageSort``` for sorting images.
- Replace ```isMultiSelectMode``` by ```isSingleSelectMode```.

## Installation

Expand All @@ -30,7 +29,7 @@ dependencyResolutionManagement {
Add the dependency in app build.gradle:
```
dependencies {
implementation 'com.github.nguyenhoanglam:ImagePicker:1.6.1'
implementation 'com.github.nguyenhoanglam:ImagePicker:1.6.2'
}
```

Expand All @@ -56,76 +55,82 @@ launcher.launch()
```
- with custom configuration:
```java
val config = ImagePickerConfig(
isFolderMode = true,
isShowCamera = true,
limitSize = 10,
selectedIndicatorType = IndicatorType.NUMBER,
rootDirectory = RootDirectory.DCIM,
subDirectory = "Image Picker",
folderGridCount = GridCount(2, 4),
imageGridCount = GridCount(3, 5),
customColor = CustomColor(
background = "#000000",
statusBar = "#000000",
toolbar = "#212121",
toolbarTitle = "#FFFFFF",
toolbarIcon = "#FFFFFF",
// ...
),
customMessage = CustomMessage(
reachLimitSize = "You can only select up to 10 images.",
noImage = "No image found.",
noPhotoAccessPermission = "Please allow permission to access photos and media.",
noCameraPermission = "Please allow permission to access camera."
// ...
),
customDrawable = CustomDrawable(
cameraIcon = R.drawable.ic_camera,
selectAllIcon = R.drawable.ic_select_all,
unselectAllIcon = R.drawable.ic_unselect_all,
loadingImagePlaceholder = R.drawable.img_loading_placeholder
// ...
),
// see more options below
val config = ImagePickerConfig(
isFolderMode = true,
isShowCamera = true,
limitSize = 10,
selectedIndicatorType = IndicatorType.NUMBER,
rootDirectory = RootDirectory.DCIM,
subDirectory = "Image Picker",
folderGridCount = GridCount(2, 4),
imageGridCount = GridCount(3, 5),
customColor = CustomColor(
background = "#000000",
statusBar = "#000000",
toolbar = "#212121",
toolbarTitle = "#FFFFFF",
toolbarIcon = "#FFFFFF",
),
customMessage = CustomMessage(
reachLimitSize = "You can only select up to 10 images.",
noImage = "No image found.",
noPhotoAccessPermission = "Please allow permission to access photos and media.",
noCameraPermission = "Please allow permission to access camera."
),
customDrawable = CustomDrawable(
cameraIcon = R.drawable.ic_camera,
selectAllIcon = R.drawable.ic_select_all,
unselectAllIcon = R.drawable.ic_unselect_all,
loadingImagePlaceholder = R.drawable.img_loading_placeholder
),
// see more options below
)

launcher.launch(config)
```

## Configuration options

| Option | Description | Default value
| --- | --- | :---: |
| `isCameraMode` | Capture an image from the camera instead of selecting from the library. If set to `true`, this option will ignore most of other options such as `isMultiSelectMode`, `isFolderMode`, `customColor`, `customIcon`... | `false`
| `isMultiSelectMode` | Allow to select multiple images. | `true`
| `isFolderMode` | Group images in folders. | `true`
| `isShowCamera` | Show the camera button. | `true`
| `isAlwaysShowDoneButton` | Show done button even if there's no image that has been selected yet. | `true`
| `isSelectAllEnabled` | Show select all images button (works if `isMultiSelectMode = true`). | `true`
| `isUnselectAllEnabled` | Show unselect all images button (works if `isMultiSelectMode = true`). | `true`
| `isImageTransitionEnabled` | Enable image transition. | `true`
| `statusBarContentMode` | Status bar content mode. | `StatusBarContent.LIGHT`
| `selectedIndicatorType` | Set selected image's indicator type. | `IndicatorType.NUMBER`
| `limitSize` | Maximum number of images that can be selected. | `Int.MAX_VALUE`
| `folderGridCount` | Number of folder columns for portrait and landscape orientation. | `GridCount(2, 4)`
| `imageGridCount` | Number of image columns for portrait and landscape orientation. | `GridCount(3, 5)`
| `doneButtonTitle` | Done button's title. | `DONE`
| `snackBarButtonTitle` | Snack bar action button's title. | `OK`
| `folderTitle` | Toolbar title for folder mode (works if `isFolderMode = true`). | `Albums`
| `imageTitle` | Toolbar title for image mode (works if `isFolderMode = false`). | `Photos`
| `rootDirectory` | Public root directory of the captured image. | `RootDirectory.DCIM`
| `subDirectory` | Subfolder of root directory where the captured image is saved. | *application name*
| `selectedImages` | Define images that will be marked as selected when launching picker. | *empty list*
| `customColor` | Custom colors: toolbar, indicator... | `CustomColor(...)`
| `customDrawable` | Custom drawable resources: back icon, camera icon, image placeholder... | `CustomDrawable(...)`
| `customMessage` | Custom messages: no permission, limit size, error... | `CustomMessage(...)`
| Option | Description | Default value
|----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| :---: |
| `isCameraMode` | Capture an image from the camera instead of selecting from the library. If set to `true`, this option will ignore most of other options such as `isMultiSelectMode`, `isFolderMode`, `customColor`, `customIcon`... | `false`
| `isSingleSelectMode` | Return single image array immediately after selecting or capturing an image. | `false`
| `isFolderMode` | Group images in folders. | `true`
| `isShowCamera` | Show the camera button. | `true`
| `isAlwaysShowDoneButton` | Show done button even if there's no image that has been selected yet. | `true`
| `isSelectAllEnabled` | Show select all images button (works if `isMultiSelectMode = true`). | `true`
| `isUnselectAllEnabled` | Show unselect all images button (works if `isMultiSelectMode = true`). | `true`
| `isImageTransitionEnabled` | Enable image transition. | `true`
| `statusBarContentMode` | Status bar content mode. | `StatusBarContent.LIGHT`
| `selectedIndicatorType` | Set selected image's indicator type. | `IndicatorType.NUMBER`
| `limitSize` | Maximum number of images that can be selected. | `Int.MAX_VALUE`
| `folderGridCount` | Number of folder columns for portrait and landscape orientation. | `GridCount(2, 4)`
| `imageGridCount` | Number of image columns for portrait and landscape orientation. | `GridCount(3, 5)`
| `imageSort` | Define images sorting type. | `ImageSort(by = SortBy.DATE_ADDED, order = SortOrder.DESC)`
| `doneButtonTitle` | Done button's title. | `DONE`
| `snackBarButtonTitle` | Snack bar action button's title. | `OK`
| `folderTitle` | Toolbar title for folder mode (works if `isFolderMode = true`). | `Gallery`
| `imageTitle` | Toolbar title for image mode (works if `isFolderMode = false`). | `Photos`
| `rootDirectory` | Public root directory of the captured image. | `RootDirectory.DCIM`
| `subDirectory` | Subfolder of root directory where the captured image is saved. | *application name*
| `selectedImages` | Define images that will be marked as selected when launching picker. | *empty list*
| `customColor` | Custom colors: toolbar, indicator... | `CustomColor(...)`
| `customDrawable` | Custom drawable resources: back icon, camera icon, image placeholder... | `CustomDrawable(...)`
| `customMessage` | Custom messages: no permission, limit size, error... | `CustomMessage(...)`

#### *ImageSort* class

Define sorting for images
| Property | Description | Default value
| -------- | ----------- | :---: |
| `by` | Sorting type: date added, date modified and display name | `DATE_ADDED`
| `order` | Sorting order: ascending and descending. | `DESC`

#### *CustomColor* class

Define custom color for views, type = `String`.
| Property | Description | Default value
| --- | --- | :---: |
| -------- | ----------- | :---: |
| `background` | Background color. | `#000000`
| `statusBar` | Status bar color. | `#000000`
| `toolbar` | Toolbar color. | `#212121`
Expand All @@ -142,7 +147,7 @@ Define custom color for views, type = `String`.

Define custom icon for the toolbar's buttons, type = `Int` (resource id). `24dp` icon size is recommended.
| Property | Description | Example
| --- | --- | :---: |
| -------- | ----------- | :---: |
| `backIcon` | Back button icon. | `R.drawable.ic_back`
| `cameraIcon` | Camera button icon. | `R.drawable.ic_camera`
| `selectAllIcon` | Select all button icon. | `R.drawable.ic_select_all`
Expand All @@ -154,17 +159,19 @@ Define custom icon for the toolbar's buttons, type = `Int` (resource id). `24dp`

Define custom message when something's wrong, type = `String`.
| Property | Description | Default value
| --- | --- | :---: |
| -------- | ----------- | :---: |
| `reachLimitSize` | Reached the limit number of images that can be selected. | `You have reached the limit number of images.`
| `cameraError` | Failed to open camera. | `Could not open camera.`
| `noCamera` | Device has no camera. | `No camera found.`
| `noImage` | Device has no image. | `No image available.`
| `noImage` | Device has no images. | `No images found.`
| `noPhotoAccessPermission` | Photos and media access permission is not granted. | `Please allow permission to access photos and media.`
| `noCameraPermission` | Camera permisson is not granted. | `Please allow permission to access camera.`
| `noCameraPermission` | Camera permission is not granted. | `Please allow permission to access camera.`

Author
--------

Copyright (c) 2023 Nguyen Hoang Lam
- [LinkedIn](https://www.linkedin.com/in/lam-nguyen-hoang-70bb21115)
- [Facebook](https://www.facebook.com/hoanglamvn90)
Copyright © 2016 Nguyen Hoang Lam

[![LinkedIn](https://img.shields.io/badge/Gmail-D14836?style=for-the-badge&logo=gmail&logoColor=white)](mailto:hoanglamvn90@gmail.com)
[![Facebook](https://img.shields.io/badge/Facebook-1877F2?style=for-the-badge&logo=facebook&logoColor=white)](https://www.facebook.com/hoanglamvn90)
[![LinkedIn](https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge&logo=linkedin&logoColor=white)](https://www.linkedin.com/in/lam-nguyen-hoang-70bb21115)
3 changes: 2 additions & 1 deletion build.gradle
Expand Up @@ -7,7 +7,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.1.2'
classpath 'com.android.tools.build:gradle:8.1.4'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
Expand All @@ -16,6 +16,7 @@ buildscript {

plugins {
id 'org.jetbrains.kotlin.jvm' version "$kotlin_version"
id 'org.jetbrains.kotlin.android' version '1.8.22' apply false
}

allprojects {
Expand Down
2 changes: 1 addition & 1 deletion example/build.gradle
Expand Up @@ -36,6 +36,6 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation 'com.github.bumptech.glide:glide:4.15.1'
implementation 'com.github.bumptech.glide:glide:4.16.0'
implementation project(path: ':imagepicker')
}
9 changes: 3 additions & 6 deletions example/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -1,9 +1,6 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (C) 2023 Image Picker
~ Author: Nguyen Hoang Lam <hoanglamvn90@gmail.com>
-->

<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<background android:drawable="@mipmap/ic_launcher_background" />
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
<monochrome android:drawable="@mipmap/ic_launcher_monochrome" />
</adaptive-icon>
9 changes: 0 additions & 9 deletions example/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml

This file was deleted.

Binary file modified example/src/main/res/mipmap-hdpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified example/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file modified example/src/main/res/mipmap-mdpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified example/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file modified example/src/main/res/mipmap-xhdpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified example/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file modified example/src/main/res/mipmap-xxhdpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified example/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file modified example/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified example/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
2 changes: 1 addition & 1 deletion example/src/main/res/values/strings.xml
@@ -1,3 +1,3 @@
<resources>
<string name="app_name">iPicker</string>
<string name="app_name">Image Picker</string>
</resources>
6 changes: 3 additions & 3 deletions imagepicker/build.gradle
Expand Up @@ -43,12 +43,12 @@ dependencies {
implementation 'com.google.android.material:material:1.10.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation "androidx.activity:activity-ktx:1.8.0"
implementation "androidx.activity:activity-ktx:1.8.1"
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2'
implementation 'androidx.core:core-ktx:1.12.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.github.bumptech.glide:glide:4.15.1'
implementation 'com.github.bumptech.glide:glide:4.16.0'
}

afterEvaluate {
Expand All @@ -62,7 +62,7 @@ afterEvaluate {
// You can then customize attributes of the publication as shown below.
groupId = 'com.github.nguyenhoanglam'
artifactId = 'final'
version = '1.6.0'
version = '1.6.2'
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion imagepicker/src/main/AndroidManifest.xml
Expand Up @@ -44,4 +44,4 @@

</application>

</manifest>
</manifest>

0 comments on commit 90d5a9d

Please sign in to comment.