Stop play/pause animation on PlaybackFragment
Prevent the play/pause button on PlaybackFragment from prematurely animating on creation, like CompactPlaybackFragment.
This commit is contained in:
parent
7f1ebeb460
commit
e85bdd0643
4 changed files with 54 additions and 31 deletions
|
@ -22,16 +22,24 @@ import org.oxycblt.auxio.ui.toColor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [Fragment] that displays more information about the song, along with more media controls.
|
* A [Fragment] that displays more information about the song, along with more media controls.
|
||||||
*
|
|
||||||
* Instantiation is done by the navigation component, **do not instantiate this fragment manually.**
|
* Instantiation is done by the navigation component, **do not instantiate this fragment manually.**
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
||||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||||
private val binding: FragmentPlaybackBinding by memberBinding(FragmentPlaybackBinding::inflate) {
|
private val binding: FragmentPlaybackBinding by memberBinding(FragmentPlaybackBinding::inflate) {
|
||||||
|
// Marquee must be disabled on destroy to prevent memory leaks
|
||||||
binding.playbackSong.isSelected = false
|
binding.playbackSong.isSelected = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Colors/Icons
|
||||||
|
private val accentColor: ColorStateList by lazy {
|
||||||
|
ColorStateList.valueOf(accent.first.toColor(requireContext()))
|
||||||
|
}
|
||||||
|
private val controlColor: ColorStateList by lazy {
|
||||||
|
ColorStateList.valueOf(R.color.control_color.toColor(requireContext()))
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
|
@ -39,19 +47,8 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
||||||
): View {
|
): View {
|
||||||
// TODO: Add a swipe-to-next-track function using a ViewPager
|
// TODO: Add a swipe-to-next-track function using a ViewPager
|
||||||
|
|
||||||
// Create accents & icons to use
|
|
||||||
val accentColor = ColorStateList.valueOf(accent.first.toColor(requireContext()))
|
|
||||||
val controlColor = ColorStateList.valueOf(R.color.control_color.toColor(requireContext()))
|
|
||||||
val normalTextColor = binding.playbackDurationCurrent.currentTextColor
|
val normalTextColor = binding.playbackDurationCurrent.currentTextColor
|
||||||
|
|
||||||
val iconPauseToPlay = ContextCompat.getDrawable(
|
|
||||||
requireContext(), R.drawable.ic_pause_to_play
|
|
||||||
) as AnimatedVectorDrawable
|
|
||||||
|
|
||||||
val iconPlayToPause = ContextCompat.getDrawable(
|
|
||||||
requireContext(), R.drawable.ic_play_to_pause
|
|
||||||
) as AnimatedVectorDrawable
|
|
||||||
|
|
||||||
// Can't set the tint of a MenuItem below Android 8, so use icons instead.
|
// Can't set the tint of a MenuItem below Android 8, so use icons instead.
|
||||||
val iconQueueActive = ContextCompat.getDrawable(
|
val iconQueueActive = ContextCompat.getDrawable(
|
||||||
requireContext(), R.drawable.ic_queue
|
requireContext(), R.drawable.ic_queue
|
||||||
|
@ -85,7 +82,7 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
||||||
queueMenuItem = menu.findItem(R.id.action_queue)
|
queueMenuItem = menu.findItem(R.id.action_queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make ellipsizing of song title work
|
// Make marquee of song title work
|
||||||
binding.playbackSong.isSelected = true
|
binding.playbackSong.isSelected = true
|
||||||
|
|
||||||
binding.playbackSeekBar.setOnSeekBarChangeListener(this)
|
binding.playbackSeekBar.setOnSeekBarChangeListener(this)
|
||||||
|
@ -105,22 +102,6 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
playbackModel.isPlaying.observe(viewLifecycleOwner) {
|
|
||||||
if (it) {
|
|
||||||
// Animate the playing status and switch the button to the accent color
|
|
||||||
// if its playing, and back to a inactive gray if not.
|
|
||||||
binding.playbackPlayPause.setImageDrawable(iconPlayToPause)
|
|
||||||
iconPlayToPause.start()
|
|
||||||
|
|
||||||
binding.playbackPlayPause.backgroundTintList = accentColor
|
|
||||||
} else {
|
|
||||||
binding.playbackPlayPause.setImageDrawable(iconPauseToPlay)
|
|
||||||
iconPauseToPlay.start()
|
|
||||||
|
|
||||||
binding.playbackPlayPause.backgroundTintList = controlColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
playbackModel.isShuffling.observe(viewLifecycleOwner) {
|
playbackModel.isShuffling.observe(viewLifecycleOwner) {
|
||||||
// Highlight the shuffle button if Playback is shuffled, and revert it if not.
|
// Highlight the shuffle button if Playback is shuffled, and revert it if not.
|
||||||
if (it) {
|
if (it) {
|
||||||
|
@ -201,11 +182,53 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
playbackModel.disableAnimation()
|
||||||
|
|
||||||
|
val iconPauseToPlay = ContextCompat.getDrawable(
|
||||||
|
requireContext(), R.drawable.ic_pause_to_play
|
||||||
|
) as AnimatedVectorDrawable
|
||||||
|
|
||||||
|
val iconPlayToPause = ContextCompat.getDrawable(
|
||||||
|
requireContext(), R.drawable.ic_play_to_pause
|
||||||
|
) as AnimatedVectorDrawable
|
||||||
|
|
||||||
|
playbackModel.isPlaying.observe(viewLifecycleOwner) {
|
||||||
|
if (it) {
|
||||||
|
if (playbackModel.canAnimate) {
|
||||||
|
binding.playbackPlayPause.setImageDrawable(iconPlayToPause)
|
||||||
|
iconPlayToPause.start()
|
||||||
|
} else {
|
||||||
|
// Use a static icon the first time around to fix premature animation
|
||||||
|
// [Which looks weird]
|
||||||
|
binding.playbackPlayPause.setImageResource(R.drawable.ic_pause_large)
|
||||||
|
|
||||||
|
playbackModel.enableAnimation()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.playbackPlayPause.backgroundTintList = accentColor
|
||||||
|
} else {
|
||||||
|
if (playbackModel.canAnimate) {
|
||||||
|
binding.playbackPlayPause.setImageDrawable(iconPauseToPlay)
|
||||||
|
iconPauseToPlay.start()
|
||||||
|
} else {
|
||||||
|
binding.playbackPlayPause.setImageResource(R.drawable.ic_play_large)
|
||||||
|
|
||||||
|
playbackModel.enableAnimation()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.playbackPlayPause.backgroundTintList = controlColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- SEEK CALLBACKS ---
|
// --- SEEK CALLBACKS ---
|
||||||
|
|
||||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||||
if (fromUser) {
|
if (fromUser) {
|
||||||
// Only update the display if the change occured from a user
|
// Only update the display when seeking, as to have PlaybackService seek
|
||||||
|
// [causing possible buffering] on every movement is really odd.
|
||||||
playbackModel.updatePositionDisplay(progress)
|
playbackModel.updatePositionDisplay(progress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback {
|
||||||
|
|
||||||
val isPlaying: LiveData<Boolean> get() = mIsPlaying
|
val isPlaying: LiveData<Boolean> get() = mIsPlaying
|
||||||
val isShuffling: LiveData<Boolean> get() = mIsShuffling
|
val isShuffling: LiveData<Boolean> get() = mIsShuffling
|
||||||
/** The current repeat mode */
|
/** The current repeat mode, see [LoopMode] for more information */
|
||||||
val loopMode: LiveData<LoopMode> get() = mLoopMode
|
val loopMode: LiveData<LoopMode> get() = mLoopMode
|
||||||
val isSeeking: LiveData<Boolean> get() = mIsSeeking
|
val isSeeking: LiveData<Boolean> get() = mIsSeeking
|
||||||
val navToItem: LiveData<BaseModel?> get() = mNavToItem
|
val navToItem: LiveData<BaseModel?> get() = mNavToItem
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 322 KiB After Width: | Height: | Size: 322 KiB |
Binary file not shown.
Before Width: | Height: | Size: 398 KiB After Width: | Height: | Size: 391 KiB |
Loading…
Reference in a new issue