This commit is contained in:
ocean 2024-05-17 11:49:11 +08:00
parent 9b91074eeb
commit d14b11fac6
39 changed files with 994 additions and 548 deletions

View File

@ -119,9 +119,6 @@ class MainActivity : BaseActivity() {
intent.putExtra(PlayDetailsActivity.KEY_DETAILS_AUDIO, audio) intent.putExtra(PlayDetailsActivity.KEY_DETAILS_AUDIO, audio)
startActivity(intent) startActivity(intent)
} }
binding.alarmClockBtn.setOnClickListener {
}
binding.playBlackBtn.setOnClickListener { binding.playBlackBtn.setOnClickListener {
val currentPlayer = MediaControllerManager.getController() val currentPlayer = MediaControllerManager.getController()

View File

@ -6,20 +6,29 @@ import android.graphics.BitmapFactory
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.os.Bundle import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.renderscript.Allocation import android.renderscript.Allocation
import android.renderscript.Element import android.renderscript.Element
import android.renderscript.RenderScript import android.renderscript.RenderScript
import android.renderscript.ScriptIntrinsicBlur import android.renderscript.ScriptIntrinsicBlur
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.widget.LinearLayout
import android.widget.RelativeLayout import android.widget.RelativeLayout
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.media3.common.Player
import androidx.media3.session.MediaController
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.player.musicoo.R import com.player.musicoo.R
import com.player.musicoo.innertube.Innertube
import com.player.musicoo.innertube.Innertube.TAG
import com.player.musicoo.media.MediaControllerManager import com.player.musicoo.media.MediaControllerManager
import com.player.musicoo.sp.AppStore import com.player.musicoo.sp.AppStore
import com.player.musicoo.util.LogTag import com.player.musicoo.util.LogTag
import com.player.musicoo.view.MusicPlayerView
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope import kotlinx.coroutines.MainScope
@ -31,11 +40,13 @@ import java.io.IOException
import java.io.InputStream import java.io.InputStream
abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope() { abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope() {
private var playerListener: Player.Listener? = null
enum class Event { enum class Event {
ActivityStart, ActivityStart,
ActivityStop, ActivityStop,
ActivityOnResume ActivityOnResume,
AutomaticallySwitchSongs,
} }
protected val TAG = LogTag.VO_ACT_LOG protected val TAG = LogTag.VO_ACT_LOG
@ -45,6 +56,7 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
protected abstract suspend fun main() protected abstract suspend fun main()
private var defer: suspend () -> Unit = {} private var defer: suspend () -> Unit = {}
private var deferRunning = false private var deferRunning = false
private lateinit var musicPlayerView: MusicPlayerView
fun defer(operation: suspend () -> Unit) { fun defer(operation: suspend () -> Unit) {
this.defer = operation this.defer = operation
@ -52,6 +64,8 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
musicPlayerView = MusicPlayerView(this, meController)
initPlayerListener()
launch { launch {
main() main()
} }
@ -90,21 +104,97 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
} }
} }
suspend fun loadBitmapWithGlide(imageUrl: String): Bitmap? { fun addMusicPlayerViewToLayout(layoutId: LinearLayout) {
return withContext(Dispatchers.IO) { if (meController != null && meController.mediaItemCount > 0 && meController.duration > 0) {
try { if (layoutId.childCount <= 0) {//没有添加view才进行添加
Glide.with(this@MoBaseActivity) layoutId.addView(musicPlayerView)
.asBitmap() }
.load(imageUrl) musicPlayerView.updateInfoUi(meController.currentMediaItem)
.submit() // 异步加载Bitmap musicPlayerView.updateSetProgress(meController)
.get() // 阻塞等待获取Bitmap musicPlayerView.updateProgressState(meController)
} catch (e: Exception) { layoutId.visibility = View.VISIBLE
e.printStackTrace() } else {
null layoutId.visibility = View.GONE
}
}
private fun initPlayerListener() {
if (this !is MoPlayDetailsActivity) {
if (playerListener == null) {
LogTag.LogD(TAG, "MoBaseActivity initPlayerListener")
meController?.addListener(getPlayerListener())
} }
} }
} }
override fun onDestroy() {
super.onDestroy()
LogTag.LogD(TAG, "MoBaseActivity onDestroy")
if (meController != null && playerListener != null) {
meController.removeListener(playerListener!!)
}
}
private fun getPlayerListener(): Player.Listener {
if (playerListener == null) {
playerListener = object : Player.Listener {
override fun onPositionDiscontinuity(
oldPosition: Player.PositionInfo,
newPosition: Player.PositionInfo,
reason: Int
) {
if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION) {
LogTag.LogD(
Innertube.TAG,
"MoBaseActivity DISCONTINUITY_REASON_AUTO_TRANSITION"
)
if (meController != null) {
musicPlayerView.updateInfoUi(meController.currentMediaItem)
musicPlayerView.updateSetProgress(meController)
musicPlayerView.updateProgressState(meController)
}
events.trySend(Event.AutomaticallySwitchSongs)
}
}
override fun onPlaybackStateChanged(playbackState: Int) {
LogTag.LogD(Innertube.TAG, "MoBaseActivity playbackState->$playbackState")
val meController = MediaControllerManager.getController()
if (meController != null) {
musicPlayerView.updateProgressState(meController)
when (playbackState) {
Player.STATE_READY -> {
musicPlayerView.updateSetProgress(meController)
}
else -> {}
}
}
}
override fun onPlayWhenReadyChanged(
playWhenReady: Boolean,
reason: Int
) {
LogTag.LogD(
Innertube.TAG,
"MoBaseActivity onPlayWhenReadyChanged->$playWhenReady"
)
musicPlayerView.updatePlayState(playWhenReady)
val meController = MediaControllerManager.getController()
if (meController != null) {
musicPlayerView.updateProgressState(meController)
}
}
}
}
return playerListener!!
}
fun applyGaussianBlur(inputBitmap: Bitmap, radius: Float, context: Context): Bitmap { fun applyGaussianBlur(inputBitmap: Bitmap, radius: Float, context: Context): Bitmap {
val rsContext = RenderScript.create(context) val rsContext = RenderScript.create(context)
val outputBitmap = val outputBitmap =
@ -120,16 +210,6 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
return outputBitmap return outputBitmap
} }
fun loadBitmapFromAsset(id: Int): Bitmap {
return try {
val inputStream: InputStream = resources.openRawResource(id)
BitmapFactory.decodeStream(inputStream)
} catch (e: IOException) {
e.printStackTrace()
throw RuntimeException("Could not load bitmap from asset")
}
}
fun showSongDescriptionDialog(description: String) { fun showSongDescriptionDialog(description: String) {
val inflater = LayoutInflater.from(this) val inflater = LayoutInflater.from(this)
val dialogView = inflater.inflate(R.layout.dialog_description, null) val dialogView = inflater.inflate(R.layout.dialog_description, null)

View File

@ -1,12 +1,12 @@
package com.player.musicoo.activity package com.player.musicoo.activity
import android.annotation.SuppressLint
import android.view.View 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
import com.player.musicoo.adapter.DetailsListAdapter import com.player.musicoo.adapter.DetailsListAdapter
import com.player.musicoo.databinding.ActivityDetailsBinding import com.player.musicoo.databinding.ActivityDetailsBinding
import com.player.musicoo.fragment.MoHomeFragment
import com.player.musicoo.innertube.Innertube import com.player.musicoo.innertube.Innertube
import com.player.musicoo.innertube.requests.moPlaylistPage import com.player.musicoo.innertube.requests.moPlaylistPage
import com.player.musicoo.util.LogTag.LogD import com.player.musicoo.util.LogTag.LogD
@ -28,6 +28,7 @@ class MoListDetailsActivity : MoBaseActivity() {
private lateinit var binding: ActivityDetailsBinding private lateinit var binding: ActivityDetailsBinding
private var browseId: String? = null private var browseId: String? = null
private var adapter: DetailsListAdapter? = null
override suspend fun main() { override suspend fun main() {
binding = ActivityDetailsBinding.inflate(layoutInflater) binding = ActivityDetailsBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
@ -50,6 +51,7 @@ class MoListDetailsActivity : MoBaseActivity() {
} }
} }
@SuppressLint("NotifyDataSetChanged")
private suspend fun onReceive() { private suspend fun onReceive() {
while (isActive) { while (isActive) {
select<Unit> { select<Unit> {
@ -60,10 +62,34 @@ class MoListDetailsActivity : MoBaseActivity() {
} }
} }
} }
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()
}
}
private fun initView() { private fun initView() {
binding.backBtn.setOnClickListener { binding.backBtn.setOnClickListener {
finish() finish()
@ -86,7 +112,7 @@ class MoListDetailsActivity : MoBaseActivity() {
binding.subtitle.text = it.subtitle binding.subtitle.text = it.subtitle
binding.secondSubtitle.text = it.secondSubtitle binding.secondSubtitle.text = it.secondSubtitle
val adapter = DetailsListAdapter(this, it.moPlaylistOrAlbumListBean) adapter = DetailsListAdapter(this, it.moPlaylistOrAlbumListBean)
binding.rv.layoutManager = binding.rv.layoutManager =
LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
binding.rv.adapter = adapter binding.rv.adapter = adapter

View File

@ -24,7 +24,9 @@ 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.sp.AppStore
import com.player.musicoo.util.LogTag.LogD import com.player.musicoo.util.LogTag.LogD
import com.player.musicoo.util.PlayMode
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
@ -65,7 +67,8 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
initImmersionBar() initImmersionBar()
initClick() initClick()
initPlayerListener() initPlayerListener()
initPlayListAdapter()
updatePlayModeUi()
val videoId = intent.getStringExtra(PLAY_DETAILS_VIDEO_ID) val videoId = intent.getStringExtra(PLAY_DETAILS_VIDEO_ID)
val playlistId = intent.getStringExtra(PLAY_DETAILS_PLAY_LIST_ID) val playlistId = intent.getStringExtra(PLAY_DETAILS_PLAY_LIST_ID)
val playlistSetVideoId = intent.getStringExtra(PLAY_DETAILS_PLAY_LIST_SET_VIDEO_ID) val playlistSetVideoId = intent.getStringExtra(PLAY_DETAILS_PLAY_LIST_SET_VIDEO_ID)
@ -79,6 +82,7 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
if (meController != null && meController.currentMediaItem != null && videoId == meController.currentMediaItem?.mediaId) { if (meController != null && meController.currentMediaItem != null && videoId == meController.currentMediaItem?.mediaId) {
//进入的id与当前的id一样就不重新去获取播放 //进入的id与当前的id一样就不重新去获取播放
updateCurrentMediaItemInfo() updateCurrentMediaItemInfo()
updateInfoUi(meController.currentMediaItem)
} else { } else {
binding.nameTv.text = intent.getStringExtra(PLAY_DETAILS_NAME) binding.nameTv.text = intent.getStringExtra(PLAY_DETAILS_NAME)
binding.descTv.text = intent.getStringExtra(PLAY_DETAILS_DESC) binding.descTv.text = intent.getStringExtra(PLAY_DETAILS_DESC)
@ -154,27 +158,42 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
binding.progressBar.progress = MediaControllerManager.getBufferedPosition().toInt() binding.progressBar.progress = MediaControllerManager.getBufferedPosition().toInt()
binding.progressBar.max = MediaControllerManager.getDuration().toInt() binding.progressBar.max = MediaControllerManager.getDuration().toInt()
updateProgressBufferingState() updateProgressBufferingState()
updatePlayListDataAndAdapter()
}
}
@SuppressLint("NotifyDataSetChanged")
private fun updatePlayListDataAndAdapter() {
if (meController != null && meController.currentMediaItem != null) {
val mediaItemCount = meController.mediaItemCount val mediaItemCount = meController.mediaItemCount
val allMediaItems: MutableList<MediaItem> = mutableListOf() val allMediaItems: MutableList<MediaItem> = mutableListOf()
for (index in 0 until mediaItemCount) { for (index in 0 until mediaItemCount) {
val mediaItemAt = meController.getMediaItemAt(index) val mediaItemAt = meController.getMediaItemAt(index)
allMediaItems.add(mediaItemAt) allMediaItems.add(mediaItemAt)
} }
playListAdapter = PlayListAdapter( playList.clear()
this@MoPlayDetailsActivity, playList.addAll(allMediaItems)
allMediaItems playListAdapter?.notifyDataSetChanged()
)
binding.playListRv.layoutManager =
LinearLayoutManager(
this@MoPlayDetailsActivity,
LinearLayoutManager.VERTICAL,
false
)
binding.playListRv.adapter = playListAdapter
} }
} }
private var playList: MutableList<MediaItem> = mutableListOf()
private fun initPlayListAdapter() {
playListAdapter = PlayListAdapter(
this@MoPlayDetailsActivity,
playList
)
binding.playListRv.layoutManager =
LinearLayoutManager(
this@MoPlayDetailsActivity,
LinearLayoutManager.VERTICAL,
false
)
binding.playListRv.adapter = playListAdapter
}
@SuppressLint("NotifyDataSetChanged")
private fun initClick() { private fun initClick() {
binding.backBtn.setOnClickListener { binding.backBtn.setOnClickListener {
finish() finish()
@ -189,6 +208,40 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
} }
} }
} }
binding.playModeBtn.setOnClickListener {
if (meController != null) {
val playModeCounter = (appStore.playMusicMode + 1) % 3
appStore.playMusicMode = when (playModeCounter) {
0 -> PlayMode.LIST_LOOP.value
1 -> PlayMode.SINGLE_LOOP.value
else -> PlayMode.RANDOM.value
}
when (AppStore(this).playMusicMode) {
PlayMode.LIST_LOOP.value -> {
meController.repeatMode = Player.REPEAT_MODE_ALL
meController.shuffleModeEnabled = false
}
PlayMode.SINGLE_LOOP.value -> {
meController.repeatMode = Player.REPEAT_MODE_ONE
meController.shuffleModeEnabled = false
}
PlayMode.RANDOM.value -> {
meController.repeatMode = Player.REPEAT_MODE_ALL
// val availableCommands = meController.availableCommands
// //控制器支持设置随机播放模式的命令
// if (availableCommands.contains(Player.COMMAND_SET_SHUFFLE_MODE)) {
// meController.shuffleModeEnabled = true
// }
meController.shuffleModeEnabled = true
}
}
updatePlayModeUi()
LogD(TAG, "repeatMode->${meController.repeatMode}")
LogD(TAG, "shuffleModeEnabled->${meController.shuffleModeEnabled}")
}
}
binding.playLayoutBtn.setOnClickListener { binding.playLayoutBtn.setOnClickListener {
if (meController != null) { if (meController != null) {
if (meController.isPlaying) { if (meController.isPlaying) {
@ -249,6 +302,30 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
} }
} }
private fun updatePlayModeUi() {
binding.modePlayImg.setImageResource(
when (AppStore(this).playMusicMode) {
PlayMode.LIST_LOOP.value -> {
R.drawable.mode_cycle_play_icon
}
PlayMode.SINGLE_LOOP.value -> {
R.drawable.mode_single_play_icon
}
PlayMode.RANDOM.value -> {
R.drawable.mode_random_play_icon
}
else -> {
R.drawable.mode_cycle_play_icon
}
}
)
}
@SuppressLint("NotifyDataSetChanged")
private fun initData( private fun initData(
videoId: String, videoId: String,
playlistId: String? = null, playlistId: String? = null,
@ -268,18 +345,6 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
binding.loadingView.visibility = View.GONE binding.loadingView.visibility = View.GONE
binding.disableClicksLayout.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) {
@ -322,6 +387,8 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
.filter { filter -> filter.mediaId != videoId } .filter { filter -> filter.mediaId != videoId }
it.addMediaItems(mediaItems) it.addMediaItems(mediaItems)
} }
updatePlayListDataAndAdapter()
} else { } else {
binding.playbackErrorLayout.visibility = View.VISIBLE binding.playbackErrorLayout.visibility = View.VISIBLE
} }

View File

@ -91,10 +91,24 @@ class MoSearchMoreActivity : MoBaseActivity() {
} }
} }
} }
events.onReceive {
when (it) {
Event.ActivityOnResume -> {
activityOnResume()
}
else -> {}
}
}
} }
} }
} }
private fun activityOnResume() {
addMusicPlayerViewToLayout(binding.playMusicLayout)
}
private fun initView() { private fun initView() {
binding.backBtn.setOnClickListener { binding.backBtn.setOnClickListener {
finish() finish()

View File

@ -59,10 +59,23 @@ class MoSingerDetailsActivity : MoBaseActivity() {
} }
} }
} }
events.onReceive {
when (it) {
Event.ActivityOnResume -> {
activityOnResume()
}
else -> {}
}
}
} }
} }
} }
private fun activityOnResume() {
addMusicPlayerViewToLayout(binding.playMusicLayout)
}
private fun initView() { private fun initView() {
binding.backBtn.setOnClickListener { binding.backBtn.setOnClickListener {
finish() finish()

View File

@ -74,16 +74,29 @@ class MoSingerMoreSongActivity : MoBaseActivity() {
Request.MoreData -> { Request.MoreData -> {
if (!currentContinuation.isNullOrEmpty()) { if (!currentContinuation.isNullOrEmpty()) {
initDataMore(currentContinuation!!) initDataMore(currentContinuation!!)
}else{ } else {
binding.refreshLayout.finishLoadMoreWithNoMoreData() binding.refreshLayout.finishLoadMoreWithNoMoreData()
} }
} }
} }
} }
events.onReceive {
when (it) {
Event.ActivityOnResume -> {
activityOnResume()
}
else -> {}
}
}
} }
} }
} }
private fun activityOnResume() {
addMusicPlayerViewToLayout(binding.playMusicLayout)
}
private fun initView() { private fun initView() {
binding.backBtn.setOnClickListener { binding.backBtn.setOnClickListener {
finish() finish()

View File

@ -15,13 +15,14 @@ import com.player.musicoo.R
import com.player.musicoo.databinding.ActivityPrimaryBinding import com.player.musicoo.databinding.ActivityPrimaryBinding
import com.player.musicoo.fragment.ImportFragment import com.player.musicoo.fragment.ImportFragment
import com.player.musicoo.fragment.MoHomeFragment import com.player.musicoo.fragment.MoHomeFragment
import com.player.musicoo.fragment.MoMeFragment
import com.player.musicoo.fragment.SearchFragment import com.player.musicoo.fragment.SearchFragment
import com.player.musicoo.media.MediaControllerManager import com.player.musicoo.media.MediaControllerManager
import com.player.musicoo.util.LogTag.LogD import com.player.musicoo.util.LogTag.LogD
import kotlinx.coroutines.isActive import kotlinx.coroutines.isActive
import kotlinx.coroutines.selects.select import kotlinx.coroutines.selects.select
class PrimaryActivity : MoBaseActivity() ,SearchFragment.SearchFragmentCancelClickListener{ class PrimaryActivity : MoBaseActivity(), SearchFragment.SearchFragmentCancelClickListener {
/** /**
* musicResponsiveListItemRenderer * musicResponsiveListItemRenderer
* musicTwoRowItemRenderer * musicTwoRowItemRenderer
@ -36,8 +37,6 @@ class PrimaryActivity : MoBaseActivity() ,SearchFragment.SearchFragmentCancelCli
binding = ActivityPrimaryBinding.inflate(layoutInflater) binding = ActivityPrimaryBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
initView() initView()
initPlayerListener()
onReceive() onReceive()
} }
@ -55,32 +54,10 @@ class PrimaryActivity : MoBaseActivity() ,SearchFragment.SearchFragmentCancelCli
updateBtnState(1) updateBtnState(1)
changeFragment(1) changeFragment(1)
} }
binding.importBtn.setOnClickListener { binding.meBtn.setOnClickListener {
updateBtnState(2) updateBtnState(2)
changeFragment(2) changeFragment(2)
} }
binding.playBlackBtn.setOnClickListener {
if (meController != null) {
if (meController.isPlaying) {
meController.pause()
updatePlayState(false)
} else {
meController.play()
updatePlayState(true)
}
updateProgressState()
}
}
binding.goDetailsBtn.setOnClickListener {
val intent = Intent(this, MoPlayDetailsActivity::class.java)
intent.putExtra(
MoPlayDetailsActivity.PLAY_DETAILS_COME_FROM,
PrimaryActivity::class.java
)
startActivity(intent)
}
} }
private fun initFragment() { private fun initFragment() {
@ -89,7 +66,7 @@ class PrimaryActivity : MoBaseActivity() ,SearchFragment.SearchFragmentCancelCli
val searchFragment = SearchFragment() val searchFragment = SearchFragment()
searchFragment.setButtonClickListener(this) searchFragment.setButtonClickListener(this)
mFragments.add(searchFragment) mFragments.add(searchFragment)
mFragments.add(ImportFragment()) mFragments.add(MoMeFragment())
updateBtnState(0) updateBtnState(0)
changeFragment(0) changeFragment(0)
} }
@ -137,10 +114,10 @@ class PrimaryActivity : MoBaseActivity() ,SearchFragment.SearchFragmentCancelCli
} }
} }
) )
importImg.setImageResource( meImg.setImageResource(
when (index) { when (index) {
2 -> R.drawable.import_select_icon 2 -> R.drawable.me_select_icon
else -> R.drawable.import_unselect_icon else -> R.drawable.me_unselect_icon
} }
) )
} }
@ -164,60 +141,13 @@ class PrimaryActivity : MoBaseActivity() ,SearchFragment.SearchFragmentCancelCli
} }
private fun activityOnResume() { private fun activityOnResume() {
if (meController != null && meController.mediaItemCount > 0 && meController.duration > 0) { addMusicPlayerViewToLayout(binding.playMusicLayout)
binding.playingStatusLayout.visibility = View.VISIBLE
updateInfoUi(meController.currentMediaItem)
} else {
binding.playingStatusLayout.visibility = View.GONE
}
} }
private fun initPlayerListener() { override fun onFragmentClick() {
meController?.addListener(playerListener) onBackPressed()
} }
private val playerListener = object : Player.Listener {
override fun onPositionDiscontinuity(
oldPosition: Player.PositionInfo,
newPosition: Player.PositionInfo,
reason: Int
) {
if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION) {
updateInfoUi(meController?.currentMediaItem)
}
}
override fun onPlaybackStateChanged(playbackState: Int) {
LogD(TAG, "playbackState->$playbackState")
updateProgressState()
when (playbackState) {
Player.STATE_READY -> {
if (meController != null) {
LogD(TAG, "meController.duration->${meController.duration}")
binding.progressBar.setMaxProgress(MediaControllerManager.getDuration())
val currentPosition = meController.currentPosition
binding.progressBar.setProgress(currentPosition)
}
}
else -> {}
}
}
override fun onPlayWhenReadyChanged(
playWhenReady: Boolean,
reason: Int
) {
updatePlayState(playWhenReady)
updateProgressState()
}
}
override fun onDestroy() {
super.onDestroy()
meController?.removeListener(playerListener)
}
private var backPressedTime: Long = 0 private var backPressedTime: Long = 0
private val backToast: Toast by lazy { private val backToast: Toast by lazy {
@ -239,56 +169,4 @@ class PrimaryActivity : MoBaseActivity() ,SearchFragment.SearchFragmentCancelCli
backPressedTime = System.currentTimeMillis() backPressedTime = System.currentTimeMillis()
} }
} }
/**
* 更新播放进度
*/
private fun updateProgressState() {
//判断是否ready与播放中否则停止更新进度
if (meController != null && meController.playbackState == Player.STATE_READY && meController.isPlaying) {
updatePlayState(meController.isPlaying)
progressHandler.removeCallbacksAndMessages(null)
progressHandler.sendEmptyMessage(1)
} else {
progressHandler.removeCallbacksAndMessages(null)
}
}
/**
* 播放进度
*/
private val progressHandler = object : Handler(Looper.myLooper()!!) {
override fun handleMessage(msg: Message) {
//判断是否ready与播放中否则停止更新进度
if (meController != null && meController.playbackState == Player.STATE_READY && meController.isPlaying) {
val currentPosition = meController.currentPosition
binding.progressBar.setProgress(currentPosition)
sendEmptyMessageDelayed(1, 50)
}
}
}
private fun updatePlayState(b: Boolean) {
if (b) {
binding.playStatusImg.setImageResource(R.drawable.playing_black_icon)
} else {
binding.playStatusImg.setImageResource(R.drawable.play_black_icon)
}
}
private fun updateInfoUi(mediaItem: MediaItem?) {
if (mediaItem == null) {
return
}
Glide.with(this@PrimaryActivity)
.load(mediaItem.mediaMetadata.artworkUri)
.into(binding.audioImg)
binding.name.text = mediaItem.mediaMetadata.title
binding.desc.text = mediaItem.mediaMetadata.artist
}
override fun onFragmentClick() {
onBackPressed()
}
} }

View File

@ -19,6 +19,7 @@ import com.player.musicoo.databinding.SoundsOfAppliancesLayoutBinding
import com.player.musicoo.databinding.SoundsOfNatureLayoutBinding import com.player.musicoo.databinding.SoundsOfNatureLayoutBinding
import com.player.musicoo.innertube.Innertube import com.player.musicoo.innertube.Innertube
import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer
import com.player.musicoo.media.MediaControllerManager
import com.player.musicoo.util.convertMillisToMinutesAndSecondsString import com.player.musicoo.util.convertMillisToMinutesAndSecondsString
import com.player.musicoo.util.getAudioDurationFromAssets import com.player.musicoo.util.getAudioDurationFromAssets
@ -28,10 +29,6 @@ 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)
@ -66,7 +63,6 @@ class DetailsListAdapter(
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
fun bind(bean: Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean) { fun bind(bean: Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean) {
binding.apply { binding.apply {
if (!bean.thumbnailUrl.isNullOrEmpty()) { if (!bean.thumbnailUrl.isNullOrEmpty()) {
image.visibility = View.VISIBLE image.visibility = View.VISIBLE
@ -87,7 +83,16 @@ class DetailsListAdapter(
name.visibility = View.VISIBLE name.visibility = View.VISIBLE
name.text = bean.name name.text = bean.name
} }
val meController = MediaControllerManager.getController()
if (meController != null && meController.currentMediaItem != null) {
if (meController.currentMediaItem?.mediaId == bean.videoId) {
binding.title.setTextColor(context.getColor(R.color.green))
binding.name.setTextColor(context.getColor(R.color.green_60))
} else {
binding.title.setTextColor(context.getColor(R.color.white))
binding.name.setTextColor(context.getColor(R.color.white_60))
}
}
} }
} }
} }

View File

@ -54,19 +54,6 @@ class PlayListAdapter(
fun bind(bean: MediaItem) { fun bind(bean: MediaItem) {
binding.apply { 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) Glide.with(context)
.load(bean.mediaMetadata.artworkUri) .load(bean.mediaMetadata.artworkUri)
.into(image) .into(image)
@ -77,7 +64,16 @@ class PlayListAdapter(
name.visibility = View.VISIBLE name.visibility = View.VISIBLE
name.text = bean.mediaMetadata.artist name.text = bean.mediaMetadata.artist
} }
val meController = MediaControllerManager.getController()
if (meController != null && meController.currentMediaItem != null) {
if (meController.currentMediaItem?.mediaId == bean.mediaId) {
binding.title.setTextColor(context.getColor(R.color.green))
binding.name.setTextColor(context.getColor(R.color.green_60))
} else {
binding.title.setTextColor(context.getColor(R.color.white))
binding.name.setTextColor(context.getColor(R.color.white_60))
}
}
} }
} }
} }

View File

@ -62,7 +62,7 @@ class MoHomeFragment : MoBaseFragment<FragmentMoHomeBinding>() {
private suspend fun initData() { private suspend fun initData() {
showLoadingUi() showLoadingUi()
Innertube.homePage()?.onSuccess { Innertube.homePage(appStore.myVisitorData)?.onSuccess {
showDataUi() showDataUi()
if (it.homePage.isNotEmpty()) { if (it.homePage.isNotEmpty()) {
for (home: Innertube.HomePage in it.homePage) { for (home: Innertube.HomePage in it.homePage) {

View File

@ -0,0 +1,60 @@
package com.player.musicoo.fragment
import android.view.LayoutInflater
import android.view.ViewGroup
import com.gyf.immersionbar.ktx.immersionBar
import com.player.musicoo.databinding.FragmentMoHomeBinding
import com.player.musicoo.databinding.FragmentMoMeBinding
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.selects.select
class MoMeFragment : MoBaseFragment<FragmentMoMeBinding>() {
private val requests: Channel<Request> = Channel(Channel.UNLIMITED)
enum class Request {
}
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentMoMeBinding
get() = FragmentMoMeBinding::inflate
override suspend fun onViewCreated() {
initView()
onReceive()
}
private fun initImmersionBar() {
immersionBar {
statusBarDarkFont(false)
statusBarView(binding.view)
}
}
private suspend fun onReceive() {
while (isActive) {
select<Unit> {
requests.onReceive {
}
}
}
}
private fun initView() {
}
override fun onResume() {
super.onResume()
initImmersionBar()
}
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
if (!hidden) {
initImmersionBar()
}
}
}

View File

@ -1,21 +1,34 @@
package com.player.musicoo.innertube.requests package com.player.musicoo.innertube.requests
import com.player.musicoo.App
import com.player.musicoo.innertube.Innertube import com.player.musicoo.innertube.Innertube
import com.player.musicoo.innertube.models.BrowseResponse import com.player.musicoo.innertube.models.BrowseResponse
import com.player.musicoo.innertube.models.Context import com.player.musicoo.innertube.models.Context
import com.player.musicoo.innertube.models.SectionListRenderer import com.player.musicoo.innertube.models.SectionListRenderer
import com.player.musicoo.innertube.models.bodies.BrowseBody import com.player.musicoo.innertube.models.bodies.BrowseBody
import com.player.musicoo.innertube.utils.runCatchingNonCancellable import com.player.musicoo.innertube.utils.runCatchingNonCancellable
import com.player.musicoo.sp.AppStore
import com.player.musicoo.util.LogTag
import io.ktor.client.call.body import io.ktor.client.call.body
import io.ktor.client.request.post import io.ktor.client.request.post
import io.ktor.client.request.setBody import io.ktor.client.request.setBody
// //
suspend fun Innertube.homePage(): Result<Innertube.BaseHomePage>? = suspend fun Innertube.homePage(visitorData: String? = null): Result<Innertube.BaseHomePage>? =
runCatchingNonCancellable { runCatchingNonCancellable {
LogTag.LogD(TAG, "visitorData->${visitorData}")
val defaultWeb = Context(
client = Context.Client(
clientName = "WEB_REMIX",
clientVersion = "1.20220918",
platform = "DESKTOP",
visitorData = visitorData
)
)
val response = client.post(browse) { val response = client.post(browse) {
setBody(BrowseBody(Context.DefaultWeb, "FEmusic_home")) setBody(BrowseBody(defaultWeb, "FEmusic_home"))
}.body<BrowseResponse>() }.body<BrowseResponse>()
val sectionListRenderer = response val sectionListRenderer = response
@ -29,7 +42,10 @@ suspend fun Innertube.homePage(): Result<Innertube.BaseHomePage>? =
val contents = sectionListRenderer?.contents val contents = sectionListRenderer?.contents
val visitorData = response.responseContext?.visitorData val visitorDataNew= response.responseContext?.visitorData
// if(!visitorDataNew.isNullOrEmpty()){
// AppStore(App.app).myVisitorData = visitorDataNew
// }
val continuations = sectionListRenderer?.continuations val continuations = sectionListRenderer?.continuations
val nextContinuationData = continuations val nextContinuationData = continuations
@ -66,7 +82,7 @@ suspend fun Innertube.homePage(): Result<Innertube.BaseHomePage>? =
} }
val baseHomePage = val baseHomePage =
Innertube.BaseHomePage( Innertube.BaseHomePage(
visitorData, visitorDataNew,
cToken, cToken,
cToken.toString(), cToken.toString(),
itct.toString(), itct.toString(),

View File

@ -1,11 +1,13 @@
package com.player.musicoo.innertube.requests package com.player.musicoo.innertube.requests
import com.player.musicoo.App
import com.player.musicoo.innertube.Innertube import com.player.musicoo.innertube.Innertube
import com.player.musicoo.innertube.models.BrowseResponse import com.player.musicoo.innertube.models.BrowseResponse
import com.player.musicoo.innertube.models.Context import com.player.musicoo.innertube.models.Context
import com.player.musicoo.innertube.models.SectionListContinuation import com.player.musicoo.innertube.models.SectionListContinuation
import com.player.musicoo.innertube.models.bodies.BrowseMoreBody import com.player.musicoo.innertube.models.bodies.BrowseMoreBody
import com.player.musicoo.innertube.utils.runCatchingNonCancellable import com.player.musicoo.innertube.utils.runCatchingNonCancellable
import com.player.musicoo.sp.AppStore
import io.ktor.client.call.body import io.ktor.client.call.body
import io.ktor.client.request.post import io.ktor.client.request.post
import io.ktor.client.request.setBody import io.ktor.client.request.setBody

View File

@ -1,10 +1,13 @@
package com.player.musicoo.innertube.requests package com.player.musicoo.innertube.requests
import com.player.musicoo.App
import com.player.musicoo.innertube.Innertube import com.player.musicoo.innertube.Innertube
import com.player.musicoo.innertube.models.BrowseResponse import com.player.musicoo.innertube.models.BrowseResponse
import com.player.musicoo.innertube.models.MusicShelfRenderer import com.player.musicoo.innertube.models.MusicShelfRenderer
import com.player.musicoo.innertube.models.bodies.BrowseBody import com.player.musicoo.innertube.models.bodies.BrowseBody
import com.player.musicoo.innertube.utils.runCatchingNonCancellable import com.player.musicoo.innertube.utils.runCatchingNonCancellable
import com.player.musicoo.sp.AppStore
import com.player.musicoo.util.LogTag
import io.ktor.client.call.body import io.ktor.client.call.body
import io.ktor.client.request.post import io.ktor.client.request.post
import io.ktor.client.request.setBody import io.ktor.client.request.setBody
@ -15,7 +18,6 @@ suspend fun Innertube.moPlaylistPage(browseId: String): Result<Innertube.MoPlayl
setBody(BrowseBody(browseId = browseId)) setBody(BrowseBody(browseId = browseId))
}.body<BrowseResponse>() }.body<BrowseResponse>()
val musicDetailHeaderRenderer = response val musicDetailHeaderRenderer = response
.header .header
?.musicDetailHeaderRenderer ?.musicDetailHeaderRenderer

View File

@ -1,5 +1,6 @@
package com.player.musicoo.innertube.requests package com.player.musicoo.innertube.requests
import com.player.musicoo.App
import com.player.musicoo.innertube.Innertube import com.player.musicoo.innertube.Innertube
import com.player.musicoo.innertube.models.BrowseResponse import com.player.musicoo.innertube.models.BrowseResponse
import com.player.musicoo.innertube.models.ContinuationResponse import com.player.musicoo.innertube.models.ContinuationResponse
@ -10,6 +11,7 @@ import com.player.musicoo.innertube.models.SectionListRenderer
import com.player.musicoo.innertube.models.bodies.BrowseBody import com.player.musicoo.innertube.models.bodies.BrowseBody
import com.player.musicoo.innertube.models.bodies.ContinuationBody import com.player.musicoo.innertube.models.bodies.ContinuationBody
import com.player.musicoo.innertube.utils.runCatchingNonCancellable import com.player.musicoo.innertube.utils.runCatchingNonCancellable
import com.player.musicoo.sp.AppStore
import com.player.musicoo.util.LogTag import com.player.musicoo.util.LogTag
import io.ktor.client.call.body import io.ktor.client.call.body
import io.ktor.client.request.post import io.ktor.client.request.post

View File

@ -39,9 +39,11 @@ import com.player.musicoo.R
import com.player.musicoo.innertube.Innertube import com.player.musicoo.innertube.Innertube
import com.player.musicoo.innertube.models.bodies.PlayerBody import com.player.musicoo.innertube.models.bodies.PlayerBody
import com.player.musicoo.innertube.requests.player import com.player.musicoo.innertube.requests.player
import com.player.musicoo.sp.AppStore
import com.player.musicoo.util.ExoPlayerDiskCacheMaxSize import com.player.musicoo.util.ExoPlayerDiskCacheMaxSize
import com.player.musicoo.util.LogTag import com.player.musicoo.util.LogTag
import com.player.musicoo.util.LogTag.LogD import com.player.musicoo.util.LogTag.LogD
import com.player.musicoo.util.PlayMode
import com.player.musicoo.util.RingBuffer import com.player.musicoo.util.RingBuffer
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -90,6 +92,22 @@ class PlaybackService : MediaSessionService(), Player.Listener {
) )
.setUsePlatformDiagnostics(false) .setUsePlatformDiagnostics(false)
.build() .build()
when (AppStore(this).playMusicMode) {
PlayMode.LIST_LOOP.value -> {
player.repeatMode = Player.REPEAT_MODE_ALL
player.shuffleModeEnabled = false
}
PlayMode.SINGLE_LOOP.value -> {
player.repeatMode = Player.REPEAT_MODE_ONE
player.shuffleModeEnabled = false
}
PlayMode.RANDOM.value -> {
player.repeatMode = Player.REPEAT_MODE_ALL
player.shuffleModeEnabled = true
}
}
player.repeatMode = Player.REPEAT_MODE_ALL player.repeatMode = Player.REPEAT_MODE_ALL
player.addListener(this) player.addListener(this)

View File

@ -3,6 +3,7 @@ package com.player.musicoo.sp
import android.content.Context import android.content.Context
import com.player.musicoo.sp.store.Store import com.player.musicoo.sp.store.Store
import com.player.musicoo.sp.store.asStoreProvider import com.player.musicoo.sp.store.asStoreProvider
import com.player.musicoo.util.PlayMode
class AppStore(context: Context) { class AppStore(context: Context) {
private val store = Store( private val store = Store(
@ -16,8 +17,20 @@ class AppStore(context: Context) {
defaultValue = emptySet() defaultValue = emptySet()
) )
var myVisitorData: String by store.string(
key = MY_VISITOR_DATA,
defaultValue = ""
)
var playMusicMode: Int by store.int(
key = PLAY_MUSIC_MODE,
defaultValue = PlayMode.LIST_LOOP.value
)
companion object { companion object {
private const val FILE_NAME = "music_oo_app" private const val FILE_NAME = "music_oo_app"
const val SEARCH_HISTORY = "search_history" const val SEARCH_HISTORY = "search_history"
const val MY_VISITOR_DATA = "my_visitor_data"
const val PLAY_MUSIC_MODE = "play_music_mode"
} }
} }

View File

@ -0,0 +1,11 @@
package com.player.musicoo.util
enum class PlayMode(val value: Int) {
LIST_LOOP(0), // 列表循环
SINGLE_LOOP(1), // 单曲循环
RANDOM(2); // 随机播放
companion object {
fun fromValue(value: Int) = entries.firstOrNull { it.value == value } ?: LIST_LOOP
}
}

View File

@ -0,0 +1,126 @@
package com.player.musicoo.view
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import androidx.media3.session.MediaController
import com.bumptech.glide.Glide
import com.player.musicoo.R
import com.player.musicoo.activity.MoPlayDetailsActivity
import com.player.musicoo.activity.PrimaryActivity
import com.player.musicoo.innertube.Innertube
import com.player.musicoo.media.MediaControllerManager
import com.player.musicoo.util.LogTag
@SuppressLint("ViewConstructor")
class MusicPlayerView(
val context: Activity,
val meController: MediaController?,
attrs: AttributeSet? = null
) :
LinearLayout(context, attrs) {
private var goDetailsBtn: LinearLayout
private var progressBar: CircularProgressBar
private var playStatusImg: ImageView
private var audioImg: ImageView
private var name: TextView
private var desc: TextView
private var playBlackBtn: LinearLayout
init {
LayoutInflater.from(context).inflate(R.layout.music_player_layout, this, true)
goDetailsBtn = findViewById(R.id.goDetailsBtn)
progressBar = findViewById(R.id.progressBar)
playStatusImg = findViewById(R.id.play_status_img)
audioImg = findViewById(R.id.audio_img)
name = findViewById(R.id.name)
desc = findViewById(R.id.desc)
playBlackBtn = findViewById(R.id.play_black_btn)
initOnClickListener()
}
private fun initOnClickListener() {
playBlackBtn.setOnClickListener {
if (meController != null) {
if (meController.isPlaying) {
meController.pause()
updatePlayState(false)
} else {
meController.play()
updatePlayState(true)
}
updateProgressState(meController)
}
}
goDetailsBtn.setOnClickListener {
val intent = Intent(context, MoPlayDetailsActivity::class.java)
intent.putExtra(
MoPlayDetailsActivity.PLAY_DETAILS_COME_FROM,
PrimaryActivity::class.java
)
context.startActivity(intent)
}
}
fun updateProgressState(meController: MediaController) {
//判断是否ready与播放中否则停止更新进度
if (meController.playbackState == Player.STATE_READY && meController.isPlaying) {
updatePlayState(meController.isPlaying)
progressHandler.removeCallbacksAndMessages(null)
progressHandler.sendEmptyMessage(1)
} else {
progressHandler.removeCallbacksAndMessages(null)
}
}
/**
* 播放进度
*/
private val progressHandler = object : Handler(Looper.myLooper()!!) {
override fun handleMessage(msg: Message) {
//判断是否ready与播放中否则停止更新进度
if (meController != null && meController.playbackState == Player.STATE_READY && meController.isPlaying) {
val currentPosition = meController.currentPosition
progressBar.setProgress(currentPosition)
sendEmptyMessageDelayed(1, 50)
}
}
}
fun updatePlayState(b: Boolean) {
if (b) {
playStatusImg.setImageResource(R.drawable.playing_black_icon)
} else {
playStatusImg.setImageResource(R.drawable.play_black_icon)
}
}
fun updateInfoUi(mediaItem: MediaItem?) {
if (mediaItem == null) {
return
}
Glide.with(context)
.load(mediaItem.mediaMetadata.artworkUri)
.into(audioImg)
name.text = mediaItem.mediaMetadata.title
desc.text = mediaItem.mediaMetadata.artist
}
fun updateSetProgress(meController: MediaController) {
progressBar.setMaxProgress(MediaControllerManager.getDuration())
val currentPosition = meController.currentPosition
progressBar.setProgress(currentPosition)
}
}

View File

@ -1,33 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="34dp"
android:height="34dp"
android:viewportWidth="34"
android:viewportHeight="34">
<path
android:pathData="M17,31.403C24.172,31.403 29.986,25.589 29.986,18.417C29.986,11.245 24.172,5.43 17,5.43C9.828,5.43 4.014,11.245 4.014,18.417C4.014,25.589 9.828,31.403 17,31.403Z"
android:strokeLineJoin="round"
android:strokeWidth="1.66667"
android:fillColor="#333333"
android:strokeColor="#333333"/>
<path
android:pathData="M16.83,10.875L16.829,18.673L22.334,24.179"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#ffffff"
android:strokeLineCap="round"/>
<path
android:pathData="M2.833,6.375L7.792,2.833"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#333333"
android:strokeLineCap="round"/>
<path
android:pathData="M31.167,6.375L26.208,2.833"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#333333"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:strokeWidth="1"
android:pathData="M18,18m-17.5,0a17.5,17.5 0,1 1,35 0a17.5,17.5 0,1 1,-35 0"
android:fillColor="#00000000"
android:strokeColor="#80F988"/>
<path
android:pathData="M22.445,22.593C24.09,21.548 25.351,19.998 26.039,18.176C26.728,16.354 26.806,14.357 26.262,12.486C25.719,10.615 24.582,8.972 23.024,7.802C21.466,6.632 19.571,6 17.623,6C15.675,6 13.779,6.632 12.221,7.802C10.663,8.972 9.527,10.615 8.983,12.486C8.44,14.357 8.518,16.354 9.206,18.176C9.894,19.998 11.156,21.548 12.8,22.593C11.519,23.199 10.419,24.131 9.612,25.297C8.804,26.462 8.317,27.819 8.2,29.232C8.195,29.43 8.269,29.622 8.405,29.766C8.541,29.91 8.728,29.994 8.926,30H26.362C26.46,29.998 26.557,29.976 26.647,29.936C26.738,29.896 26.819,29.839 26.887,29.768C26.955,29.696 27.008,29.612 27.044,29.521C27.079,29.429 27.096,29.331 27.094,29.232C26.973,27.814 26.479,26.453 25.663,25.287C24.847,24.121 23.737,23.191 22.445,22.593ZM21.749,19.132C21.231,19.715 20.601,20.189 19.896,20.525C19.192,20.861 18.427,21.052 17.647,21.087H17.443C15.913,20.956 14.492,20.243 13.472,19.096C13.405,19.019 13.354,18.929 13.322,18.833C13.29,18.736 13.277,18.633 13.285,18.532C13.294,18.43 13.322,18.331 13.369,18.24C13.416,18.15 13.48,18.069 13.559,18.004C13.637,17.939 13.728,17.89 13.826,17.86C13.923,17.831 14.026,17.821 14.127,17.832C14.229,17.842 14.327,17.873 14.417,17.922C14.506,17.971 14.585,18.038 14.648,18.118C15.403,18.949 16.439,19.471 17.557,19.581C18.631,19.635 19.704,19.114 20.748,18.076C20.889,17.942 21.077,17.869 21.271,17.872C21.466,17.875 21.651,17.953 21.789,18.091C21.926,18.228 22.005,18.414 22.007,18.608C22.01,18.802 21.937,18.99 21.803,19.132H21.749Z"
android:fillColor="#80F988"/>
</vector>

View File

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:fillColor="#00000000"
android:pathData="M18,18m-17.5,0a17.5,17.5 0,1 1,35 0a17.5,17.5 0,1 1,-35 0"
android:strokeWidth="1"
android:strokeColor="#9C9D9D" />
<path
android:fillColor="#9C9D9D"
android:fillType="evenOdd"
android:pathData="M22.445,22.593C24.09,21.548 25.351,19.998 26.039,18.176C26.728,16.354 26.806,14.357 26.262,12.486C25.719,10.615 24.582,8.972 23.024,7.802C21.466,6.632 19.571,6 17.623,6C15.675,6 13.779,6.632 12.221,7.802C10.663,8.972 9.527,10.615 8.983,12.486C8.44,14.357 8.518,16.354 9.206,18.176C9.894,19.998 11.156,21.548 12.8,22.593C11.519,23.199 10.419,24.131 9.612,25.297C8.804,26.462 8.317,27.819 8.2,29.232C8.195,29.43 8.269,29.622 8.405,29.766C8.541,29.91 8.728,29.994 8.926,30H26.362C26.46,29.998 26.557,29.976 26.647,29.936C26.738,29.896 26.819,29.839 26.887,29.768C26.955,29.696 27.008,29.612 27.044,29.521C27.079,29.429 27.096,29.331 27.094,29.232C26.973,27.814 26.479,26.453 25.663,25.287C24.847,24.121 23.737,23.191 22.445,22.593ZM21.749,19.132C21.231,19.715 20.601,20.189 19.896,20.525C19.192,20.861 18.427,21.052 17.647,21.087H17.443C15.913,20.956 14.492,20.243 13.472,19.096C13.405,19.019 13.354,18.929 13.322,18.833C13.29,18.736 13.277,18.633 13.285,18.532C13.294,18.43 13.322,18.331 13.369,18.24C13.416,18.15 13.48,18.069 13.559,18.004C13.637,17.939 13.728,17.89 13.826,17.86C13.923,17.831 14.026,17.821 14.127,17.832C14.229,17.842 14.327,17.873 14.417,17.922C14.506,17.971 14.585,18.038 14.648,18.118C15.403,18.949 16.439,19.471 17.557,19.581C18.631,19.635 19.704,19.114 20.748,18.076C20.889,17.942 21.077,17.869 21.271,17.872C21.466,17.875 21.651,17.953 21.789,18.091C21.926,18.228 22.005,18.414 22.007,18.608C22.01,18.802 21.937,18.99 21.803,19.132H21.749Z" />
</vector>

View File

@ -0,0 +1,32 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#00000000"
android:pathData="M20,16.5L22,18.5L20,20.5"
android:strokeWidth="1.5"
android:strokeColor="#ffffff"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
<path
android:fillColor="#00000000"
android:pathData="M20,3.5L22,5.5L20,7.5"
android:strokeWidth="1.5"
android:strokeColor="#ffffff"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
<path
android:fillColor="#00000000"
android:pathData="M22,5.5H18.5C14.91,5.5 12,8.41 12,12C12,15.59 14.91,18.5 18.5,18.5H22"
android:strokeWidth="1.5"
android:strokeColor="#ffffff"
android:strokeLineCap="round" />
<path
android:fillColor="#00000000"
android:pathData="M2,18.5H5.5C9.09,18.5 12,15.59 12,12C12,8.41 9.09,5.5 5.5,5.5H2"
android:strokeWidth="1.5"
android:strokeColor="#ffffff"
android:strokeLineCap="round" />
</vector>

View File

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<group>
<clip-path android:pathData="M0,0h24v24h-24z" />
<path
android:fillColor="#ffffff"
android:pathData="M21.806,6.569C23.229,8.017 24.021,9.97 24.011,12C24.014,12.695 23.92,13.386 23.734,14.055C23.673,14.267 23.53,14.446 23.338,14.553C23.145,14.66 22.918,14.686 22.706,14.625C22.492,14.566 22.31,14.425 22.198,14.233C22.086,14.041 22.053,13.814 22.106,13.598C22.243,13.076 22.313,12.539 22.316,12C22.33,10.443 21.727,8.943 20.639,7.828C19.552,6.714 18.067,6.075 16.51,6.051H8.603V7.589C8.603,8.077 8.265,8.272 7.853,8.009L4.237,5.759C4.146,5.717 4.069,5.649 4.016,5.565C3.962,5.481 3.933,5.382 3.933,5.282C3.933,5.182 3.962,5.084 4.016,5C4.069,4.915 4.146,4.848 4.237,4.806L7.86,2.368C8.265,2.105 8.611,2.285 8.611,2.781V4.318H16.51C17.501,4.319 18.481,4.518 19.394,4.905C20.306,5.291 21.131,5.857 21.821,6.569H21.806ZM20.41,18.279C20.501,18.321 20.578,18.388 20.632,18.473C20.686,18.557 20.715,18.655 20.715,18.755C20.715,18.855 20.686,18.953 20.632,19.038C20.578,19.122 20.501,19.189 20.41,19.232L16.78,21.632C16.375,21.895 16.03,21.715 16.03,21.219V19.682H7.508C6.517,19.681 5.536,19.482 4.624,19.095C3.711,18.709 2.886,18.143 2.197,17.431C0.98,16.174 0.221,14.545 0.041,12.805C-0.138,11.065 0.272,9.315 1.207,7.837C1.265,7.742 1.343,7.659 1.434,7.595C1.525,7.53 1.628,7.485 1.738,7.461C1.847,7.437 1.96,7.435 2.069,7.456C2.179,7.477 2.284,7.52 2.377,7.582C2.567,7.707 2.701,7.903 2.748,8.126C2.796,8.349 2.754,8.582 2.632,8.774C2.023,9.74 1.701,10.858 1.702,12C1.688,13.557 2.29,15.057 3.378,16.172C4.466,17.286 5.951,17.925 7.508,17.949H16.052V16.411C16.052,15.923 16.382,15.728 16.802,15.991L20.418,18.279H20.41Z" />
<path
android:fillColor="#ffffff"
android:pathData="M13.064,16.192C13.064,16.64 12.704,17 12.256,17C11.808,17 11.448,16.64 11.448,16.192V10.256L10.68,10.504C10.68,10.504 10.68,10.504 10.672,10.504C10.664,10.504 10.656,10.512 10.648,10.512C10.632,10.512 10.616,10.52 10.6,10.52C10.592,10.528 10.584,10.528 10.576,10.528C10.56,10.528 10.544,10.536 10.52,10.536C10.52,10.536 10.512,10.536 10.504,10.536C10.48,10.544 10.456,10.544 10.424,10.544C9.976,10.544 9.616,10.176 9.616,9.728C9.616,9.368 9.856,9.064 10.176,8.96H10.184C10.184,8.96 10.184,8.96 10.192,8.96L11.96,8.384C11.96,8.384 11.952,8.384 11.944,8.384C11.96,8.384 11.968,8.376 11.984,8.376L11.96,8.384C11.976,8.376 11.992,8.368 12.008,8.368L12.016,8.36C12.04,8.352 12.064,8.352 12.088,8.344C12.096,8.344 12.104,8.344 12.104,8.344C12.128,8.336 12.144,8.336 12.16,8.328C12.144,8.336 12.128,8.336 12.112,8.336C12.128,8.336 12.144,8.336 12.16,8.328H12.168C12.176,8.328 12.176,8.328 12.184,8.328C12.2,8.328 12.208,8.328 12.216,8.328C12.208,8.328 12.2,8.328 12.192,8.328C12.208,8.328 12.232,8.328 12.256,8.328C12.704,8.328 13.064,8.688 13.064,9.136V16.192ZM11.864,8.424C11.824,8.448 11.784,8.48 11.744,8.504C11.784,8.48 11.824,8.448 11.864,8.424ZM11.68,8.568C11.664,8.584 11.648,8.6 11.64,8.616C11.648,8.6 11.664,8.584 11.68,8.568ZM11.448,9.064C11.448,9.088 11.448,9.112 11.448,9.136C11.448,9.112 11.448,9.088 11.448,9.064ZM11.632,8.624C11.616,8.64 11.6,8.664 11.584,8.68C11.6,8.664 11.616,8.64 11.632,8.624ZM11.504,8.824C11.496,8.848 11.488,8.872 11.48,8.896C11.488,8.872 11.496,8.848 11.504,8.824Z" />
</group>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M11.12,20.72C5.84,20.72 1.52,16.4 1.52,11.12C1.52,5.84 5.84,1.52 11.12,1.52C16.399,1.52 20.719,5.84 20.719,11.12C20.719,16.4 16.399,20.72 11.12,20.72ZM11.12,19.12C15.519,19.12 19.119,15.52 19.119,11.12C19.119,6.72 15.519,3.12 11.12,3.12C6.72,3.12 3.12,6.72 3.12,11.12C3.12,15.52 6.72,19.12 11.12,19.12ZM17.039,20.4C16.719,20.08 16.799,19.52 17.119,19.28C17.44,19.04 18,19.04 18.24,19.36L19.76,21.2C20.08,21.52 20,22.08 19.68,22.32C19.36,22.56 18.799,22.56 18.559,22.24L17.039,20.4Z"
android:fillColor="#ffffff"
android:fillAlpha="0.85"/>
</vector>

View File

@ -1,19 +1,21 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp" android:width="36dp"
android:height="28dp" android:height="36dp"
android:viewportWidth="28" android:viewportWidth="36"
android:viewportHeight="28"> android:viewportHeight="36">
<group>
<clip-path
android:pathData="M28,0l-28,0l-0,28l28,0z"/>
<path <path
android:pathData="M13.5,2C7.149,2 2,7.149 2,13.5C2,19.851 7.149,25 13.5,25C19.851,25 25,19.851 25,13.5C25,7.149 19.851,2 13.5,2ZM11.354,6.861C11.819,6.795 12.176,6.395 12.176,5.912C12.176,5.383 11.747,4.954 11.218,4.954C11.16,4.954 11.104,4.959 11.049,4.968C7.923,5.472 5.472,7.923 4.968,11.049C4.959,11.104 4.954,11.16 4.954,11.218C4.954,11.747 5.383,12.176 5.912,12.176C6.395,12.176 6.795,11.819 6.861,11.354C7.233,9.044 9.044,7.233 11.354,6.861Z" android:fillColor="#00000000"
android:fillColor="#ffffff" android:pathData="M18,18m-17.5,0a17.5,17.5 0,1 1,35 0a17.5,17.5 0,1 1,-35 0"
android:fillAlpha="0.6" android:strokeWidth="1"
android:fillType="evenOdd"/> android:strokeColor="#9C9D9D" />
<path <group>
android:pathData="M25.431,25.434C25.745,25.107 25.745,24.594 25.431,24.279L23.264,22.111C22.938,21.796 22.425,21.796 22.111,22.111C21.796,22.437 21.796,22.95 22.111,23.265L24.278,25.434C24.429,25.585 24.639,25.667 24.848,25.667C25.058,25.667 25.268,25.585 25.431,25.434Z" <clip-path android:pathData="M32,4l-28,0l-0,28l28,0z" />
android:fillColor="#ffffff" <path
android:fillAlpha="0.6"/> android:fillColor="#9C9D9D"
</group> android:fillType="evenOdd"
android:pathData="M17.5,6C11.149,6 6,11.149 6,17.5C6,23.851 11.149,29 17.5,29C23.851,29 29,23.851 29,17.5C29,11.149 23.851,6 17.5,6ZM15.354,10.861C15.819,10.795 16.176,10.395 16.176,9.912C16.176,9.383 15.747,8.954 15.218,8.954C15.16,8.954 15.104,8.959 15.049,8.968C11.923,9.472 9.472,11.923 8.968,15.049C8.959,15.104 8.954,15.16 8.954,15.218C8.954,15.747 9.383,16.176 9.912,16.176C10.395,16.176 10.795,15.819 10.861,15.354C11.233,13.044 13.044,11.233 15.354,10.861Z" />
<path
android:fillColor="#9C9D9D"
android:pathData="M29.431,29.434C29.745,29.107 29.745,28.594 29.431,28.279L27.264,26.111C26.938,25.796 26.425,25.796 26.111,26.111C25.796,26.437 25.796,26.95 26.111,27.265L28.278,29.434C28.429,29.585 28.639,29.667 28.848,29.667C29.058,29.667 29.268,29.585 29.431,29.434Z" />
</group>
</vector> </vector>

View File

@ -100,90 +100,105 @@
android:textSize="16dp" /> android:textSize="16dp" />
</LinearLayout> </LinearLayout>
<RelativeLayout
<LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:layout_marginStart="16dp" android:layout_above="@+id/play_music_layout"
android:layout_marginEnd="16dp" android:orientation="vertical">
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:cardCornerRadius="10dp"
app:cardElevation="0dp">
<ImageView
android:id="@+id/imageView"
android:layout_width="160dp"
android:layout_height="160dp"
android:src="@mipmap/musicoo_logo_img" />
</androidx.cardview.widget.CardView>
<LinearLayout <LinearLayout
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
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:cardCornerRadius="10dp"
app:cardElevation="0dp">
<ImageView
android:id="@+id/imageView"
android:layout_width="160dp"
android:layout_height="160dp"
android:src="@mipmap/musicoo_logo_img" />
</androidx.cardview.widget.CardView>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/medium_font"
android:maxLines="2"
android:text="@string/app_name"
android:textColor="@color/white"
android:textSize="18dp" />
<TextView
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:fontFamily="@font/medium_font"
android:maxLines="1"
android:text="@string/ready_to_sleep"
android:textColor="@color/white_60"
android:textSize="12dp" />
<TextView
android:id="@+id/secondSubtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:fontFamily="@font/regular_font"
android:maxLines="1"
android:text="@string/app_name"
android:textColor="@color/white_60"
android:textSize="12dp" />
</LinearLayout>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_weight="1" android:layout_marginTop="4dp"
android:gravity="center_vertical" android:layout_marginEnd="16dp"
android:orientation="vertical"> android:layout_marginBottom="16dp"
android:overScrollMode="never"
<TextView android:scrollbars="none" />
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/medium_font"
android:maxLines="2"
android:text="@string/app_name"
android:textColor="@color/white"
android:textSize="18dp" />
<TextView
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:fontFamily="@font/medium_font"
android:maxLines="1"
android:text="@string/ready_to_sleep"
android:textColor="@color/white_60"
android:textSize="12dp" />
<TextView
android:id="@+id/secondSubtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:fontFamily="@font/regular_font"
android:maxLines="1"
android:text="@string/app_name"
android:textColor="@color/white_60"
android:textSize="12dp" />
</LinearLayout>
</LinearLayout> </LinearLayout>
<androidx.recyclerview.widget.RecyclerView <LinearLayout
android:id="@+id/rv" android:id="@+id/play_music_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_alignParentBottom="true"
android:layout_marginTop="4dp" android:orientation="vertical" />
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:overScrollMode="never" </RelativeLayout>
android:scrollbars="none" />
</LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -104,20 +104,6 @@
</LinearLayout> </LinearLayout>
<LinearLayout
android:id="@+id/alarm_clock_btn"
android:layout_width="42dp"
android:visibility="gone"
android:layout_height="42dp"
android:gravity="center">
<ImageView
android:layout_width="34dp"
android:layout_height="34dp"
android:src="@drawable/alarm_clock_icon" />
</LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/play_black_btn" android:id="@+id/play_black_btn"
android:layout_width="42dp" android:layout_width="42dp"

View File

@ -126,8 +126,8 @@
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:gravity="center"
android:background="@color/black_60" android:background="@color/black_60"
android:gravity="center"
android:orientation="vertical" android:orientation="vertical"
android:visibility="gone"> android:visibility="gone">
@ -149,9 +149,9 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:background="@drawable/drw_btn_bg" android:background="@drawable/drw_btn_bg"
android:fontFamily="@font/medium_font"
android:paddingStart="24dp" android:paddingStart="24dp"
android:paddingTop="8dp" android:paddingTop="8dp"
android:fontFamily="@font/medium_font"
android:paddingEnd="24dp" android:paddingEnd="24dp"
android:paddingBottom="8dp" android:paddingBottom="8dp"
android:text="@string/try_again" android:text="@string/try_again"
@ -294,15 +294,17 @@
android:orientation="horizontal"> android:orientation="horizontal">
<LinearLayout <LinearLayout
android:id="@+id/playModeBtn"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center"> android:gravity="center">
<ImageView <ImageView
android:id="@+id/modePlayImg"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:src="@drawable/play_mode_icon" /> android:src="@drawable/mode_cycle_play_icon" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
@ -409,10 +411,10 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/playListRv" android:id="@+id/playListRv"
android:layout_width="match_parent" android:layout_width="match_parent"
android:scrollbars="none"
android:overScrollMode="never"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_margin="16dp" /> android:layout_margin="16dp"
android:overScrollMode="never"
android:scrollbars="none" />
</LinearLayout> </LinearLayout>

View File

@ -38,126 +38,11 @@
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:orientation="vertical"> android:orientation="vertical">
<com.lihang.ShadowLayout <LinearLayout
android:id="@+id/playing_status_layout" android:id="@+id/play_music_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="12dp" android:orientation="vertical" />
android:layout_marginEnd="12dp"
android:visibility="visible"
app:hl_cornerRadius="36dp"
app:hl_layoutBackground="#FF80F988"
app:hl_shadowColor="#40040604"
app:hl_shadowOffsetX="0dp"
app:hl_shadowOffsetY="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="68dp"
android:layout_alignParentBottom="true"
android:gravity="center_vertical"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<LinearLayout
android:id="@+id/goDetailsBtn"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:elevation="0dp"
app:cardCornerRadius="24dp"
app:cardElevation="0dp">
<ImageView
android:id="@+id/audio_img"
android:layout_width="48dp"
android:scaleType="centerCrop"
android:layout_height="48dp"
android:src="@mipmap/musicoo_logo_img" />
</androidx.cardview.widget.CardView>
<com.player.musicoo.view.CircularProgressBar
android:id="@+id/progressBar"
android:layout_width="54dp"
android:layout_height="54dp"
android:layout_centerInParent="true" />
</RelativeLayout>
<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">
<com.player.musicoo.view.MarqueeTextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:fontFamily="@font/medium_font"
android:maxLines="1"
android:text="@string/app_name"
android:textColor="@color/black"
android:textSize="16dp" />
<com.player.musicoo.view.MarqueeTextView
android:id="@+id/desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="@string/app_name"
android:textColor="@color/black_60"
android:textSize="12dp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/alarm_clock_btn"
android:layout_width="42dp"
android:layout_height="42dp"
android:gravity="center"
android:visibility="gone">
<ImageView
android:layout_width="34dp"
android:layout_height="34dp"
android:src="@drawable/alarm_clock_icon" />
</LinearLayout>
<LinearLayout
android:id="@+id/play_black_btn"
android:layout_width="42dp"
android:layout_height="42dp"
android:gravity="center">
<ImageView
android:id="@+id/play_status_img"
android:layout_width="34dp"
android:layout_height="34dp"
android:src="@drawable/play_black_icon" />
</LinearLayout>
</LinearLayout>
</com.lihang.ShadowLayout>
<RelativeLayout <RelativeLayout
android:id="@+id/tab_layout" android:id="@+id/tab_layout"
@ -200,17 +85,17 @@
<LinearLayout <LinearLayout
android:id="@+id/import_btn" android:id="@+id/me_btn"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center"> android:gravity="center">
<ImageView <ImageView
android:id="@+id/import_img" android:id="@+id/me_img"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:src="@drawable/import_unselect_icon" /> android:src="@drawable/me_unselect_icon" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</RelativeLayout> </RelativeLayout>

View File

@ -106,25 +106,40 @@
android:textSize="16dp" /> android:textSize="16dp" />
</LinearLayout> </LinearLayout>
<com.scwang.smart.refresh.layout.SmartRefreshLayout <RelativeLayout
android:id="@+id/refreshLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView <com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/rv" android:id="@+id/refreshLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginStart="16dp" android:layout_above="@+id/play_music_layout">
android:layout_marginEnd="16dp"
android:overScrollMode="never"
android:scrollbars="none" />
<com.scwang.smart.refresh.footer.BallPulseFooter <androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:overScrollMode="never"
android:scrollbars="none" />
<com.scwang.smart.refresh.footer.BallPulseFooter
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:srlAnimatingColor="@color/green" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
<LinearLayout
android:id="@+id/play_music_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:srlAnimatingColor="@color/green" /> android:layout_alignParentBottom="true"
</com.scwang.smart.refresh.layout.SmartRefreshLayout> android:orientation="vertical" />
</RelativeLayout>
</LinearLayout> </LinearLayout>

View File

@ -138,67 +138,81 @@
android:textSize="16dp" /> android:textSize="16dp" />
</LinearLayout> </LinearLayout>
<androidx.core.widget.NestedScrollView <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<LinearLayout <androidx.core.widget.NestedScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:layout_above="@+id/play_music_layout">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:orientation="vertical"> android:orientation="vertical">
<TextView <LinearLayout
android:id="@+id/singerName" android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="68dp" android:layout_marginStart="16dp"
android:fontFamily="@font/medium_font" android:layout_marginEnd="16dp"
android:text="@string/app_name" android:orientation="vertical">
android:textColor="@color/white"
android:textSize="22dp" />
<TextView <TextView
android:id="@+id/singerDesc" android:id="@+id/singerName"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="68dp"
android:ellipsize="end" android:fontFamily="@font/medium_font"
android:fontFamily="@font/regular_font" android:text="@string/app_name"
android:maxLines="2" android:textColor="@color/white"
android:text="@string/app_name" android:textSize="22dp" />
android:textColor="@color/white_60"
android:textSize="14dp" />
<TextView <TextView
android:id="@+id/singerDescExpand" android:id="@+id/singerDesc"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:ellipsize="end"
android:fontFamily="@font/regular_font"
android:maxLines="2"
android:text="@string/app_name"
android:textColor="@color/white_60"
android:textSize="14dp" />
<TextView
android:id="@+id/singerDescExpand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:ellipsize="end"
android:fontFamily="@font/regular_font"
android:text="@string/expand"
android:textColor="@color/white_60"
android:textSize="12dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/content_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="2dp" android:layout_marginStart="16dp"
android:ellipsize="end" android:layout_marginTop="16dp"
android:fontFamily="@font/regular_font" android:layout_marginEnd="16dp"
android:text="@string/expand" android:orientation="vertical" />
android:textColor="@color/white_60"
android:textSize="12dp" />
</LinearLayout> </LinearLayout>
<LinearLayout </androidx.core.widget.NestedScrollView>
android:id="@+id/content_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:orientation="vertical" />
</LinearLayout>
</androidx.core.widget.NestedScrollView> <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>

View File

@ -45,6 +45,21 @@
android:text="1" android:text="1"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="16dp" /> android:textSize="16dp" />
<RelativeLayout
android:id="@+id/currentPlayingLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/black_60"
android:layout_centerInParent="true"
android:visibility="gone">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/playing_small_green_icon" />
</RelativeLayout>
</RelativeLayout> </RelativeLayout>
<LinearLayout <LinearLayout

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<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>
</RelativeLayout>

View File

@ -40,10 +40,10 @@
android:orientation="horizontal"> android:orientation="horizontal">
<ImageView <ImageView
android:layout_width="16dp" android:layout_width="24dp"
android:layout_height="16dp" android:layout_height="24dp"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:src="@drawable/search_unselect_icon" /> android:src="@drawable/search_edit_icon" />
<EditText <EditText
android:id="@+id/searchEdit" android:id="@+id/searchEdit"
@ -67,8 +67,8 @@
android:visibility="gone"> android:visibility="gone">
<ImageView <ImageView
android:layout_width="16dp" android:layout_width="24dp"
android:layout_height="16dp" android:layout_height="24dp"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:src="@drawable/cha_icon" /> android:src="@drawable/cha_icon" />
</RelativeLayout> </RelativeLayout>
@ -78,7 +78,7 @@
android:id="@+id/cancelBtn" android:id="@+id/cancelBtn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginStart="8dp" android:layout_marginStart="16dp"
android:fontFamily="@font/regular_font" android:fontFamily="@font/regular_font"
android:gravity="center" android:gravity="center"
android:text="@string/cancel" android:text="@string/cancel"

View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.lihang.ShadowLayout
android:id="@+id/playing_status_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:visibility="visible"
app:hl_cornerRadius="36dp"
app:hl_layoutBackground="#FF80F988"
app:hl_shadowColor="#40040604"
app:hl_shadowOffsetX="0dp"
app:hl_shadowOffsetY="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="68dp"
android:layout_alignParentBottom="true"
android:gravity="center_vertical"
android:paddingStart="20dp"
android:paddingEnd="20dp">
<LinearLayout
android:id="@+id/goDetailsBtn"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:elevation="0dp"
app:cardCornerRadius="24dp"
app:cardElevation="0dp">
<ImageView
android:id="@+id/audio_img"
android:layout_width="48dp"
android:scaleType="centerCrop"
android:layout_height="48dp"
android:src="@mipmap/musicoo_logo_img" />
</androidx.cardview.widget.CardView>
<com.player.musicoo.view.CircularProgressBar
android:id="@+id/progressBar"
android:layout_width="54dp"
android:layout_height="54dp"
android:layout_centerInParent="true" />
</RelativeLayout>
<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">
<com.player.musicoo.view.MarqueeTextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:fontFamily="@font/medium_font"
android:maxLines="1"
android:text="@string/app_name"
android:textColor="@color/black"
android:textSize="16dp" />
<com.player.musicoo.view.MarqueeTextView
android:id="@+id/desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="@string/app_name"
android:textColor="@color/black_60"
android:textSize="12dp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/play_black_btn"
android:layout_width="42dp"
android:layout_height="42dp"
android:gravity="center">
<ImageView
android:id="@+id/play_status_img"
android:layout_width="34dp"
android:layout_height="34dp"
android:src="@drawable/play_black_icon" />
</LinearLayout>
</LinearLayout>
</com.lihang.ShadowLayout>
</LinearLayout>

View File

@ -37,20 +37,6 @@
android:scaleType="centerCrop" android:scaleType="centerCrop"
android:src="@mipmap/musicoo_logo_img" /> 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> </RelativeLayout>
</androidx.cardview.widget.CardView> </androidx.cardview.widget.CardView>