diff --git a/.github/stale.yml b/.github/stale.yml
deleted file mode 100644
index ad3996c5a..000000000
--- a/.github/stale.yml
+++ /dev/null
@@ -1,61 +0,0 @@
-# Configuration for probot-stale - https://github.com/probot/stale
-
-# Number of days of inactivity before an Issue or Pull Request becomes stale
-daysUntilStale: 60
-
-# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
-# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
-daysUntilClose: 7
-
-# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
-onlyLabels: []
-
-# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
-exemptLabels:
- - pinned
- - security
- - "[Status] Maybe Later"
-
-# Set to true to ignore issues in a project (defaults to false)
-exemptProjects: false
-
-# Set to true to ignore issues in a milestone (defaults to false)
-exemptMilestones: false
-
-# Set to true to ignore issues with an assignee (defaults to false)
-exemptAssignees: false
-
-# Label to use when marking as stale
-staleLabel: stale
-
-# Comment to post when marking as stale. Set to `false` to disable
-markComment: >
- This issue has been automatically marked as stale because it has not had
- recent activity. It will be closed if no further activity occurs. Thank you
- for your contributions.
-
-# Comment to post when removing the stale label.
-# unmarkComment: >
-# Your comment here.
-
-# Comment to post when closing a stale Issue or Pull Request.
-# closeComment: >
-# Your comment here.
-
-# Limit the number of actions per hour, from 1-30. Default is 30
-limitPerRun: 30
-
-# Limit to only `issues` or `pulls`
-# only: issues
-
-# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
-# pulls:
-# daysUntilStale: 30
-# markComment: >
-# This pull request has been automatically marked as stale because it has not had
-# recent activity. It will be closed if no further activity occurs. Thank you
-# for your contributions.
-
-# issues:
-# exemptLabels:
-# - confirmed
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index ca2261c0d..1301858db 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,8 @@ proguardDictionaries {
android {
compileSdkVersion 29
+ buildToolsVersion = '29.0.2'
+
defaultConfig {
minSdkVersion 21
targetSdkVersion 29
@@ -81,7 +83,7 @@ android {
sourceCompatibility '1.8'
targetCompatibility '1.8'
}
- buildToolsVersion = '29.0.2'
+
configurations.all {
resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
@@ -130,10 +132,10 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.core:core-ktx:1.2.0'
- implementation 'androidx.fragment:fragment:1.2.1'
+ implementation 'androidx.fragment:fragment:1.2.2'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
- implementation 'com.google.android.material:material:1.2.0-alpha04'
+ implementation 'com.google.android.material:material:1.2.0-alpha05'
def retrofit_version = "2.6.2"
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
@@ -160,7 +162,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
- def kotlin_coroutines_version = "1.3.0"
+ def kotlin_coroutines_version = "1.3.3"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.java b/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.java
index fab4dd45f..e8f809042 100644
--- a/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.java
+++ b/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.java
@@ -51,8 +51,8 @@ import code.name.monkey.retromusic.fragments.mainactivity.GenresFragment;
import code.name.monkey.retromusic.fragments.mainactivity.PlayingQueueFragment;
import code.name.monkey.retromusic.fragments.mainactivity.PlaylistsFragment;
import code.name.monkey.retromusic.fragments.mainactivity.SongsFragment;
-import code.name.monkey.retromusic.fragments.mainactivity.folders.FoldersFragment;
-import code.name.monkey.retromusic.fragments.mainactivity.home.BannerHomeFragment;
+import code.name.monkey.retromusic.fragments.mainactivity.FoldersFragment;
+import code.name.monkey.retromusic.fragments.mainactivity.BannerHomeFragment;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.SearchQueryHelper;
import code.name.monkey.retromusic.helper.SortOrder.AlbumSortOrder;
diff --git a/app/src/main/java/code/name/monkey/retromusic/dagger/MusicComponent.kt b/app/src/main/java/code/name/monkey/retromusic/dagger/MusicComponent.kt
index 6815f918b..efa9a1c54 100644
--- a/app/src/main/java/code/name/monkey/retromusic/dagger/MusicComponent.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/dagger/MusicComponent.kt
@@ -26,7 +26,7 @@ import code.name.monkey.retromusic.fragments.mainactivity.ArtistsFragment
import code.name.monkey.retromusic.fragments.mainactivity.GenresFragment
import code.name.monkey.retromusic.fragments.mainactivity.PlaylistsFragment
import code.name.monkey.retromusic.fragments.mainactivity.SongsFragment
-import code.name.monkey.retromusic.fragments.mainactivity.home.BannerHomeFragment
+import code.name.monkey.retromusic.fragments.mainactivity.BannerHomeFragment
import dagger.Component
import javax.inject.Singleton
diff --git a/app/src/main/java/code/name/monkey/retromusic/extensions/ViewExtensions.kt b/app/src/main/java/code/name/monkey/retromusic/extensions/ViewExtensions.kt
index 64e400dca..d9a3cb502 100644
--- a/app/src/main/java/code/name/monkey/retromusic/extensions/ViewExtensions.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/extensions/ViewExtensions.kt
@@ -21,7 +21,7 @@ import android.widget.EditText
import androidx.annotation.LayoutRes
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.TintHelper
-
+import com.google.android.material.slider.Slider
@Suppress("UNCHECKED_CAST")
fun ViewGroup.inflate(@LayoutRes layout: Int): T {
@@ -45,4 +45,10 @@ fun View.showOrHide(show: Boolean) = if (show) show() else hide()
fun EditText.appHandleColor(): EditText {
TintHelper.colorHandles(this, ThemeStore.accentColor(context))
return this
+}
+
+fun Slider.setRange(progress: Float, to: Float) {
+ valueFrom = 0F
+ valueTo = to
+ value = progress
}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/NowPlayingScreen.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/NowPlayingScreen.kt
index acb67d598..2af15b230 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/NowPlayingScreen.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/NowPlayingScreen.kt
@@ -11,20 +11,19 @@ enum class NowPlayingScreen constructor(
val id: Int
) {
- NORMAL(R.string.normal, R.drawable.np_normal, 0),
- FLAT(R.string.flat, R.drawable.np_flat, 1),
- FIT(R.string.fit, R.drawable.np_fit, 12),
- TINY(R.string.tiny, R.drawable.np_tiny, 7),
- PEAK(R.string.peak, R.drawable.np_peak, 14),
-
ADAPTIVE(R.string.adaptive, R.drawable.np_adaptive, 10),
BLUR(R.string.blur, R.drawable.np_blur, 4),
BLUR_CARD(R.string.blur_card, R.drawable.np_blur_card, 9),
CARD(R.string.card, R.drawable.np_card, 6),
- COLOR(R.string.color, R.drawable.np_color, 5),
CIRCLE(R.string.circle, R.drawable.np_minimalistic_circle, 15),
+ COLOR(R.string.color, R.drawable.np_color, 5),
+ FIT(R.string.fit, R.drawable.np_fit, 12),
+ FLAT(R.string.flat, R.drawable.np_flat, 1),
FULL(R.string.full, R.drawable.np_full, 2),
MATERIAL(R.string.material, R.drawable.np_material, 11),
+ NORMAL(R.string.normal, R.drawable.np_normal, 0),
+ PEAK(R.string.peak, R.drawable.np_peak, 14),
PLAIN(R.string.plain, R.drawable.np_plain, 3),
SIMPLE(R.string.simple, R.drawable.np_simple, 8),
+ TINY(R.string.tiny, R.drawable.np_tiny, 7),
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/VolumeFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/VolumeFragment.kt
index 0ab8c3fae..c7900e5d2 100755
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/VolumeFragment.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/VolumeFragment.kt
@@ -8,7 +8,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.widget.SeekBar
import androidx.fragment.app.Fragment
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R
@@ -17,12 +16,14 @@ import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ViewUtil
import code.name.monkey.retromusic.volume.AudioVolumeObserver
import code.name.monkey.retromusic.volume.OnAudioVolumeChangedListener
+import com.google.android.material.slider.Slider
+import com.google.android.material.slider.Slider.OnChangeListener
import kotlinx.android.synthetic.main.fragment_volume.volumeDown
import kotlinx.android.synthetic.main.fragment_volume.volumeSeekBar
import kotlinx.android.synthetic.main.fragment_volume.volumeUp
-class VolumeFragment : Fragment(), SeekBar.OnSeekBarChangeListener, OnAudioVolumeChangedListener,
- View.OnClickListener {
+class VolumeFragment : Fragment(), OnAudioVolumeChangedListener,
+ View.OnClickListener, OnChangeListener {
private var audioVolumeObserver: AudioVolumeObserver? = null
@@ -51,20 +52,22 @@ class VolumeFragment : Fragment(), SeekBar.OnSeekBarChangeListener, OnAudioVolum
val audioManager = audioManager
if (audioManager != null) {
- volumeSeekBar.max = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
- volumeSeekBar.progress = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
+ volumeSeekBar.valueTo = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC).toFloat()
+ volumeSeekBar.value = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC).toFloat()
}
- volumeSeekBar.setOnSeekBarChangeListener(this)
+ volumeSeekBar.addOnChangeListener(this)
}
- override fun onAudioVolumeChanged(currentVolume: Int, maxVolume: Int) {
+ override fun onAudioVolumeChanged(currentVolume: Float, maxVolume: Float) {
if (volumeSeekBar == null) {
return
}
-
- volumeSeekBar.max = maxVolume
- volumeSeekBar.progress = currentVolume
- volumeDown.setImageResource(if (currentVolume == 0) R.drawable.ic_volume_off_white_24dp else R.drawable.ic_volume_down_white_24dp)
+ if (maxVolume <= 0) {
+ return
+ }
+ volumeSeekBar.valueTo = maxVolume
+ volumeSeekBar.valueFrom = currentVolume
+ volumeDown.setImageResource(if (currentVolume == 0.0f) R.drawable.ic_volume_off_white_24dp else R.drawable.ic_volume_down_white_24dp)
}
override fun onDestroyView() {
@@ -74,19 +77,6 @@ class VolumeFragment : Fragment(), SeekBar.OnSeekBarChangeListener, OnAudioVolum
}
}
- override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
- val audioManager = audioManager
- audioManager?.setStreamVolume(AudioManager.STREAM_MUSIC, i, 0)
- setPauseWhenZeroVolume(i < 1)
- volumeDown?.setImageResource(if (i == 0) R.drawable.ic_volume_off_white_24dp else R.drawable.ic_volume_down_white_24dp)
- }
-
- override fun onStartTrackingTouch(seekBar: SeekBar) {
- }
-
- override fun onStopTrackingTouch(seekBar: SeekBar) {
- }
-
override fun onClick(view: View) {
val audioManager = audioManager
when (view.id) {
@@ -111,10 +101,6 @@ class VolumeFragment : Fragment(), SeekBar.OnSeekBarChangeListener, OnAudioVolum
ViewUtil.setProgressDrawable(volumeSeekBar, color, true)
}
- fun removeThumb() {
- volumeSeekBar.thumb = null
- }
-
private fun setPauseWhenZeroVolume(pauseWhenZeroVolume: Boolean) {
if (PreferenceUtil.getInstance(requireContext()).pauseOnZeroVolume()) if (MusicPlayerRemote.isPlaying && pauseWhenZeroVolume) {
MusicPlayerRemote.pauseSong()
@@ -134,4 +120,14 @@ class VolumeFragment : Fragment(), SeekBar.OnSeekBarChangeListener, OnAudioVolum
return VolumeFragment()
}
}
+
+ override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) {
+ if (value <= 0) {
+ return
+ }
+ val audioManager = audioManager
+ audioManager?.setStreamVolume(AudioManager.STREAM_MUSIC, value.toInt(), 0)
+ setPauseWhenZeroVolume(value < 1.0f)
+ volumeDown.setImageResource(if (value == 0.0f) R.drawable.ic_volume_off_white_24dp else R.drawable.ic_volume_down_white_24dp)
+ }
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/home/BannerHomeFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/BannerHomeFragment.kt
similarity index 91%
rename from app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/home/BannerHomeFragment.kt
rename to app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/BannerHomeFragment.kt
index 3d06f8973..cfc5c9a56 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/home/BannerHomeFragment.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/BannerHomeFragment.kt
@@ -1,4 +1,18 @@
-package code.name.monkey.retromusic.fragments.mainactivity.home
+/*
+ * Copyright (c) 2020 Hemanth Savarala.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by
+ * the Free Software Foundation either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ */
+
+package code.name.monkey.retromusic.fragments.mainactivity
import android.app.ActivityOptions
import android.os.Bundle
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/folders/FoldersFragment.java b/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/FoldersFragment.java
similarity index 97%
rename from app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/folders/FoldersFragment.java
rename to app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/FoldersFragment.java
index 927808ae5..d3bf8c43c 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/folders/FoldersFragment.java
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/mainactivity/FoldersFragment.java
@@ -1,4 +1,18 @@
-package code.name.monkey.retromusic.fragments.mainactivity.folders;
+/*
+ * Copyright (c) 2020 Hemanth Savarala.
+ *
+ * Licensed under the GNU General Public License v3
+ *
+ * This is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by
+ * the Free Software Foundation either version 3 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ */
+
+package code.name.monkey.retromusic.fragments.mainactivity;
import android.app.Dialog;
import android.content.Context;
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/adaptive/AdaptivePlaybackControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/adaptive/AdaptivePlaybackControlsFragment.kt
index bcde8aeb6..bd8b2d935 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/adaptive/AdaptivePlaybackControlsFragment.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/adaptive/AdaptivePlaybackControlsFragment.kt
@@ -1,13 +1,10 @@
package code.name.monkey.retromusic.fragments.player.adaptive
-import android.animation.ObjectAnimator
import android.graphics.PorterDuff
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.view.animation.LinearInterpolator
-import android.widget.SeekBar
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil
@@ -16,12 +13,12 @@ import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.extensions.ripAlpha
+import code.name.monkey.retromusic.extensions.setRange
import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
-import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
@@ -212,13 +209,10 @@ class AdaptivePlaybackControlsFragment : AbsPlayerControlsFragment() {
}
override fun onUpdateProgressViews(progress: Int, total: Int) {
- progressSlider.max = total
-
- val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
- animator.duration = SLIDER_ANIMATION_TIME
- animator.interpolator = LinearInterpolator()
- animator.start()
-
+ if (total <= 0) {
+ return
+ }
+ progressSlider.setRange(progress.toFloat(), total.toFloat())
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
}
@@ -232,16 +226,14 @@ class AdaptivePlaybackControlsFragment : AbsPlayerControlsFragment() {
}
override fun setUpProgressSlider() {
- progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
- override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- if (fromUser) {
- MusicPlayerRemote.seekTo(progress)
- onUpdateProgressViews(
- MusicPlayerRemote.songProgressMillis,
- MusicPlayerRemote.songDurationMillis
- )
- }
+ progressSlider.addOnChangeListener { _, value, fromUser ->
+ if (fromUser) {
+ MusicPlayerRemote.seekTo(value.toInt())
+ onUpdateProgressViews(
+ MusicPlayerRemote.songProgressMillis,
+ MusicPlayerRemote.songDurationMillis
+ )
}
- })
+ }
}
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/blur/BlurPlaybackControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/blur/BlurPlaybackControlsFragment.kt
index 411205177..cb466d23d 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/blur/BlurPlaybackControlsFragment.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/blur/BlurPlaybackControlsFragment.kt
@@ -1,6 +1,5 @@
package code.name.monkey.retromusic.fragments.player.blur
-import android.animation.ObjectAnimator
import android.graphics.Color
import android.graphics.PorterDuff
import android.os.Bundle
@@ -9,20 +8,18 @@ import android.view.View
import android.view.ViewGroup
import android.view.animation.AccelerateInterpolator
import android.view.animation.DecelerateInterpolator
-import android.view.animation.LinearInterpolator
-import android.widget.SeekBar
import androidx.core.content.ContextCompat
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.hide
+import code.name.monkey.retromusic.extensions.setRange
import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
-import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
@@ -235,20 +232,6 @@ class BlurPlaybackControlsFragment : AbsPlayerControlsFragment() {
}
}
- override fun setUpProgressSlider() {
- progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
- override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- if (fromUser) {
- MusicPlayerRemote.seekTo(progress)
- onUpdateProgressViews(
- MusicPlayerRemote.songProgressMillis,
- MusicPlayerRemote.songDurationMillis
- )
- }
- }
- })
- }
-
private fun showBonceAnimation() {
playPauseButton.apply {
clearAnimation()
@@ -273,14 +256,23 @@ class BlurPlaybackControlsFragment : AbsPlayerControlsFragment() {
}
override fun onUpdateProgressViews(progress: Int, total: Int) {
- progressSlider.max = total
-
- val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
- animator.duration = SLIDER_ANIMATION_TIME
- animator.interpolator = LinearInterpolator()
- animator.start()
-
+ if (total <= 0) {
+ return
+ }
+ progressSlider.setRange(progress.toFloat(), total.toFloat())
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
}
+
+ override fun setUpProgressSlider() {
+ progressSlider.addOnChangeListener { _, value, fromUser ->
+ if (fromUser) {
+ MusicPlayerRemote.seekTo(value.toInt())
+ onUpdateProgressViews(
+ MusicPlayerRemote.songProgressMillis,
+ MusicPlayerRemote.songDurationMillis
+ )
+ }
+ }
+ }
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/cardblur/CardBlurPlaybackControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/cardblur/CardBlurPlaybackControlsFragment.kt
index 81f1e9c44..7326d247e 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/cardblur/CardBlurPlaybackControlsFragment.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/cardblur/CardBlurPlaybackControlsFragment.kt
@@ -1,6 +1,5 @@
package code.name.monkey.retromusic.fragments.player.cardblur
-import android.animation.ObjectAnimator
import android.graphics.Color
import android.graphics.PorterDuff
import android.os.Bundle
@@ -8,19 +7,17 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.DecelerateInterpolator
-import android.view.animation.LinearInterpolator
-import android.widget.SeekBar
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.hide
+import code.name.monkey.retromusic.extensions.setRange
import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
-import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
@@ -210,29 +207,24 @@ class CardBlurPlaybackControlsFragment : AbsPlayerControlsFragment() {
}
}
- override fun setUpProgressSlider() {
- progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
- override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- if (fromUser) {
- MusicPlayerRemote.seekTo(progress)
- onUpdateProgressViews(
- MusicPlayerRemote.songProgressMillis,
- MusicPlayerRemote.songDurationMillis
- )
- }
- }
- })
- }
-
override fun onUpdateProgressViews(progress: Int, total: Int) {
- progressSlider.max = total
-
- val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
- animator.duration = SLIDER_ANIMATION_TIME
- animator.interpolator = LinearInterpolator()
- animator.start()
-
+ if (total <= 0) {
+ return
+ }
+ progressSlider.setRange(progress.toFloat(), total.toFloat())
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
}
+
+ override fun setUpProgressSlider() {
+ progressSlider.addOnChangeListener { _, value, fromUser ->
+ if (fromUser) {
+ MusicPlayerRemote.seekTo(value.toInt())
+ onUpdateProgressViews(
+ MusicPlayerRemote.songProgressMillis,
+ MusicPlayerRemote.songDurationMillis
+ )
+ }
+ }
+ }
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/circle/CirclePlayerFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/circle/CirclePlayerFragment.kt
index 39a55edc6..dea50e38e 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/circle/CirclePlayerFragment.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/circle/CirclePlayerFragment.kt
@@ -14,7 +14,6 @@
package code.name.monkey.retromusic.fragments.player.circle
-import android.animation.ObjectAnimator
import android.content.Context
import android.graphics.Color
import android.graphics.PorterDuff
@@ -23,8 +22,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.view.animation.LinearInterpolator
-import android.widget.SeekBar
import androidx.appcompat.widget.Toolbar
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil
@@ -32,14 +29,13 @@ import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.hide
+import code.name.monkey.retromusic.extensions.setRange
import code.name.monkey.retromusic.extensions.show
-import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper.Callback
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
-import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ViewUtil
@@ -100,14 +96,7 @@ class CirclePlayerFragment : AbsPlayerFragment(), Callback, OnAudioVolumeChanged
}
private fun setupViews() {
- progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
- override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- if (fromUser) {
- MusicPlayerRemote.seekTo(progress)
- onUpdateProgressViews(MusicPlayerRemote.songProgressMillis, MusicPlayerRemote.songDurationMillis)
- }
- }
- })
+ setUpProgressSlider()
ViewUtil.setProgressDrawable(progressSlider, ThemeStore.accentColor(requireContext()))
volumeSeekBar.progressColor = ThemeStore.accentColor(requireContext())
setUpPlayPauseFab()
@@ -205,18 +194,6 @@ class CirclePlayerFragment : AbsPlayerFragment(), Callback, OnAudioVolumeChanged
}
}
- override fun onUpdateProgressViews(progress: Int, total: Int) {
- progressSlider.max = total
-
- val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
- animator.duration = AbsPlayerControlsFragment.SLIDER_ANIMATION_TIME
- animator.interpolator = LinearInterpolator()
- animator.start()
-
- songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
- songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
- }
-
private fun updatePlayPauseDrawableState() {
when {
MusicPlayerRemote.isPlaying -> playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
@@ -224,12 +201,13 @@ class CirclePlayerFragment : AbsPlayerFragment(), Callback, OnAudioVolumeChanged
}
}
- override fun onAudioVolumeChanged(currentVolume: Int, maxVolume: Int) {
+ override fun onAudioVolumeChanged(currentVolume: Float, maxVolume: Float) {
if (volumeSeekBar == null) {
return
}
- volumeSeekBar.max = maxVolume
- volumeSeekBar.progress = currentVolume
+
+ volumeSeekBar.max = maxVolume.toInt()
+ volumeSeekBar.progress = currentVolume.toInt()
}
override fun onDestroyView() {
@@ -249,4 +227,25 @@ class CirclePlayerFragment : AbsPlayerFragment(), Callback, OnAudioVolumeChanged
override fun onStopTrackingTouch(seekArc: SeekArc?) {
}
+
+ override fun onUpdateProgressViews(progress: Int, total: Int) {
+ if (total <= 0) {
+ return
+ }
+ progressSlider.setRange(progress.toFloat(), total.toFloat())
+ songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
+ songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
+ }
+
+ fun setUpProgressSlider() {
+ progressSlider.addOnChangeListener { _, value, fromUser ->
+ if (fromUser) {
+ MusicPlayerRemote.seekTo(value.toInt())
+ onUpdateProgressViews(
+ MusicPlayerRemote.songProgressMillis,
+ MusicPlayerRemote.songDurationMillis
+ )
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/color/ColorPlaybackControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/color/ColorPlaybackControlsFragment.kt
index d4b462850..a7c2bc8a1 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/color/ColorPlaybackControlsFragment.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/color/ColorPlaybackControlsFragment.kt
@@ -1,6 +1,5 @@
package code.name.monkey.retromusic.fragments.player.color
-import android.animation.ObjectAnimator
import android.graphics.Color
import android.graphics.PorterDuff
import android.os.Bundle
@@ -8,33 +7,21 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.DecelerateInterpolator
-import android.view.animation.LinearInterpolator
-import android.widget.SeekBar
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.hide
+import code.name.monkey.retromusic.extensions.setRange
import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
-import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ViewUtil
-import kotlinx.android.synthetic.main.fragment_color_player_playback_controls.nextButton
-import kotlinx.android.synthetic.main.fragment_color_player_playback_controls.playPauseButton
-import kotlinx.android.synthetic.main.fragment_color_player_playback_controls.previousButton
-import kotlinx.android.synthetic.main.fragment_color_player_playback_controls.progressSlider
-import kotlinx.android.synthetic.main.fragment_color_player_playback_controls.repeatButton
-import kotlinx.android.synthetic.main.fragment_color_player_playback_controls.shuffleButton
-import kotlinx.android.synthetic.main.fragment_color_player_playback_controls.songCurrentProgress
-import kotlinx.android.synthetic.main.fragment_color_player_playback_controls.songInfo
-import kotlinx.android.synthetic.main.fragment_color_player_playback_controls.songTotalTime
-import kotlinx.android.synthetic.main.fragment_color_player_playback_controls.text
-import kotlinx.android.synthetic.main.fragment_color_player_playback_controls.title
+import kotlinx.android.synthetic.main.fragment_color_player_playback_controls.*
class ColorPlaybackControlsFragment : AbsPlayerControlsFragment() {
@@ -47,7 +34,11 @@ class ColorPlaybackControlsFragment : AbsPlayerControlsFragment() {
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
}
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
return inflater.inflate(R.layout.fragment_color_player_playback_controls, container, false)
}
@@ -173,7 +164,10 @@ class ColorPlaybackControlsFragment : AbsPlayerControlsFragment() {
lastPlaybackControlsColor,
PorterDuff.Mode.SRC_IN
)
- else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ else -> shuffleButton.setColorFilter(
+ lastDisabledPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
}
@@ -185,7 +179,10 @@ class ColorPlaybackControlsFragment : AbsPlayerControlsFragment() {
when (MusicPlayerRemote.repeatMode) {
MusicService.REPEAT_MODE_NONE -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
- repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ repeatButton.setColorFilter(
+ lastDisabledPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
MusicService.REPEAT_MODE_ALL -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
@@ -215,26 +212,24 @@ class ColorPlaybackControlsFragment : AbsPlayerControlsFragment() {
}
}
- override fun setUpProgressSlider() {
- progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
- override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- if (fromUser) {
- MusicPlayerRemote.seekTo(progress)
- onUpdateProgressViews(MusicPlayerRemote.songProgressMillis, MusicPlayerRemote.songDurationMillis)
- }
- }
- })
- }
-
override fun onUpdateProgressViews(progress: Int, total: Int) {
- progressSlider!!.max = total
-
- val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
- animator.duration = SLIDER_ANIMATION_TIME
- animator.interpolator = LinearInterpolator()
- animator.start()
-
+ if (total <= 0) {
+ return
+ }
+ progressSlider.setRange(progress.toFloat(), total.toFloat())
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
}
+
+ override fun setUpProgressSlider() {
+ progressSlider.addOnChangeListener { _, value, fromUser ->
+ if (fromUser) {
+ MusicPlayerRemote.seekTo(value.toInt())
+ onUpdateProgressViews(
+ MusicPlayerRemote.songProgressMillis,
+ MusicPlayerRemote.songDurationMillis
+ )
+ }
+ }
+ }
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/fit/FitPlaybackControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/fit/FitPlaybackControlsFragment.kt
index 6a3f9e6f1..7dfea6d4c 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/fit/FitPlaybackControlsFragment.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/fit/FitPlaybackControlsFragment.kt
@@ -27,17 +27,7 @@ import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
-import kotlinx.android.synthetic.main.fragment_fit_playback_controls.nextButton
-import kotlinx.android.synthetic.main.fragment_fit_playback_controls.playPauseButton
-import kotlinx.android.synthetic.main.fragment_fit_playback_controls.previousButton
-import kotlinx.android.synthetic.main.fragment_fit_playback_controls.progressSlider
-import kotlinx.android.synthetic.main.fragment_fit_playback_controls.repeatButton
-import kotlinx.android.synthetic.main.fragment_fit_playback_controls.shuffleButton
-import kotlinx.android.synthetic.main.fragment_fit_playback_controls.songCurrentProgress
-import kotlinx.android.synthetic.main.fragment_fit_playback_controls.songInfo
-import kotlinx.android.synthetic.main.fragment_fit_playback_controls.songTotalTime
-import kotlinx.android.synthetic.main.fragment_fit_playback_controls.text
-import kotlinx.android.synthetic.main.fragment_fit_playback_controls.title
+import kotlinx.android.synthetic.main.fragment_fit_playback_controls.*
class FitPlaybackControlsFragment : AbsPlayerControlsFragment() {
@@ -126,10 +116,12 @@ class FitPlaybackControlsFragment : AbsPlayerControlsFragment() {
val colorBg = ATHUtil.resolveColor(activity, android.R.attr.colorBackground)
if (ColorUtil.isColorLight(colorBg)) {
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(activity, true)
- lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(activity, true)
+ lastDisabledPlaybackControlsColor =
+ MaterialValueHelper.getSecondaryDisabledTextColor(activity, true)
} else {
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(activity, false)
- lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(activity, false)
+ lastDisabledPlaybackControlsColor =
+ MaterialValueHelper.getPrimaryDisabledTextColor(activity, false)
}
val colorFinal = if (PreferenceUtil.getInstance(requireContext()).adaptiveColor) {
@@ -196,7 +188,10 @@ class FitPlaybackControlsFragment : AbsPlayerControlsFragment() {
lastPlaybackControlsColor,
PorterDuff.Mode.SRC_IN
)
- else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ else -> shuffleButton.setColorFilter(
+ lastDisabledPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
}
@@ -208,7 +203,10 @@ class FitPlaybackControlsFragment : AbsPlayerControlsFragment() {
when (MusicPlayerRemote.repeatMode) {
MusicService.REPEAT_MODE_NONE -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
- repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ repeatButton.setColorFilter(
+ lastDisabledPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
MusicService.REPEAT_MODE_ALL -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/flat/FlatPlaybackControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/flat/FlatPlaybackControlsFragment.kt
index 4780e6b12..c538794c4 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/flat/FlatPlaybackControlsFragment.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/flat/FlatPlaybackControlsFragment.kt
@@ -1,14 +1,11 @@
package code.name.monkey.retromusic.fragments.player.flat
-import android.animation.ObjectAnimator
import android.graphics.PorterDuff
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.DecelerateInterpolator
-import android.view.animation.LinearInterpolator
-import android.widget.SeekBar
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil
@@ -17,26 +14,18 @@ import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.extensions.ripAlpha
+import code.name.monkey.retromusic.extensions.setRange
import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper.Callback
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
-import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ViewUtil
-import kotlinx.android.synthetic.main.fragment_flat_player_playback_controls.playPauseButton
-import kotlinx.android.synthetic.main.fragment_flat_player_playback_controls.progressSlider
-import kotlinx.android.synthetic.main.fragment_flat_player_playback_controls.repeatButton
-import kotlinx.android.synthetic.main.fragment_flat_player_playback_controls.shuffleButton
-import kotlinx.android.synthetic.main.fragment_flat_player_playback_controls.songCurrentProgress
-import kotlinx.android.synthetic.main.fragment_flat_player_playback_controls.songInfo
-import kotlinx.android.synthetic.main.fragment_flat_player_playback_controls.songTotalTime
-import kotlinx.android.synthetic.main.fragment_flat_player_playback_controls.text
-import kotlinx.android.synthetic.main.fragment_flat_player_playback_controls.title
+import kotlinx.android.synthetic.main.fragment_flat_player_playback_controls.*
class FlatPlaybackControlsFragment : AbsPlayerControlsFragment(), Callback {
@@ -73,18 +62,6 @@ class FlatPlaybackControlsFragment : AbsPlayerControlsFragment(), Callback {
progressViewUpdateHelper.stop()
}
- override fun onUpdateProgressViews(progress: Int, total: Int) {
- progressSlider.max = total
-
- val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
- animator.duration = SLIDER_ANIMATION_TIME
- animator.interpolator = LinearInterpolator()
- animator.start()
-
- songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
- songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
- }
-
public override fun show() {
playPauseButton!!.animate()
.scaleX(1f)
@@ -106,10 +83,12 @@ class FlatPlaybackControlsFragment : AbsPlayerControlsFragment(), Callback {
val isDark = ColorUtil.isColorLight(colorBg)
if (isDark) {
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(activity, true)
- lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(activity, true)
+ lastDisabledPlaybackControlsColor =
+ MaterialValueHelper.getSecondaryDisabledTextColor(activity, true)
} else {
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(activity, false)
- lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(activity, false)
+ lastDisabledPlaybackControlsColor =
+ MaterialValueHelper.getPrimaryDisabledTextColor(activity, false)
}
val colorFinal = if (PreferenceUtil.getInstance(requireContext()).adaptiveColor) {
@@ -131,7 +110,8 @@ class FlatPlaybackControlsFragment : AbsPlayerControlsFragment(), Callback {
val isDark = ColorUtil.isColorLight(color)
val darkColor = ColorUtil.darkenColor(color)
val colorPrimary = MaterialValueHelper.getPrimaryTextColor(context, isDark)
- val colorSecondary = MaterialValueHelper.getSecondaryTextColor(context, ColorUtil.isColorLight(darkColor))
+ val colorSecondary =
+ MaterialValueHelper.getSecondaryTextColor(context, ColorUtil.isColorLight(darkColor))
TintHelper.setTintAuto(playPauseButton!!, colorPrimary, false)
TintHelper.setTintAuto(playPauseButton!!, color, true)
@@ -191,18 +171,25 @@ class FlatPlaybackControlsFragment : AbsPlayerControlsFragment(), Callback {
}
}
+ override fun onUpdateProgressViews(progress: Int, total: Int) {
+ if (total <= 0) {
+ return
+ }
+ progressSlider.setRange(progress.toFloat(), total.toFloat())
+ songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
+ songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
+ }
+
override fun setUpProgressSlider() {
- progressSlider!!.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
- override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- if (fromUser) {
- MusicPlayerRemote.seekTo(progress)
- onUpdateProgressViews(
- MusicPlayerRemote.songProgressMillis,
- MusicPlayerRemote.songDurationMillis
- )
- }
+ progressSlider.addOnChangeListener { _, value, fromUser ->
+ if (fromUser) {
+ MusicPlayerRemote.seekTo(value.toInt())
+ onUpdateProgressViews(
+ MusicPlayerRemote.songProgressMillis,
+ MusicPlayerRemote.songDurationMillis
+ )
}
- })
+ }
}
override fun onRepeatModeChanged() {
@@ -221,7 +208,10 @@ class FlatPlaybackControlsFragment : AbsPlayerControlsFragment(), Callback {
when (MusicPlayerRemote.repeatMode) {
MusicService.REPEAT_MODE_NONE -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
- repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ repeatButton.setColorFilter(
+ lastDisabledPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
MusicService.REPEAT_MODE_ALL -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
@@ -244,7 +234,10 @@ class FlatPlaybackControlsFragment : AbsPlayerControlsFragment(), Callback {
lastPlaybackControlsColor,
PorterDuff.Mode.SRC_IN
)
- else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ else -> shuffleButton.setColorFilter(
+ lastDisabledPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
}
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/full/FullPlaybackControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/full/FullPlaybackControlsFragment.kt
index 49d929673..c1ab60aad 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/full/FullPlaybackControlsFragment.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/full/FullPlaybackControlsFragment.kt
@@ -1,6 +1,5 @@
package code.name.monkey.retromusic.fragments.player.full
-import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.content.res.ColorStateList
import android.graphics.Color
@@ -12,9 +11,7 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.view.animation.DecelerateInterpolator
-import android.view.animation.LinearInterpolator
import android.widget.PopupMenu
-import android.widget.SeekBar
import androidx.core.content.ContextCompat
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ColorUtil
@@ -23,36 +20,25 @@ import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.extensions.ripAlpha
+import code.name.monkey.retromusic.extensions.setRange
import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
-import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ViewUtil
-import kotlinx.android.synthetic.main.fragment_full_player_controls.nextButton
-import kotlinx.android.synthetic.main.fragment_full_player_controls.playPauseButton
-import kotlinx.android.synthetic.main.fragment_full_player_controls.playerMenu
-import kotlinx.android.synthetic.main.fragment_full_player_controls.previousButton
-import kotlinx.android.synthetic.main.fragment_full_player_controls.progressSlider
-import kotlinx.android.synthetic.main.fragment_full_player_controls.repeatButton
-import kotlinx.android.synthetic.main.fragment_full_player_controls.shuffleButton
-import kotlinx.android.synthetic.main.fragment_full_player_controls.songCurrentProgress
-import kotlinx.android.synthetic.main.fragment_full_player_controls.songFavourite
-import kotlinx.android.synthetic.main.fragment_full_player_controls.songInfo
-import kotlinx.android.synthetic.main.fragment_full_player_controls.songTotalTime
-import kotlinx.android.synthetic.main.fragment_full_player_controls.text
-import kotlinx.android.synthetic.main.fragment_full_player_controls.title
+import kotlinx.android.synthetic.main.fragment_full_player_controls.*
/**
* Created by hemanths on 20/09/17.
*/
-class FullPlaybackControlsFragment : AbsPlayerControlsFragment(), PopupMenu.OnMenuItemClickListener {
+class FullPlaybackControlsFragment : AbsPlayerControlsFragment(),
+ PopupMenu.OnMenuItemClickListener {
private var lastPlaybackControlsColor: Int = 0
private var lastDisabledPlaybackControlsColor: Int = 0
@@ -91,17 +77,6 @@ class FullPlaybackControlsFragment : AbsPlayerControlsFragment(), PopupMenu.OnMe
progressViewUpdateHelper!!.stop()
}
- override fun onUpdateProgressViews(progress: Int, total: Int) {
- progressSlider.max = total
-
- val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
- animator.duration = SLIDER_ANIMATION_TIME
- animator.interpolator = LinearInterpolator()
- animator.start()
-
- songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
- songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
- }
public override fun show() {
playPauseButton!!.animate()
@@ -228,15 +203,25 @@ class FullPlaybackControlsFragment : AbsPlayerControlsFragment(), PopupMenu.OnMe
previousButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
}
+ override fun onUpdateProgressViews(progress: Int, total: Int) {
+ if (total <= 0) {
+ return
+ }
+ progressSlider.setRange(progress.toFloat(), total.toFloat())
+ songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
+ songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
+ }
+
override fun setUpProgressSlider() {
- progressSlider!!.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
- override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- if (fromUser) {
- MusicPlayerRemote.seekTo(progress)
- onUpdateProgressViews(MusicPlayerRemote.songProgressMillis, MusicPlayerRemote.songDurationMillis)
- }
+ progressSlider.addOnChangeListener { _, value, fromUser ->
+ if (fromUser) {
+ MusicPlayerRemote.seekTo(value.toInt())
+ onUpdateProgressViews(
+ MusicPlayerRemote.songProgressMillis,
+ MusicPlayerRemote.songDurationMillis
+ )
}
- })
+ }
}
override fun onRepeatModeChanged() {
@@ -257,7 +242,10 @@ class FullPlaybackControlsFragment : AbsPlayerControlsFragment(), PopupMenu.OnMe
lastPlaybackControlsColor,
PorterDuff.Mode.SRC_IN
)
- else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ else -> shuffleButton.setColorFilter(
+ lastDisabledPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
}
@@ -269,7 +257,10 @@ class FullPlaybackControlsFragment : AbsPlayerControlsFragment(), PopupMenu.OnMe
when (MusicPlayerRemote.repeatMode) {
MusicService.REPEAT_MODE_NONE -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
- repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ repeatButton.setColorFilter(
+ lastDisabledPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
MusicService.REPEAT_MODE_ALL -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
@@ -300,7 +291,7 @@ class FullPlaybackControlsFragment : AbsPlayerControlsFragment(), PopupMenu.OnMe
@SuppressLint("StaticFieldLeak")
fun updateIsFavorite() {
if (updateIsFavoriteTask != null) {
- updateIsFavoriteTask!!.cancel(false)
+ updateIsFavoriteTask?.cancel(false)
}
updateIsFavoriteTask = object : AsyncTask() {
override fun doInBackground(vararg params: Song): Boolean? {
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/material/MaterialControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/material/MaterialControlsFragment.kt
index 4a6a9e7a9..228444411 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/material/MaterialControlsFragment.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/material/MaterialControlsFragment.kt
@@ -1,41 +1,24 @@
package code.name.monkey.retromusic.fragments.player.material
-import android.animation.ObjectAnimator
import android.graphics.PorterDuff
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.view.animation.LinearInterpolator
-import android.widget.SeekBar
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.retromusic.R
-import code.name.monkey.retromusic.extensions.hide
-import code.name.monkey.retromusic.extensions.ripAlpha
-import code.name.monkey.retromusic.extensions.show
-import code.name.monkey.retromusic.extensions.textColorSecondary
+import code.name.monkey.retromusic.extensions.*
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
-import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ViewUtil
-import kotlinx.android.synthetic.main.fragment_material_playback_controls.nextButton
-import kotlinx.android.synthetic.main.fragment_material_playback_controls.playPauseButton
-import kotlinx.android.synthetic.main.fragment_material_playback_controls.previousButton
-import kotlinx.android.synthetic.main.fragment_material_playback_controls.progressSlider
-import kotlinx.android.synthetic.main.fragment_material_playback_controls.repeatButton
-import kotlinx.android.synthetic.main.fragment_material_playback_controls.shuffleButton
-import kotlinx.android.synthetic.main.fragment_material_playback_controls.songCurrentProgress
-import kotlinx.android.synthetic.main.fragment_material_playback_controls.songInfo
-import kotlinx.android.synthetic.main.fragment_material_playback_controls.songTotalTime
-import kotlinx.android.synthetic.main.fragment_material_playback_controls.text
-import kotlinx.android.synthetic.main.fragment_material_playback_controls.title
+import kotlinx.android.synthetic.main.fragment_material_playback_controls.*
/**
* @author Hemanth S (h4h13).
@@ -115,11 +98,13 @@ class MaterialControlsFragment : AbsPlayerControlsFragment() {
override fun setDark(color: Int) {
val colorBg = ATHUtil.resolveColor(requireContext(), R.attr.colorSurface)
if (ColorUtil.isColorLight(colorBg)) {
- lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(requireContext(), true)
+ lastPlaybackControlsColor =
+ MaterialValueHelper.getSecondaryTextColor(requireContext(), true)
lastDisabledPlaybackControlsColor =
MaterialValueHelper.getSecondaryDisabledTextColor(requireContext(), true)
} else {
- lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(requireContext(), false)
+ lastPlaybackControlsColor =
+ MaterialValueHelper.getPrimaryTextColor(requireContext(), false)
lastDisabledPlaybackControlsColor =
MaterialValueHelper.getPrimaryDisabledTextColor(requireContext(), false)
}
@@ -187,7 +172,10 @@ class MaterialControlsFragment : AbsPlayerControlsFragment() {
lastPlaybackControlsColor,
PorterDuff.Mode.SRC_IN
)
- else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ else -> shuffleButton.setColorFilter(
+ lastDisabledPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
}
@@ -199,7 +187,10 @@ class MaterialControlsFragment : AbsPlayerControlsFragment() {
when (MusicPlayerRemote.repeatMode) {
MusicService.REPEAT_MODE_NONE -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
- repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ repeatButton.setColorFilter(
+ lastDisabledPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
MusicService.REPEAT_MODE_ALL -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
@@ -218,29 +209,24 @@ class MaterialControlsFragment : AbsPlayerControlsFragment() {
public override fun hide() {
}
- override fun setUpProgressSlider() {
- progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
- override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- if (fromUser) {
- MusicPlayerRemote.seekTo(progress)
- onUpdateProgressViews(
- MusicPlayerRemote.songProgressMillis,
- MusicPlayerRemote.songDurationMillis
- )
- }
- }
- })
- }
-
override fun onUpdateProgressViews(progress: Int, total: Int) {
- progressSlider!!.max = total
-
- val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
- animator.duration = SLIDER_ANIMATION_TIME
- animator.interpolator = LinearInterpolator()
- animator.start()
-
+ if (total <= 0) {
+ return
+ }
+ progressSlider.setRange(progress.toFloat(), total.toFloat())
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
}
+
+ override fun setUpProgressSlider() {
+ progressSlider.addOnChangeListener { _, value, fromUser ->
+ if (fromUser) {
+ MusicPlayerRemote.seekTo(value.toInt())
+ onUpdateProgressViews(
+ MusicPlayerRemote.songProgressMillis,
+ MusicPlayerRemote.songDurationMillis
+ )
+ }
+ }
+ }
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/normal/PlayerPlaybackControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/normal/PlayerPlaybackControlsFragment.kt
index e98736d2b..4e3d56214 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/normal/PlayerPlaybackControlsFragment.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/normal/PlayerPlaybackControlsFragment.kt
@@ -1,6 +1,5 @@
package code.name.monkey.retromusic.fragments.player.normal
-import android.animation.ObjectAnimator
import android.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.graphics.PorterDuff
@@ -9,8 +8,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.DecelerateInterpolator
-import android.view.animation.LinearInterpolator
-import android.widget.SeekBar
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil
@@ -19,29 +16,20 @@ import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.extensions.ripAlpha
+import code.name.monkey.retromusic.extensions.setRange
import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
-import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ViewUtil
-import kotlinx.android.synthetic.main.fragment_player_playback_controls.nextButton
-import kotlinx.android.synthetic.main.fragment_player_playback_controls.playPauseButton
-import kotlinx.android.synthetic.main.fragment_player_playback_controls.previousButton
-import kotlinx.android.synthetic.main.fragment_player_playback_controls.progressSlider
-import kotlinx.android.synthetic.main.fragment_player_playback_controls.repeatButton
-import kotlinx.android.synthetic.main.fragment_player_playback_controls.shuffleButton
-import kotlinx.android.synthetic.main.fragment_player_playback_controls.songCurrentProgress
-import kotlinx.android.synthetic.main.fragment_player_playback_controls.songInfo
-import kotlinx.android.synthetic.main.fragment_player_playback_controls.songTotalTime
-import kotlinx.android.synthetic.main.fragment_player_playback_controls.text
-import kotlinx.android.synthetic.main.fragment_player_playback_controls.title
+import kotlinx.android.synthetic.main.fragment_player_playback_controls.*
-class PlayerPlaybackControlsFragment : AbsPlayerControlsFragment(), OnSharedPreferenceChangeListener {
+class PlayerPlaybackControlsFragment : AbsPlayerControlsFragment(),
+ OnSharedPreferenceChangeListener {
private var lastPlaybackControlsColor: Int = 0
private var lastDisabledPlaybackControlsColor: Int = 0
@@ -77,11 +65,13 @@ class PlayerPlaybackControlsFragment : AbsPlayerControlsFragment(), OnSharedPref
override fun setDark(color: Int) {
val colorBg = ATHUtil.resolveColor(requireContext(), android.R.attr.colorBackground)
if (ColorUtil.isColorLight(colorBg)) {
- lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(requireContext(), true)
+ lastPlaybackControlsColor =
+ MaterialValueHelper.getSecondaryTextColor(requireContext(), true)
lastDisabledPlaybackControlsColor =
MaterialValueHelper.getSecondaryDisabledTextColor(requireContext(), true)
} else {
- lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(requireContext(), false)
+ lastPlaybackControlsColor =
+ MaterialValueHelper.getPrimaryTextColor(requireContext(), false)
lastDisabledPlaybackControlsColor =
MaterialValueHelper.getPrimaryDisabledTextColor(requireContext(), false)
}
@@ -94,15 +84,15 @@ class PlayerPlaybackControlsFragment : AbsPlayerControlsFragment(), OnSharedPref
TintHelper.setTintAuto(
playPauseButton,
- MaterialValueHelper.getPrimaryTextColor(requireContext(), ColorUtil.isColorLight(colorFinal)),
+ MaterialValueHelper.getPrimaryTextColor(
+ requireContext(),
+ ColorUtil.isColorLight(colorFinal)
+ ),
false
)
TintHelper.setTintAuto(playPauseButton, colorFinal, true)
-
- ViewUtil.setProgressDrawable(progressSlider, colorFinal, false)
-
+ ViewUtil.setProgressDrawable(progressSlider, colorFinal, true)
volumeFragment?.setTintable(colorFinal)
-
updateRepeatState()
updateShuffleState()
updatePrevNextColor()
@@ -196,7 +186,10 @@ class PlayerPlaybackControlsFragment : AbsPlayerControlsFragment(), OnSharedPref
lastPlaybackControlsColor,
PorterDuff.Mode.SRC_IN
)
- else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ else -> shuffleButton.setColorFilter(
+ lastDisabledPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
}
@@ -208,7 +201,10 @@ class PlayerPlaybackControlsFragment : AbsPlayerControlsFragment(), OnSharedPref
when (MusicPlayerRemote.repeatMode) {
MusicService.REPEAT_MODE_NONE -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
- repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ repeatButton.setColorFilter(
+ lastDisabledPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
MusicService.REPEAT_MODE_ALL -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
@@ -240,32 +236,27 @@ class PlayerPlaybackControlsFragment : AbsPlayerControlsFragment(), OnSharedPref
}
}
- override fun setUpProgressSlider() {
- progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
- override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- if (fromUser) {
- MusicPlayerRemote.seekTo(progress)
- onUpdateProgressViews(
- MusicPlayerRemote.songProgressMillis,
- MusicPlayerRemote.songDurationMillis
- )
- }
- }
- })
- }
-
override fun onUpdateProgressViews(progress: Int, total: Int) {
- progressSlider.max = total
-
- val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
- animator.duration = SLIDER_ANIMATION_TIME
- animator.interpolator = LinearInterpolator()
- animator.start()
-
+ if (total <= 0) {
+ return
+ }
+ progressSlider.setRange(progress.toFloat(), total.toFloat())
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
}
+ override fun setUpProgressSlider() {
+ progressSlider.addOnChangeListener { _, value, fromUser ->
+ if (fromUser) {
+ MusicPlayerRemote.seekTo(value.toInt())
+ onUpdateProgressViews(
+ MusicPlayerRemote.songProgressMillis,
+ MusicPlayerRemote.songDurationMillis
+ )
+ }
+ }
+ }
+
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
if (key == PreferenceUtil.EXTRA_SONG_INFO) {
@@ -275,6 +266,7 @@ class PlayerPlaybackControlsFragment : AbsPlayerControlsFragment(), OnSharedPref
override fun onDestroyView() {
super.onDestroyView()
- PreferenceUtil.getInstance(requireContext()).unregisterOnSharedPreferenceChangedListener(this)
+ PreferenceUtil.getInstance(requireContext())
+ .unregisterOnSharedPreferenceChangedListener(this)
}
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/peak/PeakPlayerControlFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/peak/PeakPlayerControlFragment.kt
index 6af74e40e..b77017f31 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/peak/PeakPlayerControlFragment.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/peak/PeakPlayerControlFragment.kt
@@ -14,39 +14,29 @@
package code.name.monkey.retromusic.fragments.player.peak
-import android.animation.ObjectAnimator
import android.graphics.Color
import android.graphics.PorterDuff
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.view.animation.LinearInterpolator
-import android.widget.SeekBar
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.ripAlpha
+import code.name.monkey.retromusic.extensions.setRange
import code.name.monkey.retromusic.extensions.textColorSecondary
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
-import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ViewUtil
-import kotlinx.android.synthetic.main.fragment_peak_control_player.nextButton
-import kotlinx.android.synthetic.main.fragment_peak_control_player.playPauseButton
-import kotlinx.android.synthetic.main.fragment_peak_control_player.previousButton
-import kotlinx.android.synthetic.main.fragment_peak_control_player.progressSlider
-import kotlinx.android.synthetic.main.fragment_peak_control_player.repeatButton
-import kotlinx.android.synthetic.main.fragment_peak_control_player.shuffleButton
-import kotlinx.android.synthetic.main.fragment_peak_control_player.songCurrentProgress
-import kotlinx.android.synthetic.main.fragment_peak_control_player.songTotalTime
+import kotlinx.android.synthetic.main.fragment_peak_control_player.*
/**
* Created by hemanths on 2019-10-04.
@@ -98,11 +88,13 @@ class PeakPlayerControlFragment : AbsPlayerControlsFragment() {
override fun setDark(color: Int) {
val colorBg = ATHUtil.resolveColor(requireContext(), android.R.attr.colorBackground)
if (ColorUtil.isColorLight(colorBg)) {
- lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(requireContext(), true)
+ lastPlaybackControlsColor =
+ MaterialValueHelper.getSecondaryTextColor(requireContext(), true)
lastDisabledPlaybackControlsColor =
MaterialValueHelper.getSecondaryDisabledTextColor(requireContext(), true)
} else {
- lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(requireContext(), false)
+ lastPlaybackControlsColor =
+ MaterialValueHelper.getPrimaryTextColor(requireContext(), false)
lastDisabledPlaybackControlsColor =
MaterialValueHelper.getPrimaryDisabledTextColor(requireContext(), false)
}
@@ -122,18 +114,6 @@ class PeakPlayerControlFragment : AbsPlayerControlsFragment() {
updatePrevNextColor()
}
- override fun onUpdateProgressViews(progress: Int, total: Int) {
- progressSlider.max = total
-
- val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
- animator.duration = SLIDER_ANIMATION_TIME
- animator.interpolator = LinearInterpolator()
- animator.start()
-
- songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
- songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
- }
-
private fun updatePlayPauseDrawableState() {
if (MusicPlayerRemote.isPlaying) {
playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp)
@@ -162,15 +142,25 @@ class PeakPlayerControlFragment : AbsPlayerControlsFragment() {
}
}
+ override fun onUpdateProgressViews(progress: Int, total: Int) {
+ if (total <= 0) {
+ return
+ }
+ progressSlider.setRange(progress.toFloat(), total.toFloat())
+ songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
+ songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
+ }
+
override fun setUpProgressSlider() {
- progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
- override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- if (fromUser) {
- MusicPlayerRemote.seekTo(progress)
- onUpdateProgressViews(MusicPlayerRemote.songProgressMillis, MusicPlayerRemote.songDurationMillis)
- }
+ progressSlider.addOnChangeListener { _, value, fromUser ->
+ if (fromUser) {
+ MusicPlayerRemote.seekTo(value.toInt())
+ onUpdateProgressViews(
+ MusicPlayerRemote.songProgressMillis,
+ MusicPlayerRemote.songDurationMillis
+ )
}
- })
+ }
}
private fun setUpPlayPauseFab() {
@@ -196,7 +186,10 @@ class PeakPlayerControlFragment : AbsPlayerControlsFragment() {
lastPlaybackControlsColor,
PorterDuff.Mode.SRC_IN
)
- else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ else -> shuffleButton.setColorFilter(
+ lastDisabledPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
}
@@ -204,7 +197,10 @@ class PeakPlayerControlFragment : AbsPlayerControlsFragment() {
when (MusicPlayerRemote.repeatMode) {
MusicService.REPEAT_MODE_NONE -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
- repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ repeatButton.setColorFilter(
+ lastDisabledPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
MusicService.REPEAT_MODE_ALL -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/plain/PlainPlaybackControlsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/plain/PlainPlaybackControlsFragment.kt
index 9d279e904..db9602f90 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/plain/PlainPlaybackControlsFragment.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/plain/PlainPlaybackControlsFragment.kt
@@ -1,6 +1,5 @@
package code.name.monkey.retromusic.fragments.player.plain
-import android.animation.ObjectAnimator
import android.graphics.PorterDuff
import android.os.Bundle
import android.view.LayoutInflater
@@ -8,8 +7,6 @@ import android.view.View
import android.view.ViewGroup
import android.view.animation.AccelerateInterpolator
import android.view.animation.DecelerateInterpolator
-import android.view.animation.LinearInterpolator
-import android.widget.SeekBar
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil
@@ -18,12 +15,12 @@ import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.extensions.ripAlpha
+import code.name.monkey.retromusic.extensions.setRange
import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
-import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
@@ -86,7 +83,11 @@ class PlainPlaybackControlsFragment : AbsPlayerControlsFragment() {
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
}
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
return inflater.inflate(R.layout.fragment_plain_controls_fragment, container, false)
}
@@ -142,10 +143,12 @@ class PlainPlaybackControlsFragment : AbsPlayerControlsFragment() {
val colorBg = ATHUtil.resolveColor(context!!, android.R.attr.colorBackground)
if (ColorUtil.isColorLight(colorBg)) {
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(context!!, true)
- lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(context!!, true)
+ lastDisabledPlaybackControlsColor =
+ MaterialValueHelper.getSecondaryDisabledTextColor(context!!, true)
} else {
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(context!!, false)
- lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(context!!, false)
+ lastDisabledPlaybackControlsColor =
+ MaterialValueHelper.getPrimaryDisabledTextColor(context!!, false)
}
val colorFinal = if (PreferenceUtil.getInstance(requireContext()).adaptiveColor) {
@@ -179,7 +182,10 @@ class PlainPlaybackControlsFragment : AbsPlayerControlsFragment() {
lastPlaybackControlsColor,
PorterDuff.Mode.SRC_IN
)
- else -> shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ else -> shuffleButton.setColorFilter(
+ lastDisabledPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
}
@@ -191,7 +197,10 @@ class PlainPlaybackControlsFragment : AbsPlayerControlsFragment() {
when (MusicPlayerRemote.repeatMode) {
MusicService.REPEAT_MODE_NONE -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
- repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN)
+ repeatButton.setColorFilter(
+ lastDisabledPlaybackControlsColor,
+ PorterDuff.Mode.SRC_IN
+ )
}
MusicService.REPEAT_MODE_ALL -> {
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp)
@@ -223,20 +232,6 @@ class PlainPlaybackControlsFragment : AbsPlayerControlsFragment() {
}
}
- override fun setUpProgressSlider() {
- progressSlider.setOnSeekBarChangeListener(object : SimpleOnSeekbarChangeListener() {
- override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- if (fromUser) {
- MusicPlayerRemote.seekTo(progress)
- onUpdateProgressViews(
- MusicPlayerRemote.songProgressMillis,
- MusicPlayerRemote.songDurationMillis
- )
- }
- }
- })
- }
-
private fun showBonceAnimation() {
playPauseButton.apply {
clearAnimation()
@@ -269,14 +264,23 @@ class PlainPlaybackControlsFragment : AbsPlayerControlsFragment() {
}
override fun onUpdateProgressViews(progress: Int, total: Int) {
- progressSlider.max = total
-
- val animator = ObjectAnimator.ofInt(progressSlider, "progress", progress)
- animator.duration = SLIDER_ANIMATION_TIME
- animator.interpolator = LinearInterpolator()
- animator.start()
-
+ if (total <= 0) {
+ return
+ }
+ progressSlider.setRange(progress.toFloat(), total.toFloat())
songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
}
+
+ override fun setUpProgressSlider() {
+ progressSlider.addOnChangeListener { _, value, fromUser ->
+ if (fromUser) {
+ MusicPlayerRemote.seekTo(value.toInt())
+ onUpdateProgressViews(
+ MusicPlayerRemote.songProgressMillis,
+ MusicPlayerRemote.songDurationMillis
+ )
+ }
+ }
+ }
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/player/tiny/TinyPlayerFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/player/tiny/TinyPlayerFragment.kt
index e6918903d..60c2597c8 100644
--- a/app/src/main/java/code/name/monkey/retromusic/fragments/player/tiny/TinyPlayerFragment.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/fragments/player/tiny/TinyPlayerFragment.kt
@@ -25,12 +25,7 @@ import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ViewUtil
-import kotlinx.android.synthetic.main.fragment_tiny_player.playerSongTotalTime
-import kotlinx.android.synthetic.main.fragment_tiny_player.playerToolbar
-import kotlinx.android.synthetic.main.fragment_tiny_player.progressBar
-import kotlinx.android.synthetic.main.fragment_tiny_player.songInfo
-import kotlinx.android.synthetic.main.fragment_tiny_player.text
-import kotlinx.android.synthetic.main.fragment_tiny_player.title
+import kotlinx.android.synthetic.main.fragment_tiny_player.*
class TinyPlayerFragment : AbsPlayerFragment(), MusicProgressViewUpdateHelper.Callback {
override fun onUpdateProgressViews(progress: Int, total: Int) {
@@ -86,10 +81,12 @@ class TinyPlayerFragment : AbsPlayerFragment(), MusicProgressViewUpdateHelper.Ca
if (ColorUtil.isColorLight(colorFinal)) {
textColorPrimary = MaterialValueHelper.getSecondaryTextColor(requireContext(), true)
- textColorPrimaryDisabled = MaterialValueHelper.getSecondaryTextColor(requireContext(), true)
+ textColorPrimaryDisabled =
+ MaterialValueHelper.getSecondaryTextColor(requireContext(), true)
} else {
textColorPrimary = MaterialValueHelper.getPrimaryTextColor(requireContext(), false)
- textColorPrimaryDisabled = MaterialValueHelper.getSecondaryTextColor(requireContext(), false)
+ textColorPrimaryDisabled =
+ MaterialValueHelper.getSecondaryTextColor(requireContext(), false)
}
this.lastColor = colorFinal
@@ -143,7 +140,11 @@ class TinyPlayerFragment : AbsPlayerFragment(), MusicProgressViewUpdateHelper.Ca
}
}
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
return inflater.inflate(R.layout.fragment_tiny_player, container, false)
}
diff --git a/app/src/main/java/code/name/monkey/retromusic/helper/MusicProgressViewUpdateHelper.kt b/app/src/main/java/code/name/monkey/retromusic/helper/MusicProgressViewUpdateHelper.kt
index 5561555b2..7ff6e4e2c 100644
--- a/app/src/main/java/code/name/monkey/retromusic/helper/MusicProgressViewUpdateHelper.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/helper/MusicProgressViewUpdateHelper.kt
@@ -17,7 +17,6 @@ package code.name.monkey.retromusic.helper
import android.os.Handler
import android.os.Message
-
class MusicProgressViewUpdateHelper : Handler {
private var callback: Callback? = null
@@ -54,8 +53,8 @@ class MusicProgressViewUpdateHelper : Handler {
private fun refreshProgressViews(): Int {
val progressMillis = MusicPlayerRemote.songProgressMillis
val totalMillis = MusicPlayerRemote.songDurationMillis
-
- callback!!.onUpdateProgressViews(progressMillis, totalMillis)
+ println("$progressMillis $totalMillis")
+ callback?.onUpdateProgressViews(progressMillis, totalMillis)
if (!MusicPlayerRemote.isPlaying) {
return intervalPaused
diff --git a/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.java b/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.java
index 776e1acd7..02cffb400 100644
--- a/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.java
+++ b/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.java
@@ -32,7 +32,7 @@ import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.dialogs.OptionsSheetDialogFragment;
import code.name.monkey.retromusic.fragments.AlbumCoverStyle;
import code.name.monkey.retromusic.fragments.NowPlayingScreen;
-import code.name.monkey.retromusic.fragments.mainactivity.folders.FoldersFragment;
+import code.name.monkey.retromusic.fragments.mainactivity.FoldersFragment;
import code.name.monkey.retromusic.helper.SortOrder;
import code.name.monkey.retromusic.helper.SortOrder.AlbumSongSortOrder;
import code.name.monkey.retromusic.model.CategoryInfo;
diff --git a/app/src/main/java/code/name/monkey/retromusic/util/ViewUtil.kt b/app/src/main/java/code/name/monkey/retromusic/util/ViewUtil.kt
index bc1eb93c1..15438f9af 100644
--- a/app/src/main/java/code/name/monkey/retromusic/util/ViewUtil.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/util/ViewUtil.kt
@@ -28,6 +28,7 @@ import androidx.core.view.ViewCompat
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper
+import com.google.android.material.slider.Slider
object ViewUtil {
@@ -47,6 +48,16 @@ object ViewUtil {
}
}
+ fun setProgressDrawable(progressSlider: Slider, color: Int, thumbTint: Boolean = false) {
+ if (thumbTint) {
+ progressSlider.thumbColor = ColorStateList.valueOf(color)
+ }
+ val colorWithAlpha = ColorUtil.withAlpha(color, 0.25f)
+ progressSlider.haloColor = ColorStateList.valueOf(colorWithAlpha)
+ progressSlider.trackColorActive = ColorStateList.valueOf(color)
+ progressSlider.trackColorInactive = ColorStateList.valueOf(colorWithAlpha)
+ }
+
fun setProgressDrawable(progressSlider: ProgressBar, newColor: Int) {
val layerDrawable = progressSlider.progressDrawable as LayerDrawable
diff --git a/app/src/main/java/code/name/monkey/retromusic/views/RetroShapeableImageView.kt b/app/src/main/java/code/name/monkey/retromusic/views/RetroShapeableImageView.kt
index 79371a4a1..c81341eb6 100644
--- a/app/src/main/java/code/name/monkey/retromusic/views/RetroShapeableImageView.kt
+++ b/app/src/main/java/code/name/monkey/retromusic/views/RetroShapeableImageView.kt
@@ -16,12 +16,11 @@ package code.name.monkey.retromusic.views
import android.content.Context
import android.util.AttributeSet
import code.name.monkey.retromusic.R
-import com.google.android.material.imageview.ExperimentalImageView
import com.google.android.material.imageview.ShapeableImageView
import com.google.android.material.shape.CornerFamily
import com.google.android.material.shape.ShapeAppearanceModel
-@ExperimentalImageView
+
class RetroShapeableImageView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
@@ -29,8 +28,10 @@ class RetroShapeableImageView @JvmOverloads constructor(
) : ShapeableImageView(context, attrs, defStyle) {
init {
- val typedArray = context.obtainStyledAttributes(attrs, R.styleable.RetroShapeableImageView, defStyle, -1)
- val cornerSize = typedArray.getDimension(R.styleable.RetroShapeableImageView_retroCornerSize, 0f);
+ val typedArray =
+ context.obtainStyledAttributes(attrs, R.styleable.RetroShapeableImageView, defStyle, -1)
+ val cornerSize =
+ typedArray.getDimension(R.styleable.RetroShapeableImageView_retroCornerSize, 0f);
shapeAppearanceModel = ShapeAppearanceModel.Builder()
.setAllCorners(CornerFamily.ROUNDED, cornerSize)
.build()
diff --git a/app/src/main/java/code/name/monkey/retromusic/volume/AudioVolumeContentObserver.java b/app/src/main/java/code/name/monkey/retromusic/volume/AudioVolumeContentObserver.java
index ae63bce4a..f11c4bd3b 100644
--- a/app/src/main/java/code/name/monkey/retromusic/volume/AudioVolumeContentObserver.java
+++ b/app/src/main/java/code/name/monkey/retromusic/volume/AudioVolumeContentObserver.java
@@ -23,13 +23,16 @@ import androidx.annotation.NonNull;
public class AudioVolumeContentObserver extends ContentObserver {
private final OnAudioVolumeChangedListener mListener;
+
private final AudioManager mAudioManager;
+
private final int mAudioStreamType;
- private int mLastVolume;
+
+ private float mLastVolume;
AudioVolumeContentObserver(@NonNull Handler handler, @NonNull AudioManager audioManager,
- int audioStreamType,
- @NonNull OnAudioVolumeChangedListener listener) {
+ int audioStreamType,
+ @NonNull OnAudioVolumeChangedListener listener) {
super(handler);
mAudioManager = audioManager;
@@ -44,8 +47,8 @@ public class AudioVolumeContentObserver extends ContentObserver {
@Override
public void onChange(boolean selfChange, Uri uri) {
if (mAudioManager != null && mListener != null) {
- int maxVolume = mAudioManager.getStreamMaxVolume(mAudioStreamType);
- int currentVolume = mAudioManager.getStreamVolume(mAudioStreamType);
+ float maxVolume = mAudioManager.getStreamMaxVolume(mAudioStreamType);
+ float currentVolume = mAudioManager.getStreamVolume(mAudioStreamType);
if (currentVolume != mLastVolume) {
mLastVolume = currentVolume;
mListener.onAudioVolumeChanged(currentVolume, maxVolume);
diff --git a/app/src/main/java/code/name/monkey/retromusic/volume/OnAudioVolumeChangedListener.java b/app/src/main/java/code/name/monkey/retromusic/volume/OnAudioVolumeChangedListener.kt
similarity index 78%
rename from app/src/main/java/code/name/monkey/retromusic/volume/OnAudioVolumeChangedListener.java
rename to app/src/main/java/code/name/monkey/retromusic/volume/OnAudioVolumeChangedListener.kt
index 31813ada8..3fb91db0a 100644
--- a/app/src/main/java/code/name/monkey/retromusic/volume/OnAudioVolumeChangedListener.java
+++ b/app/src/main/java/code/name/monkey/retromusic/volume/OnAudioVolumeChangedListener.kt
@@ -11,10 +11,8 @@
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
+package code.name.monkey.retromusic.volume
-package code.name.monkey.retromusic.volume;
-
-public interface OnAudioVolumeChangedListener {
-
- void onAudioVolumeChanged(int currentVolume, int maxVolume);
+interface OnAudioVolumeChangedListener {
+ fun onAudioVolumeChanged(currentVolume: Float, maxVolume: Float)
}
\ No newline at end of file
diff --git a/app/src/main/res/layout-land/fragment_circle_player.xml b/app/src/main/res/layout-land/fragment_circle_player.xml
index 466cd3a9d..d917d4fb3 100644
--- a/app/src/main/res/layout-land/fragment_circle_player.xml
+++ b/app/src/main/res/layout-land/fragment_circle_player.xml
@@ -54,39 +54,6 @@
app:navigationIcon="@drawable/ic_keyboard_arrow_down_black_24dp"
tools:layout_editor_absoluteY="24dp" />
-
-
-
-
-
-
-
+ app:layout_constraintTop_toBottomOf="@+id/playerToolbar">
-
+ android:gravity="center"
+ android:maxLines="1"
+ android:paddingStart="0dp"
+ android:paddingEnd="16dp"
+ android:textAppearance="@style/TextViewHeadline4"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textStyle="bold"
+ tools:text="@tools:sample/lorem/random" />
+
-
+
+
+
+
+
+
+
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout-xlarge-land/fragment_player_playback_controls.xml b/app/src/main/res/layout-xlarge-land/fragment_player_playback_controls.xml
index b4c3855e1..657889fcb 100755
--- a/app/src/main/res/layout-xlarge-land/fragment_player_playback_controls.xml
+++ b/app/src/main/res/layout-xlarge-land/fragment_player_playback_controls.xml
@@ -128,17 +128,14 @@
app:layout_constraintStart_toEndOf="@+id/nextButton"
app:layout_constraintTop_toTopOf="@+id/playPauseButton">
-
diff --git a/app/src/main/res/layout/fragment_adaptive_player_playback_controls.xml b/app/src/main/res/layout/fragment_adaptive_player_playback_controls.xml
index c4d6cffa8..52d8c80ac 100644
--- a/app/src/main/res/layout/fragment_adaptive_player_playback_controls.xml
+++ b/app/src/main/res/layout/fragment_adaptive_player_playback_controls.xml
@@ -1,8 +1,8 @@
-
-
+ app:trackHeight="3dp"
+ tools:valueFrom="0.0"
+ tools:valueTo="11.0" />
-
+ tools:progress="20"
+ tools:valueFrom="0.0"
+ tools:valueTo="11.0" />
-
-
+ app:layout_constraintEnd_toStartOf="@id/songTotalTime"
+ app:layout_constraintStart_toEndOf="@id/songCurrentProgress"
+ app:layout_constraintTop_toBottomOf="@+id/volumeSeekBar"
+ app:thumbColor="?attr/colorSurface"
+ app:trackColorInactive="?attr/colorControlNormal"
+ tools:ignore="RtlHardcoded,UnusedAttribute"
+ tools:progress="20" />
-
+
-
-
-
-
+
-
-
@@ -46,7 +49,6 @@
android:minWidth="40dp"
android:singleLine="true"
android:textColor="?android:attr/textColorSecondary"
- android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@+id/progressSlider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/progressSlider"
diff --git a/app/src/main/res/layout/fragment_full_player_controls.xml b/app/src/main/res/layout/fragment_full_player_controls.xml
index c6c50f6ff..a4f85a11a 100644
--- a/app/src/main/res/layout/fragment_full_player_controls.xml
+++ b/app/src/main/res/layout/fragment_full_player_controls.xml
@@ -83,19 +83,20 @@
tools:ignore="RtlHardcoded,RtlSymmetry"
tools:text="00:22" />
-
diff --git a/app/src/main/res/layout/fragment_material_playback_controls.xml b/app/src/main/res/layout/fragment_material_playback_controls.xml
index 702beb88e..9f0200ecc 100644
--- a/app/src/main/res/layout/fragment_material_playback_controls.xml
+++ b/app/src/main/res/layout/fragment_material_playback_controls.xml
@@ -18,26 +18,22 @@
android:minWidth="40dp"
android:singleLine="true"
android:textColor="?android:attr/textColorSecondary"
- android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@+id/progressSlider"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/progressSlider"
tools:ignore="RtlHardcoded,RtlSymmetry"
tools:text="00:22" />
-
@@ -50,7 +46,6 @@
android:minWidth="40dp"
android:singleLine="true"
android:textColor="?android:attr/textColorSecondary"
- android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@+id/progressSlider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/progressSlider"
diff --git a/app/src/main/res/layout/fragment_peak_control_player.xml b/app/src/main/res/layout/fragment_peak_control_player.xml
index 840100bd5..af5ef6296 100644
--- a/app/src/main/res/layout/fragment_peak_control_player.xml
+++ b/app/src/main/res/layout/fragment_peak_control_player.xml
@@ -28,23 +28,19 @@
android:minWidth="40dp"
android:singleLine="true"
android:textColor="?android:attr/textColorSecondary"
- android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@+id/progressSlider"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/progressSlider"
tools:ignore="RtlHardcoded,RtlSymmetry"
tools:text="00:22" />
-
-
@@ -48,7 +44,6 @@
android:minWidth="40dp"
android:singleLine="true"
android:textColor="?android:attr/textColorSecondary"
- android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@+id/progressSlider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/progressSlider"
diff --git a/app/src/main/res/layout/fragment_player_playback_controls.xml b/app/src/main/res/layout/fragment_player_playback_controls.xml
index d7d2ab06e..3dd6bb1fd 100755
--- a/app/src/main/res/layout/fragment_player_playback_controls.xml
+++ b/app/src/main/res/layout/fragment_player_playback_controls.xml
@@ -18,26 +18,21 @@
android:minWidth="40dp"
android:singleLine="true"
android:textColor="?android:attr/textColorSecondary"
- android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@+id/progressSlider"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/progressSlider"
tools:ignore="RtlHardcoded,RtlSymmetry"
tools:text="00:22" />
-
@@ -50,7 +45,6 @@
android:minWidth="40dp"
android:singleLine="true"
android:textColor="?android:attr/textColorSecondary"
- android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@+id/progressSlider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
diff --git a/app/src/main/res/layout/fragment_tiny_player.xml b/app/src/main/res/layout/fragment_tiny_player.xml
index bd75804e4..83c390a9e 100644
--- a/app/src/main/res/layout/fragment_tiny_player.xml
+++ b/app/src/main/res/layout/fragment_tiny_player.xml
@@ -45,7 +45,6 @@
-
-
+ app:thumbRadius="8dp"
+ app:trackHeight="2dp" />
#000000
#FFFFFF
+ #40FFFFFF
#1DE9B6
diff --git a/gradle.properties b/gradle.properties
index a09e1510d..4e2b3ea73 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -3,10 +3,8 @@ org.gradle.daemon=true
org.gradle.parallel=true
jvmArgs='-Xmx2048m'
android.useAndroidX=true
-android.enabelR8=true
android.enableR8.fullMode=false
android.enableJetifier=true
android.debug.obsoleteApi=true
android.enableBuildCache=true
-android.jetifier.blacklist = butterknife.*\\.jar
kotlin.code.style=official
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 751631787..a2b147006 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Fri Sep 20 00:21:23 IST 2019
+#Mon Feb 24 22:35:41 IST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
diff --git a/liboverscroll/.gitignore b/liboverscroll/.gitignore
deleted file mode 100755
index 796b96d1c..000000000
--- a/liboverscroll/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build
diff --git a/liboverscroll/build.gradle b/liboverscroll/build.gradle
deleted file mode 100755
index aad70cc4a..000000000
--- a/liboverscroll/build.gradle
+++ /dev/null
@@ -1,49 +0,0 @@
-apply plugin: 'com.android.library'
-
-android {
- compileSdkVersion 29
- defaultConfig {
- minSdkVersion 21
- targetSdkVersion 28
- versionCode 1
- versionName "1.0"
- }
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
- }
- }
-}
-
-dependencies {
- implementation 'androidx.recyclerview:recyclerview:1.2.0-alpha01'
-
- testCompile 'junit:junit:4.12'
- testCompile "org.mockito:mockito-core:1.9.5"
- testCompile "org.robolectric:robolectric:3.0"
-}
-
-
-// Running from Gradle tab in IDE would create liboverscroll/build/lib/liboverscroll-sources.jar
-task sourcesJar(type: Jar) {
- from android.sourceSets.main.java.srcDirs
- classifier = 'sources'
-}
-
-task javadoc(type: Javadoc) {
- failOnError false
- source = android.sourceSets.main.java.srcDirs
- classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
-}
-
-// Running from Gradle tab in IDE would create liboverscroll/build/lib/liboverscroll-javadoc.jar
-task javadocJar(type: Jar, dependsOn: javadoc) {
- classifier = 'javadoc'
- from javadoc.destinationDir
-}
-
-artifacts {
- archives javadocJar
- archives sourcesJar
-}
diff --git a/liboverscroll/src/main/AndroidManifest.xml b/liboverscroll/src/main/AndroidManifest.xml
deleted file mode 100755
index 6d52f958a..000000000
--- a/liboverscroll/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
diff --git a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/HorizontalOverScrollBounceEffectDecorator.java b/liboverscroll/src/main/java/me/everything/android/ui/overscroll/HorizontalOverScrollBounceEffectDecorator.java
deleted file mode 100755
index 76eb2ece0..000000000
--- a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/HorizontalOverScrollBounceEffectDecorator.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package me.everything.android.ui.overscroll;
-
-import android.view.MotionEvent;
-import android.view.View;
-
-import me.everything.android.ui.overscroll.adapters.IOverScrollDecoratorAdapter;
-
-/**
- * A concrete implementation of {@link OverScrollBounceEffectDecoratorBase} for a horizontal orientation.
- *
- * @author amit
- */
-public class HorizontalOverScrollBounceEffectDecorator extends OverScrollBounceEffectDecoratorBase {
-
- protected static class MotionAttributesHorizontal extends MotionAttributes {
-
- public boolean init(View view, MotionEvent event) {
-
- // We must have history available to calc the dx. Normally it's there - if it isn't temporarily,
- // we declare the event 'invalid' and expect it in consequent events.
- if (event.getHistorySize() == 0) {
- return false;
- }
-
- // Allow for counter-orientation-direction operations (e.g. item swiping) to run fluently.
- final float dy = event.getY(0) - event.getHistoricalY(0, 0);
- final float dx = event.getX(0) - event.getHistoricalX(0, 0);
- if (Math.abs(dx) < Math.abs(dy)) {
- return false;
- }
-
- mAbsOffset = view.getTranslationX();
- mDeltaOffset = dx;
- mDir = mDeltaOffset > 0;
-
- return true;
- }
- }
-
- protected static class AnimationAttributesHorizontal extends AnimationAttributes {
-
- public AnimationAttributesHorizontal() {
- mProperty = View.TRANSLATION_X;
- }
-
- @Override
- protected void init(View view) {
- mAbsOffset = view.getTranslationX();
- mMaxOffset = view.getWidth();
- }
- }
-
- /**
- * C'tor, creating the effect with default arguments:
- *
Touch-drag ratio in 'forward' direction will be set to DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD.
- *
Touch-drag ratio in 'backwards' direction will be set to DEFAULT_TOUCH_DRAG_MOVE_RATIO_BCK.
- *
Deceleration factor (for the bounce-back effect) will be set to DEFAULT_DECELERATE_FACTOR.
- *
- * @param viewAdapter The view's encapsulation.
- */
- public HorizontalOverScrollBounceEffectDecorator(IOverScrollDecoratorAdapter viewAdapter) {
- this(viewAdapter, DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD, DEFAULT_TOUCH_DRAG_MOVE_RATIO_BCK, DEFAULT_DECELERATE_FACTOR);
- }
-
- /**
- * C'tor, creating the effect with explicit arguments.
- * @param viewAdapter The view's encapsulation.
- * @param touchDragRatioFwd Ratio of touch distance to actual drag distance when in 'forward' direction.
- * @param touchDragRatioBck Ratio of touch distance to actual drag distance when in 'backward'
- * direction (opposite to initial one).
- * @param decelerateFactor Deceleration factor used when decelerating the motion to create the
- * bounce-back effect.
- */
- public HorizontalOverScrollBounceEffectDecorator(IOverScrollDecoratorAdapter viewAdapter,
- float touchDragRatioFwd, float touchDragRatioBck, float decelerateFactor) {
- super(viewAdapter, decelerateFactor, touchDragRatioFwd, touchDragRatioBck);
- }
-
- @Override
- protected MotionAttributes createMotionAttributes() {
- return new MotionAttributesHorizontal();
- }
-
- @Override
- protected AnimationAttributes createAnimationAttributes() {
- return new AnimationAttributesHorizontal();
- }
-
- @Override
- protected void translateView(View view, float offset) {
- view.setTranslationX(offset);
- }
-
- @Override
- protected void translateViewAndEvent(View view, float offset, MotionEvent event) {
- view.setTranslationX(offset);
- event.offsetLocation(offset - event.getX(0), 0f);
- }
-}
diff --git a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/IOverScrollDecor.java b/liboverscroll/src/main/java/me/everything/android/ui/overscroll/IOverScrollDecor.java
deleted file mode 100755
index fc6f4eef0..000000000
--- a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/IOverScrollDecor.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package me.everything.android.ui.overscroll;
-
-import android.view.View;
-
-/**
- * @author amit
- */
-public interface IOverScrollDecor {
- View getView();
-
- void setOverScrollStateListener(IOverScrollStateListener listener);
- void setOverScrollUpdateListener(IOverScrollUpdateListener listener);
-
- /**
- * Get the current decorator's runtime state, i.e. one of the values specified by {@link IOverScrollState}.
- * @return The state.
- */
- int getCurrentState();
-
- /**
- * Detach the decorator from its associated view, thus disabling it entirely.
- *
- * It is best to call this only when over-scroll isn't currently in-effect - i.e. verify that
- * getCurrentState()==IOverScrollState.STATE_IDLE
as a precondition, or otherwise
- * use a state listener previously installed using
- * {@link #setOverScrollStateListener(IOverScrollStateListener)}.
- *
- * Note: Upon detachment completion, the view in question will return to the default
- * Android over-scroll configuration (i.e. {@link View.OVER_SCROLL_ALWAYS} mode). This can be
- * overridden by calling View.setOverScrollMode(mode)
immediately thereafter.
- */
- void detach();
-}
diff --git a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/IOverScrollState.java b/liboverscroll/src/main/java/me/everything/android/ui/overscroll/IOverScrollState.java
deleted file mode 100755
index 0d1e5ce28..000000000
--- a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/IOverScrollState.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package me.everything.android.ui.overscroll;
-
-/**
- * @author amit
- */
-public interface IOverScrollState {
-
- /** No over-scroll is in-effect. */
- int STATE_IDLE = 0;
-
- /** User is actively touch-dragging, thus enabling over-scroll at the view's start side. */
- int STATE_DRAG_START_SIDE = 1;
-
- /** User is actively touch-dragging, thus enabling over-scroll at the view's end side. */
- int STATE_DRAG_END_SIDE = 2;
-
- /** User has released their touch, thus throwing the view back into place via bounce-back animation. */
- int STATE_BOUNCE_BACK = 3;
-}
diff --git a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/IOverScrollStateListener.java b/liboverscroll/src/main/java/me/everything/android/ui/overscroll/IOverScrollStateListener.java
deleted file mode 100755
index a6647690a..000000000
--- a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/IOverScrollStateListener.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package me.everything.android.ui.overscroll;
-
-/**
- * A callback-listener enabling over-scroll effect clients to be notified of effect state transitions.
- *
Invoked whenever state is transitioned onto one of {@link IOverScrollState#STATE_IDLE},
- * {@link IOverScrollState#STATE_DRAG_START_SIDE}, {@link IOverScrollState#STATE_DRAG_END_SIDE}
- * or {@link IOverScrollState#STATE_BOUNCE_BACK}.
- *
- * @author amit
- *
- * @see IOverScrollUpdateListener
- */
-public interface IOverScrollStateListener {
-
- /**
- * The invoked callback.
- *
- * @param decor The associated over-scroll 'decorator'.
- * @param oldState The old over-scroll state; ID's specified by {@link IOverScrollState}, e.g.
- * {@link IOverScrollState#STATE_IDLE}.
- * @param newState The new over-scroll state; ID's specified by {@link IOverScrollState},
- * e.g. {@link IOverScrollState#STATE_IDLE}.
- */
- void onOverScrollStateChange(IOverScrollDecor decor, int oldState, int newState);
-}
diff --git a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/IOverScrollUpdateListener.java b/liboverscroll/src/main/java/me/everything/android/ui/overscroll/IOverScrollUpdateListener.java
deleted file mode 100755
index 69d8e5eea..000000000
--- a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/IOverScrollUpdateListener.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package me.everything.android.ui.overscroll;
-
-/**
- * A callback-listener enabling over-scroll effect clients to subscribe to real-time updates
- * of over-scrolling intensity, provided as the view-translation offset from pre-scroll position.
- *
- * @author amit
- *
- * @see IOverScrollStateListener
- */
-public interface IOverScrollUpdateListener {
-
- /**
- * The invoked callback.
- *
- * @param decor The associated over-scroll 'decorator'.
- * @param state One of: {@link IOverScrollState#STATE_IDLE}, {@link IOverScrollState#STATE_DRAG_START_SIDE},
- * {@link IOverScrollState#STATE_DRAG_START_SIDE} or {@link IOverScrollState#STATE_BOUNCE_BACK}.
- * @param offset The currently visible offset created due to over-scroll.
- */
- void onOverScrollUpdate(IOverScrollDecor decor, int state, float offset);
-}
diff --git a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/ListenerStubs.java b/liboverscroll/src/main/java/me/everything/android/ui/overscroll/ListenerStubs.java
deleted file mode 100755
index 8cb22d4d8..000000000
--- a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/ListenerStubs.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package me.everything.android.ui.overscroll;
-
-/**
- * @author amit
- */
-public interface ListenerStubs {
-
- class OverScrollStateListenerStub implements IOverScrollStateListener {
- @Override
- public void onOverScrollStateChange(IOverScrollDecor decor, int oldState, int newState) { }
- }
-
- class OverScrollUpdateListenerStub implements IOverScrollUpdateListener {
- @Override
- public void onOverScrollUpdate(IOverScrollDecor decor, int state, float offset) { }
- }
-}
diff --git a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/OverScrollBounceEffectDecoratorBase.java b/liboverscroll/src/main/java/me/everything/android/ui/overscroll/OverScrollBounceEffectDecoratorBase.java
deleted file mode 100755
index cd1f5f93e..000000000
--- a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/OverScrollBounceEffectDecoratorBase.java
+++ /dev/null
@@ -1,483 +0,0 @@
-package me.everything.android.ui.overscroll;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
-import android.util.Log;
-import android.util.Property;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-
-import me.everything.android.ui.overscroll.adapters.IOverScrollDecoratorAdapter;
-import me.everything.android.ui.overscroll.adapters.RecyclerViewOverScrollDecorAdapter;
-
-import static me.everything.android.ui.overscroll.IOverScrollState.*;
-import static me.everything.android.ui.overscroll.ListenerStubs.*;
-
-/**
- * A standalone view decorator adding over-scroll with a smooth bounce-back effect to (potentially) any view -
- * provided that an appropriate {@link IOverScrollDecoratorAdapter} implementation exists / can be written
- * for that view type (e.g. {@link RecyclerViewOverScrollDecorAdapter}).
- *
- * Design-wise, being a standalone class, this decorator powerfully provides the ability to add
- * the over-scroll effect over any view without adjusting the view's implementation. In essence, this
- * eliminates the need to repeatedly implement the effect per each view type (list-view,
- * recycler-view, image-view, etc.). Therefore, using it is highly recommended compared to other
- * more intrusive solutions.
- *
- * Note that this class is abstract, having {@link HorizontalOverScrollBounceEffectDecorator} and
- * {@link VerticalOverScrollBounceEffectDecorator} providing concrete implementations that are
- * view-orientation specific.
- *
- *
- * Implementation Notes
- *
- * At it's core, the class simply registers itself as a touch-listener over the decorated view and
- * intercepts touch events as needed.
- *
- * Internally, it delegates the over-scrolling calculations onto 3 state-based classes:
- *
- * - Idle state - monitors view state and touch events to intercept over-scrolling initiation
- * (in which case it hands control over to the Over-scrolling state).
- * - Over-scrolling state - handles motion events to apply the over-scroll effect as users
- * interact with the view.
- * - Bounce-back state - runs the bounce-back animation, all-the-while blocking all
- * touch events till the animation completes (in which case it hands control back to the idle
- * state).
- *
- *
- *
- * @author amit
- *
- * @see RecyclerViewOverScrollDecorAdapter
- * @see IOverScrollDecoratorAdapter
- */
-public abstract class OverScrollBounceEffectDecoratorBase implements IOverScrollDecor, View.OnTouchListener {
-
- public static final String TAG = "OverScrollDecor";
-
- public static final float DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD = 3f;
- public static final float DEFAULT_TOUCH_DRAG_MOVE_RATIO_BCK = 1f;
- public static final float DEFAULT_DECELERATE_FACTOR = -2f;
-
- protected static final int MAX_BOUNCE_BACK_DURATION_MS = 800;
- protected static final int MIN_BOUNCE_BACK_DURATION_MS = 200;
-
- protected final OverScrollStartAttributes mStartAttr = new OverScrollStartAttributes();
- protected final IOverScrollDecoratorAdapter mViewAdapter;
-
- protected final IdleState mIdleState;
- protected final OverScrollingState mOverScrollingState;
- protected final BounceBackState mBounceBackState;
- protected IDecoratorState mCurrentState;
-
- protected IOverScrollStateListener mStateListener = new OverScrollStateListenerStub();
- protected IOverScrollUpdateListener mUpdateListener = new OverScrollUpdateListenerStub();
-
- /**
- * When in over-scroll mode, keep track of dragging velocity to provide a smooth slow-down
- * for the bounce-back effect.
- */
- protected float mVelocity;
-
- /**
- * Motion attributes: keeps data describing current motion event.
- *
Orientation agnostic: subclasses provide either horizontal or vertical
- * initialization of the agnostic attributes.
- */
- protected abstract static class MotionAttributes {
- public float mAbsOffset;
- public float mDeltaOffset;
- public boolean mDir; // True = 'forward', false = 'backwards'.
-
- protected abstract boolean init(View view, MotionEvent event);
- }
-
- protected static class OverScrollStartAttributes {
- protected int mPointerId;
- protected float mAbsOffset;
- protected boolean mDir; // True = 'forward', false = 'backwards'.
- }
-
- protected abstract static class AnimationAttributes {
- public Property mProperty;
- public float mAbsOffset;
- public float mMaxOffset;
-
- protected abstract void init(View view);
- }
-
- /**
- * Interface of decorator-state delegation classes. Defines states as handles of two fundamental
- * touch events: actual movement, up/cancel.
- */
- protected interface IDecoratorState {
-
- /**
- * Handle a motion (touch) event.
- *
- * @param event The event from onTouch.
- * @return Return value for onTouch.
- */
- boolean handleMoveTouchEvent(MotionEvent event);
-
- /**
- * Handle up / touch-cancel events.
- *
- * @param event The event from onTouch.
- * @return Return value for onTouch.
- */
- boolean handleUpOrCancelTouchEvent(MotionEvent event);
-
- /**
- * Handle a transition onto this state, as it becomes 'current' state.
- * @param fromState
- */
- void handleEntryTransition(IDecoratorState fromState);
-
- /**
- * The client-perspective ID of the state associated with this (internal) one. ID's
- * are as specified in {@link IOverScrollState}.
- *
- * @return The ID, e.g. {@link IOverScrollState#STATE_IDLE}.
- */
- int getStateId();
- }
-
- /**
- * Idle state: monitors move events, trying to figure out whether over-scrolling should be
- * initiated (i.e. when scrolled further when the view is at one of its displayable ends).
- *
When such is the case, it hands over control to the over-scrolling state.
- */
- protected class IdleState implements IDecoratorState {
-
- final MotionAttributes mMoveAttr;
-
- public IdleState() {
- mMoveAttr = createMotionAttributes();
- }
-
- @Override
- public int getStateId() {
- return STATE_IDLE;
- }
-
- @Override
- public boolean handleMoveTouchEvent(MotionEvent event) {
-
- final View view = mViewAdapter.getView();
- if (!mMoveAttr.init(view, event)) {
- return false;
- }
-
- // Has over-scrolling officially started?
- if ((mViewAdapter.isInAbsoluteStart() && mMoveAttr.mDir) ||
- (mViewAdapter.isInAbsoluteEnd() && !mMoveAttr.mDir)) {
-
- // Save initial over-scroll attributes for future reference.
- mStartAttr.mPointerId = event.getPointerId(0);
- mStartAttr.mAbsOffset = mMoveAttr.mAbsOffset;
- mStartAttr.mDir = mMoveAttr.mDir;
-
- issueStateTransition(mOverScrollingState);
- return mOverScrollingState.handleMoveTouchEvent(event);
- }
-
- return false;
- }
-
- @Override
- public boolean handleUpOrCancelTouchEvent(MotionEvent event) {
- return false;
- }
-
- @Override
- public void handleEntryTransition(IDecoratorState fromState) {
- mStateListener.onOverScrollStateChange(OverScrollBounceEffectDecoratorBase.this, fromState.getStateId(), this.getStateId());
- }
- }
-
- /**
- * Handles the actual over-scrolling: thus translating the view according to configuration
- * and user interactions, dynamically.
- *
- *
The state is exited - thus completing over-scroll handling, in one of two cases:
- *
When user lets go of the view, it transitions control to the bounce-back state.
- *
When user moves the view back onto a potential 'under-scroll' state, it abruptly
- * transitions control to the idle-state, so as to return touch-events management to the
- * normal over-scroll-less environment (thus preventing under-scrolling and potentially regaining
- * regular scrolling).
- */
- protected class OverScrollingState implements IDecoratorState {
-
- protected final float mTouchDragRatioFwd;
- protected final float mTouchDragRatioBck;
-
- final MotionAttributes mMoveAttr;
- int mCurrDragState;
-
- public OverScrollingState(float touchDragRatioFwd, float touchDragRatioBck) {
- mMoveAttr = createMotionAttributes();
- mTouchDragRatioFwd = touchDragRatioFwd;
- mTouchDragRatioBck = touchDragRatioBck;
- }
-
- @Override
- public int getStateId() {
- // This is really a single class that implements 2 states, so our ID depends on what
- // it was during the last invocation.
- return mCurrDragState;
- }
-
- @Override
- public boolean handleMoveTouchEvent(MotionEvent event) {
-
- // Switching 'pointers' (e.g. fingers) on-the-fly isn't supported -- abort over-scroll
- // smoothly using the default bounce-back animation in this case.
- if (mStartAttr.mPointerId != event.getPointerId(0)) {
- issueStateTransition(mBounceBackState);
- return true;
- }
-
- final View view = mViewAdapter.getView();
- if (!mMoveAttr.init(view, event)) {
- // Keep intercepting the touch event as long as we're still over-scrolling...
- return true;
- }
-
- float deltaOffset = mMoveAttr.mDeltaOffset / (mMoveAttr.mDir == mStartAttr.mDir ? mTouchDragRatioFwd : mTouchDragRatioBck);
- float newOffset = mMoveAttr.mAbsOffset + deltaOffset;
-
- // If moved in counter direction onto a potential under-scroll state -- don't. Instead, abort
- // over-scrolling abruptly, thus returning control to which-ever touch handlers there
- // are waiting (e.g. regular scroller handlers).
- if ( (mStartAttr.mDir && !mMoveAttr.mDir && (newOffset <= mStartAttr.mAbsOffset)) ||
- (!mStartAttr.mDir && mMoveAttr.mDir && (newOffset >= mStartAttr.mAbsOffset)) ) {
- translateViewAndEvent(view, mStartAttr.mAbsOffset, event);
- mUpdateListener.onOverScrollUpdate(OverScrollBounceEffectDecoratorBase.this, mCurrDragState, 0);
-
- issueStateTransition(mIdleState);
- return true;
- }
-
- if (view.getParent() != null) {
- view.getParent().requestDisallowInterceptTouchEvent(true);
- }
-
- long dt = event.getEventTime() - event.getHistoricalEventTime(0);
- if (dt > 0) { // Sometimes (though rarely) dt==0 cause originally timing is in nanos, but is presented in millis.
- mVelocity = deltaOffset / dt;
- }
-
- translateView(view, newOffset);
- mUpdateListener.onOverScrollUpdate(OverScrollBounceEffectDecoratorBase.this, mCurrDragState, newOffset);
-
- return true;
- }
-
- @Override
- public boolean handleUpOrCancelTouchEvent(MotionEvent event) {
- issueStateTransition(mBounceBackState);
- return false;
- }
-
- @Override
- public void handleEntryTransition(IDecoratorState fromState) {
- mCurrDragState = (mStartAttr.mDir ? STATE_DRAG_START_SIDE : STATE_DRAG_END_SIDE);
- mStateListener.onOverScrollStateChange(OverScrollBounceEffectDecoratorBase.this, fromState.getStateId(), this.getStateId());
- }
- }
-
- /**
- * When entered, starts the bounce-back animation.
- *
Upon animation completion, transitions control onto the idle state; Does so by
- * registering itself as an animation listener.
- *
In the meantime, blocks (intercepts) all touch events.
- */
- protected class BounceBackState implements IDecoratorState, Animator.AnimatorListener, ValueAnimator.AnimatorUpdateListener {
-
- protected final Interpolator mBounceBackInterpolator = new DecelerateInterpolator();
- protected final float mDecelerateFactor;
- protected final float mDoubleDecelerateFactor;
-
- protected final AnimationAttributes mAnimAttributes;
-
- public BounceBackState(float decelerateFactor) {
- mDecelerateFactor = decelerateFactor;
- mDoubleDecelerateFactor = 2f * decelerateFactor;
-
- mAnimAttributes = createAnimationAttributes();
- }
-
- @Override
- public int getStateId() {
- return STATE_BOUNCE_BACK;
- }
-
- @Override
- public void handleEntryTransition(IDecoratorState fromState) {
-
- mStateListener.onOverScrollStateChange(OverScrollBounceEffectDecoratorBase.this, fromState.getStateId(), this.getStateId());
-
- Animator bounceBackAnim = createAnimator();
- bounceBackAnim.addListener(this);
-
- bounceBackAnim.start();
- }
-
- @Override
- public boolean handleMoveTouchEvent(MotionEvent event) {
- // Flush all touches down the drain till animation is over.
- return true;
- }
-
- @Override
- public boolean handleUpOrCancelTouchEvent(MotionEvent event) {
- // Flush all touches down the drain till animation is over.
- return true;
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- issueStateTransition(mIdleState);
- }
-
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mUpdateListener.onOverScrollUpdate(OverScrollBounceEffectDecoratorBase.this, STATE_BOUNCE_BACK, (Float) animation.getAnimatedValue());
- }
-
- @Override public void onAnimationStart(Animator animation) {}
- @Override public void onAnimationCancel(Animator animation) {}
- @Override public void onAnimationRepeat(Animator animation) {}
-
- protected Animator createAnimator() {
-
- final View view = mViewAdapter.getView();
-
- mAnimAttributes.init(view);
-
- // Set up a low-duration slow-down animation IN the drag direction.
-
- // Exception: If wasn't dragging in 'forward' direction (or velocity=0 -- i.e. not dragging at all),
- // skip slow-down anim directly to the bounce-back.
- if (mVelocity == 0f || (mVelocity < 0 && mStartAttr.mDir) || (mVelocity > 0 && !mStartAttr.mDir)) {
- return createBounceBackAnimator(mAnimAttributes.mAbsOffset);
- }
-
- // dt = (Vt - Vo) / a; Vt=0 ==> dt = -Vo / a
- float slowdownDuration = -mVelocity / mDecelerateFactor;
- slowdownDuration = (slowdownDuration < 0 ? 0 : slowdownDuration); // Happens in counter-direction dragging
-
- // dx = (Vt^2 - Vo^2) / 2a; Vt=0 ==> dx = -Vo^2 / 2a
- float slowdownDistance = -mVelocity * mVelocity / mDoubleDecelerateFactor;
- float slowdownEndOffset = mAnimAttributes.mAbsOffset + slowdownDistance;
-
- ObjectAnimator slowdownAnim = createSlowdownAnimator(view, (int) slowdownDuration, slowdownEndOffset);
-
- // Set up the bounce back animation, bringing the view back into the original, pre-overscroll position (translation=0).
-
- ObjectAnimator bounceBackAnim = createBounceBackAnimator(slowdownEndOffset);
-
- // Play the 2 animations as a sequence.
- AnimatorSet wholeAnim = new AnimatorSet();
- wholeAnim.playSequentially(slowdownAnim, bounceBackAnim);
- return wholeAnim;
- }
-
- protected ObjectAnimator createSlowdownAnimator(View view, int slowdownDuration, float slowdownEndOffset) {
- ObjectAnimator slowdownAnim = ObjectAnimator.ofFloat(view, mAnimAttributes.mProperty, slowdownEndOffset);
- slowdownAnim.setDuration(slowdownDuration);
- slowdownAnim.setInterpolator(mBounceBackInterpolator);
- slowdownAnim.addUpdateListener(this);
- return slowdownAnim;
- }
-
- protected ObjectAnimator createBounceBackAnimator(float startOffset) {
-
- final View view = mViewAdapter.getView();
-
- // Duration is proportional to the view's size.
- float bounceBackDuration = (Math.abs(startOffset) / mAnimAttributes.mMaxOffset) * MAX_BOUNCE_BACK_DURATION_MS;
- ObjectAnimator bounceBackAnim = ObjectAnimator.ofFloat(view, mAnimAttributes.mProperty, mStartAttr.mAbsOffset);
- bounceBackAnim.setDuration(Math.max((int) bounceBackDuration, MIN_BOUNCE_BACK_DURATION_MS));
- bounceBackAnim.setInterpolator(mBounceBackInterpolator);
- bounceBackAnim.addUpdateListener(this);
- return bounceBackAnim;
- }
- }
-
- public OverScrollBounceEffectDecoratorBase(IOverScrollDecoratorAdapter viewAdapter, float decelerateFactor, float touchDragRatioFwd, float touchDragRatioBck) {
- mViewAdapter = viewAdapter;
-
- mBounceBackState = new BounceBackState(decelerateFactor);
- mOverScrollingState = new OverScrollingState(touchDragRatioFwd, touchDragRatioBck);
- mIdleState = new IdleState();
-
- mCurrentState = mIdleState;
-
- attach();
- }
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_MOVE:
- return mCurrentState.handleMoveTouchEvent(event);
-
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- return mCurrentState.handleUpOrCancelTouchEvent(event);
- }
-
- return false;
- }
-
- @Override
- public void setOverScrollStateListener(IOverScrollStateListener listener) {
- mStateListener = (listener != null ? listener : new OverScrollStateListenerStub());
- }
-
- @Override
- public void setOverScrollUpdateListener(IOverScrollUpdateListener listener) {
- mUpdateListener = (listener != null ? listener : new OverScrollUpdateListenerStub());
- }
-
- @Override
- public int getCurrentState() {
- return mCurrentState.getStateId();
- }
-
- @Override
- public View getView() {
- return mViewAdapter.getView();
- }
-
- protected void issueStateTransition(IDecoratorState state) {
- IDecoratorState oldState = mCurrentState;
- mCurrentState = state;
- mCurrentState.handleEntryTransition(oldState);
- }
-
- protected void attach() {
- getView().setOnTouchListener(this);
- getView().setOverScrollMode(View.OVER_SCROLL_NEVER);
- }
-
- @Override
- public void detach() {
- if (mCurrentState != mIdleState) {
- Log.w(TAG, "Decorator detached while over-scroll is in effect. You might want to add a precondition of that getCurrentState()==STATE_IDLE, first.");
- }
- getView().setOnTouchListener(null);
- getView().setOverScrollMode(View.OVER_SCROLL_ALWAYS);
- }
-
- protected abstract MotionAttributes createMotionAttributes();
- protected abstract AnimationAttributes createAnimationAttributes();
- protected abstract void translateView(View view, float offset);
- protected abstract void translateViewAndEvent(View view, float offset, MotionEvent event);
-}
diff --git a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/OverScrollDecoratorHelper.java b/liboverscroll/src/main/java/me/everything/android/ui/overscroll/OverScrollDecoratorHelper.java
deleted file mode 100755
index 895102534..000000000
--- a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/OverScrollDecoratorHelper.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package me.everything.android.ui.overscroll;
-
-import android.view.View;
-import android.widget.ScrollView;
-import androidx.annotation.NonNull;
-import androidx.core.widget.NestedScrollView;
-import androidx.recyclerview.widget.RecyclerView;
-import me.everything.android.ui.overscroll.adapters.NestedScrollViewOverScrollDecorAdapter;
-import me.everything.android.ui.overscroll.adapters.RecyclerViewOverScrollDecorAdapter;
-import me.everything.android.ui.overscroll.adapters.ScrollViewOverScrollDecorAdapter;
-import me.everything.android.ui.overscroll.adapters.StaticOverScrollDecorAdapter;
-
-/**
- * @author amit
- */
-public class OverScrollDecoratorHelper {
-
- public static final int ORIENTATION_VERTICAL = 0;
-
- public static final int ORIENTATION_HORIZONTAL = 1;
-
- /**
- * Set up the over-scroll effect over a specified {@link RecyclerView} view.
- *
Only recycler-views using native Android layout managers (i.e. {@link LinearLayoutManager},
- * {@link GridLayoutManager} and {@link StaggeredGridLayoutManager}) are currently supported
- * by this convenience method.
- *
- * @param recyclerView The view.
- * @param orientation Either {@link #ORIENTATION_HORIZONTAL} or {@link #ORIENTATION_VERTICAL}.
- * @return The over-scroll effect 'decorator', enabling further effect configuration.
- */
- @NonNull
- public static IOverScrollDecor setUpOverScroll(@NonNull RecyclerView recyclerView, int orientation) {
- switch (orientation) {
- case ORIENTATION_HORIZONTAL:
- return new HorizontalOverScrollBounceEffectDecorator(
- new RecyclerViewOverScrollDecorAdapter(recyclerView));
- case ORIENTATION_VERTICAL:
- return new VerticalOverScrollBounceEffectDecorator(
- new RecyclerViewOverScrollDecorAdapter(recyclerView));
- default:
- throw new IllegalArgumentException("orientation");
- }
- }
-
- @NonNull
- public static IOverScrollDecor setUpOverScroll(@NonNull ScrollView scrollView) {
- return new VerticalOverScrollBounceEffectDecorator(new ScrollViewOverScrollDecorAdapter(scrollView));
- }
-
- @NonNull
- public static IOverScrollDecor setUpOverScroll(@NonNull NestedScrollView nestedScrollView) {
- return new VerticalOverScrollBounceEffectDecorator(
- new NestedScrollViewOverScrollDecorAdapter(nestedScrollView));
- }
-
- /**
- * Set up the over-scroll over a generic view, assumed to always be over-scroll ready (e.g.
- * a plain text field, image view).
- *
- * @param view The view.
- * @param orientation One of {@link #ORIENTATION_HORIZONTAL} or {@link #ORIENTATION_VERTICAL}.
- * @return The over-scroll effect 'decorator', enabling further effect configuration.
- */
- public static IOverScrollDecor setUpStaticOverScroll(View view, int orientation) {
- switch (orientation) {
- case ORIENTATION_HORIZONTAL:
- return new HorizontalOverScrollBounceEffectDecorator(new StaticOverScrollDecorAdapter(view));
-
- case ORIENTATION_VERTICAL:
- return new VerticalOverScrollBounceEffectDecorator(new StaticOverScrollDecorAdapter(view));
-
- default:
- throw new IllegalArgumentException("orientation");
- }
- }
-
-}
diff --git a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/VerticalOverScrollBounceEffectDecorator.java b/liboverscroll/src/main/java/me/everything/android/ui/overscroll/VerticalOverScrollBounceEffectDecorator.java
deleted file mode 100755
index bc6ce6200..000000000
--- a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/VerticalOverScrollBounceEffectDecorator.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package me.everything.android.ui.overscroll;
-
-import android.view.MotionEvent;
-import android.view.View;
-import me.everything.android.ui.overscroll.adapters.IOverScrollDecoratorAdapter;
-
-/**
- * A concrete implementation of {@link OverScrollBounceEffectDecoratorBase} for a vertical orientation.
- *
- * @author amit
- */
-public class VerticalOverScrollBounceEffectDecorator extends OverScrollBounceEffectDecoratorBase {
-
- protected static class MotionAttributesVertical extends MotionAttributes {
-
- public boolean init(View view, MotionEvent event) {
-
- // We must have history available to calc the dx. Normally it's there - if it isn't temporarily,
- // we declare the event 'invalid' and expect it in consequent events.
- if (event.getHistorySize() == 0) {
- return false;
- }
-
- // Allow for counter-orientation-direction operations (e.g. item swiping) to run fluently.
- final float dy = event.getY(0) - event.getHistoricalY(0, 0);
- final float dx = event.getX(0) - event.getHistoricalX(0, 0);
- if (Math.abs(dx) > Math.abs(dy)) {
- return false;
- }
-
- mAbsOffset = view.getTranslationY();
- mDeltaOffset = dy;
- mDir = mDeltaOffset > 0;
-
- return true;
- }
- }
-
- protected static class AnimationAttributesVertical extends AnimationAttributes {
-
- public AnimationAttributesVertical() {
- mProperty = View.TRANSLATION_Y;
- }
-
- @Override
- protected void init(View view) {
- mAbsOffset = view.getTranslationY();
- mMaxOffset = view.getHeight();
- }
- }
-
- /**
- * C'tor, creating the effect with default arguments:
- *
Touch-drag ratio in 'forward' direction will be set to DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD.
- *
Touch-drag ratio in 'backwards' direction will be set to DEFAULT_TOUCH_DRAG_MOVE_RATIO_BCK.
- *
Deceleration factor (for the bounce-back effect) will be set to DEFAULT_DECELERATE_FACTOR.
- *
- * @param viewAdapter The view's encapsulation.
- */
- public VerticalOverScrollBounceEffectDecorator(IOverScrollDecoratorAdapter viewAdapter) {
- this(viewAdapter, DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD, DEFAULT_TOUCH_DRAG_MOVE_RATIO_BCK,
- DEFAULT_DECELERATE_FACTOR);
- }
-
- /**
- * C'tor, creating the effect with explicit arguments.
- *
- * @param viewAdapter The view's encapsulation.
- * @param touchDragRatioFwd Ratio of touch distance to actual drag distance when in 'forward' direction.
- * @param touchDragRatioBck Ratio of touch distance to actual drag distance when in 'backward'
- * direction (opposite to initial one).
- * @param decelerateFactor Deceleration factor used when decelerating the motion to create the
- * bounce-back effect.
- */
- public VerticalOverScrollBounceEffectDecorator(IOverScrollDecoratorAdapter viewAdapter,
- float touchDragRatioFwd, float touchDragRatioBck, float decelerateFactor) {
- super(viewAdapter, decelerateFactor, touchDragRatioFwd, touchDragRatioBck);
- }
-
- @Override
- protected AnimationAttributes createAnimationAttributes() {
- return new AnimationAttributesVertical();
- }
-
- @Override
- protected MotionAttributes createMotionAttributes() {
- return new MotionAttributesVertical();
- }
-
- @Override
- protected void translateView(View view, float offset) {
- view.setTranslationY(offset);
- }
-
- @Override
- protected void translateViewAndEvent(View view, float offset, MotionEvent event) {
- view.setTranslationY(offset);
- event.offsetLocation(offset - event.getY(0), 0f);
- }
-}
diff --git a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/AbsListViewOverScrollDecorAdapter.java b/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/AbsListViewOverScrollDecorAdapter.java
deleted file mode 100755
index 9437fd711..000000000
--- a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/AbsListViewOverScrollDecorAdapter.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package me.everything.android.ui.overscroll.adapters;
-
-import android.view.View;
-import android.widget.AbsListView;
-
-import me.everything.android.ui.overscroll.HorizontalOverScrollBounceEffectDecorator;
-import me.everything.android.ui.overscroll.VerticalOverScrollBounceEffectDecorator;
-
-/**
- * An adapter to enable over-scrolling over object of {@link AbsListView}, namely {@link
- * android.widget.ListView} and it's extensions, and {@link android.widget.GridView}.
- *
- * @author amit
- *
- * @see HorizontalOverScrollBounceEffectDecorator
- * @see VerticalOverScrollBounceEffectDecorator
- */
-public class AbsListViewOverScrollDecorAdapter implements IOverScrollDecoratorAdapter {
-
- protected final AbsListView mView;
-
- public AbsListViewOverScrollDecorAdapter(AbsListView view) {
- mView = view;
- }
-
- @Override
- public View getView() {
- return mView;
- }
-
- @Override
- public boolean isInAbsoluteStart() {
- return mView.getChildCount() > 0 && !canScrollListUp();
- }
-
- @Override
- public boolean isInAbsoluteEnd() {
- return mView.getChildCount() > 0 && !canScrollListDown();
- }
-
- public boolean canScrollListUp() {
- // Ported from AbsListView#canScrollList() which isn't compatible to all API levels
- final int firstTop = mView.getChildAt(0).getTop();
- final int firstPosition = mView.getFirstVisiblePosition();
- return firstPosition > 0 || firstTop < mView.getListPaddingTop();
- }
-
- public boolean canScrollListDown() {
- // Ported from AbsListView#canScrollList() which isn't compatible to all API levels
- final int childCount = mView.getChildCount();
- final int itemsCount = mView.getCount();
- final int firstPosition = mView.getFirstVisiblePosition();
- final int lastPosition = firstPosition + childCount;
- final int lastBottom = mView.getChildAt(childCount - 1).getBottom();
- return lastPosition < itemsCount || lastBottom > mView.getHeight() - mView.getListPaddingBottom();
- }
-}
diff --git a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/HorizontalScrollViewOverScrollDecorAdapter.java b/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/HorizontalScrollViewOverScrollDecorAdapter.java
deleted file mode 100755
index 72c873c5f..000000000
--- a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/HorizontalScrollViewOverScrollDecorAdapter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package me.everything.android.ui.overscroll.adapters;
-
-import android.view.View;
-import android.widget.HorizontalScrollView;
-
-import me.everything.android.ui.overscroll.HorizontalOverScrollBounceEffectDecorator;
-import me.everything.android.ui.overscroll.VerticalOverScrollBounceEffectDecorator;
-
-/**
- * An adapter that enables over-scrolling support over a {@link HorizontalScrollView}.
- *
Seeing that {@link HorizontalScrollView} only supports horizontal scrolling, this adapter
- * should only be used with a {@link HorizontalOverScrollBounceEffectDecorator}.
- *
- * @author amit
- *
- * @see HorizontalOverScrollBounceEffectDecorator
- * @see VerticalOverScrollBounceEffectDecorator
- */
-public class HorizontalScrollViewOverScrollDecorAdapter implements IOverScrollDecoratorAdapter {
-
- protected final HorizontalScrollView mView;
-
- public HorizontalScrollViewOverScrollDecorAdapter(HorizontalScrollView view) {
- mView = view;
- }
-
- @Override
- public View getView() {
- return mView;
- }
-
- @Override
- public boolean isInAbsoluteStart() {
- return !mView.canScrollHorizontally(-1);
- }
-
- @Override
- public boolean isInAbsoluteEnd() {
- return !mView.canScrollHorizontally(1);
- }
-}
diff --git a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/IOverScrollDecoratorAdapter.java b/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/IOverScrollDecoratorAdapter.java
deleted file mode 100755
index 212156cb3..000000000
--- a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/IOverScrollDecoratorAdapter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package me.everything.android.ui.overscroll.adapters;
-
-import android.view.View;
-
-import me.everything.android.ui.overscroll.HorizontalOverScrollBounceEffectDecorator;
-
-/**
- * @author amitd
- *
- * @see HorizontalOverScrollBounceEffectDecorator
- */
-public interface IOverScrollDecoratorAdapter {
-
- View getView();
-
- /**
- * Is view in it's absolute start position - such that a negative over-scroll can potentially
- * be initiated. For example, in list-views, this is synonymous with the first item being
- * fully visible.
- *
- * @return Whether in absolute start position.
- */
- boolean isInAbsoluteStart();
-
- /**
- * Is view in it's absolute end position - such that an over-scroll can potentially
- * be initiated. For example, in list-views, this is synonymous with the last item being
- * fully visible.
- *
- * @return Whether in absolute end position.
- */
- boolean isInAbsoluteEnd();
-}
diff --git a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/NestedScrollViewOverScrollDecorAdapter.java b/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/NestedScrollViewOverScrollDecorAdapter.java
deleted file mode 100644
index 1d8e6b6c6..000000000
--- a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/NestedScrollViewOverScrollDecorAdapter.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2020 Hemanth Savarala.
- *
- * Licensed under the GNU General Public License v3
- *
- * This is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by
- * the Free Software Foundation either version 3 of the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- */
-
-package me.everything.android.ui.overscroll.adapters;
-
-import android.view.View;
-import androidx.annotation.NonNull;
-import androidx.core.widget.NestedScrollView;
-
-public class NestedScrollViewOverScrollDecorAdapter implements IOverScrollDecoratorAdapter {
-
- protected final NestedScrollView mView;
-
- public NestedScrollViewOverScrollDecorAdapter(@NonNull NestedScrollView view) {
- this.mView = view;
- }
-
- public View getView() {
- return this.mView;
- }
-
- public boolean isInAbsoluteEnd() {
- return !this.mView.canScrollVertically(1);
- }
-
- public boolean isInAbsoluteStart() {
- return !this.mView.canScrollVertically(-1);
- }
-}
\ No newline at end of file
diff --git a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/RecyclerViewOverScrollDecorAdapter.java b/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/RecyclerViewOverScrollDecorAdapter.java
deleted file mode 100755
index bd1f38b36..000000000
--- a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/RecyclerViewOverScrollDecorAdapter.java
+++ /dev/null
@@ -1,237 +0,0 @@
-package me.everything.android.ui.overscroll.adapters;
-
-import android.graphics.Canvas;
-import android.view.View;
-import androidx.recyclerview.widget.ItemTouchHelper;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.StaggeredGridLayoutManager;
-import java.util.List;
-import me.everything.android.ui.overscroll.HorizontalOverScrollBounceEffectDecorator;
-import me.everything.android.ui.overscroll.VerticalOverScrollBounceEffectDecorator;
-
-/**
- * @author amitd
- * @see HorizontalOverScrollBounceEffectDecorator
- * @see VerticalOverScrollBounceEffectDecorator
- */
-public class RecyclerViewOverScrollDecorAdapter implements IOverScrollDecoratorAdapter {
-
- private static class ItemTouchHelperCallbackWrapper extends ItemTouchHelper.Callback {
-
- final ItemTouchHelper.Callback mCallback;
-
- private ItemTouchHelperCallbackWrapper(ItemTouchHelper.Callback callback) {
- mCallback = callback;
- }
-
- @Override
- public boolean canDropOver(RecyclerView recyclerView, RecyclerView.ViewHolder current,
- RecyclerView.ViewHolder target) {
- return mCallback.canDropOver(recyclerView, current, target);
- }
-
- @Override
- public RecyclerView.ViewHolder chooseDropTarget(RecyclerView.ViewHolder selected,
- List dropTargets, int curX, int curY) {
- return mCallback.chooseDropTarget(selected, dropTargets, curX, curY);
- }
-
- @Override
- public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
- mCallback.clearView(recyclerView, viewHolder);
- }
-
- @Override
- public int convertToAbsoluteDirection(int flags, int layoutDirection) {
- return mCallback.convertToAbsoluteDirection(flags, layoutDirection);
- }
-
- @Override
- public long getAnimationDuration(RecyclerView recyclerView, int animationType, float animateDx,
- float animateDy) {
- return mCallback.getAnimationDuration(recyclerView, animationType, animateDx, animateDy);
- }
-
- @Override
- public int getBoundingBoxMargin() {
- return mCallback.getBoundingBoxMargin();
- }
-
- @Override
- public float getMoveThreshold(RecyclerView.ViewHolder viewHolder) {
- return mCallback.getMoveThreshold(viewHolder);
- }
-
- @Override
- public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
- return mCallback.getMovementFlags(recyclerView, viewHolder);
- }
-
- @Override
- public float getSwipeThreshold(RecyclerView.ViewHolder viewHolder) {
- return mCallback.getSwipeThreshold(viewHolder);
- }
-
- @Override
- public int interpolateOutOfBoundsScroll(RecyclerView recyclerView, int viewSize, int viewSizeOutOfBounds,
- int totalSize, long msSinceStartScroll) {
- return mCallback.interpolateOutOfBoundsScroll(recyclerView, viewSize, viewSizeOutOfBounds, totalSize,
- msSinceStartScroll);
- }
-
- @Override
- public boolean isItemViewSwipeEnabled() {
- return mCallback.isItemViewSwipeEnabled();
- }
-
- @Override
- public boolean isLongPressDragEnabled() {
- return mCallback.isLongPressDragEnabled();
- }
-
- @Override
- public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX,
- float dY, int actionState, boolean isCurrentlyActive) {
- mCallback.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
- }
-
- @Override
- public void onChildDrawOver(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX,
- float dY, int actionState, boolean isCurrentlyActive) {
- mCallback.onChildDrawOver(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
- }
-
- @Override
- public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
- RecyclerView.ViewHolder target) {
- return mCallback.onMove(recyclerView, viewHolder, target);
- }
-
- @Override
- public void onMoved(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, int fromPos,
- RecyclerView.ViewHolder target, int toPos, int x, int y) {
- mCallback.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y);
- }
-
- @Override
- public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
- mCallback.onSelectedChanged(viewHolder, actionState);
- }
-
- @Override
- public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
- mCallback.onSwiped(viewHolder, direction);
- }
- }
-
- protected class ImplHorizLayout implements Impl {
-
- @Override
- public boolean isInAbsoluteEnd() {
- return !mRecyclerView.canScrollHorizontally(1);
- }
-
- @Override
- public boolean isInAbsoluteStart() {
- return !mRecyclerView.canScrollHorizontally(-1);
- }
- }
-
- protected class ImplVerticalLayout implements Impl {
-
- @Override
- public boolean isInAbsoluteEnd() {
- return !mRecyclerView.canScrollVertically(1);
- }
-
- @Override
- public boolean isInAbsoluteStart() {
- return !mRecyclerView.canScrollVertically(-1);
- }
- }
-
- /**
- * A delegation of the adapter implementation of this view that should provide the processing
- * of {@link #isInAbsoluteStart()} and {@link #isInAbsoluteEnd()}. Essentially needed simply
- * because the implementation depends on the layout manager implementation being used.
- */
- protected interface Impl {
-
- boolean isInAbsoluteEnd();
-
- boolean isInAbsoluteStart();
- }
-
- protected final Impl mImpl;
-
- protected boolean mIsItemTouchInEffect = false;
-
- protected final RecyclerView mRecyclerView;
-
- public RecyclerViewOverScrollDecorAdapter(RecyclerView recyclerView) {
-
- mRecyclerView = recyclerView;
-
- final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
- if (layoutManager instanceof LinearLayoutManager ||
- layoutManager instanceof StaggeredGridLayoutManager) {
- final int orientation =
- (layoutManager instanceof LinearLayoutManager
- ? ((LinearLayoutManager) layoutManager).getOrientation()
- : ((StaggeredGridLayoutManager) layoutManager).getOrientation());
-
- if (orientation == LinearLayoutManager.HORIZONTAL) {
- mImpl = new ImplHorizLayout();
- } else {
- mImpl = new ImplVerticalLayout();
- }
- } else {
- throw new IllegalArgumentException(
- "Recycler views with custom layout managers are not supported by this adapter out of the box." +
- "Try implementing and providing an explicit 'impl' parameter to the other c'tors, or otherwise create a custom adapter subclass of your own.");
- }
- }
-
- public RecyclerViewOverScrollDecorAdapter(RecyclerView recyclerView, Impl impl) {
- mRecyclerView = recyclerView;
- mImpl = impl;
- }
-
- public RecyclerViewOverScrollDecorAdapter(RecyclerView recyclerView,
- ItemTouchHelper.Callback itemTouchHelperCallback) {
- this(recyclerView);
- setUpTouchHelperCallback(itemTouchHelperCallback);
- }
-
- public RecyclerViewOverScrollDecorAdapter(RecyclerView recyclerView, Impl impl,
- ItemTouchHelper.Callback itemTouchHelperCallback) {
- this(recyclerView, impl);
- setUpTouchHelperCallback(itemTouchHelperCallback);
- }
-
- @Override
- public View getView() {
- return mRecyclerView;
- }
-
- @Override
- public boolean isInAbsoluteEnd() {
- return !mIsItemTouchInEffect && mImpl.isInAbsoluteEnd();
- }
-
- @Override
- public boolean isInAbsoluteStart() {
- return !mIsItemTouchInEffect && mImpl.isInAbsoluteStart();
- }
-
- protected void setUpTouchHelperCallback(final ItemTouchHelper.Callback itemTouchHelperCallback) {
- new ItemTouchHelper(new ItemTouchHelperCallbackWrapper(itemTouchHelperCallback) {
- @Override
- public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
- mIsItemTouchInEffect = actionState != 0;
- super.onSelectedChanged(viewHolder, actionState);
- }
- }).attachToRecyclerView(mRecyclerView);
- }
-}
diff --git a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/ScrollViewOverScrollDecorAdapter.java b/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/ScrollViewOverScrollDecorAdapter.java
deleted file mode 100755
index 2c4c79cb3..000000000
--- a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/ScrollViewOverScrollDecorAdapter.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package me.everything.android.ui.overscroll.adapters;
-
-import android.view.View;
-import android.widget.ScrollView;
-
-import me.everything.android.ui.overscroll.HorizontalOverScrollBounceEffectDecorator;
-import me.everything.android.ui.overscroll.VerticalOverScrollBounceEffectDecorator;
-
-/**
- * An adapter that enables over-scrolling over a {@link ScrollView}.
- *
Seeing that {@link ScrollView} only supports vertical scrolling, this adapter
- * should only be used with a {@link VerticalOverScrollBounceEffectDecorator}. For horizontal
- * over-scrolling, use {@link HorizontalScrollViewOverScrollDecorAdapter} in conjunction with
- * a {@link android.widget.HorizontalScrollView}.
- *
- * @author amit
- *
- * @see HorizontalOverScrollBounceEffectDecorator
- * @see VerticalOverScrollBounceEffectDecorator
- */
-public class ScrollViewOverScrollDecorAdapter implements IOverScrollDecoratorAdapter {
-
- protected final ScrollView mView;
-
- public ScrollViewOverScrollDecorAdapter(ScrollView view) {
- mView = view;
- }
-
- @Override
- public View getView() {
- return mView;
- }
-
- @Override
- public boolean isInAbsoluteStart() {
- return !mView.canScrollVertically(-1);
- }
-
- @Override
- public boolean isInAbsoluteEnd() {
- return !mView.canScrollVertically(1);
- }
-}
diff --git a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/StaticOverScrollDecorAdapter.java b/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/StaticOverScrollDecorAdapter.java
deleted file mode 100755
index 95395f82d..000000000
--- a/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/StaticOverScrollDecorAdapter.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package me.everything.android.ui.overscroll.adapters;
-
-import android.view.View;
-
-import me.everything.android.ui.overscroll.HorizontalOverScrollBounceEffectDecorator;
-import me.everything.android.ui.overscroll.VerticalOverScrollBounceEffectDecorator;
-
-/**
- * A static adapter for views that are ALWAYS over-scroll-able (e.g. image view).
- *
- * @author amit
- *
- * @see HorizontalOverScrollBounceEffectDecorator
- * @see VerticalOverScrollBounceEffectDecorator
- */
-public class StaticOverScrollDecorAdapter implements IOverScrollDecoratorAdapter {
-
- protected final View mView;
-
- public StaticOverScrollDecorAdapter(View view) {
- mView = view;
- }
-
- @Override
- public View getView() {
- return mView;
- }
-
- @Override
- public boolean isInAbsoluteStart() {
- return true;
- }
-
- @Override
- public boolean isInAbsoluteEnd() {
- return true;
- }
-}
diff --git a/liboverscroll/src/test/java/me/everything/android/ui/overscroll/HorizontalOverScrollBounceEffectDecoratorTest.java b/liboverscroll/src/test/java/me/everything/android/ui/overscroll/HorizontalOverScrollBounceEffectDecoratorTest.java
deleted file mode 100755
index cddd6d21f..000000000
--- a/liboverscroll/src/test/java/me/everything/android/ui/overscroll/HorizontalOverScrollBounceEffectDecoratorTest.java
+++ /dev/null
@@ -1,640 +0,0 @@
-package me.everything.android.ui.overscroll;
-
-import android.view.MotionEvent;
-import android.view.View;
-
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-import me.everything.android.ui.overscroll.adapters.IOverScrollDecoratorAdapter;
-
-import static me.everything.android.ui.overscroll.HorizontalOverScrollBounceEffectDecorator.DEFAULT_DECELERATE_FACTOR;
-import static me.everything.android.ui.overscroll.HorizontalOverScrollBounceEffectDecorator.DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
-import static me.everything.android.ui.overscroll.IOverScrollState.*;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.*;
-import static org.mockito.Mockito.*;
-
-/**
- * @author amitd
- */
-@RunWith(RobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class HorizontalOverScrollBounceEffectDecoratorTest {
-
- View mView;
- IOverScrollDecoratorAdapter mViewAdapter;
- IOverScrollStateListener mStateListener;
- IOverScrollUpdateListener mUpdateListener;
-
- @Before
- public void setUp() throws Exception {
- mView = mock(View.class);
- mViewAdapter = mock(IOverScrollDecoratorAdapter.class);
- when(mViewAdapter.getView()).thenReturn(mView);
-
- mStateListener = mock(IOverScrollStateListener.class);
- mUpdateListener = mock(IOverScrollUpdateListener.class);
- }
-
- @Test
- public void detach_decoratorIsAttached_detachFromView() throws Exception {
-
- // Arrange
-
- HorizontalOverScrollBounceEffectDecorator uut = new HorizontalOverScrollBounceEffectDecorator(mViewAdapter);
-
- // Act
-
- uut.detach();
-
- // Assert
-
- verify(mView).setOnTouchListener(eq((View.OnTouchListener) null));
- verify(mView).setOverScrollMode(View.OVER_SCROLL_ALWAYS);
- }
-
- @Test
- public void detach_overScrollInEffect_detachFromView() throws Exception {
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);
-
- HorizontalOverScrollBounceEffectDecorator uut = getUUT();
- uut.onTouch(mView, createShortRightMoveEvent());
-
- // Act
-
- uut.detach();
-
- // Assert
-
- verify(mView).setOnTouchListener(eq((View.OnTouchListener) null));
- verify(mView).setOverScrollMode(View.OVER_SCROLL_ALWAYS);
- }
-
- /*
- * Move-action event
- */
-
- @Test
- public void onTouchMoveAction_notInViewEnds_ignoreTouchEvent() throws Exception {
-
- // Arrange
-
- MotionEvent event = createShortRightMoveEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(false);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);
-
- HorizontalOverScrollBounceEffectDecorator uut = getUUT();
-
- // Act
-
- boolean ret = uut.onTouch(mView, event);
-
- // Assert
-
- verify(mView, never()).setTranslationX(anyFloat());
- verify(mView, never()).setTranslationY(anyFloat());
- assertFalse(ret);
- assertEquals(STATE_IDLE, uut.getCurrentState());
-
- verify(mStateListener, never()).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- verify(mUpdateListener, never()).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- @Test
- public void onTouchMoveAction_dragRightInLeftEnd_overscrollRight() throws Exception {
-
- // Arrange
-
- MotionEvent event = createShortRightMoveEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);
-
- HorizontalOverScrollBounceEffectDecorator uut = getUUT();
-
- // Act
-
- final boolean ret = uut.onTouch(mView, event);
-
- // Assert
-
- final float expectedTransX = (event.getX() - event.getHistoricalX(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
- verify(mView).setTranslationX(expectedTransX);
- verify(mView, never()).setTranslationY(anyFloat());
- assertTrue(ret);
- assertEquals(STATE_DRAG_START_SIDE, uut.getCurrentState());
-
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_START_SIDE));
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(expectedTransX));
- }
-
- @Test
- public void onTouchMoveAction_dragLeftInRightEnd_overscrollLeft() throws Exception {
-
- // Arrange
-
- MotionEvent event = createShortLeftMoveEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(false);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true);
-
- HorizontalOverScrollBounceEffectDecorator uut = getUUT();
-
- // Act
-
- final boolean ret = uut.onTouch(mView, event);
-
- // Assert
-
- final float expectedTransX = (event.getX() - event.getHistoricalX(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
- verify(mView).setTranslationX(expectedTransX);
- verify(mView, never()).setTranslationY(anyFloat());
- assertTrue(ret);
- assertEquals(STATE_DRAG_END_SIDE, uut.getCurrentState());
-
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_END_SIDE));
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(expectedTransX));
- }
-
- @Test
- public void onTouchMoveAction_dragLeftInLeftEnd_ignoreTouchEvent() throws Exception {
-
- // Arrange
-
- MotionEvent event = createShortLeftMoveEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);
-
- HorizontalOverScrollBounceEffectDecorator uut = getUUT();
-
- // Act
-
- final boolean ret = uut.onTouch(mView, event);
-
- // Assert
-
- verify(mView, never()).setTranslationX(anyFloat());
- verify(mView, never()).setTranslationY(anyFloat());
- assertFalse(ret);
- assertEquals(STATE_IDLE, uut.getCurrentState());
-
- verify(mStateListener, never()).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- verify(mUpdateListener, never()).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- @Test
- public void onTouchMoveAction_dragRightInRightEnd_ignoreTouchEvent() throws Exception {
-
- // Arrange
-
- MotionEvent event = createShortRightMoveEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(false);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true);
-
- HorizontalOverScrollBounceEffectDecorator uut = getUUT();
-
- // Act
-
- boolean ret = uut.onTouch(mView, event);
-
- // Assert
-
- verify(mView, never()).setTranslationX(anyFloat());
- verify(mView, never()).setTranslationY(anyFloat());
- assertFalse(ret);
- assertEquals(STATE_IDLE, uut.getCurrentState());
-
- verify(mStateListener, never()).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- verify(mUpdateListener, never()).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- @Test
- public void onTouchMoveAction_2ndRightDragInLeftEnd_overscrollRightFurther() throws Exception {
-
- // Arrange
-
- // Bring UUT to a right-overscroll state
- MotionEvent event1 = createShortRightMoveEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);
-
- HorizontalOverScrollBounceEffectDecorator uut = getUUT();
- uut.onTouch(mView, event1);
- reset(mView);
-
- // Create 2nd right-drag event
- MotionEvent event2 = createLongRightMoveEvent();
-
- // Act
-
- final boolean ret = uut.onTouch(mView, event2);
-
- // Assert
-
- final float expectedTransX1 = (event1.getX() - event1.getHistoricalX(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
- final float expectedTransX2 = (event2.getX() - event2.getHistoricalX(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
- verify(mView).setTranslationX(expectedTransX2);
- verify(mView, never()).setTranslationY(anyFloat());
- assertTrue(ret);
- assertEquals(STATE_DRAG_START_SIDE, uut.getCurrentState());
-
- // State-change listener called only once?
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_START_SIDE));
- verify(mStateListener).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- // Update-listener called exactly twice?
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(expectedTransX1));
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(expectedTransX2));
- verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- @Test
- public void onTouchMoveAction_2ndLeftDragInRightEnd_overscrollLeftFurther() throws Exception {
-
- // Arrange
-
- // Bring UUT to a left-overscroll state
- MotionEvent event1 = createShortLeftMoveEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(false);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true);
-
- HorizontalOverScrollBounceEffectDecorator uut = getUUT();
- uut.onTouch(mView, event1);
- reset(mView);
-
- // Create 2nd left-drag event
- MotionEvent event2 = createLongLeftMoveEvent();
-
- // Act
-
- final boolean ret = uut.onTouch(mView, event2);
-
- // Assert
-
- final float expectedTransX1 = (event1.getX() - event1.getHistoricalX(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
- final float expectedTransX2 = (event2.getX() - event2.getHistoricalX(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
- verify(mView).setTranslationX(expectedTransX2);
- verify(mView, never()).setTranslationY(anyFloat());
- assertTrue(ret);
- assertEquals(STATE_DRAG_END_SIDE, uut.getCurrentState());
-
- // State-change listener called only once?
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_END_SIDE));
- verify(mStateListener).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- // Update-listener called exactly twice?
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(expectedTransX1));
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(expectedTransX2));
- verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- /**
- * When over-scroll has already started (to the right in this case) and suddenly the user changes
- * their mind and scrolls a bit in the other direction:
- *
We expect the touch to still be intercepted in that case, and the overscroll to
- * remain in effect.
- */
- @Test
- public void onTouchMoveAction_dragLeftWhenRightOverscolled_continueOverscrollingLeft() throws Exception {
-
- // Arrange
-
- // In left & right tests we use equal ratios to avoid the effect's under-scroll handling
- final float touchDragRatioFwd = 3f;
- final float touchDragRatioBck = 3f;
-
- // Bring UUT to a right-overscroll state
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);
-
- HorizontalOverScrollBounceEffectDecorator uut = getUUT(touchDragRatioFwd, touchDragRatioBck);
- MotionEvent eventMoveRight = createLongRightMoveEvent();
- uut.onTouch(mView, eventMoveRight);
- reset(mView);
- float startTransX = (eventMoveRight.getX() - eventMoveRight.getHistoricalX(0)) / touchDragRatioFwd;
- when(mView.getTranslationX()).thenReturn(startTransX);
-
- // Create the left-drag event
- MotionEvent eventMoveLeft = createShortLeftMoveEvent();
-
- // Act
-
- boolean ret = uut.onTouch(mView, eventMoveLeft);
-
- // Assert
-
- float expectedTransX = startTransX +
- (eventMoveLeft.getX() - eventMoveLeft.getHistoricalX(0)) / touchDragRatioBck;
- verify(mView).setTranslationX(expectedTransX);
- verify(mView, never()).setTranslationY(anyFloat());
- assertTrue(ret);
- assertEquals(STATE_DRAG_START_SIDE, uut.getCurrentState());
-
- // State-change listener called only once?
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_START_SIDE));
- verify(mStateListener).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- // Update-listener called exactly twice?
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(startTransX));
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(expectedTransX));
- verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- /**
- * When over-scroll has already started (to the left in this case) and suddenly the user changes
- * their mind and scrolls a bit in the other direction:
- *
We expect the touch to still be intercepted in that case, and the overscroll to remain in effect.
- */
- @Test
- public void onTouchMoveAction_dragRightWhenLeftOverscolled_continueOverscrollingRight() throws Exception {
-
- // Arrange
-
- // In left & right tests we use equal ratios to avoid the effect's under-scroll handling
- final float touchDragRatioFwd = 3f;
- final float touchDragRatioBck = 3f;
-
- // Bring UUT to a left-overscroll state
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(false);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true);
-
- HorizontalOverScrollBounceEffectDecorator uut = getUUT(touchDragRatioFwd, touchDragRatioBck);
- MotionEvent eventMoveLeft = createLongLeftMoveEvent();
- uut.onTouch(mView, eventMoveLeft);
- reset(mView);
-
- float startTransX = (eventMoveLeft.getX() - eventMoveLeft.getHistoricalX(0)) / touchDragRatioFwd;
- when(mView.getTranslationX()).thenReturn(startTransX);
-
- // Create the right-drag event
- MotionEvent eventMoveRight = createShortRightMoveEvent();
-
- // Act
-
- boolean ret = uut.onTouch(mView, eventMoveRight);
-
- // Assert
-
- float expectedTransX = startTransX + (eventMoveRight.getX() - eventMoveRight.getHistoricalX(0)) / touchDragRatioBck;
- verify(mView).setTranslationX(expectedTransX);
- verify(mView, never()).setTranslationY(anyFloat());
- assertTrue(ret);
- assertEquals(STATE_DRAG_END_SIDE, uut.getCurrentState());
-
- // State-change listener called only once?
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_END_SIDE));
- verify(mStateListener).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- // Update-listener called exactly twice?
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(startTransX));
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(expectedTransX));
- verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- @Test
- public void onTouchMoveAction_undragWhenRightOverscrolled_endOverscrolling() throws Exception {
-
- // Arrange
-
- // In left & right tests we use equal ratios to avoid the effect's under-scroll handling
- final float touchDragRatioFwd = 3f;
- final float touchDragRatioBck = 3f;
-
- // Bring UUT to a right-overscroll state
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);
-
- HorizontalOverScrollBounceEffectDecorator uut = getUUT(touchDragRatioFwd, touchDragRatioBck);
- MotionEvent eventMoveRight = createLongRightMoveEvent();
- uut.onTouch(mView, eventMoveRight);
- reset(mView);
- float startTransX = (eventMoveRight.getX() - eventMoveRight.getHistoricalX(0)) / touchDragRatioFwd;
- when(mView.getTranslationX()).thenReturn(startTransX);
-
- // Create the left-drag event
- MotionEvent eventMoveLeft = createLongLeftMoveEvent();
-
- // Act
-
- boolean ret = uut.onTouch(mView, eventMoveLeft);
-
- // Assert
-
- verify(mView).setTranslationX(0);
- verify(mView, never()).setTranslationY(anyFloat());
- assertTrue(ret);
- assertEquals(STATE_IDLE, uut.getCurrentState());
-
- // State-change listener invoked to say drag-on and drag-off (idle).
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_START_SIDE));
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_DRAG_START_SIDE), eq(STATE_IDLE));
- verify(mStateListener, times(2)).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- // Update-listener called exactly twice?
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(startTransX));
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(0f));
- verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- @Test
- public void onTouchMoveAction_undragWhenLeftOverscrolled_endOverscrolling() throws Exception {
-
- // Arrange
-
- // In left & right tests we use equal ratios to avoid the effect's under-scroll handling
- final float touchDragRatioFwd = 3f;
- final float touchDragRatioBck = 3f;
-
- // Bring UUT to a left-overscroll state
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(false);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true);
-
- HorizontalOverScrollBounceEffectDecorator uut = getUUT(touchDragRatioFwd, touchDragRatioBck);
- MotionEvent eventMoveLeft = createLongLeftMoveEvent();
- uut.onTouch(mView, eventMoveLeft);
- reset(mView);
- float startTransX = (eventMoveLeft.getX() - eventMoveLeft.getHistoricalX(0)) / touchDragRatioFwd;
- when(mView.getTranslationX()).thenReturn(startTransX);
-
- // Create the left-drag event
- MotionEvent eventMoveRight = createLongRightMoveEvent();
-
- // Act
-
- boolean ret = uut.onTouch(mView, eventMoveRight);
-
- // Assert
-
- verify(mView).setTranslationX(0);
- verify(mView, never()).setTranslationY(anyFloat());
- assertTrue(ret);
- assertEquals(STATE_IDLE, uut.getCurrentState());
-
- // State-change listener invoked to say drag-on and drag-off (idle).
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_END_SIDE));
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_DRAG_END_SIDE), eq(STATE_IDLE));
- verify(mStateListener, times(2)).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- // Update-listener called exactly twice?
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(startTransX));
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(0f));
- verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
-
- /*
- * Up action event
- */
-
- @Test
- public void onTouchUpAction_eventWhenNotOverscrolled_ignoreTouchEvent() throws Exception {
-
- // Arrange
-
- MotionEvent event = createDefaultUpActionEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true);
-
- HorizontalOverScrollBounceEffectDecorator uut = getUUT();
-
- // Act
-
- boolean ret = uut.onTouch(mView, event);
-
- // Assert
-
- verify(mView, never()).setTranslationX(anyFloat());
- verify(mView, never()).setTranslationY(anyFloat());
- assertFalse(ret);
- assertEquals(STATE_IDLE, uut.getCurrentState());
-
- verify(mStateListener, never()).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- verify(mUpdateListener, never()).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- /**
- * TODO: Make this work using a decent animation shadows / newer Robolectric
- * @throws Exception
- */
- @Ignore
- @Test
- public void onTouchUpAction_eventWhenLeftOverscrolling_smoothScrollBackToRightEnd() throws Exception {
-
- // Arrange
-
- // Bring UUT to a left-overscroll state
- MotionEvent moveEvent = createShortLeftMoveEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(false);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true);
-
- HorizontalOverScrollBounceEffectDecorator uut = getUUT();
- uut.onTouch(mView, moveEvent);
- reset(mView);
-
- // Make the view as though it's been moved by the move event
- float viewX = moveEvent.getX();
- when(mView.getTranslationX()).thenReturn(viewX);
-
- MotionEvent upEvent = createDefaultUpActionEvent();
-
- // Act
-
- boolean ret = uut.onTouch(mView, upEvent);
-
- // Assert
-
- assertTrue(ret);
-
- verify(mView, atLeastOnce()).setTranslationX(anyFloat());
- }
-
- protected MotionEvent createShortRightMoveEvent() {
- MotionEvent event = mock(MotionEvent.class);
- when(event.getAction()).thenReturn(MotionEvent.ACTION_MOVE);
- when(event.getX()).thenReturn(100f);
- when(event.getY()).thenReturn(200f);
- when(event.getX(0)).thenReturn(100f);
- when(event.getY(0)).thenReturn(200f);
- when(event.getHistorySize()).thenReturn(1);
- when(event.getHistoricalX(eq(0))).thenReturn(80f);
- when(event.getHistoricalY(eq(0))).thenReturn(190f);
- when(event.getHistoricalX(eq(0), eq(0))).thenReturn(80f);
- when(event.getHistoricalY(eq(0), eq(0))).thenReturn(190f);
- return event;
- }
-
- protected MotionEvent createLongRightMoveEvent() {
- MotionEvent event = mock(MotionEvent.class);
- when(event.getAction()).thenReturn(MotionEvent.ACTION_MOVE);
- when(event.getX()).thenReturn(150f);
- when(event.getY()).thenReturn(250f);
- when(event.getX(0)).thenReturn(150f);
- when(event.getY(0)).thenReturn(250f);
- when(event.getHistorySize()).thenReturn(1);
- when(event.getHistoricalX(eq(0))).thenReturn(100f);
- when(event.getHistoricalY(eq(0))).thenReturn(200f);
- when(event.getHistoricalX(eq(0), eq(0))).thenReturn(100f);
- when(event.getHistoricalY(eq(0), eq(0))).thenReturn(200f);
- return event;
- }
-
- protected MotionEvent createShortLeftMoveEvent() {
- MotionEvent event = mock(MotionEvent.class);
- when(event.getAction()).thenReturn(MotionEvent.ACTION_MOVE);
- when(event.getX()).thenReturn(100f);
- when(event.getY()).thenReturn(200f);
- when(event.getX(0)).thenReturn(100f);
- when(event.getY(0)).thenReturn(200f);
- when(event.getHistorySize()).thenReturn(1);
- when(event.getHistoricalX(eq(0))).thenReturn(120f);
- when(event.getHistoricalY(eq(0))).thenReturn(220f);
- when(event.getHistoricalX(eq(0), eq(0))).thenReturn(120f);
- when(event.getHistoricalY(eq(0), eq(0))).thenReturn(220f);
- return event;
- }
-
- protected MotionEvent createLongLeftMoveEvent() {
- MotionEvent event = mock(MotionEvent.class);
- when(event.getAction()).thenReturn(MotionEvent.ACTION_MOVE);
- when(event.getX()).thenReturn(50f);
- when(event.getY()).thenReturn(150f);
- when(event.getX(0)).thenReturn(50f);
- when(event.getY(0)).thenReturn(150f);
- when(event.getHistorySize()).thenReturn(1);
- when(event.getHistoricalX(eq(0))).thenReturn(100f);
- when(event.getHistoricalY(eq(0))).thenReturn(200f);
- when(event.getHistoricalX(eq(0), eq(0))).thenReturn(100f);
- when(event.getHistoricalY(eq(0), eq(0))).thenReturn(200f);
- return event;
- }
-
- protected MotionEvent createDefaultUpActionEvent() {
- MotionEvent event = mock(MotionEvent.class);
- when(event.getAction()).thenReturn(MotionEvent.ACTION_UP);
- return event;
- }
-
- protected HorizontalOverScrollBounceEffectDecorator getUUT() {
- HorizontalOverScrollBounceEffectDecorator uut = new HorizontalOverScrollBounceEffectDecorator(mViewAdapter);
- uut.setOverScrollStateListener(mStateListener);
- uut.setOverScrollUpdateListener(mUpdateListener);
- return uut;
- }
-
- protected HorizontalOverScrollBounceEffectDecorator getUUT(float touchDragRatioFwd, float touchDragRatioBck) {
- HorizontalOverScrollBounceEffectDecorator uut = new HorizontalOverScrollBounceEffectDecorator(mViewAdapter, touchDragRatioFwd, touchDragRatioBck, DEFAULT_DECELERATE_FACTOR);
- uut.setOverScrollStateListener(mStateListener);
- uut.setOverScrollUpdateListener(mUpdateListener);
- return uut;
- }
-}
diff --git a/liboverscroll/src/test/java/me/everything/android/ui/overscroll/VerticalOverScrollBounceEffectDecoratorTest.java b/liboverscroll/src/test/java/me/everything/android/ui/overscroll/VerticalOverScrollBounceEffectDecoratorTest.java
deleted file mode 100755
index b7c7ff381..000000000
--- a/liboverscroll/src/test/java/me/everything/android/ui/overscroll/VerticalOverScrollBounceEffectDecoratorTest.java
+++ /dev/null
@@ -1,600 +0,0 @@
-package me.everything.android.ui.overscroll;
-
-import android.view.MotionEvent;
-import android.view.View;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-import me.everything.android.ui.overscroll.adapters.IOverScrollDecoratorAdapter;
-
-import static me.everything.android.ui.overscroll.IOverScrollState.*;
-import static me.everything.android.ui.overscroll.VerticalOverScrollBounceEffectDecorator.DEFAULT_DECELERATE_FACTOR;
-import static me.everything.android.ui.overscroll.VerticalOverScrollBounceEffectDecorator.DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.*;
-import static org.mockito.Mockito.*;
-
-/**
- * @author amitd
- */
-@RunWith(RobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class VerticalOverScrollBounceEffectDecoratorTest {
-
- View mView;
- IOverScrollDecoratorAdapter mViewAdapter;
- IOverScrollStateListener mStateListener;
- IOverScrollUpdateListener mUpdateListener;
-
- @Before
- public void setUp() throws Exception {
- mView = mock(View.class);
- mViewAdapter = mock(IOverScrollDecoratorAdapter.class);
- when(mViewAdapter.getView()).thenReturn(mView);
-
- mStateListener = mock(IOverScrollStateListener.class);
- mUpdateListener = mock(IOverScrollUpdateListener.class);
- }
-
- @Test
- public void detach_decoratorIsAttached_detachFromView() throws Exception {
-
- // Arrange
-
- HorizontalOverScrollBounceEffectDecorator uut = new HorizontalOverScrollBounceEffectDecorator(mViewAdapter);
-
- // Act
-
- uut.detach();
-
- // Assert
-
- verify(mView).setOnTouchListener(eq((View.OnTouchListener) null));
- verify(mView).setOverScrollMode(View.OVER_SCROLL_ALWAYS);
- }
-
- @Test
- public void detach_overScrollInEffect_detachFromView() throws Exception {
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);
-
- VerticalOverScrollBounceEffectDecorator uut = getUUT();
- uut.onTouch(mView, createShortDownwardsMoveEvent());
-
- // Act
-
- uut.detach();
-
- // Assert
-
- verify(mView).setOnTouchListener(eq((View.OnTouchListener) null));
- verify(mView).setOverScrollMode(View.OVER_SCROLL_ALWAYS);
- }
-
- /*
- * Move-action event
- */
-
- @Test
- public void onTouchMoveAction_notInViewEnds_ignoreTouchEvent() throws Exception {
-
- // Arrange
-
- MotionEvent event = createShortDownwardsMoveEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(false);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);
-
- VerticalOverScrollBounceEffectDecorator uut = getUUT();
-
- // Act
-
- boolean ret = uut.onTouch(mView, event);
-
- // Assert
-
- verify(mView, never()).setTranslationX(anyFloat());
- verify(mView, never()).setTranslationY(anyFloat());
- assertFalse(ret);
- assertEquals(STATE_IDLE, uut.getCurrentState());
-
- verify(mStateListener, never()).onOverScrollStateChange(eq(uut),anyInt(), anyInt());
- verify(mUpdateListener, never()).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- @Test
- public void onTouchMoveAction_dragDownInUpperEnd_overscrollDownwards() throws Exception {
-
- // Arrange
-
- MotionEvent event = createShortDownwardsMoveEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);
-
- VerticalOverScrollBounceEffectDecorator uut = getUUT();
-
- // Act
-
- boolean ret = uut.onTouch(mView, event);
-
- // Assert
-
- float expectedTransY = (event.getY() - event.getHistoricalY(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
- verify(mView).setTranslationY(expectedTransY);
- verify(mView, never()).setTranslationX(anyFloat());
- assertTrue(ret);
- assertEquals(STATE_DRAG_START_SIDE, uut.getCurrentState());
-
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_START_SIDE));
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(expectedTransY));
- }
-
- @Test
- public void onTouchMoveAction_dragUpInBottomEnd_overscrollUpwards() throws Exception {
-
- // Arrange
-
- MotionEvent event = createShortUpwardsMoveEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(false);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true);
-
- VerticalOverScrollBounceEffectDecorator uut = getUUT();
-
- // Act
-
- boolean ret = uut.onTouch(mView, event);
-
- // Assert
-
- float expectedTransY = (event.getY() - event.getHistoricalY(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
- verify(mView).setTranslationY(expectedTransY);
- verify(mView, never()).setTranslationX(anyFloat());
- assertTrue(ret);
- assertEquals(STATE_DRAG_END_SIDE, uut.getCurrentState());
-
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_END_SIDE));
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(expectedTransY));
- }
-
- @Test
- public void onTouchMoveAction_dragUpInUpperEnd_ignoreTouchEvent() throws Exception {
-
- // Arrange
-
- MotionEvent event = createShortUpwardsMoveEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);
-
- VerticalOverScrollBounceEffectDecorator uut = getUUT();
-
- // Act
-
- boolean ret = uut.onTouch(mView, event);
-
- // Assert
-
- verify(mView, never()).setTranslationX(anyFloat());
- verify(mView, never()).setTranslationY(anyFloat());
- assertFalse(ret);
- assertEquals(STATE_IDLE, uut.getCurrentState());
-
- verify(mStateListener, never()).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- verify(mUpdateListener, never()).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- @Test
- public void onTouchMoveAction_dragDownInBottomEnd_ignoreTouchEvent() throws Exception {
-
- // Arrange
-
- MotionEvent event = createShortDownwardsMoveEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(false);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true);
-
- VerticalOverScrollBounceEffectDecorator uut = getUUT();
-
- // Act
-
- boolean ret = uut.onTouch(mView, event);
-
- // Assert
-
- verify(mView, never()).setTranslationX(anyFloat());
- verify(mView, never()).setTranslationY(anyFloat());
- assertFalse(ret);
- assertEquals(STATE_IDLE, uut.getCurrentState());
-
- verify(mStateListener, never()).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- verify(mUpdateListener, never()).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- @Test
- public void onTouchMoveAction_2ndDownDragInUpperEnd_overscrollDownwardsFurther() throws Exception {
-
- // Arrange
-
- // Bring UUT to a downwards-overscroll state
- MotionEvent event1 = createShortDownwardsMoveEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);
-
- VerticalOverScrollBounceEffectDecorator uut = getUUT();
- uut.onTouch(mView, event1);
- reset(mView);
-
- // Create 2nd downwards-drag event
- MotionEvent event2 = createLongDownwardsMoveEvent();
-
- // Act
-
- final boolean ret = uut.onTouch(mView, event2);
-
- // Assert
-
- final float expectedTransY1 = (event1.getY() - event1.getHistoricalY(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
- final float expectedTransY2 = (event2.getY() - event2.getHistoricalY(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
- verify(mView).setTranslationY(expectedTransY2);
- verify(mView, never()).setTranslationX(anyFloat());
- assertTrue(ret);
- assertEquals(STATE_DRAG_START_SIDE, uut.getCurrentState());
-
- // State-change listener called only once?
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_START_SIDE));
- verify(mStateListener).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- // Update-listener called exactly twice?
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(expectedTransY1));
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(expectedTransY2));
- verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- @Test
- public void onTouchMoveAction_2ndUpDragInBottomEnd_overscrollUpwardsFurther() throws Exception {
-
- // Arrange
-
- // Bring UUT to an upwards-overscroll state
- MotionEvent event1 = createShortUpwardsMoveEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(false);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true);
-
- VerticalOverScrollBounceEffectDecorator uut = getUUT();
- uut.onTouch(mView, event1);
- reset(mView);
-
- // Create 2nd upward-drag event
- MotionEvent event2 = createLongUpwardsMoveEvent();
-
- // Act
-
- final boolean ret = uut.onTouch(mView, event2);
-
- // Assert
-
- final float expectedTransY1 = (event1.getY() - event1.getHistoricalY(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
- final float expectedTransY2 = (event2.getY() - event2.getHistoricalY(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
- verify(mView).setTranslationY(expectedTransY2);
- verify(mView, never()).setTranslationX(anyFloat());
- assertTrue(ret);
- assertEquals(STATE_DRAG_END_SIDE, uut.getCurrentState());
-
- // State-change listener called only once?
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_END_SIDE));
- verify(mStateListener).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- // Update-listener called exactly twice?
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(expectedTransY1));
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(expectedTransY2));
- verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- /**
- * When over-scroll has already started (downwards in this case) and suddenly the user changes
- * their mind and scrolls a bit in the other direction:
- *
We expect the touch to still be intercepted in that case, and the overscroll to remain in effect.
- */
- @Test
- public void onTouchMoveAction_dragUpWhenDownOverscolled_continueOverscrollingUpwards() throws Exception {
-
- // Arrange
-
- // In down & up drag tests we use equal ratios to avoid the effect's under-scroll handling
- final float touchDragRatioFwd = 3f;
- final float touchDragRatioBck = 3f;
-
- // Bring UUT to a downwrads-overscroll state
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);
-
- VerticalOverScrollBounceEffectDecorator uut = getUUT(touchDragRatioFwd, touchDragRatioBck);
- MotionEvent eventMoveRight = createLongDownwardsMoveEvent();
- uut.onTouch(mView, eventMoveRight);
- reset(mView);
- float startTransY = (eventMoveRight.getY() - eventMoveRight.getHistoricalY(0)) / touchDragRatioFwd;
- when(mView.getTranslationY()).thenReturn(startTransY);
-
- // Create the up-drag event
- MotionEvent eventMoveUpwards = createShortUpwardsMoveEvent();
-
- // Act
-
- boolean ret = uut.onTouch(mView, eventMoveUpwards);
-
- // Assert
-
- float expectedTransY = startTransY +
- (eventMoveUpwards.getY() - eventMoveUpwards.getHistoricalY(0)) / touchDragRatioBck;
- verify(mView).setTranslationY(expectedTransY);
- verify(mView, never()).setTranslationX(anyFloat());
- assertTrue(ret);
- assertEquals(STATE_DRAG_START_SIDE, uut.getCurrentState());
-
- // State-change listener called only once?
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_START_SIDE));
- verify(mStateListener).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- // Update-listener called exactly twice?
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(startTransY));
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(expectedTransY));
- verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- /**
- * When over-scroll has already started (upwards in this case) and suddenly the user changes
- * their mind and scrolls a bit in the other direction:
- *
We expect the touch to still be intercepted in that case, and the overscroll to remain in effect.
- */
- @Test
- public void onTouchMoveAction_dragDownWhenUpOverscolled_continueOverscrollingDownwards() throws Exception {
-
- // Arrange
-
- // In up & down drag tests we use equal ratios to avoid the effect's under-scroll handling
- final float touchDragRatioFwd = 3f;
- final float touchDragRatioBck = 3f;
-
- // Bring UUT to an upwards-overscroll state
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(false);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true);
-
- VerticalOverScrollBounceEffectDecorator uut = getUUT(touchDragRatioFwd, touchDragRatioBck);
- MotionEvent eventMoveUp = createLongUpwardsMoveEvent();
- uut.onTouch(mView, eventMoveUp);
- reset(mView);
-
- float startTransY = (eventMoveUp.getY() - eventMoveUp.getHistoricalY(0)) / touchDragRatioFwd;
- when(mView.getTranslationY()).thenReturn(startTransY);
-
- // Create the down-drag event
- MotionEvent eventMoveDown = createShortDownwardsMoveEvent();
-
- // Act
-
- boolean ret = uut.onTouch(mView, eventMoveDown);
-
- // Assert
-
- float expectedTransY = startTransY + (eventMoveDown.getY() - eventMoveDown.getHistoricalY(0)) / touchDragRatioBck;
- verify(mView).setTranslationY(expectedTransY);
- verify(mView, never()).setTranslationX(anyFloat());
- assertTrue(ret);
- assertEquals(STATE_DRAG_END_SIDE, uut.getCurrentState());
-
- // State-change listener called only once?
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_END_SIDE));
- verify(mStateListener).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- // Update-listener called exactly twice?
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(startTransY));
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(expectedTransY));
- verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- @Test
- public void onTouchMoveAction_undragWhenDownOverscrolled_endOverscrolling() throws Exception {
-
- // Arrange
-
- // In left & right tests we use equal ratios to avoid the effect's under-scroll handling
- final float touchDragRatioFwd = 3f;
- final float touchDragRatioBck = 3f;
-
- // Bring UUT to a downwards-overscroll state
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);
-
- VerticalOverScrollBounceEffectDecorator uut = getUUT(touchDragRatioFwd, touchDragRatioBck);
- MotionEvent eventMoveDown = createLongDownwardsMoveEvent();
- uut.onTouch(mView, eventMoveDown);
- reset(mView);
- float startTransX = (eventMoveDown.getX() - eventMoveDown.getHistoricalX(0)) / touchDragRatioFwd;
- when(mView.getTranslationX()).thenReturn(startTransX);
-
- // Create the (negative) upwards-drag event
- MotionEvent eventMoveUp = createLongUpwardsMoveEvent();
-
- // Act
-
- boolean ret = uut.onTouch(mView, eventMoveUp);
-
- // Assert
-
- verify(mView, never()).setTranslationX(anyFloat());
- verify(mView).setTranslationY(0);
- assertTrue(ret);
- assertEquals(STATE_IDLE, uut.getCurrentState());
-
- // State-change listener invoked to say drag-on and drag-off (idle).
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_START_SIDE));
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_DRAG_START_SIDE), eq(STATE_IDLE));
- verify(mStateListener, times(2)).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- // Update-listener called exactly twice?
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(startTransX));
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(0f));
- verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- @Test
- public void onTouchMoveAction_undragWhenUpOverscrolled_endOverscrolling() throws Exception {
-
- // Arrange
-
- // In left & right tests we use equal ratios to avoid the effect's under-scroll handling
- final float touchDragRatioFwd = 3f;
- final float touchDragRatioBck = 3f;
-
- // Bring UUT to a left-overscroll state
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(false);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true);
-
- VerticalOverScrollBounceEffectDecorator uut = getUUT(touchDragRatioFwd, touchDragRatioBck);
- MotionEvent eventMoveUp = createLongUpwardsMoveEvent();
- uut.onTouch(mView, eventMoveUp);
- reset(mView);
- float startTransX = (eventMoveUp.getX() - eventMoveUp.getHistoricalX(0)) / touchDragRatioFwd;
- when(mView.getTranslationX()).thenReturn(startTransX);
-
- // Create the (negative) downwards-drag event
- MotionEvent eventMoveDown = createLongDownwardsMoveEvent();
-
- // Act
-
- boolean ret = uut.onTouch(mView, eventMoveDown);
-
- // Assert
-
- verify(mView, never()).setTranslationX(anyFloat());
- verify(mView).setTranslationY(0);
- assertTrue(ret);
- assertEquals(STATE_IDLE, uut.getCurrentState());
-
- // State-change listener invoked to say drag-on and drag-off (idle).
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_END_SIDE));
- verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_DRAG_END_SIDE), eq(STATE_IDLE));
- verify(mStateListener, times(2)).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- // Update-listener called exactly twice?
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(startTransX));
- verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(0f));
- verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- /*
- * Up action event
- */
-
- @Test
- public void onTouchUpAction_eventWhenNotOverscrolled_ignoreTouchEvent() throws Exception {
-
- // Arrange
-
- MotionEvent event = createDefaultUpActionEvent();
-
- when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
- when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true);
-
- VerticalOverScrollBounceEffectDecorator uut = getUUT();
-
- // Act
-
- boolean ret = uut.onTouch(mView, event);
-
- // Assert
-
- verify(mView, never()).setTranslationX(anyFloat());
- verify(mView, never()).setTranslationY(anyFloat());
- assertFalse(ret);
- assertEquals(STATE_IDLE, uut.getCurrentState());
-
- verify(mStateListener, never()).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
- verify(mUpdateListener, never()).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
- }
-
- protected MotionEvent createShortDownwardsMoveEvent() {
- MotionEvent event = mock(MotionEvent.class);
- when(event.getAction()).thenReturn(MotionEvent.ACTION_MOVE);
- when(event.getX()).thenReturn(200f);
- when(event.getY()).thenReturn(100f);
- when(event.getX(0)).thenReturn(200f);
- when(event.getY(0)).thenReturn(100f);
- when(event.getHistorySize()).thenReturn(1);
- when(event.getHistoricalX(eq(0))).thenReturn(190f);
- when(event.getHistoricalY(eq(0))).thenReturn(80f);
- when(event.getHistoricalX(eq(0), eq(0))).thenReturn(190f);
- when(event.getHistoricalY(eq(0), eq(0))).thenReturn(80f);
- return event;
- }
-
- protected MotionEvent createLongDownwardsMoveEvent() {
- MotionEvent event = mock(MotionEvent.class);
- when(event.getAction()).thenReturn(MotionEvent.ACTION_MOVE);
- when(event.getX()).thenReturn(250f);
- when(event.getY()).thenReturn(150f);
- when(event.getX(0)).thenReturn(250f);
- when(event.getY(0)).thenReturn(150f);
- when(event.getHistorySize()).thenReturn(1);
- when(event.getHistoricalX(eq(0))).thenReturn(200f);
- when(event.getHistoricalY(eq(0))).thenReturn(100f);
- when(event.getHistoricalX(eq(0), eq(0))).thenReturn(200f);
- when(event.getHistoricalY(eq(0), eq(0))).thenReturn(100f);
- return event;
- }
-
- protected MotionEvent createShortUpwardsMoveEvent() {
- MotionEvent event = mock(MotionEvent.class);
- when(event.getAction()).thenReturn(MotionEvent.ACTION_MOVE);
- when(event.getX()).thenReturn(200f);
- when(event.getY()).thenReturn(100f);
- when(event.getX(0)).thenReturn(200f);
- when(event.getY(0)).thenReturn(100f);
- when(event.getHistorySize()).thenReturn(1);
- when(event.getHistoricalX(eq(0))).thenReturn(220f);
- when(event.getHistoricalY(eq(0))).thenReturn(120f);
- when(event.getHistoricalX(eq(0), eq(0))).thenReturn(220f);
- when(event.getHistoricalY(eq(0), eq(0))).thenReturn(120f);
- return event;
- }
-
- protected MotionEvent createLongUpwardsMoveEvent() {
- MotionEvent event = mock(MotionEvent.class);
- when(event.getAction()).thenReturn(MotionEvent.ACTION_MOVE);
- when(event.getX()).thenReturn(200f);
- when(event.getY()).thenReturn(100f);
- when(event.getX(0)).thenReturn(200f);
- when(event.getY(0)).thenReturn(100f);
- when(event.getHistorySize()).thenReturn(1);
- when(event.getHistoricalX(eq(0))).thenReturn(250f);
- when(event.getHistoricalY(eq(0))).thenReturn(150f);
- when(event.getHistoricalX(eq(0), eq(0))).thenReturn(250f);
- when(event.getHistoricalY(eq(0), eq(0))).thenReturn(150f);
- return event;
- }
-
- protected MotionEvent createDefaultUpActionEvent() {
- MotionEvent event = mock(MotionEvent.class);
- when(event.getAction()).thenReturn(MotionEvent.ACTION_UP);
- return event;
- }
-
- protected VerticalOverScrollBounceEffectDecorator getUUT() {
- VerticalOverScrollBounceEffectDecorator uut = new VerticalOverScrollBounceEffectDecorator(mViewAdapter);
- uut.setOverScrollStateListener(mStateListener);
- uut.setOverScrollUpdateListener(mUpdateListener);
- return uut;
- }
-
- protected VerticalOverScrollBounceEffectDecorator getUUT(float touchDragRatioFwd, float touchDragRatioBck) {
- VerticalOverScrollBounceEffectDecorator uut = new VerticalOverScrollBounceEffectDecorator(mViewAdapter, touchDragRatioFwd, touchDragRatioBck, DEFAULT_DECELERATE_FACTOR);
- uut.setOverScrollStateListener(mStateListener);
- uut.setOverScrollUpdateListener(mUpdateListener);
- return uut;
- }
-}
\ No newline at end of file