diff --git a/app/src/main/java/com/shz/imagepicker/imagepickerapp/MainActivity.kt b/app/src/main/java/com/shz/imagepicker/imagepickerapp/MainActivity.kt index 38ad354..c022484 100644 --- a/app/src/main/java/com/shz/imagepicker/imagepickerapp/MainActivity.kt +++ b/app/src/main/java/com/shz/imagepicker/imagepickerapp/MainActivity.kt @@ -2,18 +2,16 @@ package com.shz.imagepicker.imagepickerapp import android.os.Bundle import android.util.Log -import android.widget.ImageView +import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.databinding.DataBindingUtil import androidx.recyclerview.widget.GridLayoutManager import com.bumptech.glide.Glide import com.shz.imagepicker.imagepicker.ImagePicker import com.shz.imagepicker.imagepicker.ImagePickerCallback -import com.shz.imagepicker.imagepicker.ImagePickerLoadDelegate import com.shz.imagepicker.imagepicker.model.GalleryPicker import com.shz.imagepicker.imagepicker.model.PickedResult import com.shz.imagepicker.imagepickerapp.databinding.ActivityMainBinding -import java.io.File class MainActivity : AppCompatActivity(), ImagePickerCallback { @@ -26,81 +24,78 @@ class MainActivity : AppCompatActivity(), ImagePickerCallback { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil.setContentView(this, R.layout.activity_main) + initializeButtons() + initializeImagesList() + } - adapter = ImagesDemoAdapter() - - binding.rv.adapter = adapter - binding.rv.layoutManager = GridLayoutManager(this, 2) + override fun onImagePickerResult(result: PickedResult) { + Log.d("MainActivity", "result: $result") + when (result) { + PickedResult.Empty -> { + adapter.submitList(emptyList()) + } + is PickedResult.Error -> { + result.throwable.printStackTrace() + AlertDialog.Builder(this) + .setTitle(R.string.action_error) + .setMessage(result.throwable.message.toString()) + .setPositiveButton(R.string.action_ok) { d, _ -> d.dismiss() } + .show() + } + is PickedResult.Multiple -> { + adapter.submitList(result.images) + } + is PickedResult.Single -> { + adapter.submitList(listOf(result.image)) + } + } + } - binding.btnCamera.setOnClickListener { + private fun initializeButtons() = with(binding) { + btnCamera.setOnClickListener { imagePicker .autoRotate(binding.switchAutoRotate.isChecked) .useCamera() .build() - .launch(this) + .launch(this@MainActivity) } - binding.btnGallery.setOnClickListener { + btnGallery.setOnClickListener { imagePicker .autoRotate(binding.switchAutoRotate.isChecked) .useGallery() -// .multipleSelection(true) + .multipleSelection(binding.switchMultipleSelection.isChecked) .build() - .launch(this) + .launch(this@MainActivity) } - binding.btnGalCustomSingle.setOnClickListener { + btnGalCustomSingle.setOnClickListener { imagePicker .autoRotate(binding.switchAutoRotate.isChecked) .useGallery() + .multipleSelection(binding.switchMultipleSelection.isChecked) .galleryPicker(GalleryPicker.CUSTOM) .loadDelegate { imageView, file -> - Glide.with(this) + Glide.with(imageView) .load(file) .into(imageView) } .build() - .launch(this) + .launch(this@MainActivity) } - binding.btnGalCustomMultiple.setOnClickListener { - imagePicker - .autoRotate(binding.switchAutoRotate.isChecked) - .useGallery() - .multipleSelection() - .galleryPicker(GalleryPicker.CUSTOM) - .loadDelegate { imageView, file -> - Glide.with(this) - .load(file) - .into(imageView) - } - .build() - .launch(this) - } - binding.btnDialog.setOnClickListener { + btnDialog.setOnClickListener { imagePicker .autoRotate(binding.switchAutoRotate.isChecked) .useGallery() .useCamera() - .multipleSelection() + .multipleSelection(binding.switchMultipleSelection.isChecked) .galleryPicker(GalleryPicker.NATIVE) .build() - .launch(this) + .launch(this@MainActivity) } } - override fun onImagePickerResult(result: PickedResult) { - Log.d("MainActivity", "result: $result") - when (result) { - PickedResult.Empty -> { - adapter.submitList(emptyList()) - } - is PickedResult.Error -> { - result.throwable.printStackTrace() - } - is PickedResult.Multiple -> { - adapter.submitList(result.images) - } - is PickedResult.Single -> { - adapter.submitList(listOf(result.image)) - } - } + private fun initializeImagesList() = with(binding) { + adapter = ImagesDemoAdapter() + recyclerImages.adapter = adapter + recyclerImages.layoutManager = GridLayoutManager(this@MainActivity, 2) } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 90c1d27..36fb09a 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -9,16 +9,16 @@ android:layout_height="match_parent"> + + + + + + + + + + + + + + @@ -62,7 +104,7 @@ android:focusable="true" android:gravity="center" android:padding="8dp" - android:text="GALLERY" + android:text="@string/action_native_gallery" android:textColor="#FFFFFF" android:textSize="16sp" /> @@ -86,12 +128,12 @@ android:focusable="true" android:gravity="center" android:padding="8dp" - android:text="Custom single gallery" + android:text="@string/action_custom_gallery" android:textColor="#FFFFFF" android:textSize="16sp" /> - - - - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1fc4e03..e2fa5c8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,11 @@ ImagePicker Android Library + Multiple selection + Auto rotate images + CAMERA + GALLERY + Custom Gallery + Interactive dialog + Error + OK \ No newline at end of file diff --git a/imagepicker/build.gradle b/imagepicker/build.gradle index 908e286..b3ccca7 100644 --- a/imagepicker/build.gradle +++ b/imagepicker/build.gradle @@ -6,7 +6,7 @@ plugins { def libraryGroupId = 'com.shz.imagepicker' def libraryArtifactId = 'imagepicker' -def libraryVersion = '2.0' +def libraryVersion = '2.0.1' android { diff --git a/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/ImagePicker.kt b/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/ImagePicker.kt index 7581a2e..270bdb3 100644 --- a/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/ImagePicker.kt +++ b/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/ImagePicker.kt @@ -30,7 +30,6 @@ class ImagePicker private constructor( private val galleryPicker: GalleryPicker, private val loadDelegate: ImagePickerLoadDelegate, ) { - /** * Checks for access Camera or Media permissions, then * launches **ImagePicker** according to defined configuration. @@ -175,7 +174,6 @@ class ImagePicker private constructor( * * @return [ImagePicker.Builder] */ - @Deprecated("GalleryPicker.CUSTOM is deprecated from Android 13 (SDK 33)") fun minimumSelectionCount(minimumSelectionCount: Int) = apply { this.minimumSelectionCount = minimumSelectionCount } @@ -189,7 +187,6 @@ class ImagePicker private constructor( * * @return [ImagePicker.Builder] */ - @Deprecated("GalleryPicker.CUSTOM is deprecated from Android 13 (SDK 33)") fun maximumSelectionCount(maximumSelectionCount: Int) = apply { this.maximumSelectionCount = maximumSelectionCount } @@ -211,12 +208,10 @@ class ImagePicker private constructor( this.galleryPicker = galleryPicker } - @Deprecated("GalleryPicker.CUSTOM is deprecated from Android 13 (SDK 33)") fun loadDelegate(loadDelegate: ImagePickerLoadDelegate) = apply { this.loadDelegate = loadDelegate } - @Deprecated("GalleryPicker.CUSTOM is deprecated from Android 13 (SDK 33)") fun loadDelegate(loadDelegate: (ImageView, File) -> Unit) = apply { this.loadDelegate = ImagePickerLoadDelegate { iv, file -> loadDelegate(iv, file) } } diff --git a/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/ImagePickerLauncher.kt b/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/ImagePickerLauncher.kt index 74db798..4bf964a 100644 --- a/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/ImagePickerLauncher.kt +++ b/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/ImagePickerLauncher.kt @@ -101,7 +101,6 @@ internal class ImagePickerLauncher(private val context: Context) { }) } - @Deprecated("GalleryPicker.CUSTOM is deprecated from Android 13 (SDK 33)") private fun launchMultipleSelectionGalleryCustom( callback: ImagePickerCallback, delegate: ImagePickerLoadDelegate, diff --git a/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/activity/customgallery/GalleryPickerCustomActivity.kt b/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/activity/customgallery/GalleryPickerCustomActivity.kt index 274decf..033f810 100644 --- a/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/activity/customgallery/GalleryPickerCustomActivity.kt +++ b/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/activity/customgallery/GalleryPickerCustomActivity.kt @@ -88,8 +88,10 @@ internal class GalleryPickerCustomActivity : ImagePickerActivity() { submitList(files) } } else { - GalleryImagesMultipleAdapter(ArrayList(files), max) { selectedFiles -> + GalleryImagesMultipleAdapter(loadDelegate, max) { selectedFiles -> onSelectionChanged(selectedFiles.size) + }.apply { + submit(files) } } } diff --git a/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/activity/customgallery/adapter/multiple/GalleryImagesMultipleAdapter.kt b/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/activity/customgallery/adapter/multiple/GalleryImagesMultipleAdapter.kt index 65771cd..c3eb89f 100644 --- a/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/activity/customgallery/adapter/multiple/GalleryImagesMultipleAdapter.kt +++ b/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/activity/customgallery/adapter/multiple/GalleryImagesMultipleAdapter.kt @@ -1,33 +1,40 @@ package com.shz.imagepicker.imagepicker.activity.customgallery.adapter.multiple -import android.graphics.BitmapFactory import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.CheckBox import android.widget.ImageView import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView +import com.shz.imagepicker.imagepicker.ImagePickerLoadDelegate import com.shz.imagepicker.imagepicker.R import java.io.File internal class GalleryImagesMultipleAdapter( - private val images: ArrayList = arrayListOf(), + private val loadDelegate: ImagePickerLoadDelegate, private val maximum: Int = Int.MAX_VALUE, private val onSelectionChanged: (List) -> Unit = {}, -) : RecyclerView.Adapter() { +) : ListAdapter(diff) { + + private var files = ArrayList() private val selectionIds: ArrayList = arrayListOf() val selectedFiles: List - get() = images.filter { - selectionIds.contains(images.indexOf(it)) - } + get() = selectionIds.map(files::get) init { setHasStableIds(true) } + fun submit(files: List) { + selectionIds.clear() + this.files = ArrayList(files) + submitList(files.map { Model(it, false) }) + } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder( LayoutInflater.from(parent.context).inflate( R.layout.image_picker_item_gallery_image_multiple, parent, false @@ -35,27 +42,26 @@ internal class GalleryImagesMultipleAdapter( ) override fun onBindViewHolder(holder: ViewHolder, position: Int) { - holder.bind(images[position], selectionIds.contains(position)) + holder.bind(getItem(position)) } - override fun getItemCount(): Int = images.size - override fun getItemId(position: Int): Long = position * 1L inner class ViewHolder(private val view: View) : RecyclerView.ViewHolder(view) { - fun bind(item: File, selected: Boolean) { + fun bind(item: Model) { view.setOnClickListener { - if (selected) { + if (item.isSelected) { selectionIds.removeAll { it == bindingAdapterPosition } - } else if (selectedFiles.size < maximum) { + } else if (selectionIds.size < maximum) { selectionIds.add(bindingAdapterPosition) } notifyItemChanged(bindingAdapterPosition) onSelectionChanged(selectedFiles) + submitList(files.mapIndexed { index, file -> Model(file, selectionIds.contains(index)) }) } - view.findViewById(R.id.image).setImageBitmap(BitmapFactory.decodeFile(item.path)) - view.findViewById(R.id.checkbox).isChecked = selected + view.findViewById(R.id.image)?.let { iv -> loadDelegate.load(iv, item.file) } + view.findViewById(R.id.checkbox).isChecked = item.isSelected } } @@ -65,16 +71,16 @@ internal class GalleryImagesMultipleAdapter( ) companion object { - private val diff = object : DiffUtil.ItemCallback() { + private val diff = object : DiffUtil.ItemCallback() { override fun areItemsTheSame( - oldItem: File, - newItem: File - ): Boolean = oldItem.path == newItem.path - - override fun areContentsTheSame(oldItem: File, newItem: File): Boolean { - TODO("Not yet implemented") - } + oldItem: Model, + newItem: Model, + ): Boolean = oldItem.file.path == newItem.file.path + override fun areContentsTheSame( + oldItem: Model, + newItem: Model, + ): Boolean = oldItem == newItem } } } diff --git a/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/activity/customgallery/adapter/single/GalleryImagesSingleAdapter.kt b/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/activity/customgallery/adapter/single/GalleryImagesSingleAdapter.kt index b3381ec..95f499b 100644 --- a/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/activity/customgallery/adapter/single/GalleryImagesSingleAdapter.kt +++ b/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/activity/customgallery/adapter/single/GalleryImagesSingleAdapter.kt @@ -1,6 +1,5 @@ package com.shz.imagepicker.imagepicker.activity.customgallery.adapter.single -import android.graphics.BitmapFactory import android.view.LayoutInflater import android.view.View import android.view.ViewGroup diff --git a/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/exception/FeatureNotSupportedException.kt b/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/exception/FeatureNotSupportedException.kt index a0c08e7..867973c 100644 --- a/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/exception/FeatureNotSupportedException.kt +++ b/imagepicker/src/main/java/com/shz/imagepicker/imagepicker/exception/FeatureNotSupportedException.kt @@ -2,7 +2,8 @@ package com.shz.imagepicker.imagepicker.exception import com.shz.imagepicker.imagepicker.ImagePicker -private const val DEFAULT_NOT_SUPPORTED_EXCEPTION_MESSAGE = "This feature is not supported on your configuration device" +private const val DEFAULT_NOT_SUPPORTED_EXCEPTION_MESSAGE = + "This feature is not supported on your configuration device" /** * Is thrown form [ImagePicker] when some feature is not supported.