mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Minor session demo app improvements
Basically this change removes a bug that makes video playback stuck when a video is playing and the user taps the UMO notification to get to the player activity. - Use `launchMode="singleTop"` for `PlayerActivity` - Change session activity to a back stacked activity on service `onDestroy`. Using a back stacked activity `onDestroy()` will be useful once this demo app implements playback resumption. The rest of the changes are aesthetic: - clean up and optimize screen space usage in UI of `PlayerActivity` - changed some colors, paddings and spacings - adds a default artwork for the `PlayerView` PiperOrigin-RevId: 534152052
This commit is contained in:
parent
b9a4e614f7
commit
96a4ae7e40
@ -40,7 +40,9 @@
|
|||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".PlayerActivity"
|
android:name=".PlayerActivity"
|
||||||
android:exported="true"/>
|
android:exported="true"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:theme="@style/Theme.AppCompat.NoActionBar"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".PlayableFolderActivity"
|
android:name=".PlayableFolderActivity"
|
||||||
|
@ -17,7 +17,6 @@ package androidx.media3.demo.session
|
|||||||
|
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
@ -70,9 +69,9 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
findViewById<ExtendedFloatingActionButton>(R.id.open_player_floating_button)
|
findViewById<ExtendedFloatingActionButton>(R.id.open_player_floating_button)
|
||||||
.setOnClickListener {
|
.setOnClickListener {
|
||||||
// display the playing media items
|
// Start the session activity that shows the playback activity. The System UI uses the same
|
||||||
val intent = Intent(this, PlayerActivity::class.java)
|
// intent in the same way to start the activity from the notification.
|
||||||
startActivity(intent)
|
browser?.sessionActivity?.send()
|
||||||
}
|
}
|
||||||
|
|
||||||
onBackPressedDispatcher.addCallback(
|
onBackPressedDispatcher.addCallback(
|
||||||
|
@ -51,6 +51,7 @@ class PlayableFolderActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val MEDIA_ITEM_ID_KEY = "MEDIA_ITEM_ID_KEY"
|
private const val MEDIA_ITEM_ID_KEY = "MEDIA_ITEM_ID_KEY"
|
||||||
|
|
||||||
fun createIntent(context: Context, mediaItemID: String): Intent {
|
fun createIntent(context: Context, mediaItemID: String): Intent {
|
||||||
val intent = Intent(context, PlayableFolderActivity::class.java)
|
val intent = Intent(context, PlayableFolderActivity::class.java)
|
||||||
intent.putExtra(MEDIA_ITEM_ID_KEY, mediaItemID)
|
intent.putExtra(MEDIA_ITEM_ID_KEY, mediaItemID)
|
||||||
@ -77,8 +78,7 @@ class PlayableFolderActivity : AppCompatActivity() {
|
|||||||
browser.shuffleModeEnabled = false
|
browser.shuffleModeEnabled = false
|
||||||
browser.prepare()
|
browser.prepare()
|
||||||
browser.play()
|
browser.play()
|
||||||
val intent = Intent(this, PlayerActivity::class.java)
|
browser.sessionActivity?.send()
|
||||||
startActivity(intent)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,9 +104,9 @@ class PlayableFolderActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
findViewById<ExtendedFloatingActionButton>(R.id.open_player_floating_button)
|
findViewById<ExtendedFloatingActionButton>(R.id.open_player_floating_button)
|
||||||
.setOnClickListener {
|
.setOnClickListener {
|
||||||
// display the playing media items
|
// Start the session activity that shows the playback activity. The System UI uses the same
|
||||||
val intent = Intent(this, PlayerActivity::class.java)
|
// intent in the same way to start the activity from the notification.
|
||||||
startActivity(intent)
|
browser?.sessionActivity?.send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ package androidx.media3.demo.session
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
|
import android.app.PendingIntent
|
||||||
import android.app.PendingIntent.*
|
import android.app.PendingIntent.*
|
||||||
import android.app.TaskStackBuilder
|
import android.app.TaskStackBuilder
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@ -55,6 +56,7 @@ class PlaybackService : MediaLibraryService() {
|
|||||||
"android.media3.session.demo.SHUFFLE_OFF"
|
"android.media3.session.demo.SHUFFLE_OFF"
|
||||||
private const val NOTIFICATION_ID = 123
|
private const val NOTIFICATION_ID = 123
|
||||||
private const val CHANNEL_ID = "demo_session_notification_channel_id"
|
private const val CHANNEL_ID = "demo_session_notification_channel_id"
|
||||||
|
private val immutableFlag = if (Build.VERSION.SDK_INT >= 23) FLAG_IMMUTABLE else 0
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
@ -78,14 +80,15 @@ class PlaybackService : MediaLibraryService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onTaskRemoved(rootIntent: Intent?) {
|
override fun onTaskRemoved(rootIntent: Intent?) {
|
||||||
if (!player.playWhenReady) {
|
if (!player.playWhenReady || player.mediaItemCount == 0) {
|
||||||
stopSelf()
|
stopSelf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
player.release()
|
mediaLibrarySession.setSessionActivity(getBackStackedActivity())
|
||||||
mediaLibrarySession.release()
|
mediaLibrarySession.release()
|
||||||
|
player.release()
|
||||||
clearListener()
|
clearListener()
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
@ -235,18 +238,9 @@ class PlaybackService : MediaLibraryService() {
|
|||||||
.build()
|
.build()
|
||||||
MediaItemTree.initialize(assets)
|
MediaItemTree.initialize(assets)
|
||||||
|
|
||||||
val sessionActivityPendingIntent =
|
|
||||||
TaskStackBuilder.create(this).run {
|
|
||||||
addNextIntent(Intent(this@PlaybackService, MainActivity::class.java))
|
|
||||||
addNextIntent(Intent(this@PlaybackService, PlayerActivity::class.java))
|
|
||||||
|
|
||||||
val immutableFlag = if (Build.VERSION.SDK_INT >= 23) FLAG_IMMUTABLE else 0
|
|
||||||
getPendingIntent(0, immutableFlag or FLAG_UPDATE_CURRENT)
|
|
||||||
}
|
|
||||||
|
|
||||||
mediaLibrarySession =
|
mediaLibrarySession =
|
||||||
MediaLibrarySession.Builder(this, player, librarySessionCallback)
|
MediaLibrarySession.Builder(this, player, librarySessionCallback)
|
||||||
.setSessionActivity(sessionActivityPendingIntent)
|
.setSessionActivity(getSingleTopActivity())
|
||||||
.setBitmapLoader(CacheBitmapLoader(DataSourceBitmapLoader(/* context= */ this)))
|
.setBitmapLoader(CacheBitmapLoader(DataSourceBitmapLoader(/* context= */ this)))
|
||||||
.build()
|
.build()
|
||||||
if (!customLayout.isEmpty()) {
|
if (!customLayout.isEmpty()) {
|
||||||
@ -255,6 +249,23 @@ class PlaybackService : MediaLibraryService() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getSingleTopActivity(): PendingIntent {
|
||||||
|
return getActivity(
|
||||||
|
this,
|
||||||
|
0,
|
||||||
|
Intent(this, PlayerActivity::class.java),
|
||||||
|
immutableFlag or FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getBackStackedActivity(): PendingIntent {
|
||||||
|
return TaskStackBuilder.create(this).run {
|
||||||
|
addNextIntent(Intent(this@PlaybackService, MainActivity::class.java))
|
||||||
|
addNextIntent(Intent(this@PlaybackService, PlayerActivity::class.java))
|
||||||
|
getPendingIntent(0, immutableFlag or FLAG_UPDATE_CURRENT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getShuffleCommandButton(sessionCommand: SessionCommand): CommandButton {
|
private fun getShuffleCommandButton(sessionCommand: SessionCommand): CommandButton {
|
||||||
val isOn = sessionCommand.customAction == CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON
|
val isOn = sessionCommand.customAction == CUSTOM_COMMAND_TOGGLE_SHUFFLE_MODE_ON
|
||||||
return CommandButton.Builder()
|
return CommandButton.Builder()
|
||||||
|
@ -19,7 +19,6 @@ import android.content.ComponentName
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.MenuItem
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
@ -46,41 +45,33 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
get() = if (controllerFuture.isDone) controllerFuture.get() else null
|
get() = if (controllerFuture.isDone) controllerFuture.get() else null
|
||||||
|
|
||||||
private lateinit var playerView: PlayerView
|
private lateinit var playerView: PlayerView
|
||||||
private lateinit var mediaList: ListView
|
private lateinit var mediaItemListView: ListView
|
||||||
private lateinit var mediaListAdapter: PlayingMediaItemArrayAdapter
|
private lateinit var mediaItemListAdapter: MediaItemListAdapter
|
||||||
private val subItemMediaList: MutableList<MediaItem> = mutableListOf()
|
private val mediaItemList: MutableList<MediaItem> = mutableListOf()
|
||||||
|
private var lastMediaItemId: String? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_player)
|
setContentView(R.layout.activity_player)
|
||||||
playerView = findViewById(R.id.player_view)
|
playerView = findViewById(R.id.player_view)
|
||||||
|
|
||||||
mediaList = findViewById(R.id.current_playing_list)
|
mediaItemListView = findViewById(R.id.current_playing_list)
|
||||||
mediaListAdapter = PlayingMediaItemArrayAdapter(this, R.layout.folder_items, subItemMediaList)
|
mediaItemListAdapter = MediaItemListAdapter(this, R.layout.folder_items, mediaItemList)
|
||||||
mediaList.adapter = mediaListAdapter
|
mediaItemListView.adapter = mediaItemListAdapter
|
||||||
mediaList.setOnItemClickListener { _, _, position, _ ->
|
mediaItemListView.setOnItemClickListener { _, _, position, _ ->
|
||||||
run {
|
run {
|
||||||
val controller = this.controller ?: return@run
|
val controller = this.controller ?: return@run
|
||||||
controller.seekToDefaultPosition(/* windowIndex= */ position)
|
if (controller.currentMediaItemIndex == position) {
|
||||||
mediaListAdapter.notifyDataSetChanged()
|
controller.playWhenReady = !controller.playWhenReady
|
||||||
|
if (controller.playWhenReady) {
|
||||||
|
playerView.hideController()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
controller.seekToDefaultPosition(/* mediaItemIndex= */ position)
|
||||||
|
mediaItemListAdapter.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
findViewById<ImageView>(R.id.shuffle_switch).setOnClickListener {
|
|
||||||
val controller = this.controller ?: return@setOnClickListener
|
|
||||||
controller.shuffleModeEnabled = !controller.shuffleModeEnabled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
findViewById<ImageView>(R.id.repeat_switch).setOnClickListener {
|
|
||||||
val controller = this.controller ?: return@setOnClickListener
|
|
||||||
when (controller.repeatMode) {
|
|
||||||
Player.REPEAT_MODE_ALL -> controller.repeatMode = Player.REPEAT_MODE_OFF
|
|
||||||
Player.REPEAT_MODE_OFF -> controller.repeatMode = Player.REPEAT_MODE_ONE
|
|
||||||
Player.REPEAT_MODE_ONE -> controller.repeatMode = Player.REPEAT_MODE_ALL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
@ -94,14 +85,6 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
releaseController()
|
releaseController()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
if (item.itemId == android.R.id.home) {
|
|
||||||
onBackPressed()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initializeController() {
|
private fun initializeController() {
|
||||||
controllerFuture =
|
controllerFuture =
|
||||||
MediaController.Builder(
|
MediaController.Builder(
|
||||||
@ -123,8 +106,6 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
updateCurrentPlaylistUI()
|
updateCurrentPlaylistUI()
|
||||||
updateMediaMetadataUI(controller.mediaMetadata)
|
updateMediaMetadataUI(controller.mediaMetadata)
|
||||||
updateShuffleSwitchUI(controller.shuffleModeEnabled)
|
|
||||||
updateRepeatSwitchUI(controller.repeatMode)
|
|
||||||
playerView.setShowSubtitleButton(controller.currentTracks.isTypeSupported(TRACK_TYPE_TEXT))
|
playerView.setShowSubtitleButton(controller.currentTracks.isTypeSupported(TRACK_TYPE_TEXT))
|
||||||
|
|
||||||
controller.addListener(
|
controller.addListener(
|
||||||
@ -133,14 +114,6 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
updateMediaMetadataUI(mediaItem?.mediaMetadata ?: MediaMetadata.EMPTY)
|
updateMediaMetadataUI(mediaItem?.mediaMetadata ?: MediaMetadata.EMPTY)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {
|
|
||||||
updateShuffleSwitchUI(shuffleModeEnabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onRepeatModeChanged(repeatMode: Int) {
|
|
||||||
updateRepeatSwitchUI(repeatMode)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTracksChanged(tracks: Tracks) {
|
override fun onTracksChanged(tracks: Tracks) {
|
||||||
playerView.setShowSubtitleButton(tracks.isTypeSupported(TRACK_TYPE_TEXT))
|
playerView.setShowSubtitleButton(tracks.isTypeSupported(TRACK_TYPE_TEXT))
|
||||||
}
|
}
|
||||||
@ -148,48 +121,26 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateShuffleSwitchUI(shuffleModeEnabled: Boolean) {
|
|
||||||
val resId =
|
|
||||||
if (shuffleModeEnabled) R.drawable.exo_styled_controls_shuffle_on
|
|
||||||
else R.drawable.exo_styled_controls_shuffle_off
|
|
||||||
findViewById<ImageView>(R.id.shuffle_switch)
|
|
||||||
.setImageDrawable(ContextCompat.getDrawable(this, resId))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateRepeatSwitchUI(repeatMode: Int) {
|
|
||||||
val resId: Int =
|
|
||||||
when (repeatMode) {
|
|
||||||
Player.REPEAT_MODE_OFF -> R.drawable.exo_styled_controls_repeat_off
|
|
||||||
Player.REPEAT_MODE_ONE -> R.drawable.exo_styled_controls_repeat_one
|
|
||||||
Player.REPEAT_MODE_ALL -> R.drawable.exo_styled_controls_repeat_all
|
|
||||||
else -> R.drawable.exo_styled_controls_repeat_off
|
|
||||||
}
|
|
||||||
findViewById<ImageView>(R.id.repeat_switch)
|
|
||||||
.setImageDrawable(ContextCompat.getDrawable(this, resId))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateMediaMetadataUI(mediaMetadata: MediaMetadata) {
|
private fun updateMediaMetadataUI(mediaMetadata: MediaMetadata) {
|
||||||
val title: CharSequence = mediaMetadata.title ?: getString(R.string.no_item_prompt)
|
val title: CharSequence = mediaMetadata.title ?: "getString(R.string.no_item_prompt)"
|
||||||
|
|
||||||
findViewById<TextView>(R.id.video_title).text = title
|
findViewById<TextView>(R.id.media_title).text = title
|
||||||
findViewById<TextView>(R.id.video_album).text = mediaMetadata.albumTitle
|
findViewById<TextView>(R.id.media_artist).text = mediaMetadata.artist
|
||||||
findViewById<TextView>(R.id.video_artist).text = mediaMetadata.artist
|
|
||||||
findViewById<TextView>(R.id.video_genre).text = mediaMetadata.genre
|
|
||||||
|
|
||||||
// Trick to update playlist UI
|
// Trick to update playlist UI
|
||||||
mediaListAdapter.notifyDataSetChanged()
|
mediaItemListAdapter.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateCurrentPlaylistUI() {
|
private fun updateCurrentPlaylistUI() {
|
||||||
val controller = this.controller ?: return
|
val controller = this.controller ?: return
|
||||||
subItemMediaList.clear()
|
mediaItemList.clear()
|
||||||
for (i in 0 until controller.mediaItemCount) {
|
for (i in 0 until controller.mediaItemCount) {
|
||||||
subItemMediaList.add(controller.getMediaItemAt(i))
|
mediaItemList.add(controller.getMediaItemAt(i))
|
||||||
}
|
}
|
||||||
mediaListAdapter.notifyDataSetChanged()
|
mediaItemListAdapter.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class PlayingMediaItemArrayAdapter(
|
private inner class MediaItemListAdapter(
|
||||||
context: Context,
|
context: Context,
|
||||||
viewID: Int,
|
viewID: Int,
|
||||||
mediaItemList: List<MediaItem>
|
mediaItemList: List<MediaItem>
|
||||||
@ -201,23 +152,31 @@ class PlayerActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
returnConvertView.findViewById<TextView>(R.id.media_item).text = mediaItem.mediaMetadata.title
|
returnConvertView.findViewById<TextView>(R.id.media_item).text = mediaItem.mediaMetadata.title
|
||||||
|
|
||||||
|
val deleteButton = returnConvertView.findViewById<Button>(R.id.delete_button)
|
||||||
if (position == controller?.currentMediaItemIndex) {
|
if (position == controller?.currentMediaItemIndex) {
|
||||||
returnConvertView.setBackgroundColor(ContextCompat.getColor(context, R.color.white))
|
// Styles for the current media item list item.
|
||||||
returnConvertView
|
returnConvertView.setBackgroundColor(
|
||||||
.findViewById<TextView>(R.id.media_item)
|
ContextCompat.getColor(context, R.color.playlist_item_background)
|
||||||
.setTextColor(ContextCompat.getColor(context, R.color.black))
|
)
|
||||||
} else {
|
|
||||||
returnConvertView.setBackgroundColor(ContextCompat.getColor(context, R.color.black))
|
|
||||||
returnConvertView
|
returnConvertView
|
||||||
.findViewById<TextView>(R.id.media_item)
|
.findViewById<TextView>(R.id.media_item)
|
||||||
.setTextColor(ContextCompat.getColor(context, R.color.white))
|
.setTextColor(ContextCompat.getColor(context, R.color.white))
|
||||||
}
|
deleteButton.visibility = View.GONE
|
||||||
|
} else {
|
||||||
returnConvertView.findViewById<Button>(R.id.delete_button).setOnClickListener {
|
// Styles for any other media item list item.
|
||||||
|
returnConvertView.setBackgroundColor(
|
||||||
|
ContextCompat.getColor(context, R.color.player_background)
|
||||||
|
)
|
||||||
|
returnConvertView
|
||||||
|
.findViewById<TextView>(R.id.media_item)
|
||||||
|
.setTextColor(ContextCompat.getColor(context, R.color.white))
|
||||||
|
deleteButton.visibility = View.VISIBLE
|
||||||
|
deleteButton.setOnClickListener {
|
||||||
val controller = this@PlayerActivity.controller ?: return@setOnClickListener
|
val controller = this@PlayerActivity.controller ?: return@setOnClickListener
|
||||||
controller.removeMediaItem(position)
|
controller.removeMediaItem(position)
|
||||||
updateCurrentPlaylistUI()
|
updateCurrentPlaylistUI()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return returnConvertView
|
return returnConvertView
|
||||||
}
|
}
|
||||||
|
BIN
demos/session/src/main/res/drawable/artwork_placeholder.png
Normal file
BIN
demos/session/src/main/res/drawable/artwork_placeholder.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
@ -19,7 +19,7 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/black"
|
android:background="@color/player_background"
|
||||||
tools:context=".PlayerActivity">
|
tools:context=".PlayerActivity">
|
||||||
|
|
||||||
<androidx.media3.ui.AspectRatioFrameLayout
|
<androidx.media3.ui.AspectRatioFrameLayout
|
||||||
@ -28,77 +28,47 @@
|
|||||||
>
|
>
|
||||||
<androidx.media3.ui.PlayerView
|
<androidx.media3.ui.PlayerView
|
||||||
android:id="@+id/player_view"
|
android:id="@+id/player_view"
|
||||||
|
android:background="@color/player_background"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
app:use_artwork="true" />
|
app:default_artwork="@drawable/artwork_placeholder"
|
||||||
|
app:repeat_toggle_modes="one|all"
|
||||||
|
app:show_shuffle_button="true"
|
||||||
|
app:shutter_background_color="@color/player_background" />
|
||||||
</androidx.media3.ui.AspectRatioFrameLayout>
|
</androidx.media3.ui.AspectRatioFrameLayout>
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/video_title"
|
android:id="@+id/media_artist"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingLeft="10dp"
|
android:paddingLeft="10dp"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="14sp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/media_title"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:paddingLeft="10dp"
|
||||||
android:paddingBottom="10dp"
|
android:paddingBottom="10dp"
|
||||||
|
android:paddingStart="10dp"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
|
||||||
<TextView
|
<View
|
||||||
android:id="@+id/video_album"
|
android:background="@color/divider"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="1dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="match_parent" />
|
||||||
android:paddingLeft="10dp"
|
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="20sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/video_artist"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:paddingLeft="10dp"
|
|
||||||
android:paddingBottom="10dp"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/video_genre"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:paddingLeft="10dp"
|
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:textSize="12sp" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/shuffle_switch"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:contentDescription="@string/shuffle"
|
|
||||||
android:src="@drawable/exo_styled_controls_shuffle_off"
|
|
||||||
android:textColor="@color/white" />
|
|
||||||
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_margin="@dimen/exo_icon_horizontal_margin"
|
|
||||||
android:id="@+id/repeat_switch"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:src="@drawable/exo_styled_controls_repeat_off"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:contentDescription="@string/repeat"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<ListView
|
<ListView
|
||||||
android:id="@+id/current_playing_list"
|
android:id="@+id/current_playing_list"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:divider="@drawable/divider"
|
android:divider="@drawable/divider"
|
||||||
android:dividerHeight="1px"
|
android:dividerHeight="1px"
|
||||||
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:paddingStart="10dp"
|
android:paddingStart="10dp"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:paddingEnd="10dp"
|
android:paddingEnd="10dp"
|
||||||
android:minHeight="50dp" />
|
android:minHeight="50dp" />
|
||||||
@ -35,6 +37,7 @@
|
|||||||
android:layout_width="50dp"
|
android:layout_width="50dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/delete_button"
|
android:id="@+id/delete_button"
|
||||||
|
android:backgroundTint="@color/playlist_item_foreground"
|
||||||
android:background="@drawable/baseline_playlist_remove_white_48"
|
android:background="@drawable/baseline_playlist_remove_white_48"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -22,4 +22,9 @@
|
|||||||
<color name="black">#FF000000</color>
|
<color name="black">#FF000000</color>
|
||||||
<color name="white">#FFFFFFFF</color>
|
<color name="white">#FFFFFFFF</color>
|
||||||
<color name="grey">#FF999999</color>
|
<color name="grey">#FF999999</color>
|
||||||
|
<color name="background">#292929</color>
|
||||||
|
<color name="player_background">#1c1c1c</color>
|
||||||
|
<color name="playlist_item_background">#363434</color>
|
||||||
|
<color name="playlist_item_foreground">#635E5E</color>
|
||||||
|
<color name="divider">#646464</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user