Added MD3 playing theme
This commit is contained in:
parent
ae13590204
commit
7debeb13c0
13 changed files with 771 additions and 0 deletions
|
@ -67,6 +67,7 @@
|
||||||
<h2>v5.8.3</h2>
|
<h2>v5.8.3</h2>
|
||||||
<h3>What's New</h3>
|
<h3>What's New</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
<li>Added a new MD3 now playing theme</li>
|
||||||
<li>Swipe down to dismiss Mini player</li>
|
<li>Swipe down to dismiss Mini player</li>
|
||||||
<li>Add support for Just Black with Material You</li>
|
<li>Add support for Just Black with Material You</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -49,6 +49,7 @@ import code.name.monkey.retromusic.fragments.player.flat.FlatPlayerFragment
|
||||||
import code.name.monkey.retromusic.fragments.player.full.FullPlayerFragment
|
import code.name.monkey.retromusic.fragments.player.full.FullPlayerFragment
|
||||||
import code.name.monkey.retromusic.fragments.player.gradient.GradientPlayerFragment
|
import code.name.monkey.retromusic.fragments.player.gradient.GradientPlayerFragment
|
||||||
import code.name.monkey.retromusic.fragments.player.material.MaterialFragment
|
import code.name.monkey.retromusic.fragments.player.material.MaterialFragment
|
||||||
|
import code.name.monkey.retromusic.fragments.player.md3.MD3PlayerFragment
|
||||||
import code.name.monkey.retromusic.fragments.player.normal.PlayerFragment
|
import code.name.monkey.retromusic.fragments.player.normal.PlayerFragment
|
||||||
import code.name.monkey.retromusic.fragments.player.peek.PeekPlayerFragment
|
import code.name.monkey.retromusic.fragments.player.peek.PeekPlayerFragment
|
||||||
import code.name.monkey.retromusic.fragments.player.plain.PlainPlayerFragment
|
import code.name.monkey.retromusic.fragments.player.plain.PlainPlayerFragment
|
||||||
|
@ -457,6 +458,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
|
||||||
Peek -> PeekPlayerFragment()
|
Peek -> PeekPlayerFragment()
|
||||||
Circle -> CirclePlayerFragment()
|
Circle -> CirclePlayerFragment()
|
||||||
Classic -> ClassicPlayerFragment()
|
Classic -> ClassicPlayerFragment()
|
||||||
|
MD3 -> MD3PlayerFragment()
|
||||||
else -> PlayerFragment()
|
else -> PlayerFragment()
|
||||||
} // must implement AbsPlayerFragment
|
} // must implement AbsPlayerFragment
|
||||||
supportFragmentManager.commit {
|
supportFragmentManager.commit {
|
||||||
|
|
|
@ -292,6 +292,9 @@ fun Context.accentColorVariant(): Int {
|
||||||
inline val @receiver:ColorInt Int.isColorLight
|
inline val @receiver:ColorInt Int.isColorLight
|
||||||
get() = ColorUtil.isColorLight(this)
|
get() = ColorUtil.isColorLight(this)
|
||||||
|
|
||||||
|
inline val @receiver:ColorInt Int.lightColor
|
||||||
|
get() = ColorUtil.withAlpha(this, 0.5F)
|
||||||
|
|
||||||
inline val @receiver:ColorInt Int.lighterColor
|
inline val @receiver:ColorInt Int.lighterColor
|
||||||
get() = ColorUtil.lightenColor(this)
|
get() = ColorUtil.lightenColor(this)
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import code.name.monkey.retromusic.util.RetroUtil
|
import code.name.monkey.retromusic.util.RetroUtil
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
|
import com.google.android.material.card.MaterialCardView
|
||||||
import dev.chrisbanes.insetter.applyInsetter
|
import dev.chrisbanes.insetter.applyInsetter
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
@ -163,6 +164,23 @@ fun BottomSheetBehavior<*>.peekHeightAnimate(value: Int): Animator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun MaterialCardView.animateRadius(cornerRadius: Float, pause: Boolean = true) {
|
||||||
|
ValueAnimator.ofFloat(radius, cornerRadius).apply {
|
||||||
|
addUpdateListener { radius = animatedValue as Float }
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
ValueAnimator.ofInt(measuredWidth, if (pause) (height * 1.5).toInt() else height).apply {
|
||||||
|
addUpdateListener {
|
||||||
|
updateLayoutParams<ViewGroup.LayoutParams> { width = animatedValue as Int }
|
||||||
|
}
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun MaterialCardView.animateToCircle() {
|
||||||
|
animateRadius(measuredHeight / 2F, pause = false)
|
||||||
|
}
|
||||||
|
|
||||||
fun View.focusAndShowKeyboard() {
|
fun View.focusAndShowKeyboard() {
|
||||||
/**
|
/**
|
||||||
* This is to be called when the window already has focus.
|
* This is to be called when the window already has focus.
|
||||||
|
|
|
@ -39,6 +39,7 @@ enum class NowPlayingScreen constructor(
|
||||||
Full(R.string.full, R.drawable.np_full, 2, AlbumCoverStyle.Full),
|
Full(R.string.full, R.drawable.np_full, 2, AlbumCoverStyle.Full),
|
||||||
Gradient(R.string.gradient, R.drawable.np_gradient, 17, AlbumCoverStyle.Full),
|
Gradient(R.string.gradient, R.drawable.np_gradient, 17, AlbumCoverStyle.Full),
|
||||||
Material(R.string.material, R.drawable.np_material, 11, AlbumCoverStyle.Normal),
|
Material(R.string.material, R.drawable.np_material, 11, AlbumCoverStyle.Normal),
|
||||||
|
MD3(R.string.md3, R.drawable.np_normal, 18, AlbumCoverStyle.Normal),
|
||||||
Normal(R.string.normal, R.drawable.np_normal, 0, AlbumCoverStyle.Normal),
|
Normal(R.string.normal, R.drawable.np_normal, 0, AlbumCoverStyle.Normal),
|
||||||
Peek(R.string.peek, R.drawable.np_peek, 14, AlbumCoverStyle.Normal),
|
Peek(R.string.peek, R.drawable.np_peek, 14, AlbumCoverStyle.Normal),
|
||||||
Plain(R.string.plain, R.drawable.np_plain, 3, AlbumCoverStyle.Normal),
|
Plain(R.string.plain, R.drawable.np_plain, 3, AlbumCoverStyle.Normal),
|
||||||
|
|
|
@ -0,0 +1,234 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Hemanth Savarla.
|
||||||
|
*
|
||||||
|
* 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.player.md3
|
||||||
|
|
||||||
|
import android.animation.ObjectAnimator
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import android.view.animation.DecelerateInterpolator
|
||||||
|
import android.view.animation.LinearInterpolator
|
||||||
|
import android.widget.ImageButton
|
||||||
|
import android.widget.SeekBar
|
||||||
|
import android.widget.TextView
|
||||||
|
import code.name.monkey.appthemehelper.ThemeStore
|
||||||
|
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.databinding.FragmentMd3PlayerPlaybackControlsBinding
|
||||||
|
import code.name.monkey.retromusic.extensions.*
|
||||||
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
|
||||||
|
import code.name.monkey.retromusic.fragments.base.goToAlbum
|
||||||
|
import code.name.monkey.retromusic.fragments.base.goToArtist
|
||||||
|
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.util.MusicUtil
|
||||||
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
|
||||||
|
class MD3PlaybackControlsFragment :
|
||||||
|
AbsPlayerControlsFragment(R.layout.fragment_md3_player_playback_controls) {
|
||||||
|
|
||||||
|
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
|
||||||
|
private var _binding: FragmentMd3PlayerPlaybackControlsBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
override val progressSlider: SeekBar
|
||||||
|
get() = binding.progressSlider
|
||||||
|
|
||||||
|
override val shuffleButton: ImageButton
|
||||||
|
get() = binding.shuffleButton
|
||||||
|
|
||||||
|
override val repeatButton: ImageButton
|
||||||
|
get() = binding.repeatButton
|
||||||
|
|
||||||
|
override val nextButton: ImageButton
|
||||||
|
get() = binding.nextButton
|
||||||
|
|
||||||
|
override val previousButton: ImageButton
|
||||||
|
get() = binding.previousButton
|
||||||
|
|
||||||
|
override val songTotalTime: TextView
|
||||||
|
get() = binding.songTotalTime
|
||||||
|
|
||||||
|
override val songCurrentProgress: TextView
|
||||||
|
get() = binding.songCurrentProgress
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
_binding = FragmentMd3PlayerPlaybackControlsBinding.bind(view)
|
||||||
|
setUpMusicControllers()
|
||||||
|
binding.playPauseButton.setOnClickListener {
|
||||||
|
if (MusicPlayerRemote.isPlaying) {
|
||||||
|
MusicPlayerRemote.pauseSong()
|
||||||
|
} else {
|
||||||
|
MusicPlayerRemote.resumePlaying()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.title.isSelected = true
|
||||||
|
binding.text.isSelected = true
|
||||||
|
binding.title.setOnClickListener {
|
||||||
|
goToAlbum(requireActivity())
|
||||||
|
}
|
||||||
|
binding.text.setOnClickListener {
|
||||||
|
goToArtist(requireActivity())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setColor(color: MediaNotificationProcessor) {
|
||||||
|
val colorBg = ATHUtil.resolveColor(requireContext(), android.R.attr.colorBackground)
|
||||||
|
if (ColorUtil.isColorLight(colorBg)) {
|
||||||
|
lastPlaybackControlsColor =
|
||||||
|
MaterialValueHelper.getSecondaryTextColor(requireContext(), true)
|
||||||
|
lastDisabledPlaybackControlsColor =
|
||||||
|
MaterialValueHelper.getSecondaryDisabledTextColor(requireContext(), true)
|
||||||
|
} else {
|
||||||
|
lastPlaybackControlsColor =
|
||||||
|
MaterialValueHelper.getPrimaryTextColor(requireContext(), false)
|
||||||
|
lastDisabledPlaybackControlsColor =
|
||||||
|
MaterialValueHelper.getPrimaryDisabledTextColor(requireContext(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
val colorFinal = if (PreferenceUtil.isAdaptiveColor) {
|
||||||
|
color.primaryTextColor
|
||||||
|
} else {
|
||||||
|
ThemeStore.accentColor(requireContext())
|
||||||
|
}.ripAlpha()
|
||||||
|
|
||||||
|
TintHelper.setTintAuto(
|
||||||
|
binding.playPauseButton,
|
||||||
|
MaterialValueHelper.getPrimaryTextColor(
|
||||||
|
requireContext(),
|
||||||
|
ColorUtil.isColorLight(colorFinal)
|
||||||
|
),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
binding.playPauseCard.setCardBackgroundColor(colorFinal)
|
||||||
|
|
||||||
|
binding.progressSlider.applyColor(colorFinal)
|
||||||
|
volumeFragment?.setTintable(colorFinal)
|
||||||
|
updateRepeatState()
|
||||||
|
updateShuffleState()
|
||||||
|
updatePrevNextColor()
|
||||||
|
updatePlayPauseDrawableState()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateSong() {
|
||||||
|
val song = MusicPlayerRemote.currentSong
|
||||||
|
binding.title.text = song.title
|
||||||
|
binding.text.text = song.artistName
|
||||||
|
|
||||||
|
if (PreferenceUtil.isSongInfo) {
|
||||||
|
binding.songInfo.text = getSongInfo(song)
|
||||||
|
binding.songInfo.show()
|
||||||
|
} else {
|
||||||
|
binding.songInfo.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
progressViewUpdateHelper.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
progressViewUpdateHelper.stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onServiceConnected() {
|
||||||
|
updatePlayPauseDrawableState()
|
||||||
|
updateRepeatState()
|
||||||
|
updateShuffleState()
|
||||||
|
updateSong()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPlayingMetaChanged() {
|
||||||
|
super.onPlayingMetaChanged()
|
||||||
|
updateSong()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPlayStateChanged() {
|
||||||
|
updatePlayPauseDrawableState()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRepeatModeChanged() {
|
||||||
|
updateRepeatState()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onShuffleModeChanged() {
|
||||||
|
updateShuffleState()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setUpPlayPauseFab() {
|
||||||
|
binding.playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
|
||||||
|
updatePlayPauseDrawableState()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updatePlayPauseDrawableState() {
|
||||||
|
if (MusicPlayerRemote.isPlaying) {
|
||||||
|
binding.playPauseButton.setImageResource(R.drawable.ic_pause_outline_small)
|
||||||
|
binding.playPauseCard.animateRadius(40F)
|
||||||
|
} else {
|
||||||
|
binding.playPauseButton.setImageResource(R.drawable.ic_play_arrow_outline_small)
|
||||||
|
binding.playPauseCard.animateToCircle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setUpMusicControllers() {
|
||||||
|
setUpPlayPauseFab()
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun show() {
|
||||||
|
binding.playPauseButton.animate()
|
||||||
|
.scaleX(1f)
|
||||||
|
.scaleY(1f)
|
||||||
|
.rotation(360f)
|
||||||
|
.setInterpolator(DecelerateInterpolator())
|
||||||
|
.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun hide() {
|
||||||
|
binding.playPauseButton.apply {
|
||||||
|
scaleX = 0f
|
||||||
|
scaleY = 0f
|
||||||
|
rotation = 0f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUpdateProgressViews(progress: Int, total: Int) {
|
||||||
|
binding.progressSlider.max = total
|
||||||
|
|
||||||
|
val animator = ObjectAnimator.ofInt(binding.progressSlider, "progress", progress)
|
||||||
|
animator.duration = SLIDER_ANIMATION_TIME
|
||||||
|
animator.interpolator = LinearInterpolator()
|
||||||
|
animator.start()
|
||||||
|
|
||||||
|
binding.songTotalTime.text = MusicUtil.getReadableDurationString(total.toLong())
|
||||||
|
binding.songCurrentProgress.text = MusicUtil.getReadableDurationString(progress.toLong())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Hemanth Savarla.
|
||||||
|
*
|
||||||
|
* 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.player.md3
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import androidx.appcompat.widget.Toolbar
|
||||||
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
|
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
|
||||||
|
import code.name.monkey.retromusic.R
|
||||||
|
import code.name.monkey.retromusic.databinding.FragmentMd3PlayerBinding
|
||||||
|
import code.name.monkey.retromusic.extensions.drawAboveSystemBars
|
||||||
|
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
|
||||||
|
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
|
||||||
|
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||||
|
import code.name.monkey.retromusic.model.Song
|
||||||
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
|
||||||
|
class MD3PlayerFragment : AbsPlayerFragment(R.layout.fragment_md3_player) {
|
||||||
|
|
||||||
|
private var lastColor: Int = 0
|
||||||
|
override val paletteColor: Int
|
||||||
|
get() = lastColor
|
||||||
|
|
||||||
|
private lateinit var controlsFragment: MD3PlaybackControlsFragment
|
||||||
|
|
||||||
|
private var _binding: FragmentMd3PlayerBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
override fun onShow() {
|
||||||
|
controlsFragment.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onHide() {
|
||||||
|
controlsFragment.hide()
|
||||||
|
onBackPressed()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBackPressed(): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toolbarIconColor(): Int {
|
||||||
|
return ATHUtil.resolveColor(requireContext(), R.attr.colorControlNormal)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onColorChanged(color: MediaNotificationProcessor) {
|
||||||
|
controlsFragment.setColor(color)
|
||||||
|
lastColor = color.backgroundColor
|
||||||
|
libraryViewModel.updateColor(color.backgroundColor)
|
||||||
|
|
||||||
|
ToolbarContentTintHelper.colorizeToolbar(
|
||||||
|
binding.playerToolbar,
|
||||||
|
ATHUtil.resolveColor(requireContext(), R.attr.colorControlNormal),
|
||||||
|
requireActivity()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toggleFavorite(song: Song) {
|
||||||
|
super.toggleFavorite(song)
|
||||||
|
if (song.id == MusicPlayerRemote.currentSong.id) {
|
||||||
|
updateIsFavorite()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFavoriteToggled() {
|
||||||
|
toggleFavorite(MusicPlayerRemote.currentSong)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
_binding = FragmentMd3PlayerBinding.bind(view)
|
||||||
|
setUpSubFragments()
|
||||||
|
setUpPlayerToolbar()
|
||||||
|
playerToolbar().drawAboveSystemBars()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setUpSubFragments() {
|
||||||
|
controlsFragment =
|
||||||
|
childFragmentManager.findFragmentById(R.id.playbackControlsFragment) as MD3PlaybackControlsFragment
|
||||||
|
val playerAlbumCoverFragment =
|
||||||
|
childFragmentManager.findFragmentById(R.id.playerAlbumCoverFragment) as PlayerAlbumCoverFragment
|
||||||
|
playerAlbumCoverFragment.setCallbacks(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setUpPlayerToolbar() {
|
||||||
|
binding.playerToolbar.inflateMenu(R.menu.menu_player)
|
||||||
|
//binding.playerToolbar.menu.setUpWithIcons()
|
||||||
|
binding.playerToolbar.setNavigationOnClickListener { requireActivity().onBackPressed() }
|
||||||
|
binding.playerToolbar.setOnMenuItemClickListener(this)
|
||||||
|
|
||||||
|
ToolbarContentTintHelper.colorizeToolbar(
|
||||||
|
binding.playerToolbar,
|
||||||
|
ATHUtil.resolveColor(requireContext(), R.attr.colorControlNormal),
|
||||||
|
requireActivity()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onServiceConnected() {
|
||||||
|
updateIsFavorite()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPlayingMetaChanged() {
|
||||||
|
updateIsFavorite()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun playerToolbar(): Toolbar {
|
||||||
|
return binding.playerToolbar
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun newInstance(): MD3PlayerFragment {
|
||||||
|
return MD3PlayerFragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
app/src/main/res/drawable/ic_pause_outline_small.xml
Normal file
16
app/src/main/res/drawable/ic_pause_outline_small.xml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:strokeWidth="1.5"
|
||||||
|
android:pathData="M6.5,5.5h3v13h-3z"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#000000" />
|
||||||
|
<path
|
||||||
|
android:strokeWidth="1.5"
|
||||||
|
android:pathData="M14.5,5.5h3v13h-3z"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#000000" />
|
||||||
|
</vector>
|
10
app/src/main/res/drawable/ic_play_arrow_outline_small.xml
Normal file
10
app/src/main/res/drawable/ic_play_arrow_outline_small.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M10,8.64L15.27,12 10,15.36V8.64M8,5v14l11,-7L8,5z" />
|
||||||
|
</vector>
|
83
app/src/main/res/layout-land/fragment_md3_player.xml
Normal file
83
app/src/main/res/layout-land/fragment_md3_player.xml
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/colorSurface" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/colorGradientBackground"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
|
||||||
|
<include layout="@layout/shadow_statusbar_toolbar" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<include layout="@layout/status_bar" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<code.name.monkey.retromusic.views.HeightFitSquareLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/playerAlbumCoverFragment"
|
||||||
|
android:name="code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:layout="@layout/fragment_album_cover" />
|
||||||
|
</code.name.monkey.retromusic.views.HeightFitSquareLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/controlsContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/playerToolbar"
|
||||||
|
style="@style/Toolbar"
|
||||||
|
android:navigationIcon="@drawable/ic_keyboard_arrow_down_black"
|
||||||
|
app:navigationIcon="@drawable/ic_keyboard_arrow_down_black" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/playbackControlsFragment"
|
||||||
|
android:name="code.name.monkey.retromusic.fragments.player.md3.MD3PlaybackControlsFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:layout_weight="1"
|
||||||
|
tools:layout="@layout/fragment_md3_player_playback_controls" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</FrameLayout>
|
58
app/src/main/res/layout/fragment_md3_player.xml
Normal file
58
app/src/main/res/layout/fragment_md3_player.xml
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/colorSurface"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true">
|
||||||
|
<include layout="@layout/shadow_statusbar_toolbar" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/statusBarContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<include layout="@layout/status_bar" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/playerAlbumCoverFragment"
|
||||||
|
android:name="code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHeight_percent="0.5"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/statusBarContainer" />
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/playbackControlsFragment"
|
||||||
|
android:name="code.name.monkey.retromusic.fragments.player.md3.MD3PlaybackControlsFragment"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/playerToolbar"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/playerAlbumCoverFragment"
|
||||||
|
tools:layout="@layout/fragment_md3_player_playback_controls" />
|
||||||
|
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/playerToolbar"
|
||||||
|
style="@style/Toolbar"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:navigationIcon="@drawable/ic_keyboard_arrow_down_black"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/playbackControlsFragment"
|
||||||
|
app:navigationIcon="@drawable/ic_keyboard_arrow_down_black" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,210 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:ignore="MissingPrefix">
|
||||||
|
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/songCurrentProgress"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:minWidth="40dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/progressSlider"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/progressSlider"
|
||||||
|
tools:ignore="RtlHardcoded,RtlSymmetry"
|
||||||
|
tools:text="@tools:sample/date/hhmmss" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatSeekBar
|
||||||
|
android:id="@+id/progressSlider"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:maxHeight="2dp"
|
||||||
|
android:paddingVertical="@dimen/seekbar_padding"
|
||||||
|
android:progressDrawable="@drawable/color_progress_seek"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/songTotalTime"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/songCurrentProgress"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:ignore="RtlHardcoded,UnusedAttribute"
|
||||||
|
tools:progress="20" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/songTotalTime"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:minWidth="40dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/progressSlider"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/progressSlider"
|
||||||
|
tools:ignore="RtlHardcoded,RtlSymmetry"
|
||||||
|
tools:text="@tools:sample/date/hhmmss" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:focusable="true"
|
||||||
|
android:freezesText="true"
|
||||||
|
android:gravity="center"
|
||||||
|
android:marqueeRepeatLimit="marquee_forever"
|
||||||
|
android:paddingHorizontal="16dp"
|
||||||
|
android:scrollHorizontally="true"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAppearance="@style/TextViewHeadline6"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/playPauseCard"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/progressSlider"
|
||||||
|
app:layout_constraintVertical_bias="0.3"
|
||||||
|
tools:text="@tools:sample/lorem/random" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:focusable="true"
|
||||||
|
android:focusableInTouchMode="true"
|
||||||
|
android:freezesText="true"
|
||||||
|
android:gravity="center"
|
||||||
|
android:marqueeRepeatLimit="marquee_forever"
|
||||||
|
android:paddingHorizontal="16dp"
|
||||||
|
android:paddingVertical="8dp"
|
||||||
|
android:scrollHorizontally="true"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAppearance="@style/TextViewBody1"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
app:layout_constrainedWidth="true"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/title"
|
||||||
|
tools:text="@tools:sample/full_names" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/songInfo"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:paddingHorizontal="16dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:textSize="12sp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/volumeFragmentContainer"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
tools:text="@tools:sample/full_names" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageButton
|
||||||
|
android:id="@+id/previousButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@null"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/playPauseCard"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/playPauseCard"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/playPauseCard"
|
||||||
|
app:srcCompat="@drawable/ic_skip_previous_outline"
|
||||||
|
tools:backgroundTint="?colorPrimaryDark"
|
||||||
|
tools:ignore="MissingPrefix"
|
||||||
|
tools:tint="@color/md_black_1000" />
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:id="@+id/playPauseCard"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:cardBackgroundColor="?colorSecondary"
|
||||||
|
app:cardCornerRadius="40dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/repeatButton"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/text"
|
||||||
|
tools:tint="@color/md_black_1000">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/playPauseButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/transparent"
|
||||||
|
android:padding="32dp"
|
||||||
|
app:srcCompat="@drawable/ic_pause_outline_small"
|
||||||
|
tools:tint="@color/md_black_1000" />
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageButton
|
||||||
|
android:id="@+id/nextButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@null"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/playPauseCard"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/playPauseCard"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/playPauseCard"
|
||||||
|
app:srcCompat="@drawable/ic_skip_next_outline"
|
||||||
|
tools:backgroundTint="?colorPrimaryDark"
|
||||||
|
tools:ignore="MissingPrefix"
|
||||||
|
tools:tint="@color/md_black_1000" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/shuffleButton"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:background="@null"
|
||||||
|
android:paddingVertical="16dp"
|
||||||
|
android:src="@drawable/ic_shuffle"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/songInfo"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/repeatButton"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/playPauseCard"
|
||||||
|
tools:ignore="MissingPrefix"
|
||||||
|
tools:tint="@color/md_black_1000" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/repeatButton"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:background="@null"
|
||||||
|
android:paddingVertical="16dp"
|
||||||
|
android:src="@drawable/ic_repeat"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/songInfo"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/shuffleButton"
|
||||||
|
app:layout_constraintHorizontal_chainStyle="spread_inside"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/playPauseCard"
|
||||||
|
tools:ignore="MissingPrefix"
|
||||||
|
tools:tint="@color/md_black_1000" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/volumeFragmentContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
tools:background="@color/md_red_400"
|
||||||
|
tools:layout_height="52dp" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -239,6 +239,7 @@
|
||||||
<string name="material">Material</string>
|
<string name="material">Material</string>
|
||||||
<string name="md_error_label">Error</string>
|
<string name="md_error_label">Error</string>
|
||||||
<string name="md_storage_perm_error">Permission error</string>
|
<string name="md_storage_perm_error">Permission error</string>
|
||||||
|
<string name="md3" translatable="false">MD3</string>
|
||||||
<string name="my_name">Name</string>
|
<string name="my_name">Name</string>
|
||||||
<string name="my_top_tracks">Most played</string>
|
<string name="my_top_tracks">Most played</string>
|
||||||
<string name="never">Never</string>
|
<string name="never">Never</string>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue