Skip to content

Commit 4192e90

Browse files
committed
feat: allow closing photos and videos with a swipe gesture (#5609)
1 parent 946c018 commit 4192e90

File tree

5 files changed

+101
-5
lines changed

5 files changed

+101
-5
lines changed

app/src/main/java/com/nextcloud/talk/fullscreenfile/FullScreenImageActivity.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ package com.nextcloud.talk.fullscreenfile
1212
import android.content.Intent
1313
import android.os.Bundle
1414
import android.util.Log
15+
import com.nextcloud.talk.ui.SwipeToCloseLayout
1516
import android.view.Menu
1617
import android.view.MenuItem
1718
import android.view.View
@@ -133,6 +134,12 @@ class FullScreenImageActivity : AppCompatActivity() {
133134
binding.photoView.visibility = View.VISIBLE
134135
displayImage(path)
135136
}
137+
138+
binding.swipeToCloseLayout.setOnSwipeToCloseListener(object : SwipeToCloseLayout.OnSwipeToCloseListener {
139+
override fun onSwipeToClose() {
140+
finish()
141+
}
142+
})
136143
}
137144

138145
private fun displayImage(path: String) {

app/src/main/java/com/nextcloud/talk/fullscreenfile/FullScreenMediaActivity.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import com.nextcloud.talk.BuildConfig
3939
import com.nextcloud.talk.R
4040
import com.nextcloud.talk.application.NextcloudTalkApplication
4141
import com.nextcloud.talk.databinding.ActivityFullScreenMediaBinding
42+
import com.nextcloud.talk.ui.SwipeToCloseLayout
4243
import com.nextcloud.talk.ui.dialog.SaveToStorageDialogFragment
4344
import com.nextcloud.talk.utils.Mimetype.VIDEO_PREFIX_GENERIC
4445
import java.io.File
@@ -135,6 +136,12 @@ class FullScreenMediaActivity : AppCompatActivity() {
135136
}
136137
}
137138
)
139+
140+
binding.swipeToCloseLayout.setOnSwipeToCloseListener(object : SwipeToCloseLayout.OnSwipeToCloseListener {
141+
override fun onSwipeToClose() {
142+
finish()
143+
}
144+
})
138145
}
139146

140147
override fun onStart() {
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package com.nextcloud.talk.ui
2+
3+
import android.content.Context
4+
import android.util.AttributeSet
5+
import android.view.MotionEvent
6+
import android.view.View
7+
import android.widget.FrameLayout
8+
import androidx.customview.widget.ViewDragHelper
9+
import kotlin.math.abs
10+
11+
class SwipeToCloseLayout @JvmOverloads constructor(
12+
context: Context,
13+
attrs: AttributeSet? = null,
14+
defStyleAttr: Int = 0
15+
) : FrameLayout(context, attrs, defStyleAttr) {
16+
17+
private var dragHelper: ViewDragHelper
18+
private var swipeListener: OnSwipeToCloseListener? = null
19+
private var dragThreshold = 0.3f // 30% of height to trigger close
20+
21+
interface OnSwipeToCloseListener {
22+
fun onSwipeToClose()
23+
}
24+
25+
init {
26+
dragHelper = ViewDragHelper.create(this, 1.0f, DragCallback())
27+
}
28+
29+
fun setOnSwipeToCloseListener(listener: OnSwipeToCloseListener) {
30+
this.swipeListener = listener
31+
}
32+
33+
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
34+
val action = ev.actionMasked
35+
if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
36+
dragHelper.cancel()
37+
return false
38+
}
39+
return dragHelper.shouldInterceptTouchEvent(ev)
40+
}
41+
42+
override fun onTouchEvent(ev: MotionEvent): Boolean {
43+
dragHelper.processTouchEvent(ev)
44+
return true
45+
}
46+
47+
private inner class DragCallback : ViewDragHelper.Callback() {
48+
override fun tryCaptureView(child: View, pointerId: Int): Boolean {
49+
return true // Capture any child view
50+
}
51+
52+
override fun getViewVerticalDragRange(child: View): Int {
53+
return height
54+
}
55+
56+
override fun clampViewPositionVertical(child: View, therapeutic: Int, dy: Int): Int {
57+
return therapeutic
58+
}
59+
60+
override fun onViewReleased(releasedChild: View, xvel: Float, yvel: Float) {
61+
val totalDragDistance = abs(releasedChild.top)
62+
if (totalDragDistance > height * dragThreshold || abs(yvel) > dragHelper.minVelocity) {
63+
swipeListener?.onSwipeToClose()
64+
} else {
65+
dragHelper.settleCapturedViewAt(0, 0)
66+
invalidate()
67+
}
68+
}
69+
70+
override fun onViewPositionChanged(changedView: View, left: Int, top: Int, dx: Int, dy: Int) {
71+
val progress = 1f - (abs(top).toFloat() / height)
72+
alpha = progress.coerceIn(0.5f, 1.0f)
73+
}
74+
}
75+
76+
override fun computeScroll() {
77+
if (dragHelper.continueSettling(true)) {
78+
postInvalidateOnAnimation()
79+
}
80+
}
81+
}

app/src/main/res/layout/activity_full_screen_image.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
~ SPDX-FileCopyrightText: 2021 Dariusz Olszewski <starypatyk@gmail.com>
88
~ SPDX-License-Identifier: GPL-3.0-or-later
99
-->
10-
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
10+
<com.nextcloud.talk.ui.SwipeToCloseLayout xmlns:android="http://schemas.android.com/apk/res/android"
1111
xmlns:tools="http://schemas.android.com/tools"
1212
xmlns:app="http://schemas.android.com/apk/res-auto"
13-
android:id="@+id/image_wrapper_view"
13+
android:id="@+id/swipe_to_close_layout"
1414
android:layout_width="match_parent"
1515
android:layout_height="match_parent"
1616
tools:context=".fullscreenfile.FullScreenImageActivity">
@@ -35,4 +35,4 @@
3535
android:layout_height="match_parent"
3636
android:visibility="invisible" />
3737

38-
</FrameLayout>
38+
</com.nextcloud.talk.ui.SwipeToCloseLayout>

app/src/main/res/layout/activity_full_screen_media.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
~ SPDX-FileCopyrightText: 2021 Marcel Hibbe <dev@mhibbe.de>
77
~ SPDX-License-Identifier: GPL-3.0-or-later
88
-->
9-
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
9+
<com.nextcloud.talk.ui.SwipeToCloseLayout xmlns:android="http://schemas.android.com/apk/res/android"
1010
xmlns:app="http://schemas.android.com/apk/res-auto"
1111
xmlns:tools="http://schemas.android.com/tools"
12+
android:id="@+id/swipe_to_close_layout"
1213
android:layout_width="match_parent"
1314
android:layout_height="match_parent"
1415
tools:context=".fullscreenfile.FullScreenMediaActivity">
@@ -28,4 +29,4 @@
2829
app:show_buffering="when_playing"
2930
app:show_shuffle_button="true" />
3031

31-
</FrameLayout>
32+
</com.nextcloud.talk.ui.SwipeToCloseLayout>

0 commit comments

Comments
 (0)