parent
316c4399ce
commit
c83a865032
|
@ -13,12 +13,14 @@ import android.view.ViewGroup
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.os.BundleCompat
|
||||||
import androidx.media3.common.MediaItem
|
import androidx.media3.common.MediaItem
|
||||||
import androidx.media3.common.MediaMetadata
|
import androidx.media3.common.MediaMetadata
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.media3.session.MediaController
|
import androidx.media3.session.MediaController
|
||||||
import androidx.media3.session.SessionCommand
|
import androidx.media3.session.SessionCommand
|
||||||
|
import androidx.media3.session.SessionResult
|
||||||
import androidx.media3.session.SessionToken
|
import androidx.media3.session.SessionToken
|
||||||
import coil.load
|
import coil.load
|
||||||
import coil.transform.CircleCropTransformation
|
import coil.transform.CircleCropTransformation
|
||||||
|
@ -26,6 +28,7 @@ import coil.transform.RoundedCornersTransformation
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
|
import com.orhanobut.logger.Logger
|
||||||
import kr.co.vividnext.sodalive.R
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.playlist.detail.AudioContentPlaylistContent
|
import kr.co.vividnext.sodalive.audio_content.playlist.detail.AudioContentPlaylistContent
|
||||||
import kr.co.vividnext.sodalive.common.Constants
|
import kr.co.vividnext.sodalive.common.Constants
|
||||||
|
@ -95,9 +98,9 @@ class AudioContentPlayerFragment(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
handler.removeCallbacksAndMessages(null)
|
||||||
mediaController?.release()
|
mediaController?.release()
|
||||||
mediaController = null
|
mediaController = null
|
||||||
handler.removeCallbacksAndMessages(null)
|
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,13 +173,6 @@ class AudioContentPlayerFragment(
|
||||||
override fun onPlaybackStateChanged(playbackState: Int) {
|
override fun onPlaybackStateChanged(playbackState: Int) {
|
||||||
mediaController?.let {
|
mediaController?.let {
|
||||||
when (playbackState) {
|
when (playbackState) {
|
||||||
Player.STATE_READY -> {
|
|
||||||
binding.sbProgress.max = it.duration.toInt()
|
|
||||||
binding.tvTotalTime.text = Utils.convertDurationToString(
|
|
||||||
it.duration.toInt()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Player.STATE_ENDED -> it.seekTo(0)
|
Player.STATE_ENDED -> it.seekTo(0)
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
|
@ -212,6 +208,26 @@ class AudioContentPlayerFragment(
|
||||||
}
|
}
|
||||||
val sessionCommand = SessionCommand("UPDATE_PLAYLIST", Bundle.EMPTY)
|
val sessionCommand = SessionCommand("UPDATE_PLAYLIST", Bundle.EMPTY)
|
||||||
mediaController!!.sendCustomCommand(sessionCommand, extras)
|
mediaController!!.sendCustomCommand(sessionCommand, extras)
|
||||||
|
} else {
|
||||||
|
context?.let {
|
||||||
|
val sessionCommand = SessionCommand("GET_PLAYLIST", Bundle.EMPTY)
|
||||||
|
val resultFuture = mediaController!!.sendCustomCommand(sessionCommand, Bundle.EMPTY)
|
||||||
|
resultFuture.addListener(
|
||||||
|
{
|
||||||
|
val result = resultFuture.get()
|
||||||
|
if (result.resultCode == SessionResult.RESULT_SUCCESS) {
|
||||||
|
val data = BundleCompat.getParcelableArrayList(
|
||||||
|
result.extras,
|
||||||
|
Constants.EXTRA_AUDIO_CONTENT_PLAYLIST,
|
||||||
|
AudioContentPlaylistContent::class.java
|
||||||
|
)
|
||||||
|
|
||||||
|
Logger.e("playlist: $data")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ContextCompat.getMainExecutor(it)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,8 +313,13 @@ class AudioContentPlayerFragment(
|
||||||
|
|
||||||
private fun updateTimeUI() {
|
private fun updateTimeUI() {
|
||||||
mediaController?.let {
|
mediaController?.let {
|
||||||
|
val duration = it.duration
|
||||||
val currentPosition = it.currentPosition
|
val currentPosition = it.currentPosition
|
||||||
|
|
||||||
|
binding.sbProgress.max = duration.toInt()
|
||||||
binding.sbProgress.progress = currentPosition.toInt()
|
binding.sbProgress.progress = currentPosition.toInt()
|
||||||
|
|
||||||
|
binding.tvTotalTime.text = Utils.convertDurationToString(duration.toInt())
|
||||||
binding.tvProgressTime.text = Utils.convertDurationToString(currentPosition.toInt())
|
binding.tvProgressTime.text = Utils.convertDurationToString(currentPosition.toInt())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,8 @@ class AudioContentPlayerService : MediaSessionService() {
|
||||||
|
|
||||||
val compositeDisposable = CompositeDisposable()
|
val compositeDisposable = CompositeDisposable()
|
||||||
|
|
||||||
|
private val playlist = ArrayList<AudioContentPlaylistContent>()
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
|
@ -81,6 +83,14 @@ class AudioContentPlayerService : MediaSessionService() {
|
||||||
|
|
||||||
override fun onGetSession(controllerInfo: MediaSession.ControllerInfo) = mediaSession
|
override fun onGetSession(controllerInfo: MediaSession.ControllerInfo) = mediaSession
|
||||||
|
|
||||||
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
if (intent?.action == "STOP_SERVICE") {
|
||||||
|
onStopService()
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onStartCommand(intent, flags, startId)
|
||||||
|
}
|
||||||
|
|
||||||
private fun initPlayer() {
|
private fun initPlayer() {
|
||||||
player = ExoPlayer.Builder(this).build()
|
player = ExoPlayer.Builder(this).build()
|
||||||
player!!.addListener(object : Player.Listener {
|
player!!.addListener(object : Player.Listener {
|
||||||
|
@ -116,7 +126,7 @@ class AudioContentPlayerService : MediaSessionService() {
|
||||||
.add(SessionCommand("UPDATE_PLAYLIST", Bundle.EMPTY))
|
.add(SessionCommand("UPDATE_PLAYLIST", Bundle.EMPTY))
|
||||||
.add(SessionCommand("PLAY_NEXT_CONTENT", Bundle.EMPTY))
|
.add(SessionCommand("PLAY_NEXT_CONTENT", Bundle.EMPTY))
|
||||||
.add(SessionCommand("PLAY_PREVIOUS_CONTENT", Bundle.EMPTY))
|
.add(SessionCommand("PLAY_PREVIOUS_CONTENT", Bundle.EMPTY))
|
||||||
.add(SessionCommand("SEEK_TO", Bundle.EMPTY))
|
.add(SessionCommand("GET_PLAYLIST", Bundle.EMPTY))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
return MediaSession.ConnectionResult.AcceptedResultBuilder(session)
|
return MediaSession.ConnectionResult.AcceptedResultBuilder(session)
|
||||||
|
@ -139,6 +149,7 @@ class AudioContentPlayerService : MediaSessionService() {
|
||||||
)
|
)
|
||||||
|
|
||||||
if (playlist != null) {
|
if (playlist != null) {
|
||||||
|
this@AudioContentPlayerService.playlist.addAll(playlist)
|
||||||
playlistManager = AudioContentPlaylistManager(playlist)
|
playlistManager = AudioContentPlaylistManager(playlist)
|
||||||
playNextContent()
|
playNextContent()
|
||||||
}
|
}
|
||||||
|
@ -156,6 +167,22 @@ class AudioContentPlayerService : MediaSessionService() {
|
||||||
Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
|
Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"GET_PLAYLIST" -> {
|
||||||
|
val extras = Bundle().apply {
|
||||||
|
putParcelableArrayList(
|
||||||
|
Constants.EXTRA_AUDIO_CONTENT_PLAYLIST,
|
||||||
|
playlist
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Futures.immediateFuture(
|
||||||
|
SessionResult(
|
||||||
|
SessionResult.RESULT_SUCCESS,
|
||||||
|
extras
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
else -> super.onCustomCommand(session, controller, customCommand, args)
|
else -> super.onCustomCommand(session, controller, customCommand, args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,6 +197,12 @@ class AudioContentPlayerService : MediaSessionService() {
|
||||||
stopForeground(true)
|
stopForeground(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mediaSession?.run {
|
||||||
|
player.release()
|
||||||
|
release()
|
||||||
|
mediaSession = null
|
||||||
|
}
|
||||||
|
|
||||||
stopSelf()
|
stopSelf()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,40 @@
|
||||||
package kr.co.vividnext.sodalive.audio_content.playlist.detail
|
package kr.co.vividnext.sodalive.audio_content.playlist.detail
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.ComponentName
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.SharedPreferences
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.media3.common.MediaItem
|
||||||
|
import androidx.media3.common.Player
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
|
import androidx.media3.session.MediaController
|
||||||
|
import androidx.media3.session.SessionToken
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import coil.load
|
import coil.load
|
||||||
|
import coil.transform.RoundedCornersTransformation
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.player.AudioContentPlayerFragment
|
import kr.co.vividnext.sodalive.audio_content.player.AudioContentPlayerFragment
|
||||||
|
import kr.co.vividnext.sodalive.audio_content.player.AudioContentPlayerService
|
||||||
import kr.co.vividnext.sodalive.audio_content.playlist.modify.AudioContentPlaylistModifyActivity
|
import kr.co.vividnext.sodalive.audio_content.playlist.modify.AudioContentPlaylistModifyActivity
|
||||||
import kr.co.vividnext.sodalive.base.BaseActivity
|
import kr.co.vividnext.sodalive.base.BaseActivity
|
||||||
import kr.co.vividnext.sodalive.base.SodaDialog
|
import kr.co.vividnext.sodalive.base.SodaDialog
|
||||||
import kr.co.vividnext.sodalive.common.Constants
|
import kr.co.vividnext.sodalive.common.Constants
|
||||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||||
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
import kr.co.vividnext.sodalive.databinding.ActivityAudioContentPlaylistDetailBinding
|
import kr.co.vividnext.sodalive.databinding.ActivityAudioContentPlaylistDetailBinding
|
||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
class AudioContentPlaylistDetailActivity : BaseActivity<ActivityAudioContentPlaylistDetailBinding>(
|
class AudioContentPlaylistDetailActivity : BaseActivity<ActivityAudioContentPlaylistDetailBinding>(
|
||||||
|
@ -34,10 +48,6 @@ class AudioContentPlaylistDetailActivity : BaseActivity<ActivityAudioContentPlay
|
||||||
|
|
||||||
private var playlistId: Long = 0
|
private var playlistId: Long = 0
|
||||||
|
|
||||||
private val playerFragment: AudioContentPlayerFragment by lazy {
|
|
||||||
AudioContentPlayerFragment(screenWidth, ArrayList(contentList))
|
|
||||||
}
|
|
||||||
|
|
||||||
private val modifyPlaylistResult = registerForActivityResult(
|
private val modifyPlaylistResult = registerForActivityResult(
|
||||||
ActivityResultContracts.StartActivityForResult()
|
ActivityResultContracts.StartActivityForResult()
|
||||||
) { result ->
|
) { result ->
|
||||||
|
@ -47,6 +57,101 @@ class AudioContentPlaylistDetailActivity : BaseActivity<ActivityAudioContentPlay
|
||||||
}
|
}
|
||||||
|
|
||||||
private val contentList = mutableListOf<AudioContentPlaylistContent>()
|
private val contentList = mutableListOf<AudioContentPlaylistContent>()
|
||||||
|
private var mediaController: MediaController? = null
|
||||||
|
private val handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
private val preferenceChangeListener =
|
||||||
|
SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
|
||||||
|
// 특정 키에 대한 값이 변경될 때 UI 업데이트
|
||||||
|
if (key == Constants.PREF_IS_PLAYER_SERVICE_RUNNING) {
|
||||||
|
handler.postDelayed(
|
||||||
|
{
|
||||||
|
if (sharedPreferences.getBoolean(key, false)) {
|
||||||
|
initAndVisibleMiniPlayer()
|
||||||
|
} else {
|
||||||
|
deInitMiniPlayer()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
500
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initAndVisibleMiniPlayer() {
|
||||||
|
binding.clMiniPlayer.visibility = View.VISIBLE
|
||||||
|
binding.clMiniPlayer.setOnClickListener { showPlayerFragment() }
|
||||||
|
binding.ivStop.setOnClickListener {
|
||||||
|
val stopIntent = Intent(
|
||||||
|
applicationContext,
|
||||||
|
AudioContentPlayerService::class.java
|
||||||
|
)
|
||||||
|
stopIntent.action = "STOP_SERVICE"
|
||||||
|
startService(stopIntent)
|
||||||
|
}
|
||||||
|
connectPlayerService()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun connectPlayerService() {
|
||||||
|
val componentName = ComponentName(applicationContext, AudioContentPlayerService::class.java)
|
||||||
|
val sessionToken = SessionToken(applicationContext, componentName)
|
||||||
|
val mediaControllerFuture =
|
||||||
|
MediaController.Builder(applicationContext, sessionToken).buildAsync()
|
||||||
|
mediaControllerFuture.addListener(
|
||||||
|
{
|
||||||
|
mediaController = mediaControllerFuture.get()
|
||||||
|
setupMediaController()
|
||||||
|
binding.ivPlayOrPause.setOnClickListener {
|
||||||
|
mediaController?.let {
|
||||||
|
if (it.playWhenReady) {
|
||||||
|
it.pause()
|
||||||
|
} else {
|
||||||
|
it.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ContextCompat.getMainExecutor(applicationContext)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupMediaController() {
|
||||||
|
if (mediaController == null) {
|
||||||
|
deInitMiniPlayer()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaController!!.addListener(object : Player.Listener {
|
||||||
|
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
|
||||||
|
mediaItem?.mediaMetadata?.let {
|
||||||
|
binding.ivPlayerCover.load(it.artworkUri) {
|
||||||
|
crossfade(true)
|
||||||
|
placeholder(R.drawable.ic_place_holder)
|
||||||
|
transformations(RoundedCornersTransformation(5.3f.dpToPx()))
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.tvPlayerTitle.text = it.title
|
||||||
|
binding.tvPlayerNickname.text = it.artist
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
|
||||||
|
binding.ivPlayOrPause.setImageResource(
|
||||||
|
if (playWhenReady) {
|
||||||
|
R.drawable.ic_player_pause
|
||||||
|
} else {
|
||||||
|
R.drawable.ic_player_play
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deInitMiniPlayer() {
|
||||||
|
binding.clMiniPlayer.visibility = View.GONE
|
||||||
|
mediaController?.release()
|
||||||
|
mediaController = null
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
playlistId = intent.getLongExtra(Constants.EXTRA_AUDIO_CONTENT_PLAYLIST_ID, 0)
|
playlistId = intent.getLongExtra(Constants.EXTRA_AUDIO_CONTENT_PLAYLIST_ID, 0)
|
||||||
|
@ -59,6 +164,26 @@ class AudioContentPlaylistDetailActivity : BaseActivity<ActivityAudioContentPlay
|
||||||
|
|
||||||
bindData()
|
bindData()
|
||||||
viewModel.getPlaylistDetail(playlistId)
|
viewModel.getPlaylistDetail(playlistId)
|
||||||
|
SharedPreferenceManager.registerOnSharedPreferenceChangeListener(preferenceChangeListener)
|
||||||
|
|
||||||
|
if (SharedPreferenceManager.isPlayerServiceRunning) {
|
||||||
|
initAndVisibleMiniPlayer()
|
||||||
|
} else {
|
||||||
|
deInitMiniPlayer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
deInitMiniPlayer()
|
||||||
|
SharedPreferenceManager.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener)
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showPlayerFragment(
|
||||||
|
contentList: ArrayList<AudioContentPlaylistContent> = arrayListOf()
|
||||||
|
) {
|
||||||
|
val playerFragment = AudioContentPlayerFragment(screenWidth, contentList)
|
||||||
|
playerFragment.show(supportFragmentManager, playerFragment.tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setupView() {
|
override fun setupView() {
|
||||||
|
@ -105,10 +230,13 @@ class AudioContentPlaylistDetailActivity : BaseActivity<ActivityAudioContentPlay
|
||||||
recyclerView.adapter = adapter
|
recyclerView.adapter = adapter
|
||||||
|
|
||||||
binding.llPlay.setOnClickListener {
|
binding.llPlay.setOnClickListener {
|
||||||
if (playerFragment.isAdded) return@setOnClickListener
|
showPlayerFragment(contentList = ArrayList(contentList))
|
||||||
playerFragment.show(supportFragmentManager, playerFragment.tag)
|
|
||||||
}
|
}
|
||||||
binding.llShuffle.setOnClickListener { }
|
binding.llShuffle.setOnClickListener {
|
||||||
|
val shuffledList = ArrayList(contentList).apply { shuffle(Random) }
|
||||||
|
showPlayerFragment(contentList = shuffledList)
|
||||||
|
}
|
||||||
|
|
||||||
binding.tvBack.setOnClickListener { finish() }
|
binding.tvBack.setOnClickListener { finish() }
|
||||||
binding.ivEdit.setOnClickListener {
|
binding.ivEdit.setOnClickListener {
|
||||||
modifyPlaylistResult.launch(
|
modifyPlaylistResult.launch(
|
||||||
|
|
|
@ -14,6 +14,18 @@ object SharedPreferenceManager {
|
||||||
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun registerOnSharedPreferenceChangeListener(
|
||||||
|
listener: SharedPreferences.OnSharedPreferenceChangeListener
|
||||||
|
) {
|
||||||
|
sharedPreferences.registerOnSharedPreferenceChangeListener(listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unregisterOnSharedPreferenceChangeListener(
|
||||||
|
listener: SharedPreferences.OnSharedPreferenceChangeListener
|
||||||
|
) {
|
||||||
|
sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener)
|
||||||
|
}
|
||||||
|
|
||||||
fun clear() {
|
fun clear() {
|
||||||
sharedPreferences.edit { it.clear() }
|
sharedPreferences.edit { it.clear() }
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,9 +286,81 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginVertical="18dp"
|
android:layout_marginVertical="18dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toTopOf="@+id/cl_mini_player"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/ll_play" />
|
app:layout_constraintTop_toBottomOf="@+id/ll_play" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/cl_mini_player"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/color_222222"
|
||||||
|
android:paddingHorizontal="13.3dp"
|
||||||
|
android:paddingVertical="10.7dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_player_cover"
|
||||||
|
android:layout_width="36.7dp"
|
||||||
|
android:layout_height="36.7dp"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:src="@mipmap/ic_launcher" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_player_title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="10.7dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:textColor="@color/color_eeeeee"
|
||||||
|
android:textSize="13sp"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/iv_play_or_pause"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/iv_player_cover"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/iv_player_cover"
|
||||||
|
tools:text="JFLA 커버곡 Avicii for your self" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_player_nickname"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="2.3dp"
|
||||||
|
android:textColor="@color/color_d2d2d2"
|
||||||
|
android:textSize="11sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/tv_player_title"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/tv_player_title"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/tv_player_title"
|
||||||
|
tools:ignore="SmallSp"
|
||||||
|
tools:text="JFLA 커버곡 Avicii for your self" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_play_or_pause"
|
||||||
|
android:layout_width="25dp"
|
||||||
|
android:layout_height="25dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/iv_stop"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/iv_stop"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/iv_stop"
|
||||||
|
tools:src="@drawable/btn_bar_play" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_stop"
|
||||||
|
android:layout_width="25dp"
|
||||||
|
android:layout_height="25dp"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:src="@drawable/ic_noti_stop"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
Loading…
Reference in New Issue