Fix overlap between main fragment and player bottom bar
This commit is contained in:
parent
fbbd90111d
commit
822adcac4a
|
@ -1,30 +1,24 @@
|
||||||
package audio.funkwhale.ffa.activities
|
package audio.funkwhale.ffa.activities
|
||||||
|
|
||||||
import android.animation.Animator
|
|
||||||
import android.animation.AnimatorListenerAdapter
|
|
||||||
import android.animation.ObjectAnimator
|
import android.animation.ObjectAnimator
|
||||||
|
import android.animation.ValueAnimator
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.DisplayMetrics
|
|
||||||
import android.view.Gravity
|
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.animation.AccelerateDecelerateInterpolator
|
import android.view.animation.AccelerateDecelerateInterpolator
|
||||||
import android.widget.SeekBar
|
|
||||||
import androidx.activity.addCallback
|
import androidx.activity.addCallback
|
||||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
|
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.content.res.AppCompatResources
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.appcompat.widget.PopupMenu
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.graphics.drawable.toDrawable
|
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.flowWithLifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.fragment.NavHostFragment
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
|
@ -33,54 +27,41 @@ import audio.funkwhale.ffa.R
|
||||||
import audio.funkwhale.ffa.databinding.ActivityMainBinding
|
import audio.funkwhale.ffa.databinding.ActivityMainBinding
|
||||||
import audio.funkwhale.ffa.fragments.AddToPlaylistDialog
|
import audio.funkwhale.ffa.fragments.AddToPlaylistDialog
|
||||||
import audio.funkwhale.ffa.fragments.BrowseFragmentDirections
|
import audio.funkwhale.ffa.fragments.BrowseFragmentDirections
|
||||||
import audio.funkwhale.ffa.fragments.LandscapeQueueFragment
|
|
||||||
import audio.funkwhale.ffa.fragments.NowPlayingFragment
|
import audio.funkwhale.ffa.fragments.NowPlayingFragment
|
||||||
import audio.funkwhale.ffa.fragments.QueueFragment
|
import audio.funkwhale.ffa.fragments.QueueFragment
|
||||||
import audio.funkwhale.ffa.fragments.TrackInfoDetailsFragment
|
|
||||||
import audio.funkwhale.ffa.model.Track
|
import audio.funkwhale.ffa.model.Track
|
||||||
import audio.funkwhale.ffa.playback.MediaControlsManager
|
import audio.funkwhale.ffa.playback.MediaControlsManager
|
||||||
import audio.funkwhale.ffa.playback.PinService
|
import audio.funkwhale.ffa.playback.PinService
|
||||||
import audio.funkwhale.ffa.playback.PlayerService
|
import audio.funkwhale.ffa.playback.PlayerService
|
||||||
import audio.funkwhale.ffa.repositories.FavoritedRepository
|
import audio.funkwhale.ffa.repositories.FavoritedRepository
|
||||||
import audio.funkwhale.ffa.repositories.FavoritesRepository
|
|
||||||
import audio.funkwhale.ffa.repositories.Repository
|
|
||||||
import audio.funkwhale.ffa.utils.AppContext
|
import audio.funkwhale.ffa.utils.AppContext
|
||||||
import audio.funkwhale.ffa.utils.Command
|
import audio.funkwhale.ffa.utils.Command
|
||||||
import audio.funkwhale.ffa.utils.CommandBus
|
import audio.funkwhale.ffa.utils.CommandBus
|
||||||
import audio.funkwhale.ffa.utils.CoverArt
|
|
||||||
import audio.funkwhale.ffa.utils.Event
|
import audio.funkwhale.ffa.utils.Event
|
||||||
import audio.funkwhale.ffa.utils.EventBus
|
import audio.funkwhale.ffa.utils.EventBus
|
||||||
import audio.funkwhale.ffa.utils.FFACache
|
|
||||||
import audio.funkwhale.ffa.utils.OAuth
|
import audio.funkwhale.ffa.utils.OAuth
|
||||||
import audio.funkwhale.ffa.utils.ProgressBus
|
|
||||||
import audio.funkwhale.ffa.utils.Settings
|
import audio.funkwhale.ffa.utils.Settings
|
||||||
import audio.funkwhale.ffa.utils.Userinfo
|
import audio.funkwhale.ffa.utils.Userinfo
|
||||||
import audio.funkwhale.ffa.utils.authorize
|
import audio.funkwhale.ffa.utils.authorize
|
||||||
import audio.funkwhale.ffa.utils.log
|
import audio.funkwhale.ffa.utils.log
|
||||||
import audio.funkwhale.ffa.utils.logError
|
import audio.funkwhale.ffa.utils.logError
|
||||||
import audio.funkwhale.ffa.utils.maybeNormalizeUrl
|
|
||||||
import audio.funkwhale.ffa.utils.mustNormalizeUrl
|
import audio.funkwhale.ffa.utils.mustNormalizeUrl
|
||||||
import audio.funkwhale.ffa.utils.onApi
|
import audio.funkwhale.ffa.utils.onApi
|
||||||
import audio.funkwhale.ffa.utils.toast
|
import audio.funkwhale.ffa.utils.toast
|
||||||
import audio.funkwhale.ffa.utils.untilNetwork
|
|
||||||
import audio.funkwhale.ffa.views.DisableableFrameLayout
|
|
||||||
import com.github.kittinunf.fuel.Fuel
|
import com.github.kittinunf.fuel.Fuel
|
||||||
import com.github.kittinunf.fuel.coroutines.awaitStringResponse
|
import com.github.kittinunf.fuel.coroutines.awaitStringResponse
|
||||||
import com.google.android.exoplayer2.Player
|
|
||||||
import com.google.android.exoplayer2.offline.DownloadService
|
import com.google.android.exoplayer2.offline.DownloadService
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_COLLAPSED
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
|
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.preference.PowerPreference
|
import com.preference.PowerPreference
|
||||||
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation
|
|
||||||
import kotlinx.coroutines.Dispatchers.Default
|
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
|
import kotlinx.coroutines.flow.collect
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import org.koin.java.KoinJavaComponent.inject
|
import org.koin.java.KoinJavaComponent.inject
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
enum class ResultCode(val code: Int) {
|
enum class ResultCode(val code: Int) {
|
||||||
LOGOUT(1001)
|
LOGOUT(1001)
|
||||||
|
@ -102,6 +83,32 @@ class MainActivity : AppCompatActivity() {
|
||||||
AppContext.init(this)
|
AppContext.init(this)
|
||||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||||
|
|
||||||
|
binding.nowPlayingBottomSheet.hide()
|
||||||
|
binding.nowPlayingBottomSheet.addBottomSheetCallback(
|
||||||
|
object : BottomSheetBehavior.BottomSheetCallback() {
|
||||||
|
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
||||||
|
// Set the proper margin on the other child
|
||||||
|
val anim = if (newState == BottomSheetBehavior.STATE_HIDDEN) {
|
||||||
|
ValueAnimator.ofInt(binding.nowPlayingBottomSheet.peekHeight, 0)
|
||||||
|
} else {
|
||||||
|
ValueAnimator.ofInt(0, binding.nowPlayingBottomSheet.peekHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
anim.apply {
|
||||||
|
duration = 200
|
||||||
|
addUpdateListener {
|
||||||
|
val params =
|
||||||
|
binding.navHostFragmentWrapper.layoutParams as CoordinatorLayout.LayoutParams
|
||||||
|
params.setMargins(0, 0, 0, it.animatedValue as Int)
|
||||||
|
}
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
setSupportActionBar(binding.appbar)
|
setSupportActionBar(binding.appbar)
|
||||||
|
@ -125,10 +132,10 @@ class MainActivity : AppCompatActivity() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
binding.nowPlaying.getFragment<NowPlayingFragment>().apply {
|
binding.nowPlaying.getFragment<NowPlayingFragment>().apply {
|
||||||
favoritedRepository.update(requireContext(), lifecycleScope)
|
favoritedRepository.update(this@MainActivity, lifecycleScope)
|
||||||
|
|
||||||
startService(Intent(requireContext(), PlayerService::class.java))
|
startService(Intent(this@MainActivity, PlayerService::class.java))
|
||||||
DownloadService.start(requireContext(), PinService::class.java)
|
DownloadService.start(this@MainActivity, PinService::class.java)
|
||||||
|
|
||||||
CommandBus.send(Command.RefreshService)
|
CommandBus.send(Command.RefreshService)
|
||||||
|
|
||||||
|
@ -237,6 +244,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.nav_downloads -> startActivity(Intent(this, DownloadsActivity::class.java))
|
R.id.nav_downloads -> startActivity(Intent(this, DownloadsActivity::class.java))
|
||||||
R.id.settings -> resultLauncher.launch(Intent(this, SettingsActivity::class.java))
|
R.id.settings -> resultLauncher.launch(Intent(this, SettingsActivity::class.java))
|
||||||
}
|
}
|
||||||
|
@ -251,13 +259,13 @@ class MainActivity : AppCompatActivity() {
|
||||||
private fun watchEventBus() {
|
private fun watchEventBus() {
|
||||||
lifecycleScope.launch(Main) {
|
lifecycleScope.launch(Main) {
|
||||||
EventBus.get().collect { event ->
|
EventBus.get().collect { event ->
|
||||||
when(event) {
|
when (event) {
|
||||||
is Event.LogOut -> logout()
|
is Event.LogOut -> logout()
|
||||||
is Event.PlaybackError -> toast(event.message)
|
is Event.PlaybackError -> toast(event.message)
|
||||||
is Event.PlaybackStopped -> binding.nowPlayingBottomSheet.hide()
|
is Event.PlaybackStopped -> binding.nowPlayingBottomSheet.hide()
|
||||||
is Event.TrackFinished -> incrementListenCount(event.track)
|
is Event.TrackFinished -> incrementListenCount(event.track)
|
||||||
is Event.QueueChanged -> {
|
is Event.QueueChanged -> {
|
||||||
if(binding.nowPlayingBottomSheet.isHidden) binding.nowPlayingBottomSheet.show()
|
if (binding.nowPlayingBottomSheet.isHidden) binding.nowPlayingBottomSheet.show()
|
||||||
findViewById<View>(R.id.nav_queue)?.let { view ->
|
findViewById<View>(R.id.nav_queue)?.let { view ->
|
||||||
ObjectAnimator.ofFloat(view, View.ROTATION, 0f, 360f).let {
|
ObjectAnimator.ofFloat(view, View.ROTATION, 0f, 360f).let {
|
||||||
it.duration = 500
|
it.duration = 500
|
||||||
|
@ -266,71 +274,41 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lifecycleScope.launch(Main) {
|
lifecycleScope.launch(Main) {
|
||||||
CommandBus.get().collect { command ->
|
CommandBus.get().flowWithLifecycle(
|
||||||
if (command is Command.StartService) {
|
this@MainActivity.lifecycle, Lifecycle.State.RESUMED
|
||||||
Build.VERSION_CODES.O.onApi(
|
).collect { command ->
|
||||||
{
|
when(command) {
|
||||||
startForegroundService(
|
is Command.StartService -> startService(command.command)
|
||||||
Intent(
|
is Command.RefreshTrack -> refreshTrack(command.track)
|
||||||
this@MainActivity,
|
is Command.AddToPlaylist -> AddToPlaylistDialog.show(
|
||||||
PlayerService::class.java
|
layoutInflater,
|
||||||
).apply {
|
this@MainActivity,
|
||||||
putExtra(PlayerService.INITIAL_COMMAND_KEY, command.command.toString())
|
lifecycleScope,
|
||||||
}
|
command.tracks
|
||||||
)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
startService(
|
|
||||||
Intent(this@MainActivity, PlayerService::class.java).apply {
|
|
||||||
putExtra(PlayerService.INITIAL_COMMAND_KEY, command.command.toString())
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
} else if (command is Command.RefreshTrack) {
|
else -> {}
|
||||||
refreshCurrentTrack(command.track)
|
|
||||||
} else if (command is Command.AddToPlaylist) {
|
|
||||||
if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
|
|
||||||
AddToPlaylistDialog.show(
|
|
||||||
layoutInflater,
|
|
||||||
this@MainActivity,
|
|
||||||
lifecycleScope,
|
|
||||||
command.tracks
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshCurrentTrack(track: Track?) {
|
private fun startService(command: Command) {
|
||||||
track?.let {
|
val intent = Intent(this@MainActivity, PlayerService::class.java).apply {
|
||||||
if (binding.nowPlaying.visibility == View.GONE) {
|
putExtra(PlayerService.INITIAL_COMMAND_KEY, command.toString())
|
||||||
binding.nowPlaying.visibility = View.VISIBLE
|
}
|
||||||
binding.nowPlaying.alpha = 0f
|
ContextCompat.startForegroundService(this, intent)
|
||||||
|
}
|
||||||
|
|
||||||
binding.nowPlaying.animate()
|
private fun refreshTrack(track: Track?) {
|
||||||
.alpha(1.0f)
|
if (track != null) {
|
||||||
.setDuration(400)
|
binding.nowPlayingBottomSheet.show()
|
||||||
.setListener(null)
|
|
||||||
.start()
|
|
||||||
|
|
||||||
(binding.navHostFragment.layoutParams as? ViewGroup.MarginLayoutParams)?.let {
|
|
||||||
it.bottomMargin = it.bottomMargin * 2
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.landscapeQueue?.let { landscape_queue ->
|
|
||||||
(landscape_queue.layoutParams as? ViewGroup.MarginLayoutParams)?.let {
|
|
||||||
it.bottomMargin = it.bottomMargin * 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,27 +5,27 @@ import android.util.AttributeSet
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
import androidx.core.content.res.use
|
||||||
import audio.funkwhale.ffa.R
|
import audio.funkwhale.ffa.R
|
||||||
import audio.funkwhale.ffa.utils.BottomSheetIneractable
|
import audio.funkwhale.ffa.utils.BottomSheetIneractable
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
|
||||||
import com.google.android.material.card.MaterialCardView
|
import com.google.android.material.card.MaterialCardView
|
||||||
|
|
||||||
import androidx.core.content.res.use
|
|
||||||
|
|
||||||
|
class NowPlayingBottomSheet @JvmOverloads constructor(
|
||||||
class NowPlayingBottomSheet @JvmOverloads constructor (
|
|
||||||
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||||
) : MaterialCardView(context, attrs), BottomSheetIneractable {
|
) : MaterialCardView(context, attrs), BottomSheetIneractable {
|
||||||
val behavior = BottomSheetBehavior<NowPlayingBottomSheet>(context, attrs)
|
private val behavior = BottomSheetBehavior<NowPlayingBottomSheet>()
|
||||||
|
|
||||||
private val targetHeaderId: Int
|
private val targetHeaderId: Int
|
||||||
|
|
||||||
|
val peekHeight get() = behavior.peekHeight
|
||||||
|
|
||||||
init {
|
init {
|
||||||
targetHeaderId =context.theme.obtainStyledAttributes(
|
targetHeaderId = context.theme.obtainStyledAttributes(
|
||||||
attrs, R.styleable.NowPlaying, defStyleAttr, 0
|
attrs, R.styleable.NowPlaying, defStyleAttr, 0
|
||||||
).use {
|
).use {
|
||||||
it.getResourceId(R.styleable.NowPlaying_target_header, NO_ID)
|
it.getResourceId(R.styleable.NowPlaying_target_header, NO_ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,10 @@ class NowPlayingBottomSheet @JvmOverloads constructor (
|
||||||
} ?: hide()
|
} ?: hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addBottomSheetCallback(callback: BottomSheetCallback) {
|
||||||
|
behavior.addBottomSheetCallback(callback)
|
||||||
|
}
|
||||||
|
|
||||||
// Bottom sheet interactions
|
// Bottom sheet interactions
|
||||||
override val isHidden: Boolean get() = behavior.state == BottomSheetBehavior.STATE_HIDDEN
|
override val isHidden: Boolean get() = behavior.state == BottomSheetBehavior.STATE_HIDDEN
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,9 @@
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintVertical_weight="10">
|
app:layout_constraintVertical_weight="10">
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/nav_host_fragment_wrapper"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:baselineAligned="false"
|
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<androidx.fragment.app.FragmentContainerView
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
|
|
@ -6,28 +6,28 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:background="@color/surface"
|
|
||||||
app:layout_constraintVertical_weight="10"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
<androidx.fragment.app.FragmentContainerView
|
|
||||||
android:id="@+id/nav_host_fragment"
|
|
||||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
app:defaultNavHost="true"
|
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
|
||||||
app:navGraph="@navigation/main_nav"
|
|
||||||
tools:layout="@layout/fragment_artists" />
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
||||||
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintBottom_toTopOf="@id/appbar_wrapper">
|
app:layout_constraintBottom_toTopOf="@id/appbar_wrapper">
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/nav_host_fragment_wrapper"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
>
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/nav_host_fragment"
|
||||||
|
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:defaultNavHost="true"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||||
|
app:navGraph="@navigation/main_nav"
|
||||||
|
tools:layout="@layout/fragment_artists"
|
||||||
|
/>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
<audio.funkwhale.ffa.views.NowPlayingBottomSheet
|
<audio.funkwhale.ffa.views.NowPlayingBottomSheet
|
||||||
android:id="@+id/now_playing_bottom_sheet"
|
android:id="@+id/now_playing_bottom_sheet"
|
||||||
style="?attr/bottomSheetStyle"
|
style="?attr/bottomSheetStyle"
|
||||||
|
|
Loading…
Reference in New Issue