update
This commit is contained in:
parent
8c4629497c
commit
9b91074eeb
@ -62,6 +62,9 @@
|
||||
<activity
|
||||
android:name=".activity.MoSearchMoreActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".activity.MoSingerMoreSongActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<service
|
||||
android:name=".service.PlaybackService"
|
||||
|
||||
@ -3,19 +3,19 @@ package com.player.musicoo.activity
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.renderscript.Allocation
|
||||
import android.renderscript.Element
|
||||
import android.renderscript.RenderScript
|
||||
import android.renderscript.ScriptIntrinsicBlur
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.target.CustomTarget
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import com.player.musicoo.R
|
||||
import com.player.musicoo.media.MediaControllerManager
|
||||
import com.player.musicoo.sp.AppStore
|
||||
@ -137,15 +137,20 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
|
||||
title.text = getString(R.string.description)
|
||||
val content = dialogView.findViewById<TextView>(R.id.dialog_content)
|
||||
content.text = description
|
||||
val okBtn = dialogView.findViewById<TextView>(R.id.dialog_ok_btn)
|
||||
val close = dialogView.findViewById<RelativeLayout>(R.id.closeBtn)
|
||||
val dialogBuilder = AlertDialog.Builder(this)
|
||||
.setView(dialogView)
|
||||
val dialog = dialogBuilder.create()
|
||||
dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
dialog.show()
|
||||
okBtn.setOnClickListener {
|
||||
close.setOnClickListener {
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
fun extractTextBeforeNewline(text: String): String {
|
||||
// 用换行符分割文本,取第一个部分
|
||||
return text.split("\n\n")[0]
|
||||
}
|
||||
|
||||
}
|
||||
@ -76,22 +76,28 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
||||
// 处理来自 PrimaryActivity 的情况
|
||||
updateCurrentMediaItemInfo()
|
||||
} else {
|
||||
binding.nameTv.text = intent.getStringExtra(PLAY_DETAILS_NAME)
|
||||
binding.descTv.text = intent.getStringExtra(PLAY_DETAILS_DESC)
|
||||
if (meController != null && meController.currentMediaItem != null && videoId == meController.currentMediaItem?.mediaId) {
|
||||
//进入的id与当前的id一样就不重新去获取播放
|
||||
updateCurrentMediaItemInfo()
|
||||
} else {
|
||||
binding.nameTv.text = intent.getStringExtra(PLAY_DETAILS_NAME)
|
||||
binding.descTv.text = intent.getStringExtra(PLAY_DETAILS_DESC)
|
||||
|
||||
if (videoId.isNullOrEmpty()) {
|
||||
finish()
|
||||
return
|
||||
if (videoId.isNullOrEmpty()) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
//传入进来的ID,就是进入此界面的当前ID
|
||||
currentVideoID = videoId
|
||||
//根据进来界面的当前ID来获取资源。
|
||||
initData(
|
||||
videoId,
|
||||
playlistId,
|
||||
playlistSetVideoId,
|
||||
params
|
||||
)
|
||||
}
|
||||
//传入进来的ID,就是进入此界面的当前ID
|
||||
currentVideoID = videoId
|
||||
//根据进来界面的当前ID来获取资源。
|
||||
initData(
|
||||
videoId,
|
||||
playlistId,
|
||||
playlistSetVideoId,
|
||||
params
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
onReceive()
|
||||
@ -130,7 +136,8 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
||||
binding.playbackErrorLayout.visibility = View.GONE
|
||||
binding.loadingView.visibility = View.GONE
|
||||
binding.disableClicksLayout.visibility = View.GONE
|
||||
val currentString = convertMillisToMinutesAndSecondsString(MediaControllerManager.getCurrentPosition())
|
||||
val currentString =
|
||||
convertMillisToMinutesAndSecondsString(MediaControllerManager.getCurrentPosition())
|
||||
binding.progressDurationTv.text = currentString
|
||||
if (MediaControllerManager.getDuration() > 0) {
|
||||
binding.totalDurationTv.visibility = View.VISIBLE
|
||||
|
||||
@ -83,8 +83,11 @@ class MoSearchMoreActivity : MoBaseActivity() {
|
||||
}
|
||||
|
||||
Request.MoreData -> {
|
||||
LogD(TAG, "Request.MoreData")
|
||||
currentContinuation?.let { it1 -> initDataMore(it1) }
|
||||
if (!currentContinuation.isNullOrEmpty()) {
|
||||
initDataMore(currentContinuation!!)
|
||||
}else{
|
||||
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,8 +141,10 @@ class MoSearchMoreActivity : MoBaseActivity() {
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private suspend fun initDataMore(continuation: String) {
|
||||
Innertube.moSearchPage(ContinuationBody(continuation = continuation))?.onSuccess { result ->
|
||||
LogD(TAG, "initDataMore result->$result")
|
||||
currentContinuation = result.continuation
|
||||
if (currentContinuation.isNullOrEmpty()) {
|
||||
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||
}
|
||||
if (result.searchResultList.isNotEmpty()) {
|
||||
list.addAll(result.searchResultList)
|
||||
if (!isFinishing) {
|
||||
@ -147,10 +152,10 @@ class MoSearchMoreActivity : MoBaseActivity() {
|
||||
}
|
||||
binding.refreshLayout.finishLoadMore(true)
|
||||
} else {
|
||||
binding.refreshLayout.finishLoadMore(2000, true, false)
|
||||
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||
}
|
||||
}?.onFailure {
|
||||
binding.refreshLayout.finishLoadMore(2000, false, false)
|
||||
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +1,10 @@
|
||||
package com.player.musicoo.activity
|
||||
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.bumptech.glide.Glide
|
||||
import com.gyf.immersionbar.ktx.immersionBar
|
||||
import com.player.musicoo.adapter.DetailsListAdapter
|
||||
import com.player.musicoo.databinding.ActivityDetailsBinding
|
||||
import com.player.musicoo.databinding.ActivitySingerDetailsBinding
|
||||
import com.player.musicoo.fragment.MoHomeFragment
|
||||
import com.player.musicoo.innertube.Innertube
|
||||
import com.player.musicoo.innertube.requests.moPlaylistPage
|
||||
import com.player.musicoo.innertube.requests.moSingerListPage
|
||||
import com.player.musicoo.util.LogTag.LogD
|
||||
import com.player.musicoo.view.SingerDetailsOtherView
|
||||
@ -75,6 +70,9 @@ class MoSingerDetailsActivity : MoBaseActivity() {
|
||||
binding.tryAgainBtn.setOnClickListener {
|
||||
requests.trySend(Request.TryAgain)
|
||||
}
|
||||
binding.singerDescExpand.setOnClickListener {
|
||||
showSongDescriptionDialog(binding.singerDesc.text.toString())
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun initData(browseId: String) {
|
||||
@ -86,7 +84,14 @@ class MoSingerDetailsActivity : MoBaseActivity() {
|
||||
.load(it.thumbnail)
|
||||
.into(binding.singerImg)
|
||||
binding.singerName.text = it.title
|
||||
binding.singerDesc.text = it.description
|
||||
if (it.description.isNullOrEmpty()) {
|
||||
binding.singerDesc.visibility = View.GONE
|
||||
binding.singerDescExpand.visibility = View.GONE
|
||||
} else {
|
||||
binding.singerDesc.visibility = View.VISIBLE
|
||||
binding.singerDescExpand.visibility = View.VISIBLE
|
||||
binding.singerDesc.text = extractTextBeforeNewline(it.description)
|
||||
}
|
||||
if (it.list != null) {
|
||||
for (bean: Innertube.SingerDetailsListPage in it.list) {
|
||||
if (bean.contents?.musicShelfContentList != null && bean.contents.musicShelfContentList.isNotEmpty()) {
|
||||
|
||||
@ -0,0 +1,170 @@
|
||||
package com.player.musicoo.activity
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.gyf.immersionbar.ktx.immersionBar
|
||||
import com.player.musicoo.adapter.SingerMoreSongAdapter
|
||||
import com.player.musicoo.databinding.ActivitySearchMoreBinding
|
||||
import com.player.musicoo.innertube.Innertube
|
||||
import com.player.musicoo.innertube.models.bodies.BrowseBody
|
||||
import com.player.musicoo.innertube.models.bodies.ContinuationBody
|
||||
import com.player.musicoo.innertube.requests.moSingerDetailsMoreLoadMorePage
|
||||
import com.player.musicoo.innertube.requests.moSingerDetailsMorePage
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.selects.select
|
||||
|
||||
class MoSingerMoreSongActivity : MoBaseActivity() {
|
||||
private val requests: Channel<Request> = Channel(Channel.UNLIMITED)
|
||||
|
||||
enum class Request {
|
||||
TryAgain,
|
||||
MoreData,
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SINGER_MORE_SONG_BROWSE_ID = "singer_more_song_browse_id"
|
||||
const val SINGER_MORE_SONG_PARAMS = "singer_more_song_params"
|
||||
const val SINGER_MORE_TYPE = "singer_more_type"
|
||||
}
|
||||
|
||||
private lateinit var binding: ActivitySearchMoreBinding
|
||||
private var browseId: String? = null
|
||||
private var params: String? = null
|
||||
private var type: String? = null
|
||||
private var list: MutableList<Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults> =
|
||||
mutableListOf()
|
||||
private var currentContinuation: String? = null
|
||||
private var adapter: SingerMoreSongAdapter? = null
|
||||
|
||||
override suspend fun main() {
|
||||
binding = ActivitySearchMoreBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
browseId = intent.getStringExtra(SINGER_MORE_SONG_BROWSE_ID)
|
||||
params = intent.getStringExtra(SINGER_MORE_SONG_PARAMS)
|
||||
type = intent.getStringExtra(SINGER_MORE_TYPE)
|
||||
if (browseId.isNullOrEmpty() || params.isNullOrEmpty()) {
|
||||
return
|
||||
}
|
||||
initImmersionBar()
|
||||
initView()
|
||||
initAdapter()
|
||||
initData(browseId!!, params!!)
|
||||
onReceive()
|
||||
}
|
||||
|
||||
private fun initImmersionBar() {
|
||||
immersionBar {
|
||||
statusBarDarkFont(false)
|
||||
statusBarView(binding.view)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun onReceive() {
|
||||
while (isActive) {
|
||||
select<Unit> {
|
||||
requests.onReceive {
|
||||
when (it) {
|
||||
Request.TryAgain -> {
|
||||
initData(browseId!!, params!!)
|
||||
}
|
||||
|
||||
Request.MoreData -> {
|
||||
if (!currentContinuation.isNullOrEmpty()) {
|
||||
initDataMore(currentContinuation!!)
|
||||
}else{
|
||||
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
binding.backBtn.setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
binding.tryAgainBtn.setOnClickListener {
|
||||
requests.trySend(Request.TryAgain)
|
||||
}
|
||||
binding.refreshLayout.setEnableRefresh(false)
|
||||
binding.refreshLayout.setEnableLoadMore(true)
|
||||
binding.refreshLayout.setOnLoadMoreListener {
|
||||
requests.trySend(Request.MoreData)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initAdapter() {
|
||||
adapter = SingerMoreSongAdapter(this, list, type)
|
||||
if (type == "MUSIC_PAGE_TYPE_ARTIST_DISCOGRAPHY") {
|
||||
binding.rv.layoutManager = GridLayoutManager(this, 2)
|
||||
} else {
|
||||
binding.rv.layoutManager =
|
||||
LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
||||
}
|
||||
binding.rv.adapter = adapter
|
||||
}
|
||||
|
||||
private suspend fun initData(browseId: String, params: String) {
|
||||
showLoadingUi()
|
||||
Innertube.moSingerDetailsMorePage(BrowseBody(browseId = browseId, params = params))
|
||||
?.onSuccess { result ->
|
||||
showDataUi()
|
||||
val title = result.title
|
||||
if (title.isNullOrEmpty()) {
|
||||
binding.title.visibility = View.GONE
|
||||
} else {
|
||||
binding.title.visibility = View.VISIBLE
|
||||
binding.title.text = title
|
||||
}
|
||||
currentContinuation = result.continuation
|
||||
list.clear()
|
||||
list.addAll(result.songList)
|
||||
|
||||
}?.onFailure {
|
||||
showNoContentUi()
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private suspend fun initDataMore(continuation: String) {
|
||||
Innertube.moSingerDetailsMoreLoadMorePage(ContinuationBody(continuation = continuation))
|
||||
?.onSuccess { result ->
|
||||
currentContinuation = result.continuation
|
||||
if (currentContinuation.isNullOrEmpty()) {
|
||||
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||
}
|
||||
if (result.songList.isNotEmpty()) {
|
||||
list.addAll(result.songList)
|
||||
if (!isFinishing) {
|
||||
adapter?.notifyDataSetChanged()
|
||||
binding.refreshLayout.finishLoadMore(true)
|
||||
}
|
||||
} else {
|
||||
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||
}
|
||||
}?.onFailure {
|
||||
binding.refreshLayout.finishLoadMoreWithNoMoreData()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,145 @@
|
||||
package com.player.musicoo.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.media3.common.C
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.Player
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.player.musicoo.R
|
||||
import com.player.musicoo.activity.MoListDetailsActivity
|
||||
import com.player.musicoo.activity.MoPlayDetailsActivity
|
||||
import com.player.musicoo.activity.MoSingerDetailsActivity
|
||||
import com.player.musicoo.databinding.MusicTowRowItemBinding
|
||||
import com.player.musicoo.databinding.PlayListItemBinding
|
||||
import com.player.musicoo.databinding.SearchResultOtherItemBinding
|
||||
import com.player.musicoo.databinding.SearchResultOtherLayoutBinding
|
||||
import com.player.musicoo.innertube.Innertube
|
||||
import com.player.musicoo.media.MediaControllerManager
|
||||
import com.player.musicoo.util.LogTag
|
||||
|
||||
class SingerMoreSongAdapter(
|
||||
private val context: Context,
|
||||
private val list: List<Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults>,
|
||||
private val type: String? = null,
|
||||
) :
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
TYPE_ONE -> {
|
||||
val binding =
|
||||
SearchResultOtherItemBinding.inflate(
|
||||
LayoutInflater.from(context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
ViewHolderOne(binding)
|
||||
}
|
||||
|
||||
TYPE_TWO -> {
|
||||
val binding =
|
||||
MusicTowRowItemBinding.inflate(LayoutInflater.from(context), parent, false)
|
||||
ViewHolderTow(binding)
|
||||
}
|
||||
|
||||
else -> throw IllegalArgumentException("Invalid view type")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val bean = list[position]
|
||||
when (holder.itemViewType) {
|
||||
TYPE_ONE -> {
|
||||
val typeOneHolder = holder as ViewHolderOne
|
||||
typeOneHolder.bind(bean)
|
||||
typeOneHolder.itemView.setOnClickListener {
|
||||
val intent = Intent(context, MoPlayDetailsActivity::class.java)
|
||||
intent.putExtra(
|
||||
MoPlayDetailsActivity.PLAY_DETAILS_VIDEO_ID,
|
||||
bean.videoId
|
||||
)
|
||||
intent.putExtra(
|
||||
MoPlayDetailsActivity.PLAY_DETAILS_PLAY_LIST_ID,
|
||||
bean.playlistId
|
||||
)
|
||||
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_NAME, bean.title)
|
||||
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, bean.name)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
TYPE_TWO -> {
|
||||
val typeTwoHolder = holder as ViewHolderTow
|
||||
typeTwoHolder.bind(bean)
|
||||
typeTwoHolder.itemView.setOnClickListener {
|
||||
val intent = Intent(context, MoListDetailsActivity::class.java)
|
||||
intent.putExtra(
|
||||
MoListDetailsActivity.PLAY_LIST_PAGE_BROWSE_ID,
|
||||
bean.browseId
|
||||
)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val TYPE_ONE = 1
|
||||
private val TYPE_TWO = 2
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (type == "MUSIC_PAGE_TYPE_ARTIST_DISCOGRAPHY") {
|
||||
TYPE_TWO
|
||||
} else {
|
||||
TYPE_ONE
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = list.size
|
||||
|
||||
inner class ViewHolderOne(private val binding: SearchResultOtherItemBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun bind(bean: Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults) {
|
||||
|
||||
binding.apply {
|
||||
Glide.with(context)
|
||||
.load(bean.thumbnail)
|
||||
.into(image)
|
||||
title.text = bean.title
|
||||
name.text = bean.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class ViewHolderTow(private val binding: MusicTowRowItemBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun bind(bean: Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults) {
|
||||
|
||||
binding.apply {
|
||||
Glide.with(context)
|
||||
.load(bean.thumbnail)
|
||||
.into(image)
|
||||
nameTv.text = bean.title
|
||||
descTv.text = bean.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var itemClickListener: OnItemClickListener? = null
|
||||
|
||||
fun setOnItemClickListener(listener: OnItemClickListener) {
|
||||
itemClickListener = listener
|
||||
}
|
||||
|
||||
interface OnItemClickListener {
|
||||
fun onItemClick(position: Int)
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package com.player.musicoo.adapter
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.view.LayoutInflater
|
||||
@ -8,11 +9,12 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.player.musicoo.activity.MoListDetailsActivity
|
||||
import com.player.musicoo.activity.MoPlayDetailsActivity
|
||||
import com.player.musicoo.activity.MoSingerDetailsActivity
|
||||
import com.player.musicoo.databinding.MusicTowRowItemBinding
|
||||
import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer
|
||||
|
||||
class TowRowListAdapter(
|
||||
private val context: Context,
|
||||
private val context: Activity,
|
||||
private val list: List<MusicCarouselShelfRenderer.Content>,
|
||||
) :
|
||||
RecyclerView.Adapter<TowRowListAdapter.ViewHolder>() {
|
||||
@ -35,6 +37,8 @@ class TowRowListAdapter(
|
||||
|
||||
val browseId = browseEndpoint?.browseId
|
||||
|
||||
val pageType = browseEndpoint?.type
|
||||
|
||||
val watchEndpoint = bean.musicTwoRowItemRenderer
|
||||
?.navigationEndpoint
|
||||
?.watchEndpoint
|
||||
@ -81,9 +85,21 @@ class TowRowListAdapter(
|
||||
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, desc)
|
||||
context.startActivity(intent)
|
||||
} else {
|
||||
val intent = Intent(context, MoListDetailsActivity::class.java)
|
||||
intent.putExtra(MoListDetailsActivity.PLAY_LIST_PAGE_BROWSE_ID, browseId)
|
||||
context.startActivity(intent)
|
||||
if (pageType == "MUSIC_PAGE_TYPE_ARTIST") {
|
||||
val intent = Intent(context, MoSingerDetailsActivity::class.java)
|
||||
intent.putExtra(
|
||||
MoSingerDetailsActivity.SINGER_DETAILS_PAGE_BROWSE_ID,
|
||||
browseId
|
||||
)
|
||||
context.startActivity(intent)
|
||||
if (context is MoSingerDetailsActivity) {
|
||||
context.finish()
|
||||
}
|
||||
} else {
|
||||
val intent = Intent(context, MoListDetailsActivity::class.java)
|
||||
intent.putExtra(MoListDetailsActivity.PLAY_LIST_PAGE_BROWSE_ID, browseId)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
package com.player.musicoo.innertube
|
||||
|
||||
import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer
|
||||
import com.player.musicoo.innertube.models.MusicResponsiveListItemRenderer
|
||||
import com.player.musicoo.innertube.models.MusicShelfRenderer
|
||||
import com.player.musicoo.innertube.models.MusicTwoRowItemRenderer
|
||||
import com.player.musicoo.innertube.models.NavigationEndpoint
|
||||
import com.player.musicoo.innertube.models.Runs
|
||||
import com.player.musicoo.innertube.models.Thumbnail
|
||||
import com.player.musicoo.innertube.utils.brotli
|
||||
import com.player.musicoo.util.LogTag
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.okhttp.OkHttp
|
||||
import io.ktor.client.plugins.BrowserUserAgent
|
||||
@ -15,11 +18,6 @@ import io.ktor.client.request.header
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpHeaders
|
||||
import io.ktor.serialization.kotlinx.json.json
|
||||
import com.player.musicoo.innertube.models.NavigationEndpoint
|
||||
import com.player.musicoo.innertube.models.Runs
|
||||
import com.player.musicoo.innertube.models.Thumbnail
|
||||
import com.player.musicoo.innertube.utils.brotli
|
||||
import com.player.musicoo.util.LogTag
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
@ -176,7 +174,10 @@ object Innertube {
|
||||
)
|
||||
|
||||
data class SingerDetailsListPage(
|
||||
val pageType: String? = null,
|
||||
val title: String?,
|
||||
val browseId: String? = null,
|
||||
val params: String? = null,
|
||||
val contents: SingerDetailsContent?
|
||||
) {
|
||||
data class SingerDetailsContent(
|
||||
@ -240,6 +241,24 @@ object Innertube {
|
||||
)
|
||||
}
|
||||
|
||||
data class BaseSingleColumnBrowseSongResults(
|
||||
val title: String? = null,
|
||||
val continuation: String? = null,
|
||||
val songList: List<SingleColumnBrowseSongResults>
|
||||
) {
|
||||
data class SingleColumnBrowseSongResults(
|
||||
val title: String?,
|
||||
val name: String?,
|
||||
val thumbnail: String?,
|
||||
val videoId: String? = null,
|
||||
val playlistId: String? = null,
|
||||
val browseId: String? = null,
|
||||
val params: String? = null,
|
||||
val pageType: String? = null
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
data class ArtistPage(
|
||||
val name: String?,
|
||||
val description: String?,
|
||||
|
||||
@ -26,7 +26,7 @@ data class BrowseResponse(
|
||||
|
||||
@Serializable
|
||||
data class ContinuationContents(
|
||||
val sectionListContinuation : SectionListContinuation?
|
||||
val sectionListContinuation: SectionListContinuation?
|
||||
)
|
||||
|
||||
@Serializable
|
||||
@ -34,7 +34,13 @@ data class BrowseResponse(
|
||||
@JsonNames("musicVisualHeaderRenderer")
|
||||
val musicImmersiveHeaderRenderer: MusicImmersiveHeaderRenderer?,
|
||||
val musicDetailHeaderRenderer: MusicDetailHeaderRenderer?,
|
||||
val musicHeaderRenderer: MusicHeaderRenderer?
|
||||
) {
|
||||
@Serializable
|
||||
data class MusicHeaderRenderer(
|
||||
val title: Runs?
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MusicDetailHeaderRenderer(
|
||||
val title: Runs?,
|
||||
|
||||
@ -2,10 +2,13 @@ package com.player.musicoo.innertube.requests
|
||||
|
||||
import com.player.musicoo.innertube.Innertube
|
||||
import com.player.musicoo.innertube.models.BrowseResponse
|
||||
import com.player.musicoo.innertube.models.ContinuationResponse
|
||||
import com.player.musicoo.innertube.models.GridRenderer
|
||||
import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer
|
||||
import com.player.musicoo.innertube.models.MusicShelfRenderer
|
||||
import com.player.musicoo.innertube.models.SectionListRenderer
|
||||
import com.player.musicoo.innertube.models.bodies.BrowseBody
|
||||
import com.player.musicoo.innertube.models.bodies.ContinuationBody
|
||||
import com.player.musicoo.innertube.utils.runCatchingNonCancellable
|
||||
import com.player.musicoo.util.LogTag
|
||||
import io.ktor.client.call.body
|
||||
@ -53,6 +56,9 @@ suspend fun Innertube.moSingerListPage(browseId: String): Result<Innertube.Singe
|
||||
if (sectionListRendererContents != null) {
|
||||
for (content: SectionListRenderer.Content in sectionListRendererContents) {
|
||||
var title = ""
|
||||
var browseId = ""
|
||||
var params = ""
|
||||
var pageType = ""
|
||||
val musicShelfRendererContents: MutableList<MusicShelfRenderer.Content> =
|
||||
mutableListOf()
|
||||
val musicCarouselShelfContents: MutableList<MusicCarouselShelfRenderer.Content> =
|
||||
@ -64,6 +70,14 @@ suspend fun Innertube.moSingerListPage(browseId: String): Result<Innertube.Singe
|
||||
musicShelfRendererContents.clear()
|
||||
musicShelfRendererContents.addAll(content.musicShelfRenderer.contents)
|
||||
}
|
||||
val browseEndpoint = content.musicShelfRenderer.title
|
||||
?.runs
|
||||
?.firstOrNull()
|
||||
?.navigationEndpoint
|
||||
?.browseEndpoint
|
||||
|
||||
browseId = browseEndpoint?.browseId ?: ""
|
||||
params = browseEndpoint?.params ?: ""
|
||||
}
|
||||
if (content.musicCarouselShelfRenderer != null) {
|
||||
title = content.musicCarouselShelfRenderer.header
|
||||
@ -75,6 +89,17 @@ suspend fun Innertube.moSingerListPage(browseId: String): Result<Innertube.Singe
|
||||
musicCarouselShelfContents.clear()
|
||||
musicCarouselShelfContents.addAll(content.musicCarouselShelfRenderer.contents)
|
||||
}
|
||||
val browseEndpoint = content.musicCarouselShelfRenderer.header
|
||||
?.musicCarouselShelfBasicHeaderRenderer
|
||||
?.title
|
||||
?.runs
|
||||
?.firstOrNull()
|
||||
?.navigationEndpoint
|
||||
?.browseEndpoint
|
||||
|
||||
browseId = browseEndpoint?.browseId ?: ""
|
||||
params = browseEndpoint?.params ?: ""
|
||||
pageType = browseEndpoint?.type ?: ""
|
||||
}
|
||||
|
||||
val singerDetailsContent = Innertube.SingerDetailsListPage.SingerDetailsContent(
|
||||
@ -83,20 +108,13 @@ suspend fun Innertube.moSingerListPage(browseId: String): Result<Innertube.Singe
|
||||
)
|
||||
|
||||
val singerDetails =
|
||||
Innertube.SingerDetailsListPage(title = title, contents = singerDetailsContent)
|
||||
|
||||
// LogTag.LogD(TAG, "title->${singerDetails.title}")
|
||||
// LogTag.LogD(
|
||||
// TAG,
|
||||
// "musicShelfContentList size->${singerDetails.contents?.musicShelfContentList?.size}"
|
||||
// )
|
||||
// LogTag.LogD(
|
||||
// TAG,
|
||||
// "musicCarouselShelfContentList size->${singerDetails.contents?.musicCarouselShelfContentList?.size}"
|
||||
// )
|
||||
//
|
||||
// LogTag.LogD(TAG, "--------------------------------------------")
|
||||
|
||||
Innertube.SingerDetailsListPage(
|
||||
title = title,
|
||||
contents = singerDetailsContent,
|
||||
browseId = browseId,
|
||||
params = params,
|
||||
pageType = pageType,
|
||||
)
|
||||
if (title.isNotEmpty()) {
|
||||
list.add(singerDetails)
|
||||
}
|
||||
@ -109,4 +127,184 @@ suspend fun Innertube.moSingerListPage(browseId: String): Result<Innertube.Singe
|
||||
description = description,
|
||||
list
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
suspend fun Innertube.moSingerDetailsMorePage(body: BrowseBody): Result<Innertube.BaseSingleColumnBrowseSongResults>? =
|
||||
runCatchingNonCancellable {
|
||||
val response = client.post(browse) {
|
||||
setBody(body)
|
||||
}.body<BrowseResponse>()
|
||||
|
||||
val gridRenderer = response.contents
|
||||
?.singleColumnBrowseResultsRenderer
|
||||
?.tabs?.firstOrNull()
|
||||
?.tabRenderer
|
||||
?.content
|
||||
?.sectionListRenderer
|
||||
?.contents
|
||||
?.firstOrNull()
|
||||
?.gridRenderer
|
||||
|
||||
|
||||
val musicPlaylistShelfRenderer = response.contents
|
||||
?.singleColumnBrowseResultsRenderer
|
||||
?.tabs
|
||||
?.firstOrNull()
|
||||
?.tabRenderer
|
||||
?.content
|
||||
?.sectionListRenderer
|
||||
?.contents
|
||||
?.firstOrNull()
|
||||
?.musicShelfRenderer
|
||||
|
||||
val title = response.header?.musicHeaderRenderer?.title?.text
|
||||
val continuation = musicPlaylistShelfRenderer
|
||||
?.continuations
|
||||
?.firstOrNull()
|
||||
?.nextContinuationData
|
||||
?.continuation
|
||||
|
||||
val songList: MutableList<Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults> =
|
||||
mutableListOf()
|
||||
|
||||
val contentList = musicPlaylistShelfRenderer?.contents
|
||||
val contentGridItems = gridRenderer?.items
|
||||
if (contentList != null) {
|
||||
for (content: MusicShelfRenderer.Content in contentList) {
|
||||
val contentTitle = content.musicResponsiveListItemRenderer
|
||||
?.flexColumns
|
||||
?.firstOrNull()
|
||||
?.musicResponsiveListItemFlexColumnRenderer
|
||||
?.text?.text
|
||||
|
||||
val name = content.musicResponsiveListItemRenderer
|
||||
?.flexColumns
|
||||
?.get(1)
|
||||
?.musicResponsiveListItemFlexColumnRenderer
|
||||
?.text?.text
|
||||
|
||||
val thumbnail = content.musicResponsiveListItemRenderer
|
||||
?.thumbnail
|
||||
?.musicThumbnailRenderer
|
||||
?.thumbnail
|
||||
?.thumbnails?.let {
|
||||
it.getOrNull(2) ?: it.getOrNull(1) ?: it.getOrNull(0)
|
||||
}?.url
|
||||
|
||||
val navigationEndpoint = content.musicResponsiveListItemRenderer
|
||||
?.flexColumns
|
||||
?.firstOrNull()
|
||||
?.musicResponsiveListItemFlexColumnRenderer
|
||||
?.text
|
||||
?.runs
|
||||
?.firstOrNull()
|
||||
?.navigationEndpoint
|
||||
|
||||
val videoId = navigationEndpoint?.watchEndpoint?.videoId
|
||||
val playlistId = navigationEndpoint?.watchEndpoint?.playlistId
|
||||
|
||||
|
||||
songList.add(
|
||||
Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults(
|
||||
title = contentTitle,
|
||||
name = name,
|
||||
thumbnail = thumbnail,
|
||||
videoId = videoId,
|
||||
playlistId = playlistId
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if (contentGridItems != null) {
|
||||
for (content: GridRenderer.Item in contentGridItems) {
|
||||
songList.add(
|
||||
Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults(
|
||||
title = content.musicTwoRowItemRenderer?.title?.runs?.firstOrNull()?.text,
|
||||
name = content.musicTwoRowItemRenderer?.subtitle?.text,
|
||||
thumbnail = content.musicTwoRowItemRenderer
|
||||
?.thumbnailRenderer
|
||||
?.musicThumbnailRenderer
|
||||
?.thumbnail
|
||||
?.thumbnails?.let {
|
||||
it.getOrNull(2) ?: it.getOrNull(1) ?: it.getOrNull(0)
|
||||
}?.url,
|
||||
browseId = content.musicTwoRowItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId,
|
||||
params = content.musicTwoRowItemRenderer?.navigationEndpoint?.browseEndpoint?.params,
|
||||
pageType = content.musicTwoRowItemRenderer?.navigationEndpoint?.browseEndpoint?.type
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Innertube.BaseSingleColumnBrowseSongResults(
|
||||
title = title,
|
||||
songList = songList,
|
||||
continuation = continuation
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun Innertube.moSingerDetailsMoreLoadMorePage(body: ContinuationBody): Result<Innertube.BaseSingleColumnBrowseSongResults>? =
|
||||
runCatchingNonCancellable {
|
||||
val response = client.post(browse) {
|
||||
setBody(body)
|
||||
}.body<ContinuationResponse>()
|
||||
|
||||
val continuation = response.continuationContents
|
||||
?.musicShelfContinuation
|
||||
?.continuations
|
||||
?.firstOrNull()
|
||||
?.nextContinuationData
|
||||
?.continuation
|
||||
|
||||
val songList: MutableList<Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults> =
|
||||
mutableListOf()
|
||||
|
||||
val contentList = response.continuationContents?.musicShelfContinuation?.contents
|
||||
if (contentList != null) {
|
||||
for (content: MusicShelfRenderer.Content in contentList) {
|
||||
val title = content.musicResponsiveListItemRenderer
|
||||
?.flexColumns
|
||||
?.firstOrNull()
|
||||
?.musicResponsiveListItemFlexColumnRenderer
|
||||
?.text?.text
|
||||
|
||||
val name = content.musicResponsiveListItemRenderer
|
||||
?.flexColumns
|
||||
?.get(1)
|
||||
?.musicResponsiveListItemFlexColumnRenderer
|
||||
?.text?.text
|
||||
|
||||
val thumbnail = content.musicResponsiveListItemRenderer
|
||||
?.thumbnail
|
||||
?.musicThumbnailRenderer
|
||||
?.thumbnail
|
||||
?.thumbnails?.let {
|
||||
it.getOrNull(2) ?: it.getOrNull(1) ?: it.getOrNull(0)
|
||||
}?.url
|
||||
|
||||
val navigationEndpoint = content.musicResponsiveListItemRenderer
|
||||
?.flexColumns
|
||||
?.firstOrNull()
|
||||
?.musicResponsiveListItemFlexColumnRenderer
|
||||
?.text
|
||||
?.runs
|
||||
?.firstOrNull()
|
||||
?.navigationEndpoint
|
||||
|
||||
val videoId = navigationEndpoint?.watchEndpoint?.videoId
|
||||
val playlistId = navigationEndpoint?.watchEndpoint?.playlistId
|
||||
|
||||
|
||||
songList.add(
|
||||
Innertube.BaseSingleColumnBrowseSongResults.SingleColumnBrowseSongResults(
|
||||
title, name, thumbnail, videoId, playlistId
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
Innertube.BaseSingleColumnBrowseSongResults(
|
||||
continuation = continuation,
|
||||
songList = songList
|
||||
)
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package com.player.musicoo.view
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
@ -12,7 +13,7 @@ import com.player.musicoo.adapter.TowRowListAdapter
|
||||
import com.player.musicoo.innertube.Innertube
|
||||
|
||||
@SuppressLint("ViewConstructor")
|
||||
class MusicTowRowListView(context: Context, homePage: Innertube.HomePage) : ModuleView(context) {
|
||||
class MusicTowRowListView(context: Activity, homePage: Innertube.HomePage) : ModuleView(context) {
|
||||
init {
|
||||
contentView = inflate(getContext(), R.layout.music_list_layout, this)
|
||||
val title = contentView?.findViewById<TextView>(R.id.title)
|
||||
|
||||
@ -1,21 +1,50 @@
|
||||
package com.player.musicoo.view
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.player.musicoo.R
|
||||
import com.player.musicoo.activity.MoSearchMoreActivity
|
||||
import com.player.musicoo.activity.MoSingerMoreSongActivity
|
||||
import com.player.musicoo.adapter.TowRowListAdapter
|
||||
import com.player.musicoo.innertube.Innertube
|
||||
|
||||
@SuppressLint("ViewConstructor")
|
||||
class SingerDetailsOtherView (context: Context, bean: Innertube.SingerDetailsListPage) :
|
||||
class SingerDetailsOtherView(context: Activity, bean: Innertube.SingerDetailsListPage) :
|
||||
ModuleView(context) {
|
||||
init {
|
||||
contentView = inflate(getContext(), R.layout.singer_music_list_layout, this)
|
||||
val title = contentView?.findViewById<TextView>(R.id.title)
|
||||
title?.text = bean.title
|
||||
val moreBtn = contentView?.findViewById<LinearLayout>(R.id.moreBtn)
|
||||
moreBtn?.setOnClickListener {
|
||||
val intent = Intent(context, MoSingerMoreSongActivity::class.java)
|
||||
intent.putExtra(
|
||||
MoSingerMoreSongActivity.SINGER_MORE_SONG_BROWSE_ID,
|
||||
bean.browseId
|
||||
)
|
||||
intent.putExtra(MoSingerMoreSongActivity.SINGER_MORE_SONG_PARAMS, bean.params)
|
||||
intent.putExtra(MoSingerMoreSongActivity.SINGER_MORE_TYPE, bean.pageType)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
when (bean.pageType) {
|
||||
"MUSIC_PAGE_TYPE_ARTIST_DISCOGRAPHY" -> {
|
||||
moreBtn?.visibility = VISIBLE
|
||||
}
|
||||
|
||||
"MUSIC_PAGE_TYPE_PLAYLIST" -> {
|
||||
moreBtn?.visibility = VISIBLE
|
||||
}
|
||||
|
||||
else -> {
|
||||
moreBtn?.visibility = GONE
|
||||
}
|
||||
}
|
||||
|
||||
val rv = contentView?.findViewById<RecyclerView>(R.id.rv)
|
||||
|
||||
|
||||
@ -2,11 +2,14 @@ package com.player.musicoo.view
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.player.musicoo.R
|
||||
import com.player.musicoo.activity.MoSingerMoreSongActivity
|
||||
import com.player.musicoo.adapter.SingerDetailsSongListAdapter
|
||||
import com.player.musicoo.innertube.Innertube
|
||||
|
||||
@ -18,6 +21,14 @@ class SingerDetailsSongView(context: Context, bean: Innertube.SingerDetailsListP
|
||||
val title = contentView?.findViewById<TextView>(R.id.title)
|
||||
title?.text = bean.title
|
||||
|
||||
val moreBtn = contentView?.findViewById<LinearLayout>(R.id.moreBtn)
|
||||
moreBtn?.setOnClickListener {
|
||||
val intent = Intent(context, MoSingerMoreSongActivity::class.java)
|
||||
intent.putExtra(MoSingerMoreSongActivity.SINGER_MORE_SONG_BROWSE_ID, bean.browseId)
|
||||
intent.putExtra(MoSingerMoreSongActivity.SINGER_MORE_SONG_PARAMS, bean.params)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
val rv = contentView?.findViewById<RecyclerView>(R.id.rv)
|
||||
|
||||
val adapter = SingerDetailsSongListAdapter(context, bean.contents?.musicShelfContentList!!)
|
||||
|
||||
8
app/src/main/res/drawable/drw_dialog_bg.xml
Normal file
8
app/src/main/res/drawable/drw_dialog_bg.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="@color/main_bg_color" />
|
||||
<corners android:radius="16dp" />
|
||||
|
||||
</shape>
|
||||
@ -54,10 +54,10 @@
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminateTint="@color/green"
|
||||
android:progressBackgroundTint="@color/green"
|
||||
android:progressTint="@color/green"
|
||||
android:layout_height="wrap_content" />
|
||||
android:progressTint="@color/green" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@ -176,10 +176,13 @@
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv"
|
||||
android:layout_width="match_parent"
|
||||
android:scrollbars="none"
|
||||
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:layout_height="wrap_content"
|
||||
android:layout_margin="16dp" />
|
||||
android:scrollbars="none" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@ -118,9 +118,7 @@
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:overScrollMode="never"
|
||||
android:scrollbars="none"
|
||||
tools:itemCount="10"
|
||||
tools:listitem="@layout/music_responsive_item" />
|
||||
android:scrollbars="none" />
|
||||
|
||||
<com.scwang.smart.refresh.footer.BallPulseFooter
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingBottom="12dp"
|
||||
android:paddingTop="12dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<RelativeLayout
|
||||
|
||||
@ -1,56 +1,78 @@
|
||||
<!-- custom_dialog_layout.xml -->
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="0dp"
|
||||
android:orientation="vertical"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="0dp">
|
||||
android:padding="16dp"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:background="@drawable/drw_dialog_bg"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/main_bg_color"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:src="@mipmap/musicoo_logo_img" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dialog_title"
|
||||
android:layout_width="wrap_content"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:fontFamily="@font/medium_font"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16dp" />
|
||||
</LinearLayout>
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dialog_content"
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@mipmap/musicoo_logo_img" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dialog_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:fontFamily="@font/medium_font"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/closeBtn"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentEnd="true">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:src="@drawable/cha_icon" />
|
||||
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:fontFamily="@font/regular_font"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="@color/white_60"
|
||||
android:textSize="14dp" />
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dialog_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/regular_font"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="@color/white_60"
|
||||
android:textSize="14dp" />
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:visibility="gone"
|
||||
android:layout_height="40dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
@ -88,4 +110,4 @@
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
</LinearLayout>
|
||||
|
||||
@ -6,15 +6,43 @@
|
||||
android:orientation="vertical"
|
||||
tools:ignore="MissingDefaultResource">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/medium_font"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="18dp" />
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="32dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/medium_font"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="18dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/moreBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/regular_font"
|
||||
android:text="@string/more"
|
||||
android:textColor="@color/white_60"
|
||||
android:textSize="12dp" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:rotation="270"
|
||||
android:src="@drawable/arrow_bottom_grey_icon" />
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user