Respect system animation disabling #341
This commit is contained in:
@@ -15,8 +15,8 @@ android {
|
|||||||
applicationId 'org.koitharu.kotatsu'
|
applicationId 'org.koitharu.kotatsu'
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 33
|
targetSdkVersion 33
|
||||||
versionCode 532
|
versionCode 533
|
||||||
versionName '5.0-a3'
|
versionName '5.0-a4'
|
||||||
generatedDensities = []
|
generatedDensities = []
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
|
|||||||
@@ -12,12 +12,11 @@ import android.view.ViewOutlineProvider
|
|||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
import androidx.annotation.FloatRange
|
import androidx.annotation.FloatRange
|
||||||
import androidx.core.graphics.ColorUtils
|
|
||||||
import org.koitharu.kotatsu.parsers.util.replaceWith
|
import org.koitharu.kotatsu.parsers.util.replaceWith
|
||||||
import org.koitharu.kotatsu.utils.ext.getAnimationDuration
|
import org.koitharu.kotatsu.utils.ext.getAnimationDuration
|
||||||
import org.koitharu.kotatsu.utils.ext.getThemeColor
|
import org.koitharu.kotatsu.utils.ext.getThemeColor
|
||||||
|
import org.koitharu.kotatsu.utils.ext.isAnimationsEnabled
|
||||||
import org.koitharu.kotatsu.utils.ext.resolveDp
|
import org.koitharu.kotatsu.utils.ext.resolveDp
|
||||||
import kotlin.random.Random
|
|
||||||
import com.google.android.material.R as materialR
|
import com.google.android.material.R as materialR
|
||||||
|
|
||||||
class SegmentedBarView @JvmOverloads constructor(
|
class SegmentedBarView @JvmOverloads constructor(
|
||||||
@@ -34,29 +33,10 @@ class SegmentedBarView @JvmOverloads constructor(
|
|||||||
private var scaleFactor = 1f
|
private var scaleFactor = 1f
|
||||||
private var scaleAnimator: ValueAnimator? = null
|
private var scaleAnimator: ValueAnimator? = null
|
||||||
|
|
||||||
var segments: List<Segment>
|
|
||||||
get() = segmentsData
|
|
||||||
set(value) {
|
|
||||||
scaleAnimator?.cancel()
|
|
||||||
scaleAnimator = null
|
|
||||||
segmentsData.replaceWith(value)
|
|
||||||
updateSizes()
|
|
||||||
invalidate()
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
paint.strokeWidth = context.resources.resolveDp(1f)
|
paint.strokeWidth = context.resources.resolveDp(1f)
|
||||||
outlineProvider = OutlineProvider()
|
outlineProvider = OutlineProvider()
|
||||||
clipToOutline = true
|
clipToOutline = true
|
||||||
|
|
||||||
if (isInEditMode) {
|
|
||||||
segments = List(Random.nextInt(3, 5)) {
|
|
||||||
Segment(
|
|
||||||
percent = Random.nextFloat(),
|
|
||||||
color = ColorUtils.HSLToColor(floatArrayOf(Random.nextInt(0, 360).toFloat(), 0.5f, 0.5f)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
||||||
@@ -107,8 +87,15 @@ class SegmentedBarView @JvmOverloads constructor(
|
|||||||
|
|
||||||
fun animateSegments(value: List<Segment>) {
|
fun animateSegments(value: List<Segment>) {
|
||||||
scaleAnimator?.cancel()
|
scaleAnimator?.cancel()
|
||||||
scaleFactor = 0f
|
|
||||||
segmentsData.replaceWith(value)
|
segmentsData.replaceWith(value)
|
||||||
|
if (!context.isAnimationsEnabled) {
|
||||||
|
scaleAnimator = null
|
||||||
|
scaleFactor = 1f
|
||||||
|
updateSizes()
|
||||||
|
invalidate()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
scaleFactor = 0f
|
||||||
updateSizes()
|
updateSizes()
|
||||||
invalidate()
|
invalidate()
|
||||||
val animator = ValueAnimator.ofFloat(0f, 1f)
|
val animator = ValueAnimator.ofFloat(0f, 1f)
|
||||||
@@ -124,7 +111,7 @@ class SegmentedBarView @JvmOverloads constructor(
|
|||||||
segmentsSizes.clear()
|
segmentsSizes.clear()
|
||||||
segmentsSizes.ensureCapacity(segmentsData.size + 1)
|
segmentsSizes.ensureCapacity(segmentsData.size + 1)
|
||||||
var w = width.toFloat()
|
var w = width.toFloat()
|
||||||
val maxScale = (scaleFactor * (segments.size - 1)).coerceAtLeast(1f)
|
val maxScale = (scaleFactor * (segmentsData.size - 1)).coerceAtLeast(1f)
|
||||||
for ((index, segment) in segmentsData.withIndex()) {
|
for ((index, segment) in segmentsData.withIndex()) {
|
||||||
val scale = (scaleFactor * (index + 1) / maxScale).coerceAtMost(1f)
|
val scale = (scaleFactor * (index + 1) / maxScale).coerceAtMost(1f)
|
||||||
val segmentWidth = (w * segment.percent).coerceAtLeast(
|
val segmentWidth = (w * segment.percent).coerceAtLeast(
|
||||||
|
|||||||
@@ -6,12 +6,13 @@ import org.koitharu.kotatsu.databinding.ItemHeader2Binding
|
|||||||
import org.koitharu.kotatsu.list.ui.model.ListHeader2
|
import org.koitharu.kotatsu.list.ui.model.ListHeader2
|
||||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||||
|
import org.koitharu.kotatsu.utils.ext.isAnimationsEnabled
|
||||||
import org.koitharu.kotatsu.utils.ext.setTextAndVisible
|
import org.koitharu.kotatsu.utils.ext.setTextAndVisible
|
||||||
|
|
||||||
fun listHeader2AD(
|
fun listHeader2AD(
|
||||||
listener: MangaListListener,
|
listener: MangaListListener,
|
||||||
) = adapterDelegateViewBinding<ListHeader2, ListModel, ItemHeader2Binding>(
|
) = adapterDelegateViewBinding<ListHeader2, ListModel, ItemHeader2Binding>(
|
||||||
{ layoutInflater, parent -> ItemHeader2Binding.inflate(layoutInflater, parent, false) }
|
{ layoutInflater, parent -> ItemHeader2Binding.inflate(layoutInflater, parent, false) },
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var ignoreChecking = false
|
var ignoreChecking = false
|
||||||
@@ -26,11 +27,15 @@ fun listHeader2AD(
|
|||||||
|
|
||||||
bind { payloads ->
|
bind { payloads ->
|
||||||
if (payloads.isNotEmpty()) {
|
if (payloads.isNotEmpty()) {
|
||||||
binding.scrollView.smoothScrollTo(0, 0)
|
if (context.isAnimationsEnabled) {
|
||||||
|
binding.scrollView.smoothScrollTo(0, 0)
|
||||||
|
} else {
|
||||||
|
binding.scrollView.scrollTo(0, 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ignoreChecking = true
|
ignoreChecking = true
|
||||||
binding.chipsTags.setChips(item.chips) // TODO use recyclerview
|
binding.chipsTags.setChips(item.chips) // TODO use recyclerview
|
||||||
ignoreChecking = false
|
ignoreChecking = false
|
||||||
binding.textViewFilter.setTextAndVisible(item.sortOrder?.titleRes ?: 0)
|
binding.textViewFilter.setTextAndVisible(item.sortOrder?.titleRes ?: 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import org.koitharu.kotatsu.explore.ui.ExploreFragment
|
|||||||
import org.koitharu.kotatsu.settings.tools.ToolsFragment
|
import org.koitharu.kotatsu.settings.tools.ToolsFragment
|
||||||
import org.koitharu.kotatsu.shelf.ui.ShelfFragment
|
import org.koitharu.kotatsu.shelf.ui.ShelfFragment
|
||||||
import org.koitharu.kotatsu.tracker.ui.feed.FeedFragment
|
import org.koitharu.kotatsu.tracker.ui.feed.FeedFragment
|
||||||
|
import org.koitharu.kotatsu.utils.ext.firstVisibleItemPosition
|
||||||
|
import org.koitharu.kotatsu.utils.ext.isAnimationsEnabled
|
||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
|
|
||||||
private const val TAG_PRIMARY = "primary"
|
private const val TAG_PRIMARY = "primary"
|
||||||
@@ -44,7 +46,11 @@ class MainNavigationDelegate(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
val recyclerView = fragment.recyclerView
|
val recyclerView = fragment.recyclerView
|
||||||
recyclerView.smoothScrollToPosition(0)
|
if (recyclerView.context.isAnimationsEnabled) {
|
||||||
|
recyclerView.smoothScrollToPosition(0)
|
||||||
|
} else {
|
||||||
|
recyclerView.firstVisibleItemPosition = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleOnBackPressed() {
|
override fun handleOnBackPressed() {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter
|
|||||||
import org.koitharu.kotatsu.reader.ui.pager.ReaderPage
|
import org.koitharu.kotatsu.reader.ui.pager.ReaderPage
|
||||||
import org.koitharu.kotatsu.reader.ui.pager.standard.PagerReaderFragment
|
import org.koitharu.kotatsu.reader.ui.pager.standard.PagerReaderFragment
|
||||||
import org.koitharu.kotatsu.utils.ext.doOnPageChanged
|
import org.koitharu.kotatsu.utils.ext.doOnPageChanged
|
||||||
|
import org.koitharu.kotatsu.utils.ext.isAnimationsEnabled
|
||||||
import org.koitharu.kotatsu.utils.ext.recyclerView
|
import org.koitharu.kotatsu.utils.ext.recyclerView
|
||||||
import org.koitharu.kotatsu.utils.ext.resetTransformations
|
import org.koitharu.kotatsu.utils.ext.resetTransformations
|
||||||
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
|
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
|
||||||
@@ -74,15 +75,17 @@ class ReversedReaderFragment : BaseReader<FragmentReaderStandardBinding>() {
|
|||||||
|
|
||||||
override fun switchPageBy(delta: Int) {
|
override fun switchPageBy(delta: Int) {
|
||||||
with(binding.pager) {
|
with(binding.pager) {
|
||||||
setCurrentItem(currentItem - delta, true)
|
setCurrentItem(currentItem - delta, context.isAnimationsEnabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun switchPageTo(position: Int, smooth: Boolean) {
|
override fun switchPageTo(position: Int, smooth: Boolean) {
|
||||||
binding.pager.setCurrentItem(
|
with(binding.pager) {
|
||||||
reversed(position),
|
setCurrentItem(
|
||||||
smooth && (binding.pager.currentItem - position).absoluteValue < PagerReaderFragment.SMOOTH_SCROLL_LIMIT,
|
reversed(position),
|
||||||
)
|
smooth && context.isAnimationsEnabled && (currentItem - position).absoluteValue < PagerReaderFragment.SMOOTH_SCROLL_LIMIT,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?) {
|
override fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import org.koitharu.kotatsu.reader.ui.pager.BaseReader
|
|||||||
import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter
|
import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter
|
||||||
import org.koitharu.kotatsu.reader.ui.pager.ReaderPage
|
import org.koitharu.kotatsu.reader.ui.pager.ReaderPage
|
||||||
import org.koitharu.kotatsu.utils.ext.doOnPageChanged
|
import org.koitharu.kotatsu.utils.ext.doOnPageChanged
|
||||||
|
import org.koitharu.kotatsu.utils.ext.isAnimationsEnabled
|
||||||
import org.koitharu.kotatsu.utils.ext.recyclerView
|
import org.koitharu.kotatsu.utils.ext.recyclerView
|
||||||
import org.koitharu.kotatsu.utils.ext.resetTransformations
|
import org.koitharu.kotatsu.utils.ext.resetTransformations
|
||||||
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
|
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
|
||||||
@@ -93,15 +94,17 @@ class PagerReaderFragment : BaseReader<FragmentReaderStandardBinding>() {
|
|||||||
|
|
||||||
override fun switchPageBy(delta: Int) {
|
override fun switchPageBy(delta: Int) {
|
||||||
with(binding.pager) {
|
with(binding.pager) {
|
||||||
setCurrentItem(currentItem + delta, true)
|
setCurrentItem(currentItem + delta, context.isAnimationsEnabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun switchPageTo(position: Int, smooth: Boolean) {
|
override fun switchPageTo(position: Int, smooth: Boolean) {
|
||||||
binding.pager.setCurrentItem(
|
with(binding.pager) {
|
||||||
position,
|
setCurrentItem(
|
||||||
smooth && (binding.pager.currentItem - position).absoluteValue < SMOOTH_SCROLL_LIMIT,
|
position,
|
||||||
)
|
smooth && context.isAnimationsEnabled && (currentItem - position).absoluteValue < SMOOTH_SCROLL_LIMIT,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getCurrentState(): ReaderState? = bindingOrNull()?.run {
|
override fun getCurrentState(): ReaderState? = bindingOrNull()?.run {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter
|
|||||||
import org.koitharu.kotatsu.reader.ui.pager.ReaderPage
|
import org.koitharu.kotatsu.reader.ui.pager.ReaderPage
|
||||||
import org.koitharu.kotatsu.utils.ext.findCenterViewPosition
|
import org.koitharu.kotatsu.utils.ext.findCenterViewPosition
|
||||||
import org.koitharu.kotatsu.utils.ext.firstVisibleItemPosition
|
import org.koitharu.kotatsu.utils.ext.firstVisibleItemPosition
|
||||||
|
import org.koitharu.kotatsu.utils.ext.isAnimationsEnabled
|
||||||
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
|
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -103,11 +104,13 @@ class WebtoonReaderFragment : BaseReader<FragmentReaderWebtoonBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun switchPageBy(delta: Int) {
|
override fun switchPageBy(delta: Int) {
|
||||||
binding.recyclerView.smoothScrollBy(
|
with(binding.recyclerView) {
|
||||||
0,
|
if (context.isAnimationsEnabled) {
|
||||||
(binding.recyclerView.height * 0.9).toInt() * delta,
|
smoothScrollBy(0, (height * 0.9).toInt() * delta, scrollInterpolator)
|
||||||
scrollInterpolator,
|
} else {
|
||||||
)
|
nestedScrollBy(0, (height * 0.9).toInt() * delta)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun switchPageTo(position: Int, smooth: Boolean) {
|
override fun switchPageTo(position: Int, smooth: Boolean) {
|
||||||
|
|||||||
@@ -135,6 +135,9 @@ fun Window.setNavigationBarTransparentCompat(context: Context, elevation: Float,
|
|||||||
val Context.animatorDurationScale: Float
|
val Context.animatorDurationScale: Float
|
||||||
get() = Settings.Global.getFloat(this.contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE, 1f)
|
get() = Settings.Global.getFloat(this.contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE, 1f)
|
||||||
|
|
||||||
|
val Context.isAnimationsEnabled: Boolean
|
||||||
|
get() = animatorDurationScale > 0f
|
||||||
|
|
||||||
fun ViewPropertyAnimator.applySystemAnimatorScale(context: Context): ViewPropertyAnimator = apply {
|
fun ViewPropertyAnimator.applySystemAnimatorScale(context: Context): ViewPropertyAnimator = apply {
|
||||||
this.duration = (this.duration * context.animatorDurationScale).toLong()
|
this.duration = (this.duration * context.animatorDurationScale).toLong()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user