draft: switch to overlay for focus indicator
This commit is contained in:
parent
8f08b1b678
commit
d345e62e9f
|
@ -45,6 +45,7 @@ import com.bumptech.glide.util.Util
|
||||||
import com.github.chrisbanes.photoview.OnPhotoTapListener
|
import com.github.chrisbanes.photoview.OnPhotoTapListener
|
||||||
import com.github.chrisbanes.photoview.PhotoView
|
import com.github.chrisbanes.photoview.PhotoView
|
||||||
import com.keylesspalace.tusky.R
|
import com.keylesspalace.tusky.R
|
||||||
|
import com.keylesspalace.tusky.databinding.DialogFocusBinding
|
||||||
import com.keylesspalace.tusky.entity.Attachment.Focus
|
import com.keylesspalace.tusky.entity.Attachment.Focus
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
|
@ -161,48 +162,15 @@ fun <T> T.makeFocusDialog(
|
||||||
previewUri: Uri,
|
previewUri: Uri,
|
||||||
onUpdateFocus: suspend (Focus) -> Boolean
|
onUpdateFocus: suspend (Focus) -> Boolean
|
||||||
) where T : Activity, T : LifecycleOwner {
|
) where T : Activity, T : LifecycleOwner {
|
||||||
var focus = existingFocus ?: Focus(0.0f, 0.0f) // Default to center
|
val focus = existingFocus ?: Focus(0.0f, 0.0f) // Default to center
|
||||||
|
|
||||||
val dialogLayout = LinearLayout(this)
|
val dialogBinding = DialogFocusBinding.inflate(layoutInflater)
|
||||||
val padding = Utils.dpToPx(this, 8)
|
|
||||||
dialogLayout.setPadding(padding, padding, padding, padding)
|
|
||||||
dialogLayout.orientation = LinearLayout.VERTICAL
|
|
||||||
|
|
||||||
val baseImageRequest = Glide.with(this)
|
Glide.with(this)
|
||||||
.load(previewUri)
|
.load(previewUri)
|
||||||
.downsample(DownsampleStrategy.CENTER_INSIDE)
|
.downsample(DownsampleStrategy.CENTER_INSIDE)
|
||||||
|
.into(dialogBinding.imageView)
|
||||||
|
|
||||||
var imageView: PhotoView? = null
|
|
||||||
|
|
||||||
// Note all calls of this function are after imageView goes non-null
|
|
||||||
fun imageRequest() {
|
|
||||||
baseImageRequest.transform(HighlightFocus(focus))
|
|
||||||
.into(object : CustomTarget<Drawable>(4096, 4096) {
|
|
||||||
override fun onLoadCleared(placeholder: Drawable?) {
|
|
||||||
imageView!!.setImageDrawable(placeholder)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
|
|
||||||
imageView!!.setImageDrawable(resource)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
imageView = PhotoView(this).apply {
|
|
||||||
maximumScale = 6f
|
|
||||||
setOnPhotoTapListener(object : OnPhotoTapListener {
|
|
||||||
override fun onPhotoTap(view: ImageView, x: Float, y: Float) {
|
|
||||||
focus = Focus(x * 2 - 1, 1 - y * 2) // PhotoView range is 0..1 Y-down but Mastodon API range is -1..1 Y-up
|
|
||||||
imageRequest()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
val margin = Utils.dpToPx(this, 4)
|
|
||||||
dialogLayout.addView(imageView)
|
|
||||||
(imageView.layoutParams as LinearLayout.LayoutParams).weight = 1f
|
|
||||||
imageView.layoutParams.height = 0
|
|
||||||
(imageView.layoutParams as LinearLayout.LayoutParams).setMargins(0, margin, 0, 0)
|
|
||||||
|
|
||||||
val okListener = { dialog: DialogInterface, _: Int ->
|
val okListener = { dialog: DialogInterface, _: Int ->
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
|
@ -214,7 +182,7 @@ fun <T> T.makeFocusDialog(
|
||||||
}
|
}
|
||||||
|
|
||||||
val dialog = AlertDialog.Builder(this)
|
val dialog = AlertDialog.Builder(this)
|
||||||
.setView(dialogLayout)
|
.setView(dialogBinding.root)
|
||||||
.setPositiveButton(android.R.string.ok, okListener)
|
.setPositiveButton(android.R.string.ok, okListener)
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.create()
|
.create()
|
||||||
|
@ -226,8 +194,7 @@ fun <T> T.makeFocusDialog(
|
||||||
|
|
||||||
dialog.show()
|
dialog.show()
|
||||||
|
|
||||||
// Load the image and manually set it into the ImageView because it doesn't have a fixed size.
|
|
||||||
imageRequest()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Activity.showFailedFocusMessage() {
|
private fun Activity.showFailedFocusMessage() {
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.keylesspalace.tusky.components.compose.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import androidx.appcompat.content.res.AppCompatResources
|
||||||
|
import com.keylesspalace.tusky.R
|
||||||
|
import com.keylesspalace.tusky.entity.Attachment
|
||||||
|
|
||||||
|
class FocusIndicatorView
|
||||||
|
@JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = 0
|
||||||
|
) : View(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
private var focusDrawable: Drawable = AppCompatResources.getDrawable(context, R.drawable.spellcheck)!! // TODO: use an actual drawable suited as indicator
|
||||||
|
private var posX = 0f
|
||||||
|
private var posY = 0f
|
||||||
|
|
||||||
|
fun setFocus(focus: Attachment.Focus) {
|
||||||
|
// TODO
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFocus() {
|
||||||
|
// TODO
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||||
|
// TODO: only handle events if they are on top of the image below
|
||||||
|
// TODO: don't handle all event actions
|
||||||
|
|
||||||
|
posX = event.x
|
||||||
|
posY = event.y
|
||||||
|
invalidate()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDraw(canvas: Canvas) {
|
||||||
|
super.onDraw(canvas)
|
||||||
|
focusDrawable.setBounds(
|
||||||
|
posX.toInt() - focusDrawable.intrinsicWidth / 2,
|
||||||
|
posY.toInt() - focusDrawable.intrinsicHeight / 2,
|
||||||
|
posX.toInt() + focusDrawable.intrinsicWidth / 2,
|
||||||
|
posY.toInt() + focusDrawable.intrinsicHeight / 2
|
||||||
|
)
|
||||||
|
focusDrawable.draw(canvas)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<!-- todo add padding -->
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imageView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
<com.keylesspalace.tusky.components.compose.view.FocusIndicatorView
|
||||||
|
android:id="@+id/focusIndicator"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
Loading…
Reference in New Issue