Roll back image viewer but retain swiping fix (#1863)
This fixes crashes with images which were too wide (aspect ratio wise).
This commit is contained in:
parent
b3b4794a2b
commit
f37a589dce
4 changed files with 73 additions and 61 deletions
|
@ -159,7 +159,7 @@ dependencies {
|
|||
|
||||
implementation "com.github.connyduck:sparkbutton:4.0.0"
|
||||
|
||||
implementation 'com.github.MikeOrtiz:TouchImageView:3.0.1'
|
||||
implementation "com.github.chrisbanes:PhotoView:2.3.0"
|
||||
|
||||
implementation "com.mikepenz:materialdrawer:$materialdrawerVersion"
|
||||
implementation "com.mikepenz:materialdrawer-iconics:$materialdrawerVersion"
|
||||
|
|
|
@ -33,9 +33,9 @@ import at.connyduck.sparkbutton.helpers.Utils
|
|||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.target.CustomTarget
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import com.github.chrisbanes.photoview.PhotoView
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.util.withLifecycleContext
|
||||
import com.ortiz.touchview.TouchImageView
|
||||
|
||||
// https://github.com/tootsuite/mastodon/blob/1656663/app/models/media_attachment.rb#L94
|
||||
private const val MEDIA_DESCRIPTION_CHARACTER_LIMIT = 420
|
||||
|
@ -50,8 +50,8 @@ fun <T> T.makeCaptionDialog(existingDescription: String?,
|
|||
dialogLayout.setPadding(padding, padding, padding, padding)
|
||||
|
||||
dialogLayout.orientation = LinearLayout.VERTICAL
|
||||
val imageView = TouchImageView(this).apply {
|
||||
maxZoom = 6f
|
||||
val imageView = PhotoView(this).apply {
|
||||
maximumScale = 6f
|
||||
}
|
||||
|
||||
val displayMetrics = DisplayMetrics()
|
||||
|
|
|
@ -29,6 +29,7 @@ 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
|
||||
import com.github.chrisbanes.photoview.PhotoViewAttacher
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.entity.Attachment
|
||||
import com.keylesspalace.tusky.util.hide
|
||||
|
@ -45,6 +46,7 @@ class ViewImageFragment : ViewMediaFragment() {
|
|||
fun onPhotoTap()
|
||||
}
|
||||
|
||||
private lateinit var attacher: PhotoViewAttacher
|
||||
private lateinit var photoActionsListener: PhotoActionsListener
|
||||
private lateinit var toolbar: View
|
||||
private var transition = BehaviorSubject.create<Unit>()
|
||||
|
@ -61,9 +63,68 @@ class ViewImageFragment : ViewMediaFragment() {
|
|||
photoActionsListener = context as PhotoActionsListener
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun setupMediaView(url: String, previewUrl: String?) {
|
||||
descriptionView = mediaDescription
|
||||
photoView.transitionName = url
|
||||
attacher = PhotoViewAttacher(photoView).apply {
|
||||
// This prevents conflicts with ViewPager
|
||||
setAllowParentInterceptOnEdge(true)
|
||||
|
||||
// Clicking outside the photo closes the viewer.
|
||||
setOnOutsidePhotoTapListener { photoActionsListener.onDismiss() }
|
||||
setOnClickListener { onMediaTap() }
|
||||
|
||||
/* A vertical swipe motion also closes the viewer. This is especially useful when the photo
|
||||
* mostly fills the screen so clicking outside is difficult. */
|
||||
setOnSingleFlingListener { _, _, velocityX, velocityY ->
|
||||
var result = false
|
||||
if (abs(velocityY) > abs(velocityX)) {
|
||||
photoActionsListener.onDismiss()
|
||||
result = true
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
val gestureDetector = GestureDetector(requireContext(), object : GestureDetector.SimpleOnGestureListener() {
|
||||
override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
|
||||
onMediaTap()
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
var lastY = 0f
|
||||
|
||||
photoView.setOnTouchListener { v, event ->
|
||||
// This part is for scaling/translating on vertical move.
|
||||
// We use raw coordinates to get the correct ones during scaling
|
||||
|
||||
gestureDetector.onTouchEvent(event)
|
||||
|
||||
if (event.action == MotionEvent.ACTION_DOWN) {
|
||||
lastY = event.rawY
|
||||
} else if (event.pointerCount == 1
|
||||
&& attacher.scale == 1f
|
||||
&& event.action == MotionEvent.ACTION_MOVE
|
||||
) {
|
||||
val diff = event.rawY - lastY
|
||||
// This code is to prevent transformations during page scrolling
|
||||
// If we are already translating or we reached the threshold, then transform.
|
||||
if (photoView.translationY != 0f || abs(diff) > 40) {
|
||||
photoView.translationY += (diff)
|
||||
val scale = (-abs(photoView.translationY) / 720 + 1).coerceAtLeast(0.5f)
|
||||
photoView.scaleY = scale
|
||||
photoView.scaleX = scale
|
||||
lastY = event.rawY
|
||||
return@setOnTouchListener true
|
||||
}
|
||||
} else if (event.action == MotionEvent.ACTION_UP || event.action == MotionEvent.ACTION_CANCEL) {
|
||||
onGestureEnd()
|
||||
}
|
||||
attacher.onTouch(v, event)
|
||||
}
|
||||
|
||||
startedTransition = false
|
||||
loadImageFromNetwork(url, previewUrl, photoView)
|
||||
}
|
||||
|
@ -74,64 +135,9 @@ class ViewImageFragment : ViewMediaFragment() {
|
|||
return inflater.inflate(R.layout.fragment_view_image, container, false)
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val gestureDetector = GestureDetector(requireContext(), object : GestureDetector.SimpleOnGestureListener() {
|
||||
override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
|
||||
onMediaTap()
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
var lastY = 0f
|
||||
photoView.setOnTouchListener { _, event ->
|
||||
// This part is for scaling/translating on vertical move.
|
||||
// We use raw coordinates to get the correct ones during scaling
|
||||
var result = true
|
||||
|
||||
gestureDetector.onTouchEvent(event)
|
||||
|
||||
if (event.action == MotionEvent.ACTION_DOWN) {
|
||||
lastY = event.rawY
|
||||
} else if (!photoView.isZoomed && event.action == MotionEvent.ACTION_MOVE) {
|
||||
val diff = event.rawY - lastY
|
||||
// This code is to prevent transformations during page scrolling
|
||||
// If we are already translating or we reached the threshold, then transform.
|
||||
if (photoView.translationY != 0f || abs(diff) > 40) {
|
||||
photoView.translationY += (diff)
|
||||
val scale = (-abs(photoView.translationY) / 720 + 1).coerceAtLeast(0.5f)
|
||||
photoView.scaleY = scale
|
||||
photoView.scaleX = scale
|
||||
lastY = event.rawY
|
||||
}
|
||||
return@setOnTouchListener true
|
||||
} else if (event.action == MotionEvent.ACTION_UP || event.action == MotionEvent.ACTION_CANCEL) {
|
||||
onGestureEnd()
|
||||
} else if (event.pointerCount >= 2 || photoView.canScrollHorizontally(1) && photoView.canScrollHorizontally(-1)) {
|
||||
// Starting from here is adapted code from TouchImageView to play nice with pager.
|
||||
|
||||
// Can scroll horizontally checks if there's still a part of the image.
|
||||
// That can be scrolled until you reach the edge multi-touch event.
|
||||
val parent = view.parent
|
||||
result = when (event.action) {
|
||||
MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE -> {
|
||||
// Disallow RecyclerView to intercept touch events.
|
||||
parent.requestDisallowInterceptTouchEvent(true)
|
||||
// Disable touch on view
|
||||
false
|
||||
}
|
||||
MotionEvent.ACTION_UP -> {
|
||||
// Allow RecyclerView to intercept touch events.
|
||||
parent.requestDisallowInterceptTouchEvent(false)
|
||||
true
|
||||
}
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
val arguments = this.requireArguments()
|
||||
val attachment = arguments.getParcelable<Attachment>(ARG_ATTACHMENT)
|
||||
|
@ -267,7 +273,13 @@ class ViewImageFragment : ViewMediaFragment() {
|
|||
// another branch. take() will unsubscribe after we have it to not leak menmory
|
||||
transition
|
||||
.take(1)
|
||||
.subscribe { target.onResourceReady(resource, null) }
|
||||
.subscribe {
|
||||
target.onResourceReady(resource, null)
|
||||
// It's needed. Don't ask why, I don't know, setImageDrawable() should
|
||||
// do it by itself but somehow it doesn't work automatically.
|
||||
// Just do it. If you don't, image will jump around when touched.
|
||||
attacher.update()
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
|
||||
<com.ortiz.touchview.TouchImageView
|
||||
<com.github.chrisbanes.photoview.PhotoView
|
||||
android:id="@+id/photoView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
|
Loading…
Reference in a new issue