添加add playlist

This commit is contained in:
ocean 2024-06-26 13:46:44 +08:00
parent 87f3fdd933
commit ca30bb789a
12 changed files with 936 additions and 39 deletions

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="LockedOrientationActivity">
tools:ignore="LockedOrientationActivity,DiscouragedApi">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
@ -89,6 +89,9 @@
<activity
android:name=".activity.MoLikedSongsActivity"
android:screenOrientation="portrait" />
<activity
android:name=".activity.MoPlaylistSongsActivity"
android:screenOrientation="portrait" />
<service
android:name=".service.PlaybackService"

View File

@ -364,7 +364,6 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
return currentCountryCode !in restrictedCountryCodes
}
suspend fun showAddPlaylistBottomDialog(favoriteBean: FavoriteBean) {
bottomAddPlaylistSheetDialog = BottomSheetDialog(this)
val view = layoutInflater.inflate(R.layout.add_playlist_layout, null)
@ -398,6 +397,8 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
).show()
}
} else {
val isOffline = App.appOfflineDBManager.getOfflineBeanByID(favoriteBean.videoId) != null
val isFavorite = App.appFavoriteDBManager.getFavoriteBeanByID(favoriteBean.videoId) != null
App.appPlaylistDBManager.insertOrUpdatePlaylistItem(
PlaylistItem(
playlistId = playlist[position].id,
@ -405,8 +406,8 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
title = favoriteBean.title,
name = favoriteBean.name,
thumbnail = favoriteBean.thumbnail,
isOffline = false,
isFavorite = favoriteBean.isFavorite
isOffline = isOffline,
isFavorite = isFavorite
)
)
withContext(Dispatchers.Main) {
@ -460,14 +461,16 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
}
val currentPlaylist = App.appPlaylistDBManager.getPlaylistByTitle(text)
if (currentPlaylist != null) {
val isOffline = App.appOfflineDBManager.getOfflineBeanByID(favoriteBean.videoId) != null//返回非null则为true
val isFavorite = App.appFavoriteDBManager.getFavoriteBeanByID(favoriteBean.videoId) != null
val playlistItem = PlaylistItem(
playlistId = currentPlaylist.id,
videoId = favoriteBean.videoId,
title = favoriteBean.title,
name = favoriteBean.name,
thumbnail = favoriteBean.thumbnail,
isOffline = false,
isFavorite = favoriteBean.isFavorite
isOffline = isOffline,
isFavorite = isFavorite
)
App.appPlaylistDBManager.insertOrUpdatePlaylistItem(playlistItem)
}

View File

@ -6,7 +6,6 @@ import android.graphics.drawable.ColorDrawable
import android.view.LayoutInflater
import android.view.View
import android.view.animation.AnimationUtils
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.annotation.OptIn
import androidx.appcompat.app.AlertDialog
@ -22,10 +21,10 @@ import melody.offline.music.R
import melody.offline.music.adapter.OfflineSongsAdapter
import melody.offline.music.ads.AdPlacement
import melody.offline.music.ads.LolAdWrapper
import melody.offline.music.bean.FavoriteBean
import melody.offline.music.bean.OfflineBean
import melody.offline.music.databinding.ActivityOfflineSongsBinding
import melody.offline.music.util.AnalysisUtil
import melody.offline.music.util.DownloadUtil
import melody.offline.music.util.LogTag
import org.json.JSONObject
@ -38,6 +37,7 @@ class MoOfflineSongsActivity : MoBaseActivity() {
data class OnFavorites(val bean: OfflineBean) : Request()
data class OnDownloadRemove(val id: String) : Request()
data class UpdateFavorite(val id: String) : Request()
data class OnAddPlaylist(val bean: OfflineBean) : Request()
}
private lateinit var binding: ActivityOfflineSongsBinding
@ -130,7 +130,17 @@ class MoOfflineSongsActivity : MoBaseActivity() {
}
}
is Request.OnAddPlaylist -> {
showAddPlaylistBottomDialog(
FavoriteBean(
videoId = it.bean.videoId,
title = it.bean.title,
name = it.bean.name,
thumbnail = it.bean.thumbnail,
isFavorite = it.bean.isFavorite
)
)
}
}
}
events.onReceive {
@ -190,7 +200,10 @@ class MoOfflineSongsActivity : MoBaseActivity() {
}
}
binding.moreAddPlaylistBtn.setOnClickListener {
if (currentPosition >= 0) {
requests.trySend(Request.OnAddPlaylist(offlineList[currentPosition]))
hideBottomLayout()
}
}
binding.favoritesBtn.setOnClickListener {
if (currentPosition >= 0) {

View File

@ -24,7 +24,7 @@ import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.gyf.immersionbar.ktx.immersionBar
import melody.offline.music.R
import melody.offline.music.adapter.PlayListAdapter
import melody.offline.music.adapter.DetailsPlayListAdapter
import melody.offline.music.databinding.ActivityMoPlayDetailsBinding
import melody.offline.music.innertube.Innertube
import melody.offline.music.media.MediaControllerManager
@ -75,7 +75,7 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
private var currentVideoID = ""
private var comeFrom: Class<*>? = null
private var playListAdapter: PlayListAdapter? = null
private var detailsPlayListAdapter: DetailsPlayListAdapter? = null
private var startPlayTime = 0L
@ -414,20 +414,20 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
}
playList.clear()
playList.addAll(allMediaItems)
playListAdapter?.notifyDataSetChanged()
detailsPlayListAdapter?.notifyDataSetChanged()
}
}
private var playList: MutableList<MediaItem> = mutableListOf()
private fun initPlayListAdapter() {
playListAdapter = PlayListAdapter(
detailsPlayListAdapter = DetailsPlayListAdapter(
this@MoPlayDetailsActivity, playList
)
binding.playListRv.layoutManager = LinearLayoutManager(
this@MoPlayDetailsActivity, LinearLayoutManager.VERTICAL, false
)
binding.playListRv.adapter = playListAdapter
binding.playListRv.adapter = detailsPlayListAdapter
}
@SuppressLint("NotifyDataSetChanged")
@ -663,8 +663,8 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION || reason == Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT) {
updateProgressUi()
updateInfoUi(meController?.currentMediaItem)
if (playListAdapter != null) {
playListAdapter?.notifyDataSetChanged()
if (detailsPlayListAdapter != null) {
detailsPlayListAdapter?.notifyDataSetChanged()
}
}
}

View File

@ -0,0 +1,241 @@
package melody.offline.music.activity
import android.annotation.SuppressLint
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.view.LayoutInflater
import android.view.View
import android.view.animation.AnimationUtils
import android.widget.TextView
import androidx.annotation.OptIn
import androidx.appcompat.app.AlertDialog
import androidx.media3.common.util.UnstableApi
import androidx.recyclerview.widget.LinearLayoutManager
import com.bumptech.glide.Glide
import com.gyf.immersionbar.ktx.immersionBar
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.selects.select
import melody.offline.music.App
import melody.offline.music.R
import melody.offline.music.adapter.PlaylistSongsAdapter
import melody.offline.music.ads.AdPlacement
import melody.offline.music.ads.LolAdWrapper
import melody.offline.music.bean.PlaylistItem
import melody.offline.music.databinding.ActivityPlaylistSongsBinding
@OptIn(UnstableApi::class)
class MoPlaylistSongsActivity : MoBaseActivity() {
companion object {
const val PLAYLIST_ID = "playlist_id"
const val PLAYLIST_TITLE = "playlist_title"
}
private val requests: Channel<Request> = Channel(Channel.UNLIMITED)
sealed class Request {
data object TryAgain : Request()
}
private lateinit var binding: ActivityPlaylistSongsBinding
private var adapter: PlaylistSongsAdapter? = null
private var playlistItems: MutableList<PlaylistItem> = mutableListOf()
private var currentPosition = -1
private var playlistId = -1
private var playlistTitle = ""
override suspend fun main() {
binding = ActivityPlaylistSongsBinding.inflate(layoutInflater)
setContentView(binding.root)
playlistId = intent.getIntExtra(PLAYLIST_ID, -1)
playlistTitle = intent.getStringExtra(PLAYLIST_TITLE) ?: ""
LolAdWrapper.shared.showAdTiming(this, AdPlacement.INST_ME_PAGE_LIST)
initImmersionBar()
initView()
initAdapter()
LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_ME_PAGE_LIST)
initData()
onReceive()
}
private fun initImmersionBar() {
immersionBar {
statusBarDarkFont(false)
statusBarView(binding.view)
}
}
@SuppressLint("NotifyDataSetChanged")
private suspend fun onReceive() {
while (isActive) {
select<Unit> {
requests.onReceive {
when (it) {
Request.TryAgain -> {
initData()
}
}
}
events.onReceive {
when (it) {
Event.ActivityOnResume -> {
activityOnResume()
}
Event.AutomaticallySwitchSongs -> {
if (adapter != null) {
adapter?.notifyDataSetChanged()
}
}
else -> {}
}
}
}
}
}
@SuppressLint("NotifyDataSetChanged")
private fun activityOnResume() {
addMusicPlayerViewToLayout(binding.playMusicLayout)
if (adapter != null) {
adapter?.notifyDataSetChanged()
}
LolAdWrapper.shared.loadAdShowNativeAd(
this,
AdPlacement.NATIVE_ME_PAGE_LIST,
binding.frameAd,
R.layout.ad_layout_admob_banner,
R.layout.ad_layout_max_banner
)
}
private fun initView() {
binding.titleText.text = playlistTitle
binding.layoutInfo.setOnClickListener { }
binding.backBtn.setOnClickListener {
finish()
}
binding.tryAgainBtn.setOnClickListener {
requests.trySend(Request.TryAgain)
}
binding.bottomCloseBtn.setOnClickListener {
hideBottomLayout()
}
binding.bottomBlankLayout.setOnClickListener {
hideBottomLayout()
}
binding.moreDownloadBtn.setOnClickListener {
if (currentPosition >= 0) {
}
}
binding.moreAddPlaylistBtn.setOnClickListener {
if (currentPosition >= 0) {
}
}
binding.favoritesBtn.setOnClickListener {
if (currentPosition >= 0) {
}
}
}
private fun initAdapter() {
adapter = PlaylistSongsAdapter(this, playlistItems)
adapter?.setOnMoreClickListener(object : PlaylistSongsAdapter.OnMoreClickListener {
override fun onMoreClick(position: Int) {
currentPosition = position
toggleBottomLayout(position)
}
})
binding.rv.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
binding.rv.adapter = adapter
}
@SuppressLint("NotifyDataSetChanged")
private suspend fun initData() {
showLoadingUi()
playlistItems.clear()
playlistItems.addAll(App.appPlaylistDBManager.getPlaylistItems(playlistId))
if (playlistItems.size > 0) {
showDataUi()
} else {
showNoContentUi()
}
if (adapter != null) {
adapter?.notifyDataSetChanged()
}
}
private fun showRemoveDownloadDialogHint(id: String) {
val inflater = LayoutInflater.from(this)
val dialogView = inflater.inflate(R.layout.dialog_hint, null)
val okBtn = dialogView.findViewById<TextView>(R.id.dialog_ok_btn)
val cancelBtn = dialogView.findViewById<TextView>(R.id.dialog_cancel_btn)
val dialogBuilder = AlertDialog.Builder(this).setView(dialogView)
val dialog = dialogBuilder.create()
dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialog.show()
okBtn.setOnClickListener {
dialog.dismiss()
}
cancelBtn.setOnClickListener {
dialog.dismiss()
}
}
private fun updateFavoriteUi(b: Boolean) {
if (b) {
binding.favoritesImg.setImageResource(R.drawable.favorited_icon)
} else {
binding.favoritesImg.setImageResource(R.drawable.not_favorited_icon)
}
}
private fun toggleBottomLayout(position: Int) {
if (binding.bottomLayout.visibility == View.VISIBLE) {
hideBottomLayout()
} else {
showBottomLayout(position)
}
}
private fun showBottomLayout(position: Int) {
val slideUpAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_up)
binding.bottomLayout.startAnimation(slideUpAnimation)
binding.bottomLayout.visibility = View.VISIBLE
val bean = playlistItems[position]
Glide.with(this).load(bean.thumbnail).into(binding.songImg)
binding.title.text = bean.title
if (bean.name.isEmpty()) {
binding.name.visibility = View.GONE
} else {
binding.name.visibility = View.VISIBLE
binding.name.text = bean.name
}
}
private fun hideBottomLayout() {
val slideDownAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_down)
binding.bottomLayout.startAnimation(slideDownAnimation)
binding.bottomLayout.visibility = View.GONE
}
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
}
}

View File

@ -10,17 +10,17 @@ import androidx.media3.common.MediaItem
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import melody.offline.music.R
import melody.offline.music.databinding.PlayListItemBinding
import melody.offline.music.databinding.DetailsPlayListItemBinding
import melody.offline.music.media.MediaControllerManager
class PlayListAdapter(
class DetailsPlayListAdapter(
private val context: Context,
private val list: List<MediaItem>,
) :
RecyclerView.Adapter<PlayListAdapter.ViewHolder>() {
RecyclerView.Adapter<DetailsPlayListAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = PlayListItemBinding.inflate(LayoutInflater.from(context), parent, false)
val binding = DetailsPlayListItemBinding.inflate(LayoutInflater.from(context), parent, false)
return ViewHolder(binding)
}
@ -46,7 +46,7 @@ class PlayListAdapter(
override fun getItemCount(): Int = list.size
inner class ViewHolder(private val binding: PlayListItemBinding) :
inner class ViewHolder(private val binding: DetailsPlayListItemBinding) :
RecyclerView.ViewHolder(binding.root) {
@SuppressLint("SetTextI18n")

View File

@ -0,0 +1,121 @@
package melody.offline.music.adapter
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import melody.offline.music.R
import melody.offline.music.activity.MoOfflineSongsActivity
import melody.offline.music.activity.MoPlayDetailsActivity
import melody.offline.music.bean.OfflineBean
import melody.offline.music.bean.PlaylistItem
import melody.offline.music.databinding.PlayListItemBinding
import melody.offline.music.media.MediaControllerManager
class PlaylistSongsAdapter(
private val context: Context,
private val list: List<PlaylistItem>,
) : RecyclerView.Adapter<PlaylistSongsAdapter.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.binding.moreBtn.setOnClickListener {
if (moreClickListener != null) {
moreClickListener?.onMoreClick(position)
}
}
holder.binding.downloadBtn.setOnClickListener {
if (itemDownloadClickListener != null) {
itemDownloadClickListener?.onDownloadItemClick(position)
}
}
holder.itemView.setOnClickListener {
// val intent = Intent(context, MoPlayDetailsActivity::class.java)
// intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_VIDEO_ID, bean.videoId)
// intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_NAME, bean.title)
// intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, bean.name)
// intent.putExtra(
// MoPlayDetailsActivity.PLAY_DETAILS_COME_FROM, MoOfflineSongsActivity::class.java
// )
// context.startActivity(intent)
}
}
override fun getItemCount(): Int = list.size
inner class ViewHolder(val binding: PlayListItemBinding) :
RecyclerView.ViewHolder(binding.root) {
@SuppressLint("SetTextI18n")
fun bind(bean: PlaylistItem) {
binding.apply {
Glide.with(context).load(bean.thumbnail).into(image)
title.text = bean.title
if (bean.name.isEmpty()) {
name.visibility = View.GONE
} else {
name.visibility = View.VISIBLE
name.text = bean.name
}
if (bean.size?.isNotEmpty() == true) {
size.text = bean.size
size.visibility = View.VISIBLE
} else {
size.visibility = View.GONE
}
if (bean.isOffline) {
downloadCoImg.visibility = View.VISIBLE
downloadImg.setImageResource(R.drawable.download_done_icon)
} else {
downloadCoImg.visibility = View.GONE
downloadImg.setImageResource(R.drawable.download_icon)
}
}
}
}
private var itemDownloadClickListener: OnItemDownloadClickListener? = null
fun setOnDownloadItemClickListener(listener: OnItemDownloadClickListener) {
itemDownloadClickListener = listener
}
interface OnItemDownloadClickListener {
fun onDownloadItemClick(position: Int)
}
private var itemClickListener: OnItemClickListener? = null
fun setOnItemClickListener(listener: OnItemClickListener) {
itemClickListener = listener
}
interface OnItemClickListener {
fun onItemClick(position: Int)
}
private var moreClickListener: OnMoreClickListener? = null
fun setOnMoreClickListener(listener: OnMoreClickListener) {
moreClickListener = listener
}
interface OnMoreClickListener {
fun onMoreClick(position: Int)
}
}

View File

@ -30,6 +30,7 @@ import melody.offline.music.App
import melody.offline.music.R
import melody.offline.music.activity.MoLikedSongsActivity
import melody.offline.music.activity.MoOfflineSongsActivity
import melody.offline.music.activity.MoPlaylistSongsActivity
import melody.offline.music.activity.SettingsActivity
import melody.offline.music.adapter.LikedSongsAdapter
import melody.offline.music.adapter.NewPlayListAdapter
@ -186,7 +187,9 @@ class MoMeFragment : MoBaseFragment<FragmentMoMeBinding>(), NewPlayListAdapter.O
}
override fun onItemClick(position: Int) {
val intent = Intent(requireActivity(), MoPlaylistSongsActivity::class.java)
intent.putExtra(MoPlaylistSongsActivity.PLAYLIST_ID, playlist[position].id)
startActivity(intent)
}
private var bottomSheetDialog: BottomSheetDialog? = null

View File

@ -0,0 +1,362 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/main_bg_color"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@mipmap/settings_bg_img" />
<View
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="0dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/view"
android:orientation="vertical">
<LinearLayout
android:id="@+id/title_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:orientation="horizontal">
<RelativeLayout
android:id="@+id/back_btn"
android:layout_width="42dp"
android:layout_height="42dp"
android:background="@drawable/drw_back_bg">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/back_icon" />
</RelativeLayout>
<TextView
android:id="@+id/title_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:fontFamily="@font/medium_font"
android:gravity="center"
android:text="@string/app_name"
android:textColor="@color/white"
android:textSize="18dp" />
<RelativeLayout
android:id="@+id/playlist_title_more_btn"
android:layout_width="42dp"
android:layout_height="42dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/three_dots_icon" />
</RelativeLayout>
</LinearLayout>
<FrameLayout
android:id="@+id/frame_ad"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp" />
<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:layout_height="wrap_content"
android:indeterminateTint="@color/green"
android:progressBackgroundTint="@color/green"
android:progressTint="@color/green" />
</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>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/play_music_layout"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:overScrollMode="never"
android:scrollbars="none" />
</LinearLayout>
<LinearLayout
android:id="@+id/play_music_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="vertical" />
</RelativeLayout>
</LinearLayout>
<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:id="@+id/layout_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/drw_bottom_layout_bg"
android:orientation="vertical"
android:paddingBottom="32dp"
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>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="18dp"
android:paddingEnd="18dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="0dp"
app:cardBackgroundColor="@color/transparent"
app:cardCornerRadius="10dp"
app:cardElevation="0dp">
<ImageView
android:id="@+id/songImg"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@mipmap/app_logo" />
</androidx.cardview.widget.CardView>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="vertical">
<melody.offline.music.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" />
<melody.offline.music.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
android:id="@+id/favoritesBtn"
android:layout_width="32dp"
android:layout_height="32dp"
android:background="@drawable/drw_round_48_bg"
android:gravity="center">
<ImageView
android:id="@+id/favoritesImg"
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/not_favorited_icon" />
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="16dp"
android:background="@color/liner_color" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/moreDownloadBtn"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginTop="4dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/downloadImg"
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/more_downloaded_icon" />
<ProgressBar
android:id="@+id/downloadLoading"
android:layout_width="24dp"
android:layout_height="24dp"
android:indeterminateTint="@color/green"
android:progressBackgroundTint="@color/green"
android:progressTint="@color/green"
android:visibility="gone" />
</RelativeLayout>
<TextView
android:id="@+id/downloadTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/download_remove_offline"
android:textColor="@color/white"
android:textSize="14dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/moreAddPlaylistBtn"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginTop="4dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/more_add_playlist_icon" />
<TextView
android:id="@+id/addPlaylistTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/add_to_playlist"
android:textColor="@color/white"
android:textSize="14dp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View 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/app_logo" />
<RelativeLayout
android:id="@+id/listPlayView"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black_60">
<melody.offline.music.view.MusicBarsView
android:layout_width="wrap_content"
android:layout_height="16dp"
android:layout_centerInParent="true" />
</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">
<melody.offline.music.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" />
<melody.offline.music.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>

View File

@ -32,17 +32,17 @@
<ImageView
android:id="@+id/image"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@mipmap/app_logo" />
<RelativeLayout
android:id="@+id/listPlayView"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black_60">
android:background="@color/black_60"
android:visibility="gone">
<melody.offline.music.view.MusicBarsView
android:layout_width="wrap_content"
@ -58,8 +58,9 @@
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="vertical">
@ -67,24 +68,84 @@
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/regular_font"
android:fontFamily="@font/medium_font"
android:maxLines="1"
android:text="@string/app_name"
android:textColor="@color/white"
android:textSize="14dp" />
<melody.offline.music.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
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/downloadCoImg"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginEnd="4dp"
android:src="@drawable/download_green_done_icon" />
<TextView
android:id="@+id/size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:fontFamily="@font/regular_font"
android:text="@string/app_name"
android:textColor="@color/white_60"
android:textSize="12dp" />
<melody.offline.music.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
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/downloadBtn"
android:layout_width="40dp"
android:layout_height="40dp"
android:gravity="center">
<ImageView
android:id="@+id/downloadImg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/download_icon" />
</LinearLayout>
<LinearLayout
android:id="@+id/moreBtn"
android:layout_width="40dp"
android:layout_height="40dp"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/three_dots_icon" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -53,5 +53,5 @@
android:scrollbars="none"
android:overScrollMode="never"
tools:itemCount="1"
tools:listitem="@layout/play_list_item" />
tools:listitem="@layout/details_play_list_item" />
</LinearLayout>