Skip to content

Commit 7cf43ae

Browse files
committed
Reader : Take manual scroll into account during vertical auto-scroll [#1180]
1 parent fffd5c5 commit 7cf43ae

File tree

6 files changed

+49
-17
lines changed

6 files changed

+49
-17
lines changed

app/src/main/java/me/devsaki/hentoid/activities/AboutActivity.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.os.Bundle
44
import android.view.View
55
import androidx.fragment.app.Fragment
66
import androidx.fragment.app.commit
7+
import androidx.lifecycle.lifecycleScope
78
import androidx.recyclerview.widget.RecyclerView
89
import com.mikepenz.aboutlibraries.Libs
910
import com.mikepenz.aboutlibraries.LibsBuilder
@@ -55,7 +56,8 @@ class AboutActivity : BaseActivity() {
5556
recyclerView.setBackgroundColor(
5657
getThemedColor(R.color.window_background_light)
5758
)
58-
val scrollListener = ScrollPositionListener { _ -> /* Nothing */ }
59+
val scrollListener =
60+
ScrollPositionListener(lifecycleScope) { _ -> /* Nothing */ }
5961
scrollListener.setOnEndOutOfBoundScrollListener {
6062
AchievementsManager.trigger(16)
6163
}

app/src/main/java/me/devsaki/hentoid/fragments/library/LibraryContentFragment.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ class LibraryContentFragment : Fragment(), ChangeGroupDialogFragment.Parent,
164164
private var llm: LinearLayoutManager? = null
165165

166166
// Scroll listener for the top FAB
167-
private val scrollListener = ScrollPositionListener { i -> onScrollPositionChange(i) }
167+
private val scrollListener =
168+
ScrollPositionListener(lifecycleScope) { i -> onScrollPositionChange(i) }
168169

169170
// === FASTADAPTER COMPONENTS AND HELPERS
170171
private var itemAdapter: ItemAdapter<ContentItem>? = null
@@ -357,7 +358,7 @@ class LibraryContentFragment : Fragment(), ChangeGroupDialogFragment.Parent,
357358

358359
// Hide FAB when scrolling up
359360
binding?.topFab?.apply {
360-
scrollListener.setDeltaYListener(lifecycleScope) { i: Int ->
361+
scrollListener.setDeltaYListener { i: Int ->
361362
isVisible = (Settings.topFabEnabled && i > 0)
362363
}
363364

@@ -1148,7 +1149,10 @@ class LibraryContentFragment : Fragment(), ChangeGroupDialogFragment.Parent,
11481149
calledFromOnStart: Boolean
11491150
) {
11501151
selectExtension?.let { se ->
1151-
if (isSelected) IntRange(start, end).forEach { se.select(it, false, true) }
1152+
if (isSelected) IntRange(start, end).forEach { se.select(it,
1153+
fireEvent = false,
1154+
considerSelectableFlag = true
1155+
) }
11521156
else se.deselect(IntRange(start, end).toMutableList())
11531157
}
11541158
}

app/src/main/java/me/devsaki/hentoid/fragments/reader/ReaderPagerFragment.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ class ReaderPagerFragment : Fragment(R.layout.fragment_reader_pager),
121121
var reachedPosition = -1
122122

123123
private var hasGalleryBeenShown = false
124-
override val scrollListener = ScrollPositionListener { onScrollPositionChange(it) }
124+
override val scrollListener =
125+
ScrollPositionListener(lifecycleScope) { onScrollPositionChange(it) }
125126
private var orientation = DeviceOrientation.PORTRAIT
126127

127128
override var displayParams: DisplayParams? = null
@@ -491,6 +492,8 @@ class ReaderPagerFragment : Fragment(R.layout.fragment_reader_pager),
491492
slideshowMgr = ReaderSlideshow(this, lifecycleScope)
492493
slideshowMgr.init(it, this.resources)
493494

495+
scrollListener.setAbsYListener { slideshowMgr.onManualScrollY() }
496+
494497
// Fix page button
495498
it.viewerFixBtn.setOnClickListener { fixPage() }
496499

app/src/main/java/me/devsaki/hentoid/fragments/reader/ReaderSlideshow.kt

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class ReaderSlideshow(private val pager: Pager, lifecycleScope: LifecycleCorouti
5454

5555
private var hasGoneBack = false
5656

57+
private var autoScrollFactor = 1f
58+
5759
// Debouncer for the slideshow slider
5860
private val slideshowSliderDebouncer: Debouncer<Int>
5961

@@ -227,21 +229,26 @@ class ReaderSlideshow(private val pager: Pager, lifecycleScope: LifecycleCorouti
227229
}
228230

229231
private fun activateAutoScroll(factor: Float = -1f) {
230-
val theFactor = if (factor < 0) {
232+
autoScrollFactor = if (factor < 0) {
231233
val scrollParams = getScrollParams()
232234
scrollParams.second
233235
} else factor
234236

235-
// Create a a specific ReaderSmoothScroller to perform vertical slideshow (=auto-scroll)
237+
// Create a specific ReaderSmoothScroller to perform vertical slideshow (=auto-scroll)
236238
// Mandatory; if we don't recreate it, we can't change scrolling speed as it is cached internally
237-
val smoothScroller = ReaderSmoothScroller(controlsOverlay!!.root.context)
238-
smoothScroller.apply {
239+
ReaderSmoothScroller(controlsOverlay!!.root.context).apply {
239240
setCurrentPositionY(pager.scrollListener.totalScrolledY)
240241
setItemHeight(pager.adapter.getDimensionsAtPosition(pager.absImageIndex).y)
241242
targetPosition = pager.adapter.itemCount - 1
242-
setSpeed(900f / (theFactor / 4f))
243+
setSpeed(900f / (autoScrollFactor / 4f))
244+
pager.setAndStartSmoothScroll(this)
243245
}
244-
pager.setAndStartSmoothScroll(smoothScroller)
246+
}
247+
248+
fun onManualScrollY() {
249+
if (!isSlideshowActive) return
250+
if (VIEWER_ORIENTATION_VERTICAL != pager.displayParams?.orientation) return
251+
activateAutoScroll(autoScrollFactor)
245252
}
246253

247254
private fun onSlideshowTick() {

app/src/main/java/me/devsaki/hentoid/widget/ReaderSmoothScroller.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class ReaderSmoothScroller(context: Context) : LinearSmoothScroller(context) {
2323
}
2424

2525
fun setSpeed(speed: Float) {
26-
Timber.i("SPEED : %s", speed)
26+
Timber.d("SPEED : $speed")
2727
this.speed = speed
2828
}
2929

@@ -61,7 +61,7 @@ class ReaderSmoothScroller(context: Context) : LinearSmoothScroller(context) {
6161
mInterimTargetDy = scrollVector.y.toInt()
6262
val time = calculateTimeForScrolling(mInterimTargetDy)
6363
// To avoid UI hiccups, trigger a smooth scroll to a distance little further than the
64-
// interim target. Since we track the distance travelled in onSeekTargetStep callback, it
64+
// interim target. Since we track the distance traveled in onSeekTargetStep callback, it
6565
// won't actually scroll more than what we need.
6666
action.update(mInterimTargetDx, mInterimTargetDy, time, mLinearInterpolator)
6767
}

app/src/main/java/me/devsaki/hentoid/widget/ScrollPositionListener.kt

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package me.devsaki.hentoid.widget
22

3+
import androidx.core.util.Consumer
34
import androidx.recyclerview.widget.LinearLayoutManager
45
import androidx.recyclerview.widget.RecyclerView
56
import kotlinx.coroutines.CoroutineScope
67
import me.devsaki.hentoid.util.Debouncer
78

8-
class ScrollPositionListener(private val onPositionChangeListener: (Int) -> Unit) :
9+
class ScrollPositionListener(
10+
scope: CoroutineScope,
11+
private val onPositionChangeListener: (Int) -> Unit
12+
) :
913
RecyclerView.OnScrollListener() {
1014
private var isScrollEnabled = true
1115

@@ -24,19 +28,31 @@ class ScrollPositionListener(private val onPositionChangeListener: (Int) -> Unit
2428

2529
private var deltaEventDebouncer: Debouncer<Int>? = null
2630

31+
private var onScrollYDelta: Consumer<Int>? = null
32+
private var onScrollYAbs: Consumer<Int>? = null
33+
2734
private var onPositionReachedListener: ((Int) -> Unit)? = null
2835

2936
private var onStartOutOfBoundScroll: Runnable? = null
3037
private var onEndOutOfBoundScroll: Runnable? = null
3138

3239

33-
fun setDeltaYListener(scope: CoroutineScope, deltaYListener: (Int) -> Unit) {
34-
deltaEventDebouncer = Debouncer(scope, 75) { i: Int ->
35-
deltaYListener.invoke(i - mInitialOffsetY)
40+
init {
41+
deltaEventDebouncer = Debouncer(scope, 75) { absY: Int ->
42+
onScrollYAbs?.accept(absY)
43+
onScrollYDelta?.accept(absY - mInitialOffsetY)
3644
mInitialOffsetY = -1
3745
}
3846
}
3947

48+
fun setDeltaYListener(deltaYListener: Consumer<Int>) {
49+
onScrollYDelta = deltaYListener
50+
}
51+
52+
fun setAbsYListener(absYListener: Consumer<Int>) {
53+
onScrollYAbs = absYListener
54+
}
55+
4056
fun setOnStartOutOfBoundScrollListener(onStartOutOfBoundScrollListener: Runnable?) {
4157
onStartOutOfBoundScroll = onStartOutOfBoundScrollListener
4258
}

0 commit comments

Comments
 (0)