update
This commit is contained in:
parent
195ec0f242
commit
c90b8a6930
@ -1,5 +1,6 @@
|
|||||||
package com.player.musicoo.activity
|
package com.player.musicoo.activity
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.gyf.immersionbar.ktx.immersionBar
|
import com.gyf.immersionbar.ktx.immersionBar
|
||||||
@ -45,8 +46,10 @@ class MoListDetailsActivity : MoBaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun initData(browseId: String) {
|
private suspend fun initData(browseId: String) {
|
||||||
|
showLoadingUi()
|
||||||
Innertube.moPlaylistPage(browseId)
|
Innertube.moPlaylistPage(browseId)
|
||||||
?.onSuccess {
|
?.onSuccess {
|
||||||
|
showDataUi()
|
||||||
Glide.with(this)
|
Glide.with(this)
|
||||||
.load(it.thumbnail)
|
.load(it.thumbnail)
|
||||||
.into(binding.imageView)
|
.into(binding.imageView)
|
||||||
@ -61,7 +64,23 @@ class MoListDetailsActivity : MoBaseActivity() {
|
|||||||
binding.rv.adapter = adapter
|
binding.rv.adapter = adapter
|
||||||
|
|
||||||
}?.onFailure {
|
}?.onFailure {
|
||||||
|
showNoContentUi()
|
||||||
LogD(TAG, "moPlaylistPage onFailure->${it}")
|
LogD(TAG, "moPlaylistPage onFailure->${it}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showDataUi() {
|
||||||
|
binding.loadingLayout.visibility = View.GONE
|
||||||
|
binding.noContentLayout.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showLoadingUi() {
|
||||||
|
binding.loadingLayout.visibility = View.VISIBLE
|
||||||
|
binding.noContentLayout.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showNoContentUi() {
|
||||||
|
binding.loadingLayout.visibility = View.GONE
|
||||||
|
binding.noContentLayout.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,28 +1,36 @@
|
|||||||
package com.player.musicoo.activity
|
package com.player.musicoo.activity
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.os.Message
|
import android.os.Message
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.animation.AnimationUtils
|
||||||
import androidx.annotation.OptIn
|
import androidx.annotation.OptIn
|
||||||
import androidx.media3.common.MediaItem
|
import androidx.media3.common.MediaItem
|
||||||
import androidx.media3.common.PlaybackException
|
import androidx.media3.common.PlaybackException
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.request.target.CustomTarget
|
||||||
|
import com.bumptech.glide.request.transition.Transition
|
||||||
import com.gyf.immersionbar.ktx.immersionBar
|
import com.gyf.immersionbar.ktx.immersionBar
|
||||||
import com.player.musicoo.R
|
import com.player.musicoo.R
|
||||||
|
import com.player.musicoo.adapter.PlayListAdapter
|
||||||
import com.player.musicoo.databinding.ActivityMoPlayDetailsBinding
|
import com.player.musicoo.databinding.ActivityMoPlayDetailsBinding
|
||||||
import com.player.musicoo.innertube.Innertube
|
import com.player.musicoo.innertube.Innertube
|
||||||
import com.player.musicoo.media.MediaControllerManager
|
import com.player.musicoo.media.MediaControllerManager
|
||||||
import com.player.musicoo.media.SongRadio
|
import com.player.musicoo.media.SongRadio
|
||||||
|
import com.player.musicoo.util.LogTag.LogD
|
||||||
import com.player.musicoo.util.asMediaItem
|
import com.player.musicoo.util.asMediaItem
|
||||||
import com.player.musicoo.util.convertMillisToMinutesAndSecondsString
|
import com.player.musicoo.util.convertMillisToMinutesAndSecondsString
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.selects.select
|
import kotlinx.coroutines.selects.select
|
||||||
import com.player.musicoo.util.LogTag.LogD
|
|
||||||
|
|
||||||
@OptIn(UnstableApi::class)
|
@OptIn(UnstableApi::class)
|
||||||
class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
||||||
@ -42,6 +50,7 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
private var currentVideoID = ""
|
private var currentVideoID = ""
|
||||||
|
|
||||||
private var comeFrom: Class<*>? = null
|
private var comeFrom: Class<*>? = null
|
||||||
|
private var playListAdapter: PlayListAdapter? = null
|
||||||
|
|
||||||
private fun initImmersionBar() {
|
private fun initImmersionBar() {
|
||||||
immersionBar {
|
immersionBar {
|
||||||
@ -120,9 +129,8 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
if (meController != null && meController.currentMediaItem != null) {
|
if (meController != null && meController.currentMediaItem != null) {
|
||||||
binding.playbackErrorLayout.visibility = View.GONE
|
binding.playbackErrorLayout.visibility = View.GONE
|
||||||
binding.loadingView.visibility = View.GONE
|
binding.loadingView.visibility = View.GONE
|
||||||
|
binding.disableClicksLayout.visibility = View.GONE
|
||||||
|
val currentString = convertMillisToMinutesAndSecondsString(MediaControllerManager.getCurrentPosition())
|
||||||
val currentString = convertMillisToMinutesAndSecondsString(meController.currentPosition)
|
|
||||||
binding.progressDurationTv.text = currentString
|
binding.progressDurationTv.text = currentString
|
||||||
if (MediaControllerManager.getDuration() > 0) {
|
if (MediaControllerManager.getDuration() > 0) {
|
||||||
binding.totalDurationTv.visibility = View.VISIBLE
|
binding.totalDurationTv.visibility = View.VISIBLE
|
||||||
@ -133,13 +141,31 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
binding.totalDurationTv.text =
|
binding.totalDurationTv.text =
|
||||||
convertMillisToMinutesAndSecondsString(MediaControllerManager.getDuration())
|
convertMillisToMinutesAndSecondsString(MediaControllerManager.getDuration())
|
||||||
|
|
||||||
binding.sbProgress.value = meController.currentPosition.toFloat()
|
binding.sbProgress.value = MediaControllerManager.getCurrentPosition().toFloat()
|
||||||
binding.sbProgress.valueTo = MediaControllerManager.getDuration().toFloat()
|
binding.sbProgress.valueTo = MediaControllerManager.getDuration().toFloat()
|
||||||
updateProgressState()
|
updateProgressState()
|
||||||
|
|
||||||
binding.progressBar.progress = meController.bufferedPosition.toInt()
|
binding.progressBar.progress = MediaControllerManager.getBufferedPosition().toInt()
|
||||||
binding.progressBar.max = MediaControllerManager.getDuration().toInt()
|
binding.progressBar.max = MediaControllerManager.getDuration().toInt()
|
||||||
updateProgressBufferingState()
|
updateProgressBufferingState()
|
||||||
|
|
||||||
|
val mediaItemCount = meController.mediaItemCount
|
||||||
|
val allMediaItems: MutableList<MediaItem> = mutableListOf()
|
||||||
|
for (index in 0 until mediaItemCount) {
|
||||||
|
val mediaItemAt = meController.getMediaItemAt(index)
|
||||||
|
allMediaItems.add(mediaItemAt)
|
||||||
|
}
|
||||||
|
playListAdapter = PlayListAdapter(
|
||||||
|
this@MoPlayDetailsActivity,
|
||||||
|
allMediaItems
|
||||||
|
)
|
||||||
|
binding.playListRv.layoutManager =
|
||||||
|
LinearLayoutManager(
|
||||||
|
this@MoPlayDetailsActivity,
|
||||||
|
LinearLayoutManager.VERTICAL,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
binding.playListRv.adapter = playListAdapter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,6 +173,16 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
binding.backBtn.setOnClickListener {
|
binding.backBtn.setOnClickListener {
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
binding.tryAgainBtn.setOnClickListener {
|
||||||
|
if (meController != null) {
|
||||||
|
updateInfoUi(meController.currentMediaItem)
|
||||||
|
updateProgressState()
|
||||||
|
if (!meController.isPlaying) {
|
||||||
|
meController.prepare()
|
||||||
|
meController.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
binding.playLayoutBtn.setOnClickListener {
|
binding.playLayoutBtn.setOnClickListener {
|
||||||
if (meController != null) {
|
if (meController != null) {
|
||||||
if (meController.isPlaying) {
|
if (meController.isPlaying) {
|
||||||
@ -184,7 +220,13 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.listLayoutBtn.setOnClickListener {
|
binding.listLayoutBtn.setOnClickListener {
|
||||||
LogD(TAG, "meController?.mediaItemCount->${meController?.mediaItemCount}")
|
toggleBottomLayout()
|
||||||
|
}
|
||||||
|
binding.bottomCloseBtn.setOnClickListener {
|
||||||
|
toggleBottomLayout()
|
||||||
|
}
|
||||||
|
binding.bottomBlankLayout.setOnClickListener {
|
||||||
|
toggleBottomLayout()
|
||||||
}
|
}
|
||||||
binding.progressBar.progress = 0
|
binding.progressBar.progress = 0
|
||||||
binding.sbProgress.value = 0f
|
binding.sbProgress.value = 0f
|
||||||
@ -218,7 +260,20 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
|
|
||||||
if (songRadioList.isEmpty()) {//集合为空则展示错误提示
|
if (songRadioList.isEmpty()) {//集合为空则展示错误提示
|
||||||
binding.loadingView.visibility = View.GONE
|
binding.loadingView.visibility = View.GONE
|
||||||
|
binding.disableClicksLayout.visibility = View.GONE
|
||||||
binding.playbackErrorLayout.visibility = View.VISIBLE
|
binding.playbackErrorLayout.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
playListAdapter = PlayListAdapter(
|
||||||
|
this@MoPlayDetailsActivity,
|
||||||
|
songRadioList.map(Innertube.SongItem::asMediaItem)
|
||||||
|
)
|
||||||
|
binding.playListRv.layoutManager =
|
||||||
|
LinearLayoutManager(
|
||||||
|
this@MoPlayDetailsActivity,
|
||||||
|
LinearLayoutManager.VERTICAL,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
binding.playListRv.adapter = playListAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFinishing) {
|
if (isFinishing) {
|
||||||
@ -269,6 +324,7 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val playerListener = object : Player.Listener {
|
private val playerListener = object : Player.Listener {
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
override fun onPositionDiscontinuity(
|
override fun onPositionDiscontinuity(
|
||||||
oldPosition: Player.PositionInfo,
|
oldPosition: Player.PositionInfo,
|
||||||
newPosition: Player.PositionInfo,
|
newPosition: Player.PositionInfo,
|
||||||
@ -278,7 +334,11 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION
|
if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION
|
||||||
|| reason == Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT
|
|| reason == Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT
|
||||||
) {
|
) {
|
||||||
|
updateProgressUi()
|
||||||
updateInfoUi(meController?.currentMediaItem)
|
updateInfoUi(meController?.currentMediaItem)
|
||||||
|
if (playListAdapter != null) {
|
||||||
|
playListAdapter?.notifyDataSetChanged()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,11 +361,14 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
when (playbackState) {
|
when (playbackState) {
|
||||||
Player.STATE_BUFFERING -> {
|
Player.STATE_BUFFERING -> {
|
||||||
binding.loadingView.visibility = View.VISIBLE
|
binding.loadingView.visibility = View.VISIBLE
|
||||||
|
binding.disableClicksLayout.visibility = View.VISIBLE
|
||||||
|
binding.playbackErrorLayout.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
Player.STATE_READY -> {
|
Player.STATE_READY -> {
|
||||||
binding.playbackErrorLayout.visibility = View.GONE
|
binding.playbackErrorLayout.visibility = View.GONE
|
||||||
binding.loadingView.visibility = View.GONE
|
binding.loadingView.visibility = View.GONE
|
||||||
|
binding.disableClicksLayout.visibility = View.GONE
|
||||||
binding.totalDurationTv.visibility = View.VISIBLE
|
binding.totalDurationTv.visibility = View.VISIBLE
|
||||||
binding.totalDurationTv.text =
|
binding.totalDurationTv.text =
|
||||||
convertMillisToMinutesAndSecondsString(
|
convertMillisToMinutesAndSecondsString(
|
||||||
@ -320,6 +383,7 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
binding.loadingView.visibility = View.GONE
|
binding.loadingView.visibility = View.GONE
|
||||||
|
binding.disableClicksLayout.visibility = View.GONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateProgressState()
|
updateProgressState()
|
||||||
@ -343,9 +407,24 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
binding.playbackErrorLayout.visibility = View.VISIBLE
|
binding.playbackErrorLayout.visibility = View.VISIBLE
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
Glide.with(this@MoPlayDetailsActivity)
|
|
||||||
|
Glide.with(this)
|
||||||
|
.asBitmap()
|
||||||
.load(mediaItem.mediaMetadata.artworkUri)
|
.load(mediaItem.mediaMetadata.artworkUri)
|
||||||
.into(binding.thumbnail)
|
.placeholder(R.mipmap.musicoo_logo_img)
|
||||||
|
.into(object : CustomTarget<Bitmap>() {
|
||||||
|
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
|
||||||
|
binding.thumbnail.setImageBitmap(resource)
|
||||||
|
val blurredBitmap = applyGaussianBlur(resource, 25f, this@MoPlayDetailsActivity)
|
||||||
|
binding.imageView.setImageBitmap(blurredBitmap)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLoadCleared(placeholder: Drawable?) {
|
||||||
|
if (placeholder != null) {
|
||||||
|
binding.thumbnail.setImageDrawable(placeholder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
binding.nameTv.text = mediaItem.mediaMetadata.title
|
binding.nameTv.text = mediaItem.mediaMetadata.title
|
||||||
binding.descTv.text = mediaItem.mediaMetadata.artist
|
binding.descTv.text = mediaItem.mediaMetadata.artist
|
||||||
@ -372,11 +451,11 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
override fun handleMessage(msg: Message) {
|
override fun handleMessage(msg: Message) {
|
||||||
//判断是否ready与播放中,否则停止更新进度
|
//判断是否ready与播放中,否则停止更新进度
|
||||||
if (meController != null && meController.playbackState == Player.STATE_READY && meController.isPlaying) {
|
if (meController != null && meController.playbackState == Player.STATE_READY && meController.isPlaying) {
|
||||||
val currentPosition = meController.currentPosition
|
val currentPosition = MediaControllerManager.getCurrentPosition()
|
||||||
val currentString = convertMillisToMinutesAndSecondsString(currentPosition)
|
val currentString = convertMillisToMinutesAndSecondsString(currentPosition)
|
||||||
binding.progressDurationTv.text = currentString
|
binding.progressDurationTv.text = currentString
|
||||||
|
|
||||||
val currentBufferedPosition = meController.bufferedPosition
|
val currentBufferedPosition = MediaControllerManager.getBufferedPosition()
|
||||||
binding.progressBar.progress = currentBufferedPosition.toInt()
|
binding.progressBar.progress = currentBufferedPosition.toInt()
|
||||||
|
|
||||||
// 更新 SeekBar 的进度
|
// 更新 SeekBar 的进度
|
||||||
@ -405,7 +484,7 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
private val progressBufferingHandler = object : Handler(Looper.myLooper()!!) {
|
private val progressBufferingHandler = object : Handler(Looper.myLooper()!!) {
|
||||||
override fun handleMessage(msg: Message) {
|
override fun handleMessage(msg: Message) {
|
||||||
if (meController != null && meController.isLoading) {
|
if (meController != null && meController.isLoading) {
|
||||||
val currentBufferedPosition = meController.bufferedPosition
|
val currentBufferedPosition = MediaControllerManager.getBufferedPosition()
|
||||||
binding.progressBar.progress = currentBufferedPosition.toInt()
|
binding.progressBar.progress = currentBufferedPosition.toInt()
|
||||||
sendEmptyMessageDelayed(1, 50)
|
sendEmptyMessageDelayed(1, 50)
|
||||||
}
|
}
|
||||||
@ -419,4 +498,25 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
|||||||
binding.playImg.setImageResource(R.drawable.play_green_icon)
|
binding.playImg.setImageResource(R.drawable.play_green_icon)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun toggleBottomLayout() {
|
||||||
|
if (binding.bottomLayout.visibility == View.VISIBLE) {
|
||||||
|
hideBottomLayout()
|
||||||
|
} else {
|
||||||
|
showBottomLayout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showBottomLayout() {
|
||||||
|
val slideUpAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_up)
|
||||||
|
binding.bottomLayout.startAnimation(slideUpAnimation)
|
||||||
|
binding.bottomLayout.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hideBottomLayout() {
|
||||||
|
val slideDownAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_down)
|
||||||
|
binding.bottomLayout.startAnimation(slideDownAnimation)
|
||||||
|
binding.bottomLayout.visibility = View.GONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -10,6 +10,7 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.player.musicoo.App
|
import com.player.musicoo.App
|
||||||
import com.player.musicoo.R
|
import com.player.musicoo.R
|
||||||
|
import com.player.musicoo.activity.MoPlayDetailsActivity
|
||||||
import com.player.musicoo.activity.PlayDetailsActivity
|
import com.player.musicoo.activity.PlayDetailsActivity
|
||||||
import com.player.musicoo.bean.Audio
|
import com.player.musicoo.bean.Audio
|
||||||
import com.player.musicoo.databinding.DetailsListItemBinding
|
import com.player.musicoo.databinding.DetailsListItemBinding
|
||||||
@ -27,6 +28,10 @@ class DetailsListAdapter(
|
|||||||
) :
|
) :
|
||||||
RecyclerView.Adapter<DetailsListAdapter.ViewHolder>() {
|
RecyclerView.Adapter<DetailsListAdapter.ViewHolder>() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val FROM_TAG = "list_details_activity_to_adapter"
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
val binding = DetailsListItemBinding.inflate(LayoutInflater.from(context), parent, false)
|
val binding = DetailsListItemBinding.inflate(LayoutInflater.from(context), parent, false)
|
||||||
return ViewHolder(binding)
|
return ViewHolder(binding)
|
||||||
@ -35,6 +40,23 @@ class DetailsListAdapter(
|
|||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
val bean = list[position]
|
val bean = list[position]
|
||||||
holder.bind(bean)
|
holder.bind(bean)
|
||||||
|
|
||||||
|
val videoId = bean.videoId
|
||||||
|
|
||||||
|
holder.itemView.setOnClickListener {
|
||||||
|
val intent = Intent(context, MoPlayDetailsActivity::class.java)
|
||||||
|
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_VIDEO_ID, videoId)
|
||||||
|
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_PLAY_LIST_ID, bean.playlistId)
|
||||||
|
intent.putExtra(
|
||||||
|
MoPlayDetailsActivity.PLAY_DETAILS_PLAY_LIST_SET_VIDEO_ID,
|
||||||
|
bean.playlistSetVideoId
|
||||||
|
)
|
||||||
|
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_PLAY_PARAMS, bean.params)
|
||||||
|
|
||||||
|
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_NAME, bean.name)
|
||||||
|
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, bean.title)
|
||||||
|
context.startActivity(intent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int = list.size
|
override fun getItemCount(): Int = list.size
|
||||||
|
|||||||
@ -0,0 +1,94 @@
|
|||||||
|
package com.player.musicoo.adapter
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.media3.common.C
|
||||||
|
import androidx.media3.common.MediaItem
|
||||||
|
import androidx.media3.common.Player
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.player.musicoo.R
|
||||||
|
import com.player.musicoo.databinding.PlayListItemBinding
|
||||||
|
import com.player.musicoo.media.MediaControllerManager
|
||||||
|
|
||||||
|
class PlayListAdapter(
|
||||||
|
private val context: Context,
|
||||||
|
private val list: List<MediaItem>,
|
||||||
|
) :
|
||||||
|
RecyclerView.Adapter<PlayListAdapter.ViewHolder>() {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val binding = PlayListItemBinding.inflate(LayoutInflater.from(context), parent, false)
|
||||||
|
return ViewHolder(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
val bean = list[position]
|
||||||
|
holder.bind(bean)
|
||||||
|
|
||||||
|
holder.itemView.setOnClickListener {
|
||||||
|
val meController = MediaControllerManager.getController()
|
||||||
|
if (meController != null && meController.currentMediaItem != null) {
|
||||||
|
var index = holder.bindingAdapterPosition
|
||||||
|
if (index > meController.mediaItemCount) {
|
||||||
|
index = 1
|
||||||
|
}
|
||||||
|
meController.seekTo(index, C.TIME_UNSET)
|
||||||
|
if (!meController.isPlaying) {
|
||||||
|
meController.prepare()
|
||||||
|
meController.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = list.size
|
||||||
|
|
||||||
|
inner class ViewHolder(private val binding: PlayListItemBinding) :
|
||||||
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
fun bind(bean: MediaItem) {
|
||||||
|
|
||||||
|
binding.apply {
|
||||||
|
val meController = MediaControllerManager.getController()
|
||||||
|
if (meController != null && meController.currentMediaItem != null) {
|
||||||
|
if (meController.currentMediaItem?.mediaId == bean.mediaId) {
|
||||||
|
binding.currentPlayingLayout.visibility = View.VISIBLE
|
||||||
|
binding.title.setTextColor(context.getColor(R.color.green))
|
||||||
|
binding.name.setTextColor(context.getColor(R.color.green_60))
|
||||||
|
} else {
|
||||||
|
binding.currentPlayingLayout.visibility = View.GONE
|
||||||
|
binding.title.setTextColor(context.getColor(R.color.white))
|
||||||
|
binding.name.setTextColor(context.getColor(R.color.white_60))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Glide.with(context)
|
||||||
|
.load(bean.mediaMetadata.artworkUri)
|
||||||
|
.into(image)
|
||||||
|
title.text = bean.mediaMetadata.title
|
||||||
|
if (bean.mediaMetadata.artist.isNullOrEmpty()) {
|
||||||
|
name.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
name.visibility = View.VISIBLE
|
||||||
|
name.text = bean.mediaMetadata.artist
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var itemClickListener: OnItemClickListener? = null
|
||||||
|
|
||||||
|
fun setOnItemClickListener(listener: OnItemClickListener) {
|
||||||
|
itemClickListener = listener
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnItemClickListener {
|
||||||
|
fun onItemClick(position: Int)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ import android.view.ViewGroup
|
|||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.player.musicoo.activity.MoListDetailsActivity
|
import com.player.musicoo.activity.MoListDetailsActivity
|
||||||
|
import com.player.musicoo.activity.MoPlayDetailsActivity
|
||||||
import com.player.musicoo.databinding.MusicTowRowItemBinding
|
import com.player.musicoo.databinding.MusicTowRowItemBinding
|
||||||
import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer
|
import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer
|
||||||
|
|
||||||
@ -34,38 +35,66 @@ class TowRowListAdapter(
|
|||||||
|
|
||||||
val browseId = browseEndpoint?.browseId
|
val browseId = browseEndpoint?.browseId
|
||||||
|
|
||||||
holder.bind(bean)
|
val watchEndpoint = bean.musicTwoRowItemRenderer
|
||||||
|
?.navigationEndpoint
|
||||||
|
?.watchEndpoint
|
||||||
|
|
||||||
|
val videoId = watchEndpoint?.videoId
|
||||||
|
val playlistId = watchEndpoint?.playlistId
|
||||||
|
val playlistSetVideoId = watchEndpoint?.playlistSetVideoId
|
||||||
|
val params = watchEndpoint?.params
|
||||||
|
|
||||||
|
|
||||||
|
val url = bean.musicTwoRowItemRenderer
|
||||||
|
?.thumbnailRenderer
|
||||||
|
?.musicThumbnailRenderer
|
||||||
|
?.thumbnail
|
||||||
|
?.thumbnails
|
||||||
|
?.let { it.getOrNull(1) ?: it.getOrNull(0) }
|
||||||
|
?.url ?: ""
|
||||||
|
val name = bean.musicTwoRowItemRenderer
|
||||||
|
?.title
|
||||||
|
?.runs
|
||||||
|
?.firstOrNull()
|
||||||
|
?.text ?: ""
|
||||||
|
val desc = bean.musicTwoRowItemRenderer
|
||||||
|
?.subtitle
|
||||||
|
?.runs
|
||||||
|
?.map { it.text }
|
||||||
|
?.joinToString("") ?: ""
|
||||||
|
|
||||||
|
holder.bind(url = url, name = name, desc = desc)
|
||||||
|
|
||||||
holder.itemView.setOnClickListener {
|
holder.itemView.setOnClickListener {
|
||||||
|
if (browseId.isNullOrEmpty()) {
|
||||||
|
val intent = Intent(context, MoPlayDetailsActivity::class.java)
|
||||||
|
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_VIDEO_ID, videoId)
|
||||||
|
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_PLAY_LIST_ID, playlistId)
|
||||||
|
if (playlistSetVideoId != null) {
|
||||||
|
intent.putExtra(
|
||||||
|
MoPlayDetailsActivity.PLAY_DETAILS_PLAY_LIST_SET_VIDEO_ID,
|
||||||
|
playlistSetVideoId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_PLAY_PARAMS, params)
|
||||||
|
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_NAME, name)
|
||||||
|
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, desc)
|
||||||
|
context.startActivity(intent)
|
||||||
|
} else {
|
||||||
val intent = Intent(context, MoListDetailsActivity::class.java)
|
val intent = Intent(context, MoListDetailsActivity::class.java)
|
||||||
intent.putExtra(MoListDetailsActivity.PLAY_LIST_PAGE_BROWSE_ID, browseId)
|
intent.putExtra(MoListDetailsActivity.PLAY_LIST_PAGE_BROWSE_ID, browseId)
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int = list.size
|
override fun getItemCount(): Int = list.size
|
||||||
|
|
||||||
inner class ViewHolder(private val binding: MusicTowRowItemBinding) :
|
inner class ViewHolder(private val binding: MusicTowRowItemBinding) :
|
||||||
RecyclerView.ViewHolder(binding.root) {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
fun bind(content: MusicCarouselShelfRenderer.Content) {
|
fun bind(url: String, name: String, desc: String) {
|
||||||
val url = content.musicTwoRowItemRenderer
|
|
||||||
?.thumbnailRenderer
|
|
||||||
?.musicThumbnailRenderer
|
|
||||||
?.thumbnail
|
|
||||||
?.thumbnails
|
|
||||||
?.let { it.getOrNull(1) ?: it.getOrNull(0) }
|
|
||||||
?.url
|
|
||||||
val name = content.musicTwoRowItemRenderer
|
|
||||||
?.title
|
|
||||||
?.runs
|
|
||||||
?.firstOrNull()
|
|
||||||
?.text
|
|
||||||
val desc = content.musicTwoRowItemRenderer
|
|
||||||
?.subtitle
|
|
||||||
?.runs
|
|
||||||
?.map { it.text }
|
|
||||||
?.joinToString("")
|
|
||||||
binding.apply {
|
binding.apply {
|
||||||
Glide.with(context)
|
Glide.with(context)
|
||||||
.load(url)
|
.load(url)
|
||||||
|
|||||||
@ -90,6 +90,7 @@ class MoHomeFragment : MoBaseFragment<FragmentMoHomeBinding>() {
|
|||||||
initHomeDataMore(it)
|
initHomeDataMore(it)
|
||||||
} else {
|
} else {
|
||||||
LogD(TAG, "homePage size 0")
|
LogD(TAG, "homePage size 0")
|
||||||
|
showNoContentUi()
|
||||||
}
|
}
|
||||||
}?.onFailure {
|
}?.onFailure {
|
||||||
showNoContentUi()
|
showNoContentUi()
|
||||||
@ -141,16 +142,17 @@ class MoHomeFragment : MoBaseFragment<FragmentMoHomeBinding>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showDataUi(){
|
private fun showDataUi() {
|
||||||
binding.loadingLayout.visibility = View.GONE
|
binding.loadingLayout.visibility = View.GONE
|
||||||
binding.noContentLayout.visibility = View.GONE
|
binding.noContentLayout.visibility = View.GONE
|
||||||
}
|
}
|
||||||
private fun showLoadingUi(){
|
|
||||||
|
private fun showLoadingUi() {
|
||||||
binding.loadingLayout.visibility = View.VISIBLE
|
binding.loadingLayout.visibility = View.VISIBLE
|
||||||
binding.noContentLayout.visibility = View.GONE
|
binding.noContentLayout.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showNoContentUi(){
|
private fun showNoContentUi() {
|
||||||
binding.loadingLayout.visibility = View.GONE
|
binding.loadingLayout.visibility = View.GONE
|
||||||
binding.noContentLayout.visibility = View.VISIBLE
|
binding.noContentLayout.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|||||||
@ -193,7 +193,9 @@ object Innertube {
|
|||||||
val timeText: String?,
|
val timeText: String?,
|
||||||
val browseId: String,
|
val browseId: String,
|
||||||
val videoId: String?,
|
val videoId: String?,
|
||||||
val playlistId: String?,
|
val playlistId: String? = null,
|
||||||
|
val playlistSetVideoId: String? = null,
|
||||||
|
val params: String? = null,
|
||||||
val musicVideoType: String?,
|
val musicVideoType: String?,
|
||||||
val pageType: String?,
|
val pageType: String?,
|
||||||
val thumbnailUrl: String?
|
val thumbnailUrl: String?
|
||||||
|
|||||||
@ -80,7 +80,11 @@ suspend fun Innertube.moPlaylistPage(browseId: String): Result<Innertube.MoPlayl
|
|||||||
|
|
||||||
val bean = Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean(
|
val bean = Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean(
|
||||||
title = runs0?.text,
|
title = runs0?.text,
|
||||||
name = runs1?.text,
|
name = runs1?.text ?: musicDetailHeaderRenderer
|
||||||
|
?.subtitle
|
||||||
|
?.runs
|
||||||
|
?.map { it.text }
|
||||||
|
?.joinToString(""),
|
||||||
desc = runs2?.text,
|
desc = runs2?.text,
|
||||||
timeText = content.musicResponsiveListItemRenderer
|
timeText = content.musicResponsiveListItemRenderer
|
||||||
?.fixedColumns?.firstOrNull()
|
?.fixedColumns?.firstOrNull()
|
||||||
@ -92,6 +96,8 @@ suspend fun Innertube.moPlaylistPage(browseId: String): Result<Innertube.MoPlayl
|
|||||||
browseId = browseEndpoint?.browseId.toString(),
|
browseId = browseEndpoint?.browseId.toString(),
|
||||||
videoId = watchEndpoint?.videoId,
|
videoId = watchEndpoint?.videoId,
|
||||||
playlistId = watchEndpoint?.playlistId,
|
playlistId = watchEndpoint?.playlistId,
|
||||||
|
playlistSetVideoId = watchEndpoint?.playlistSetVideoId,
|
||||||
|
params = watchEndpoint?.params,
|
||||||
musicVideoType = watchEndpoint?.type,
|
musicVideoType = watchEndpoint?.type,
|
||||||
pageType = browseEndpoint?.type,
|
pageType = browseEndpoint?.type,
|
||||||
thumbnailUrl = thumbnailUrl
|
thumbnailUrl = thumbnailUrl
|
||||||
|
|||||||
@ -177,4 +177,26 @@ object MediaControllerManager {
|
|||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getCurrentPosition(): Long {
|
||||||
|
mediaController?.let {
|
||||||
|
if (it.currentPosition > 0 && it.currentPosition < it.duration) {
|
||||||
|
return it.currentPosition
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBufferedPosition(): Long {
|
||||||
|
mediaController?.let {
|
||||||
|
if (it.bufferedPosition > 0) {
|
||||||
|
return it.bufferedPosition
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,12 +57,10 @@ class PlaybackService : MediaSessionService(), Player.Listener {
|
|||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
val cacheEvictor = when (val size = ExoPlayerDiskCacheMaxSize.`2GB`){
|
val cacheEvictor = when (val size = ExoPlayerDiskCacheMaxSize.`2GB`) {
|
||||||
ExoPlayerDiskCacheMaxSize.Unlimited -> NoOpCacheEvictor()
|
ExoPlayerDiskCacheMaxSize.Unlimited -> NoOpCacheEvictor()
|
||||||
else -> LeastRecentlyUsedCacheEvictor(size.bytes)
|
else -> LeastRecentlyUsedCacheEvictor(size.bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove in a future release
|
|
||||||
val directory = cacheDir.resolve("exoplayer").also { directory ->
|
val directory = cacheDir.resolve("exoplayer").also { directory ->
|
||||||
if (directory.exists()) return@also
|
if (directory.exists()) return@also
|
||||||
|
|
||||||
@ -80,7 +78,6 @@ class PlaybackService : MediaSessionService(), Player.Listener {
|
|||||||
}
|
}
|
||||||
cache = SimpleCache(directory, cacheEvictor, StandaloneDatabaseProvider(this))
|
cache = SimpleCache(directory, cacheEvictor, StandaloneDatabaseProvider(this))
|
||||||
|
|
||||||
|
|
||||||
player = ExoPlayer.Builder(this, createRendersFactory(), createMediaSourceFactory())
|
player = ExoPlayer.Builder(this, createRendersFactory(), createMediaSourceFactory())
|
||||||
.setHandleAudioBecomingNoisy(true)
|
.setHandleAudioBecomingNoisy(true)
|
||||||
.setWakeMode(C.WAKE_MODE_LOCAL)
|
.setWakeMode(C.WAKE_MODE_LOCAL)
|
||||||
@ -181,7 +178,7 @@ class PlaybackService : MediaSessionService(), Player.Listener {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LogD(TAG,"service urlResult->$urlResult")
|
LogD(TAG, "service urlResult->$urlResult")
|
||||||
|
|
||||||
urlResult?.getOrThrow()?.let { url ->
|
urlResult?.getOrThrow()?.let { url ->
|
||||||
ringBuffer.append(videoId to url.toUri())
|
ringBuffer.append(videoId to url.toUri())
|
||||||
|
|||||||
8
app/src/main/res/drawable/drw_bottom_close_btn_bg.xml
Normal file
8
app/src/main/res/drawable/drw_bottom_close_btn_bg.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
|
||||||
|
<solid android:color="#FF555555" />
|
||||||
|
<corners android:radius="20dp" />
|
||||||
|
|
||||||
|
</shape>
|
||||||
10
app/src/main/res/drawable/drw_bottom_layout_bg.xml
Normal file
10
app/src/main/res/drawable/drw_bottom_layout_bg.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
|
||||||
|
<solid android:color="@color/bottom_layout_bg_color" />
|
||||||
|
<corners
|
||||||
|
android:topLeftRadius="18dp"
|
||||||
|
android:topRightRadius="18dp" />
|
||||||
|
|
||||||
|
</shape>
|
||||||
9
app/src/main/res/drawable/playing_small_green_icon.xml
Normal file
9
app/src/main/res/drawable/playing_small_green_icon.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="14dp"
|
||||||
|
android:height="17dp"
|
||||||
|
android:viewportWidth="14"
|
||||||
|
android:viewportHeight="17">
|
||||||
|
<path
|
||||||
|
android:pathData="M7,16.8C6.629,16.8 6.273,16.653 6.01,16.39C5.747,16.127 5.6,15.771 5.6,15.4V1.4C5.6,1.029 5.747,0.673 6.01,0.41C6.273,0.147 6.629,0 7,0C7.371,0 7.727,0.147 7.99,0.41C8.252,0.673 8.4,1.029 8.4,1.4V15.4C8.4,15.771 8.252,16.127 7.99,16.39C7.727,16.653 7.371,16.8 7,16.8ZM1.4,14C1.029,14 0.673,13.852 0.41,13.59C0.147,13.327 0,12.971 0,12.6V5.6C0,5.229 0.148,4.873 0.41,4.61C0.673,4.348 1.029,4.2 1.4,4.2C1.771,4.2 2.127,4.348 2.39,4.61C2.652,4.873 2.8,5.229 2.8,5.6V12.6C2.8,12.784 2.764,12.966 2.693,13.136C2.623,13.306 2.52,13.46 2.39,13.59C2.26,13.72 2.106,13.823 1.936,13.893C1.766,13.964 1.584,14 1.4,14ZM12.6,14C12.229,14 11.873,13.852 11.61,13.59C11.347,13.327 11.2,12.971 11.2,12.6V5.6C11.2,5.229 11.348,4.873 11.61,4.61C11.873,4.348 12.229,4.2 12.6,4.2C12.971,4.2 13.327,4.348 13.59,4.61C13.852,4.873 14,5.229 14,5.6V12.6C14,12.971 13.852,13.327 13.59,13.59C13.327,13.852 12.971,14 12.6,14Z"
|
||||||
|
android:fillColor="#FF80F988"/>
|
||||||
|
</vector>
|
||||||
@ -16,11 +16,17 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp" />
|
android:layout_height="0dp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_below="@+id/view"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/title_layout"
|
android:id="@+id/title_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@+id/view"
|
|
||||||
android:layout_margin="16dp"
|
android:layout_margin="16dp"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
@ -39,10 +45,65 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/loadingLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:indeterminateTint="@color/green"
|
||||||
|
android:progressBackgroundTint="@color/green"
|
||||||
|
android:progressTint="@color/green"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/no_content_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/no_content_iv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@mipmap/no_content_img" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
android:layout_marginEnd="32dp"
|
||||||
|
android:fontFamily="@font/medium_font"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/content_loading_failed"
|
||||||
|
android:textSize="14dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tryAgainBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:background="@drawable/drw_btn_bg"
|
||||||
|
android:fontFamily="@font/medium_font"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingStart="32dp"
|
||||||
|
android:paddingEnd="32dp"
|
||||||
|
android:text="@string/try_again"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="16dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_below="@+id/title_layout"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@ -119,4 +180,6 @@
|
|||||||
android:layout_margin="16dp" />
|
android:layout_margin="16dp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|||||||
@ -23,7 +23,7 @@
|
|||||||
android:id="@+id/imageView"
|
android:id="@+id/imageView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="5"
|
android:layout_weight="8"
|
||||||
android:scaleType="centerCrop" />
|
android:scaleType="centerCrop" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
@ -40,15 +40,15 @@
|
|||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="5"
|
android:layout_weight="8"
|
||||||
android:background="@drawable/drw_details_bg"
|
android:background="@drawable/drw_details_bg"
|
||||||
android:visibility="gone" />
|
android:visibility="visible" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:background="@color/main_bg_color" />
|
android:background="@color/black" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -122,19 +122,42 @@
|
|||||||
android:progressBackgroundTint="@color/green"
|
android:progressBackgroundTint="@color/green"
|
||||||
android:progressTint="@color/green" />
|
android:progressTint="@color/green" />
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:id="@+id/playback_error_layout"
|
android:id="@+id/playback_error_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_centerInParent="true"
|
android:gravity="center"
|
||||||
android:background="@color/black_60"
|
android:background="@color/black_60"
|
||||||
android:padding="24dp"
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:layout_marginEnd="24dp"
|
||||||
|
|
||||||
android:fontFamily="@font/medium_font"
|
android:fontFamily="@font/medium_font"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/playback_error"
|
android:text="@string/playback_error"
|
||||||
android:textColor="@color/white_80"
|
android:textColor="@color/white_80"
|
||||||
android:textSize="16dp"
|
android:textSize="16dp" />
|
||||||
android:visibility="gone" />
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tryAgainBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:background="@drawable/drw_btn_bg"
|
||||||
|
android:paddingStart="24dp"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:fontFamily="@font/medium_font"
|
||||||
|
android:paddingEnd="24dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:text="@string/try_again"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="16dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
@ -346,4 +369,50 @@
|
|||||||
android:orientation="horizontal" />
|
android:orientation="horizontal" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/bottom_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/bottom_blank_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="68dp"
|
||||||
|
android:layout_weight="3" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="5"
|
||||||
|
android:background="@drawable/drw_bottom_layout_bg"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="visible">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/bottomCloseBtn"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="30dp"
|
||||||
|
android:layout_height="4dp"
|
||||||
|
android:background="@drawable/drw_bottom_close_btn_bg"
|
||||||
|
android:gravity="center" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/playListRv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_margin="16dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|||||||
@ -78,6 +78,7 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:id="@+id/sv"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginTop="-2dp">
|
android:layout_marginTop="-2dp">
|
||||||
|
|||||||
90
app/src/main/res/layout/play_list_item.xml
Normal file
90
app/src/main/res/layout/play_list_item.xml
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout 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="wrap_content"
|
||||||
|
tools:ignore="MissingDefaultResource">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingBottom="12dp">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="16dp">
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:elevation="0dp"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:cardCornerRadius="4dp"
|
||||||
|
app:cardElevation="0dp">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/image"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:src="@mipmap/musicoo_logo_img" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/currentPlayingLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/black_60"
|
||||||
|
android:gravity="center"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/playing_small_green_icon" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.player.musicoo.view.MarqueeTextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/regular_font"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="14dp" />
|
||||||
|
|
||||||
|
<com.player.musicoo.view.MarqueeTextView
|
||||||
|
android:id="@+id/name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/regular_font"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textColor="@color/white_60"
|
||||||
|
android:textSize="12dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
@ -8,4 +8,6 @@
|
|||||||
<color name="white_80">#CCFFFFFF</color>
|
<color name="white_80">#CCFFFFFF</color>
|
||||||
<color name="main_bg_color">#151718</color>
|
<color name="main_bg_color">#151718</color>
|
||||||
<color name="green">#FF80F988</color>
|
<color name="green">#FF80F988</color>
|
||||||
|
<color name="green_60">#9980F988</color>
|
||||||
|
<color name="bottom_layout_bg_color">#1A1A1A</color>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Reference in New Issue
Block a user