PixelDroid-App-Android/app/src/main/java/org/pixeldroid/app/postCreation/photoEdit/cropper/CropImageView.kt

101 lines
3.7 KiB
Kotlin
Raw Normal View History

2022-10-17 13:23:02 +02:00
package org.pixeldroid.app.postCreation.photoEdit.cropper
import android.content.Context
import android.graphics.Rect
import android.graphics.RectF
import android.graphics.drawable.Drawable
import android.net.Uri
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.FrameLayout
import androidx.core.graphics.toRect
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
2022-10-19 00:19:42 +02:00
import org.pixeldroid.app.databinding.CropImageViewBinding
import org.pixeldroid.app.postCreation.photoEdit.VideoEditActivity
2022-10-17 13:23:02 +02:00
/** Custom view that provides cropping capabilities to an image. */
class CropImageView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null) :
FrameLayout(context!!, attrs) {
2022-10-19 00:19:42 +02:00
private val binding: CropImageViewBinding =
CropImageViewBinding.inflate(LayoutInflater.from(context), this, true)
2022-10-17 13:23:02 +02:00
init {
2022-10-19 00:19:42 +02:00
binding.CropOverlayView.setInitialAttributeValues()
2022-10-17 13:23:02 +02:00
}
/**
* Gets the crop window's position relative to the parent's view at screen.
*
2022-10-19 00:19:42 +02:00
* @return a Rect instance containing notCropped area boundaries of the source Bitmap
2022-10-17 13:23:02 +02:00
*/
val cropWindowRect: RectF?
2022-10-19 00:19:42 +02:00
get() = binding.CropOverlayView.cropWindowRect
2022-10-17 13:23:02 +02:00
/** Reset crop window to initial rectangle. */
fun resetCropRect() {
2022-10-19 00:19:42 +02:00
binding.CropOverlayView.resetCropWindowRect()
2022-10-17 13:23:02 +02:00
}
2022-10-19 00:19:42 +02:00
fun getInitialCropWindowRect(): Rect = binding.CropOverlayView.initialCropWindowRect
2022-10-17 13:23:02 +02:00
/**
2022-10-19 00:19:42 +02:00
* Sets the image loaded from the given URI as the content of the CropImageView
2022-10-17 13:23:02 +02:00
*
* @param uri the URI to load the image from
*/
2022-10-19 00:19:42 +02:00
fun setImageUriAsync(uri: Uri, cropRelativeDimensions: VideoEditActivity.RelativeCropPosition) {
// either no existing task is working or we canceled it, need to load new URI
binding.CropOverlayView.initialCropWindowRect = null
2022-10-17 13:23:02 +02:00
Glide.with(this).load(uri).fitCenter().listener(object : RequestListener<Drawable> {
2022-10-19 00:19:42 +02:00
override fun onLoadFailed(
e: GlideException?,
m: Any?,
t: Target<Drawable>?,
i: Boolean,
): Boolean {
return false
}
2022-10-17 13:23:02 +02:00
override fun onResourceReady(
resource: Drawable?,
model: Any?,
target: Target<Drawable>?,
dataSource: DataSource?,
2022-10-19 00:19:42 +02:00
isFirstResource: Boolean,
2022-10-17 13:23:02 +02:00
): Boolean {
// Get width and height that the image will take on the screen
val drawnWidth = resource?.intrinsicWidth ?: width
val drawnHeight = resource?.intrinsicHeight ?: height
2022-10-19 00:19:42 +02:00
binding.CropOverlayView.initialCropWindowRect = RectF(
(width - drawnWidth) / 2f,
(height - drawnHeight) / 2f,
(width + drawnWidth) / 2f,
(height + drawnHeight) / 2f
).toRect()
binding.CropOverlayView.setCropWindowLimits(
drawnWidth.toFloat(),
drawnHeight.toFloat()
)
binding.CropOverlayView.invalidate()
binding.CropOverlayView.setBounds(width, height)
binding.CropOverlayView.resetCropOverlayView()
if (!cropRelativeDimensions.notCropped()) binding.CropOverlayView.setRecordedCropWindowRect(cropRelativeDimensions)
binding.CropOverlayView.visibility = VISIBLE
2022-10-17 13:23:02 +02:00
// Indicate to Glide that the image hasn't been set yet
return false
}
2022-10-19 00:19:42 +02:00
}).into(binding.ImageViewImage)
2022-10-17 13:23:02 +02:00
}
}