Added Material Cab for Album and Artist details
This commit is contained in:
parent
72964be920
commit
0c5edf8ef6
21 changed files with 750 additions and 610 deletions
|
@ -126,6 +126,7 @@ dependencies {
|
|||
implementation 'com.squareup.retrofit2:retrofit:2.6.2'
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.6.2'
|
||||
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.2'
|
||||
implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
|
||||
|
||||
implementation 'com.afollestad.material-dialogs:core:3.1.1'
|
||||
implementation 'com.afollestad.material-dialogs:input:3.1.1'
|
||||
|
|
|
@ -4,25 +4,44 @@ import android.app.ActivityOptions
|
|||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.*
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.SubMenu
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.recyclerview.widget.*
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.*
|
||||
import code.name.monkey.retromusic.*
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.MaterialUtil
|
||||
import code.name.monkey.retromusic.App
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
|
||||
import code.name.monkey.retromusic.activities.tageditor.*
|
||||
import code.name.monkey.retromusic.activities.tageditor.AbsTagEditorActivity
|
||||
import code.name.monkey.retromusic.activities.tageditor.AlbumTagEditorActivity
|
||||
import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter
|
||||
import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter
|
||||
import code.name.monkey.retromusic.dialogs.*
|
||||
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
|
||||
import code.name.monkey.retromusic.dialogs.DeleteSongsDialog
|
||||
import code.name.monkey.retromusic.extensions.show
|
||||
import code.name.monkey.retromusic.glide.*
|
||||
import code.name.monkey.retromusic.glide.ArtistGlideRequest
|
||||
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
|
||||
import code.name.monkey.retromusic.glide.SongGlideRequest
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.SortOrder.AlbumSongSortOrder
|
||||
import code.name.monkey.retromusic.model.*
|
||||
import code.name.monkey.retromusic.mvp.presenter.*
|
||||
import code.name.monkey.retromusic.util.*
|
||||
import code.name.monkey.retromusic.interfaces.CabHolder
|
||||
import code.name.monkey.retromusic.model.Album
|
||||
import code.name.monkey.retromusic.model.Artist
|
||||
import code.name.monkey.retromusic.mvp.presenter.AlbumDetailsPresenter
|
||||
import code.name.monkey.retromusic.mvp.presenter.AlbumDetailsView
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.NavigationUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.RetroColorUtil
|
||||
import com.afollestad.materialcab.MaterialCab
|
||||
import com.bumptech.glide.Glide
|
||||
import kotlinx.android.synthetic.main.activity_album.*
|
||||
import kotlinx.android.synthetic.main.activity_album_content.*
|
||||
|
@ -30,263 +49,251 @@ import java.util.*
|
|||
import javax.inject.Inject
|
||||
import android.util.Pair as UtilPair
|
||||
|
||||
class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView {
|
||||
|
||||
private lateinit var simpleSongAdapter: SimpleSongAdapter
|
||||
private lateinit var album: Album
|
||||
private lateinit var artistImage: ImageView
|
||||
private val savedSortOrder: String
|
||||
get() = PreferenceUtil.getInstance(this).albumDetailSongSortOrder
|
||||
class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, CabHolder {
|
||||
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
|
||||
cab?.let {
|
||||
if (it.isActive) it.finish()
|
||||
}
|
||||
cab = MaterialCab(this, R.id.cab_stub)
|
||||
.setMenu(menuRes)
|
||||
.setCloseDrawableRes(R.drawable.ic_close_white_24dp)
|
||||
.setBackgroundColor(RetroColorUtil.shiftBackgroundColorForLightText(ATHUtil.resolveColor(this, R.attr.colorPrimary)))
|
||||
.start(callback)
|
||||
return cab as MaterialCab
|
||||
}
|
||||
|
||||
override fun createContentView(): View {
|
||||
return wrapSlidingMusicPanel(R.layout.activity_album)
|
||||
}
|
||||
private lateinit var simpleSongAdapter: SimpleSongAdapter
|
||||
private lateinit var album: Album
|
||||
private lateinit var artistImage: ImageView
|
||||
private var cab: MaterialCab? = null
|
||||
private val savedSortOrder: String
|
||||
get() = PreferenceUtil.getInstance(this).albumDetailSongSortOrder
|
||||
|
||||
@Inject
|
||||
lateinit var albumDetailsPresenter: AlbumDetailsPresenter
|
||||
override fun createContentView(): View {
|
||||
return wrapSlidingMusicPanel(R.layout.activity_album)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setDrawUnderStatusBar()
|
||||
super.onCreate(savedInstanceState)
|
||||
toggleBottomNavigationView(true)
|
||||
setStatusbarColor(Color.TRANSPARENT)
|
||||
setNavigationbarColorAuto()
|
||||
setTaskDescriptionColorAuto()
|
||||
setLightNavigationBar(true)
|
||||
setLightStatusbar(ColorUtil.isColorLight(ATHUtil.resolveColor(this, R.attr.colorPrimary)))
|
||||
@Inject
|
||||
lateinit var albumDetailsPresenter: AlbumDetailsPresenter
|
||||
|
||||
ActivityCompat.postponeEnterTransition(this)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setDrawUnderStatusBar()
|
||||
super.onCreate(savedInstanceState)
|
||||
toggleBottomNavigationView(true)
|
||||
setStatusbarColor(Color.TRANSPARENT)
|
||||
setNavigationbarColorAuto()
|
||||
setTaskDescriptionColorAuto()
|
||||
setLightNavigationBar(true)
|
||||
setLightStatusbar(ColorUtil.isColorLight(ATHUtil.resolveColor(this, R.attr.colorPrimary)))
|
||||
|
||||
App.musicComponent.inject(this)
|
||||
artistImage = findViewById(R.id.artistImage)
|
||||
ActivityCompat.postponeEnterTransition(this)
|
||||
|
||||
setupRecyclerView()
|
||||
App.musicComponent.inject(this)
|
||||
artistImage = findViewById(R.id.artistImage)
|
||||
|
||||
artistImage.setOnClickListener {
|
||||
val artistPairs = ActivityOptions.makeSceneTransitionAnimation(
|
||||
this,
|
||||
UtilPair.create(
|
||||
artistImage,
|
||||
getString(R.string.transition_artist_image)
|
||||
)
|
||||
)
|
||||
NavigationUtil.goToArtistOptions(this, album.artistId, artistPairs)
|
||||
}
|
||||
playAction.apply {
|
||||
setOnClickListener { MusicPlayerRemote.openQueue(album.songs!!, 0, true) }
|
||||
}
|
||||
shuffleAction.apply {
|
||||
setOnClickListener { MusicPlayerRemote.openAndShuffleQueue(album.songs!!, true) }
|
||||
}
|
||||
setupRecyclerView()
|
||||
|
||||
artistImage.setOnClickListener {
|
||||
val artistPairs = ActivityOptions.makeSceneTransitionAnimation(this, UtilPair.create(artistImage, getString(R.string.transition_artist_image)))
|
||||
NavigationUtil.goToArtistOptions(this, album.artistId, artistPairs)
|
||||
}
|
||||
playAction.apply {
|
||||
setOnClickListener { MusicPlayerRemote.openQueue(album.songs!!, 0, true) }
|
||||
}
|
||||
shuffleAction.apply {
|
||||
setOnClickListener { MusicPlayerRemote.openAndShuffleQueue(album.songs!!, true) }
|
||||
}
|
||||
|
||||
|
||||
albumDetailsPresenter.attachView(this)
|
||||
albumDetailsPresenter.attachView(this)
|
||||
|
||||
if (intent.extras!!.containsKey(EXTRA_ALBUM_ID)) {
|
||||
intent.extras?.getInt(EXTRA_ALBUM_ID)?.let { albumDetailsPresenter.loadAlbum(it) }
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
if (intent.extras!!.containsKey(EXTRA_ALBUM_ID)) {
|
||||
intent.extras?.getInt(EXTRA_ALBUM_ID)?.let { albumDetailsPresenter.loadAlbum(it) }
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
simpleSongAdapter = SimpleSongAdapter(this, ArrayList(), R.layout.item_song)
|
||||
recyclerView.apply {
|
||||
layoutManager = LinearLayoutManager(this@AlbumDetailsActivity)
|
||||
itemAnimator = DefaultItemAnimator()
|
||||
isNestedScrollingEnabled = false
|
||||
adapter = simpleSongAdapter
|
||||
}
|
||||
}
|
||||
private fun setupRecyclerView() {
|
||||
simpleSongAdapter = SimpleSongAdapter(this, ArrayList(), R.layout.item_song, this)
|
||||
recyclerView.apply {
|
||||
layoutManager = LinearLayoutManager(this@AlbumDetailsActivity)
|
||||
itemAnimator = DefaultItemAnimator()
|
||||
isNestedScrollingEnabled = false
|
||||
adapter = simpleSongAdapter
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
albumDetailsPresenter.detachView()
|
||||
}
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
albumDetailsPresenter.detachView()
|
||||
}
|
||||
|
||||
override fun complete() {
|
||||
ActivityCompat.startPostponedEnterTransition(this)
|
||||
}
|
||||
override fun complete() {
|
||||
ActivityCompat.startPostponedEnterTransition(this)
|
||||
}
|
||||
|
||||
override fun album(album: Album) {
|
||||
override fun album(album: Album) {
|
||||
|
||||
if (album.songs!!.isEmpty()) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
this.album = album
|
||||
if (album.songs!!.isEmpty()) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
this.album = album
|
||||
|
||||
albumTitle.text = album.title
|
||||
if (MusicUtil.getYearString(album.year) == "-") {
|
||||
albumText.text = String.format(
|
||||
"%s • %s",
|
||||
album.artistName,
|
||||
MusicUtil.getReadableDurationString(
|
||||
MusicUtil.getTotalDuration(
|
||||
this,
|
||||
album.songs
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
albumText.text = String.format(
|
||||
"%s • %s • %s",
|
||||
album.artistName,
|
||||
MusicUtil.getYearString(album.year),
|
||||
MusicUtil.getReadableDurationString(
|
||||
MusicUtil.getTotalDuration(
|
||||
this,
|
||||
album.songs
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
loadAlbumCover()
|
||||
simpleSongAdapter.swapDataSet(album.songs)
|
||||
albumDetailsPresenter.loadMore(album.artistId)
|
||||
}
|
||||
albumTitle.text = album.title
|
||||
if (MusicUtil.getYearString(album.year) == "-") {
|
||||
albumText.text = String.format("%s • %s", album.artistName, MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(this, album.songs)))
|
||||
} else {
|
||||
albumText.text = String.format("%s • %s • %s", album.artistName, MusicUtil.getYearString(album.year), MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(this, album.songs)))
|
||||
}
|
||||
loadAlbumCover()
|
||||
simpleSongAdapter.swapDataSet(album.songs)
|
||||
albumDetailsPresenter.loadMore(album.artistId)
|
||||
}
|
||||
|
||||
override fun moreAlbums(albums: ArrayList<Album>) {
|
||||
moreTitle.show()
|
||||
moreRecyclerView.show()
|
||||
moreTitle.text = String.format(getString(R.string.label_more_from), album.artistName)
|
||||
override fun moreAlbums(albums: ArrayList<Album>) {
|
||||
moreTitle.show()
|
||||
moreRecyclerView.show()
|
||||
moreTitle.text = String.format(getString(R.string.label_more_from), album.artistName)
|
||||
|
||||
val albumAdapter = HorizontalAlbumAdapter(this, albums, false, null)
|
||||
moreRecyclerView.layoutManager = GridLayoutManager(
|
||||
this,
|
||||
1,
|
||||
GridLayoutManager.HORIZONTAL,
|
||||
false
|
||||
)
|
||||
moreRecyclerView.adapter = albumAdapter
|
||||
}
|
||||
val albumAdapter = HorizontalAlbumAdapter(this, albums, false, null)
|
||||
moreRecyclerView.layoutManager = GridLayoutManager(
|
||||
this,
|
||||
1,
|
||||
GridLayoutManager.HORIZONTAL,
|
||||
false
|
||||
)
|
||||
moreRecyclerView.adapter = albumAdapter
|
||||
}
|
||||
|
||||
override fun loadArtistImage(artist: Artist) {
|
||||
ArtistGlideRequest.Builder.from(Glide.with(this), artist).generatePalette(this).build()
|
||||
.dontAnimate().dontTransform().into(object : RetroMusicColoredTarget(artistImage) {
|
||||
override fun onColorReady(color: Int) {
|
||||
override fun loadArtistImage(artist: Artist) {
|
||||
ArtistGlideRequest.Builder.from(Glide.with(this), artist).generatePalette(this).build()
|
||||
.dontAnimate().dontTransform().into(object : RetroMusicColoredTarget(artistImage) {
|
||||
override fun onColorReady(color: Int) {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadAlbumCover() {
|
||||
SongGlideRequest.Builder.from(Glide.with(this), album.safeGetFirstSong())
|
||||
.checkIgnoreMediaStore(this).generatePalette(this).build().dontAnimate().dontTransform()
|
||||
.into(object : RetroMusicColoredTarget(image) {
|
||||
override fun onColorReady(color: Int) {
|
||||
setColors(color)
|
||||
}
|
||||
})
|
||||
}
|
||||
private fun loadAlbumCover() {
|
||||
SongGlideRequest.Builder.from(Glide.with(this), album.safeGetFirstSong())
|
||||
.checkIgnoreMediaStore(this).generatePalette(this).build().dontAnimate().dontTransform()
|
||||
.into(object : RetroMusicColoredTarget(image) {
|
||||
override fun onColorReady(color: Int) {
|
||||
setColors(color)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun setColors(color: Int) {
|
||||
val themeColor = if (PreferenceUtil.getInstance(this).adaptiveColor) color
|
||||
else ThemeStore.accentColor(this)
|
||||
private fun setColors(color: Int) {
|
||||
val themeColor = if (PreferenceUtil.getInstance(this).adaptiveColor) color
|
||||
else ThemeStore.accentColor(this)
|
||||
|
||||
songTitle.setTextColor(themeColor)
|
||||
moreTitle.setTextColor(themeColor)
|
||||
songTitle.setTextColor(themeColor)
|
||||
moreTitle.setTextColor(themeColor)
|
||||
|
||||
val buttonColor = if (PreferenceUtil.getInstance(this).adaptiveColor) color
|
||||
else ATHUtil.resolveColor(this, R.attr.cardBackgroundColor)
|
||||
val buttonColor = if (PreferenceUtil.getInstance(this).adaptiveColor) color
|
||||
else ATHUtil.resolveColor(this, R.attr.cardBackgroundColor)
|
||||
|
||||
MaterialUtil.setTint(button = shuffleAction, color = buttonColor)
|
||||
MaterialUtil.setTint(button = playAction, color = buttonColor)
|
||||
MaterialUtil.setTint(button = shuffleAction, color = buttonColor)
|
||||
MaterialUtil.setTint(button = playAction, color = buttonColor)
|
||||
|
||||
toolbar.setBackgroundColor(ATHUtil.resolveColor(this, R.attr.colorPrimary))
|
||||
setSupportActionBar(toolbar)
|
||||
supportActionBar?.title = null
|
||||
}
|
||||
toolbar.setBackgroundColor(ATHUtil.resolveColor(this, R.attr.colorPrimary))
|
||||
setSupportActionBar(toolbar)
|
||||
supportActionBar?.title = null
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_album_detail, menu)
|
||||
val sortOrder = menu.findItem(R.id.action_sort_order)
|
||||
setUpSortOrderMenu(sortOrder.subMenu)
|
||||
return super.onCreateOptionsMenu(menu)
|
||||
}
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_album_detail, menu)
|
||||
val sortOrder = menu.findItem(R.id.action_sort_order)
|
||||
setUpSortOrderMenu(sortOrder.subMenu)
|
||||
return super.onCreateOptionsMenu(menu)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return handleSortOrderMenuItem(item)
|
||||
}
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return handleSortOrderMenuItem(item)
|
||||
}
|
||||
|
||||
private fun handleSortOrderMenuItem(item: MenuItem): Boolean {
|
||||
var sortOrder: String? = null
|
||||
val songs = simpleSongAdapter.dataSet
|
||||
when (item.itemId) {
|
||||
R.id.action_play_next -> {
|
||||
MusicPlayerRemote.playNext(songs)
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_current_playing -> {
|
||||
MusicPlayerRemote.enqueue(songs)
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_playlist -> {
|
||||
AddToPlaylistDialog.create(songs).show(supportFragmentManager, "ADD_PLAYLIST")
|
||||
return true
|
||||
}
|
||||
R.id.action_delete_from_device -> {
|
||||
DeleteSongsDialog.create(songs).show(supportFragmentManager, "DELETE_SONGS")
|
||||
return true
|
||||
}
|
||||
android.R.id.home -> {
|
||||
super.onBackPressed()
|
||||
return true
|
||||
}
|
||||
R.id.action_tag_editor -> {
|
||||
val intent = Intent(this, AlbumTagEditorActivity::class.java)
|
||||
intent.putExtra(AbsTagEditorActivity.EXTRA_ID, album.id)
|
||||
startActivityForResult(intent, TAG_EDITOR_REQUEST)
|
||||
return true
|
||||
}
|
||||
/*Sort*/
|
||||
R.id.action_sort_order_title -> sortOrder = AlbumSongSortOrder.SONG_A_Z
|
||||
R.id.action_sort_order_title_desc -> sortOrder = AlbumSongSortOrder.SONG_Z_A
|
||||
R.id.action_sort_order_track_list -> sortOrder = AlbumSongSortOrder.SONG_TRACK_LIST
|
||||
R.id.action_sort_order_artist_song_duration -> sortOrder = AlbumSongSortOrder.SONG_DURATION
|
||||
}
|
||||
if (sortOrder != null) {
|
||||
item.isChecked = true
|
||||
setSaveSortOrder(sortOrder)
|
||||
}
|
||||
return true
|
||||
}
|
||||
private fun handleSortOrderMenuItem(item: MenuItem): Boolean {
|
||||
var sortOrder: String? = null
|
||||
val songs = simpleSongAdapter.dataSet
|
||||
when (item.itemId) {
|
||||
R.id.action_play_next -> {
|
||||
MusicPlayerRemote.playNext(songs)
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_current_playing -> {
|
||||
MusicPlayerRemote.enqueue(songs)
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_playlist -> {
|
||||
AddToPlaylistDialog.create(songs).show(supportFragmentManager, "ADD_PLAYLIST")
|
||||
return true
|
||||
}
|
||||
R.id.action_delete_from_device -> {
|
||||
DeleteSongsDialog.create(songs).show(supportFragmentManager, "DELETE_SONGS")
|
||||
return true
|
||||
}
|
||||
android.R.id.home -> {
|
||||
super.onBackPressed()
|
||||
return true
|
||||
}
|
||||
R.id.action_tag_editor -> {
|
||||
val intent = Intent(this, AlbumTagEditorActivity::class.java)
|
||||
intent.putExtra(AbsTagEditorActivity.EXTRA_ID, album.id)
|
||||
startActivityForResult(intent, TAG_EDITOR_REQUEST)
|
||||
return true
|
||||
}
|
||||
/*Sort*/
|
||||
R.id.action_sort_order_title -> sortOrder = AlbumSongSortOrder.SONG_A_Z
|
||||
R.id.action_sort_order_title_desc -> sortOrder = AlbumSongSortOrder.SONG_Z_A
|
||||
R.id.action_sort_order_track_list -> sortOrder = AlbumSongSortOrder.SONG_TRACK_LIST
|
||||
R.id.action_sort_order_artist_song_duration -> sortOrder = AlbumSongSortOrder.SONG_DURATION
|
||||
}
|
||||
if (sortOrder != null) {
|
||||
item.isChecked = true
|
||||
setSaveSortOrder(sortOrder)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun setUpSortOrderMenu(sortOrder: SubMenu) {
|
||||
when (savedSortOrder) {
|
||||
AlbumSongSortOrder.SONG_A_Z -> sortOrder.findItem(R.id.action_sort_order_title)
|
||||
.isChecked = true
|
||||
AlbumSongSortOrder.SONG_Z_A -> sortOrder.findItem(R.id.action_sort_order_title_desc)
|
||||
.isChecked = true
|
||||
AlbumSongSortOrder.SONG_TRACK_LIST -> sortOrder.findItem(R.id.action_sort_order_track_list)
|
||||
.isChecked = true
|
||||
AlbumSongSortOrder.SONG_DURATION -> sortOrder.findItem(R.id.action_sort_order_artist_song_duration)
|
||||
.isChecked = true
|
||||
}
|
||||
}
|
||||
private fun setUpSortOrderMenu(sortOrder: SubMenu) {
|
||||
when (savedSortOrder) {
|
||||
AlbumSongSortOrder.SONG_A_Z -> sortOrder.findItem(R.id.action_sort_order_title)
|
||||
.isChecked = true
|
||||
AlbumSongSortOrder.SONG_Z_A -> sortOrder.findItem(R.id.action_sort_order_title_desc)
|
||||
.isChecked = true
|
||||
AlbumSongSortOrder.SONG_TRACK_LIST -> sortOrder.findItem(R.id.action_sort_order_track_list)
|
||||
.isChecked = true
|
||||
AlbumSongSortOrder.SONG_DURATION -> sortOrder.findItem(R.id.action_sort_order_artist_song_duration)
|
||||
.isChecked = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun setSaveSortOrder(sortOrder: String?) {
|
||||
PreferenceUtil.getInstance(this).albumDetailSongSortOrder = sortOrder
|
||||
reload()
|
||||
}
|
||||
private fun setSaveSortOrder(sortOrder: String?) {
|
||||
PreferenceUtil.getInstance(this).albumDetailSongSortOrder = sortOrder
|
||||
reload()
|
||||
}
|
||||
|
||||
override fun onMediaStoreChanged() {
|
||||
super.onMediaStoreChanged()
|
||||
reload()
|
||||
}
|
||||
override fun onMediaStoreChanged() {
|
||||
super.onMediaStoreChanged()
|
||||
reload()
|
||||
}
|
||||
|
||||
private fun reload() {
|
||||
if (intent.extras!!.containsKey(EXTRA_ALBUM_ID)) {
|
||||
intent.extras?.getInt(EXTRA_ALBUM_ID)?.let { albumDetailsPresenter.loadAlbum(it) }
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
private fun reload() {
|
||||
if (intent.extras!!.containsKey(EXTRA_ALBUM_ID)) {
|
||||
intent.extras?.getInt(EXTRA_ALBUM_ID)?.let { albumDetailsPresenter.loadAlbum(it) }
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
companion object {
|
||||
|
||||
const val EXTRA_ALBUM_ID = "extra_album_id"
|
||||
private const val TAG_EDITOR_REQUEST = 2001
|
||||
}
|
||||
const val EXTRA_ALBUM_ID = "extra_album_id"
|
||||
private const val TAG_EDITOR_REQUEST = 2001
|
||||
}
|
||||
}
|
|
@ -3,26 +3,39 @@ package code.name.monkey.retromusic.activities
|
|||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.os.*
|
||||
import android.text.*
|
||||
import android.view.*
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.Html
|
||||
import android.text.Spanned
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.recyclerview.widget.*
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import code.name.monkey.appthemehelper.ThemeStore
|
||||
import code.name.monkey.appthemehelper.util.*
|
||||
import code.name.monkey.retromusic.*
|
||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.MaterialUtil
|
||||
import code.name.monkey.retromusic.App
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
|
||||
import code.name.monkey.retromusic.adapter.album.*
|
||||
import code.name.monkey.retromusic.adapter.album.AlbumAdapter
|
||||
import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter
|
||||
import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter
|
||||
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
|
||||
import code.name.monkey.retromusic.glide.*
|
||||
import code.name.monkey.retromusic.glide.ArtistGlideRequest
|
||||
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.interfaces.CabHolder
|
||||
import code.name.monkey.retromusic.model.Artist
|
||||
import code.name.monkey.retromusic.mvp.presenter.*
|
||||
import code.name.monkey.retromusic.rest.LastFMRestClient
|
||||
import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsPresenter
|
||||
import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsView
|
||||
import code.name.monkey.retromusic.rest.model.LastFmArtist
|
||||
import code.name.monkey.retromusic.util.*
|
||||
import com.afollestad.materialcab.MaterialCab
|
||||
import com.bumptech.glide.Glide
|
||||
import kotlinx.android.synthetic.main.activity_artist_content.*
|
||||
import kotlinx.android.synthetic.main.activity_artist_details.*
|
||||
|
@ -30,269 +43,277 @@ import java.util.*
|
|||
import javax.inject.Inject
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView {
|
||||
class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView, CabHolder {
|
||||
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
|
||||
cab?.let {
|
||||
if (it.isActive) it.finish()
|
||||
}
|
||||
cab = MaterialCab(this, R.id.cab_stub)
|
||||
.setMenu(menuRes)
|
||||
.setCloseDrawableRes(R.drawable.ic_close_white_24dp)
|
||||
.setBackgroundColor(RetroColorUtil.shiftBackgroundColorForLightText(ATHUtil.resolveColor(this, R.attr.colorPrimary)))
|
||||
.start(callback)
|
||||
return cab as MaterialCab
|
||||
}
|
||||
|
||||
private var biography: Spanned? = null
|
||||
private lateinit var artist: Artist
|
||||
private var lastFMRestClient: LastFMRestClient? = null
|
||||
private lateinit var songAdapter: SimpleSongAdapter
|
||||
private lateinit var albumAdapter: AlbumAdapter
|
||||
private var forceDownload: Boolean = false
|
||||
private var cab: MaterialCab? = null
|
||||
private var biography: Spanned? = null
|
||||
private lateinit var artist: Artist
|
||||
private lateinit var songAdapter: SimpleSongAdapter
|
||||
private lateinit var albumAdapter: AlbumAdapter
|
||||
private var forceDownload: Boolean = false
|
||||
|
||||
override fun createContentView(): View {
|
||||
return wrapSlidingMusicPanel(R.layout.activity_artist_details)
|
||||
}
|
||||
override fun createContentView(): View {
|
||||
return wrapSlidingMusicPanel(R.layout.activity_artist_details)
|
||||
}
|
||||
|
||||
@Inject
|
||||
lateinit var artistDetailsPresenter: ArtistDetailsPresenter
|
||||
@Inject
|
||||
lateinit var artistDetailsPresenter: ArtistDetailsPresenter
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setDrawUnderStatusBar()
|
||||
super.onCreate(savedInstanceState)
|
||||
toggleBottomNavigationView(true)
|
||||
setStatusbarColor(Color.TRANSPARENT)
|
||||
setNavigationbarColorAuto()
|
||||
setTaskDescriptionColorAuto()
|
||||
setLightNavigationBar(true)
|
||||
setLightStatusbar(ColorUtil.isColorLight(ATHUtil.resolveColor(this, R.attr.colorPrimary)))
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setDrawUnderStatusBar()
|
||||
super.onCreate(savedInstanceState)
|
||||
toggleBottomNavigationView(true)
|
||||
setStatusbarColor(Color.TRANSPARENT)
|
||||
setNavigationbarColorAuto()
|
||||
setTaskDescriptionColorAuto()
|
||||
setLightNavigationBar(true)
|
||||
setLightStatusbar(ColorUtil.isColorLight(ATHUtil.resolveColor(this, R.attr.colorPrimary)))
|
||||
|
||||
ActivityCompat.postponeEnterTransition(this)
|
||||
ActivityCompat.postponeEnterTransition(this)
|
||||
|
||||
lastFMRestClient = LastFMRestClient(this)
|
||||
setUpViews()
|
||||
|
||||
setUpViews()
|
||||
playAction.apply {
|
||||
setOnClickListener { MusicPlayerRemote.openQueue(artist.songs, 0, true) }
|
||||
}
|
||||
shuffleAction.apply {
|
||||
setOnClickListener { MusicPlayerRemote.openAndShuffleQueue(artist.songs, true) }
|
||||
}
|
||||
|
||||
playAction.apply {
|
||||
setOnClickListener { MusicPlayerRemote.openQueue(artist.songs, 0, true) }
|
||||
}
|
||||
shuffleAction.apply {
|
||||
setOnClickListener { MusicPlayerRemote.openAndShuffleQueue(artist.songs, true) }
|
||||
}
|
||||
biographyText.setOnClickListener {
|
||||
if (biographyText.maxLines == 4) {
|
||||
biographyText.maxLines = Integer.MAX_VALUE
|
||||
} else {
|
||||
biographyText.maxLines = 4
|
||||
}
|
||||
}
|
||||
|
||||
biographyText.setOnClickListener {
|
||||
if (biographyText.maxLines == 4) {
|
||||
biographyText.maxLines = Integer.MAX_VALUE
|
||||
} else {
|
||||
biographyText.maxLines = 4
|
||||
}
|
||||
}
|
||||
App.musicComponent.inject(this)
|
||||
artistDetailsPresenter.attachView(this)
|
||||
|
||||
App.musicComponent.inject(this)
|
||||
artistDetailsPresenter.attachView(this)
|
||||
if (intent.extras!!.containsKey(EXTRA_ARTIST_ID)) {
|
||||
intent.extras?.getInt(EXTRA_ARTIST_ID)?.let { artistDetailsPresenter.loadArtist(it) }
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
if (intent.extras!!.containsKey(EXTRA_ARTIST_ID)) {
|
||||
intent.extras?.getInt(EXTRA_ARTIST_ID)?.let { artistDetailsPresenter.loadArtist(it) }
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
artistDetailsPresenter.detachView()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
artistDetailsPresenter.detachView()
|
||||
}
|
||||
private fun setUpViews() {
|
||||
setupRecyclerView()
|
||||
setupContainerHeight()
|
||||
}
|
||||
|
||||
private fun setUpViews() {
|
||||
setupRecyclerView()
|
||||
setupContainerHeight()
|
||||
}
|
||||
private fun setupContainerHeight() {
|
||||
imageContainer?.let {
|
||||
val params = it.layoutParams
|
||||
params.width = DensityUtil.getScreenHeight(this) / 2
|
||||
it.layoutParams = params
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupContainerHeight() {
|
||||
imageContainer?.let {
|
||||
val params = it.layoutParams
|
||||
params.width = DensityUtil.getScreenHeight(this) / 2
|
||||
it.layoutParams = params
|
||||
}
|
||||
}
|
||||
private fun setupRecyclerView() {
|
||||
albumAdapter = HorizontalAlbumAdapter(this, ArrayList(), false, null)
|
||||
albumRecyclerView.apply {
|
||||
itemAnimator = DefaultItemAnimator()
|
||||
layoutManager = GridLayoutManager(this.context, 1, GridLayoutManager.HORIZONTAL, false)
|
||||
adapter = albumAdapter
|
||||
}
|
||||
songAdapter = SimpleSongAdapter(this, ArrayList(), R.layout.item_song, this)
|
||||
recyclerView.apply {
|
||||
itemAnimator = DefaultItemAnimator()
|
||||
layoutManager = LinearLayoutManager(this.context)
|
||||
adapter = songAdapter
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
albumAdapter = HorizontalAlbumAdapter(this, ArrayList(), false, null)
|
||||
albumRecyclerView.apply {
|
||||
itemAnimator = DefaultItemAnimator()
|
||||
layoutManager = GridLayoutManager(this.context, 1, GridLayoutManager.HORIZONTAL, false)
|
||||
adapter = albumAdapter
|
||||
}
|
||||
songAdapter = SimpleSongAdapter(this, ArrayList(), R.layout.item_song)
|
||||
recyclerView.apply {
|
||||
itemAnimator = DefaultItemAnimator()
|
||||
layoutManager = LinearLayoutManager(this.context)
|
||||
adapter = songAdapter
|
||||
}
|
||||
}
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
when (requestCode) {
|
||||
REQUEST_CODE_SELECT_IMAGE -> if (resultCode == Activity.RESULT_OK) {
|
||||
data?.data?.let {
|
||||
CustomArtistImageUtil.getInstance(this).setCustomArtistImage(artist, it)
|
||||
}
|
||||
}
|
||||
else -> if (resultCode == Activity.RESULT_OK) {
|
||||
reload()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
when (requestCode) {
|
||||
REQUEST_CODE_SELECT_IMAGE -> if (resultCode == Activity.RESULT_OK) {
|
||||
data?.data?.let {
|
||||
CustomArtistImageUtil.getInstance(this).setCustomArtistImage(artist, it)
|
||||
}
|
||||
}
|
||||
else -> if (resultCode == Activity.RESULT_OK) {
|
||||
reload()
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun showEmptyView() {
|
||||
|
||||
override fun showEmptyView() {
|
||||
}
|
||||
|
||||
}
|
||||
override fun complete() {
|
||||
ActivityCompat.startPostponedEnterTransition(this)
|
||||
}
|
||||
|
||||
override fun complete() {
|
||||
ActivityCompat.startPostponedEnterTransition(this)
|
||||
}
|
||||
override fun artist(artist: Artist) {
|
||||
if (artist.songCount <= 0) {
|
||||
finish()
|
||||
}
|
||||
this.artist = artist
|
||||
loadArtistImage()
|
||||
|
||||
override fun artist(artist: Artist) {
|
||||
if (artist.songCount <= 0) {
|
||||
finish()
|
||||
}
|
||||
this.artist = artist
|
||||
loadArtistImage()
|
||||
if (RetroUtil.isAllowedToDownloadMetadata(this)) {
|
||||
loadBiography(artist.name)
|
||||
}
|
||||
artistTitle.text = artist.name
|
||||
text.text = String.format(
|
||||
"%s • %s",
|
||||
MusicUtil.getArtistInfoString(this, artist),
|
||||
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(this, artist.songs))
|
||||
)
|
||||
|
||||
if (RetroUtil.isAllowedToDownloadMetadata(this)) {
|
||||
loadBiography(artist.name)
|
||||
}
|
||||
artistTitle.text = artist.name
|
||||
text.text = String.format(
|
||||
"%s • %s",
|
||||
MusicUtil.getArtistInfoString(this, artist),
|
||||
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(this, artist.songs))
|
||||
)
|
||||
songAdapter.swapDataSet(artist.songs)
|
||||
albumAdapter.swapDataSet(artist.albums!!)
|
||||
}
|
||||
|
||||
songAdapter.swapDataSet(artist.songs)
|
||||
albumAdapter.swapDataSet(artist.albums!!)
|
||||
}
|
||||
private fun loadBiography(
|
||||
name: String, lang: String? = Locale.getDefault().language
|
||||
) {
|
||||
biography = null
|
||||
this.lang = lang
|
||||
artistDetailsPresenter.loadBiography(name, lang, null)
|
||||
}
|
||||
|
||||
private fun loadBiography(
|
||||
name: String, lang: String? = Locale.getDefault().language
|
||||
) {
|
||||
biography = null
|
||||
this.lang = lang
|
||||
artistDetailsPresenter.loadBiography(name, lang, null)
|
||||
}
|
||||
override fun artistInfo(lastFmArtist: LastFmArtist?) {
|
||||
if (lastFmArtist != null && lastFmArtist.artist != null) {
|
||||
val bioContent = lastFmArtist.artist.bio.content
|
||||
if (bioContent != null && bioContent.trim { it <= ' ' }.isNotEmpty()) {
|
||||
biographyText.visibility = View.VISIBLE
|
||||
biographyTitle.visibility = View.VISIBLE
|
||||
biography = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
Html.fromHtml(bioContent, Html.FROM_HTML_MODE_LEGACY)
|
||||
} else {
|
||||
Html.fromHtml(bioContent)
|
||||
}
|
||||
biographyText.text = biography
|
||||
}
|
||||
}
|
||||
|
||||
override fun artistInfo(lastFmArtist: LastFmArtist?) {
|
||||
if (lastFmArtist != null && lastFmArtist.artist != null) {
|
||||
val bioContent = lastFmArtist.artist.bio.content
|
||||
if (bioContent != null && bioContent.trim { it <= ' ' }.isNotEmpty()) {
|
||||
biographyText.visibility = View.VISIBLE
|
||||
biographyTitle.visibility = View.VISIBLE
|
||||
biography = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
Html.fromHtml(bioContent, Html.FROM_HTML_MODE_LEGACY)
|
||||
} else {
|
||||
Html.fromHtml(bioContent)
|
||||
}
|
||||
biographyText.text = biography
|
||||
}
|
||||
}
|
||||
// If the "lang" parameter is set and no biography is given, retry with default language
|
||||
if (biography == null && lang != null) {
|
||||
loadBiography(artist.name, null)
|
||||
}
|
||||
}
|
||||
|
||||
// If the "lang" parameter is set and no biography is given, retry with default language
|
||||
if (biography == null && lang != null) {
|
||||
loadBiography(artist.name, null)
|
||||
}
|
||||
}
|
||||
private var lang: String? = null
|
||||
|
||||
private var lang: String? = null
|
||||
private fun loadArtistImage() {
|
||||
ArtistGlideRequest.Builder.from(Glide.with(this), artist).generatePalette(this).build()
|
||||
.dontAnimate().into(object : RetroMusicColoredTarget(artistImage) {
|
||||
override fun onColorReady(color: Int) {
|
||||
setColors(color)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun loadArtistImage() {
|
||||
ArtistGlideRequest.Builder.from(Glide.with(this), artist).generatePalette(this).build()
|
||||
.dontAnimate().into(object : RetroMusicColoredTarget(artistImage) {
|
||||
override fun onColorReady(color: Int) {
|
||||
setColors(color)
|
||||
}
|
||||
})
|
||||
}
|
||||
private fun setColors(color: Int) {
|
||||
|
||||
private fun setColors(color: Int) {
|
||||
val textColor = if (PreferenceUtil.getInstance(this).adaptiveColor) color
|
||||
else ThemeStore.accentColor(this)
|
||||
|
||||
val textColor = if (PreferenceUtil.getInstance(this).adaptiveColor) color
|
||||
else ThemeStore.accentColor(this)
|
||||
albumTitle.setTextColor(textColor)
|
||||
songTitle.setTextColor(textColor)
|
||||
biographyTitle.setTextColor(textColor)
|
||||
|
||||
albumTitle.setTextColor(textColor)
|
||||
songTitle.setTextColor(textColor)
|
||||
biographyTitle.setTextColor(textColor)
|
||||
val buttonColor = if (PreferenceUtil.getInstance(this).adaptiveColor) color
|
||||
else ATHUtil.resolveColor(this, R.attr.cardBackgroundColor)
|
||||
|
||||
val buttonColor = if (PreferenceUtil.getInstance(this).adaptiveColor) color
|
||||
else ATHUtil.resolveColor(this, R.attr.cardBackgroundColor)
|
||||
MaterialUtil.setTint(button = shuffleAction, color = buttonColor)
|
||||
MaterialUtil.setTint(button = playAction, color = buttonColor)
|
||||
|
||||
MaterialUtil.setTint(button = shuffleAction, color = buttonColor)
|
||||
MaterialUtil.setTint(button = playAction, color = buttonColor)
|
||||
toolbar.setBackgroundColor(ATHUtil.resolveColor(this, R.attr.colorPrimary))
|
||||
setSupportActionBar(toolbar)
|
||||
supportActionBar?.title = null
|
||||
}
|
||||
|
||||
toolbar.setBackgroundColor(ATHUtil.resolveColor(this, R.attr.colorPrimary))
|
||||
setSupportActionBar(toolbar)
|
||||
supportActionBar?.title = null
|
||||
}
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return handleSortOrderMenuItem(item)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return handleSortOrderMenuItem(item)
|
||||
}
|
||||
private fun handleSortOrderMenuItem(item: MenuItem): Boolean {
|
||||
val songs = artist.songs
|
||||
when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
super.onBackPressed()
|
||||
return true
|
||||
}
|
||||
R.id.action_play_next -> {
|
||||
MusicPlayerRemote.playNext(songs)
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_current_playing -> {
|
||||
MusicPlayerRemote.enqueue(songs)
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_playlist -> {
|
||||
AddToPlaylistDialog.create(songs).show(supportFragmentManager, "ADD_PLAYLIST")
|
||||
return true
|
||||
}
|
||||
R.id.action_set_artist_image -> {
|
||||
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
||||
intent.type = "image/*"
|
||||
startActivityForResult(
|
||||
Intent.createChooser(
|
||||
intent, getString(R.string.pick_from_local_storage)
|
||||
), REQUEST_CODE_SELECT_IMAGE
|
||||
)
|
||||
return true
|
||||
}
|
||||
R.id.action_reset_artist_image -> {
|
||||
Toast.makeText(
|
||||
this@ArtistDetailActivity,
|
||||
resources.getString(R.string.updating),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
CustomArtistImageUtil.getInstance(this@ArtistDetailActivity)
|
||||
.resetCustomArtistImage(artist)
|
||||
forceDownload = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun handleSortOrderMenuItem(item: MenuItem): Boolean {
|
||||
val songs = artist.songs
|
||||
when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
super.onBackPressed()
|
||||
return true
|
||||
}
|
||||
R.id.action_play_next -> {
|
||||
MusicPlayerRemote.playNext(songs)
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_current_playing -> {
|
||||
MusicPlayerRemote.enqueue(songs)
|
||||
return true
|
||||
}
|
||||
R.id.action_add_to_playlist -> {
|
||||
AddToPlaylistDialog.create(songs).show(supportFragmentManager, "ADD_PLAYLIST")
|
||||
return true
|
||||
}
|
||||
R.id.action_set_artist_image -> {
|
||||
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
||||
intent.type = "image/*"
|
||||
startActivityForResult(
|
||||
Intent.createChooser(
|
||||
intent,
|
||||
getString(R.string.pick_from_local_storage)
|
||||
), REQUEST_CODE_SELECT_IMAGE
|
||||
)
|
||||
return true
|
||||
}
|
||||
R.id.action_reset_artist_image -> {
|
||||
Toast.makeText(
|
||||
this@ArtistDetailActivity,
|
||||
resources.getString(R.string.updating),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
CustomArtistImageUtil.getInstance(this@ArtistDetailActivity)
|
||||
.resetCustomArtistImage(artist)
|
||||
forceDownload = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_artist_detail, menu)
|
||||
return super.onCreateOptionsMenu(menu)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_artist_detail, menu)
|
||||
return super.onCreateOptionsMenu(menu)
|
||||
}
|
||||
override fun onMediaStoreChanged() {
|
||||
super.onMediaStoreChanged()
|
||||
reload()
|
||||
}
|
||||
|
||||
override fun onMediaStoreChanged() {
|
||||
super.onMediaStoreChanged()
|
||||
reload()
|
||||
}
|
||||
private fun reload() {
|
||||
if (intent.extras!!.containsKey(EXTRA_ARTIST_ID)) {
|
||||
intent.extras?.getInt(EXTRA_ARTIST_ID)?.let { artistDetailsPresenter.loadArtist(it) }
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
private fun reload() {
|
||||
if (intent.extras!!.containsKey(EXTRA_ARTIST_ID)) {
|
||||
intent.extras?.getInt(EXTRA_ARTIST_ID)?.let { artistDetailsPresenter.loadArtist(it) }
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
companion object {
|
||||
|
||||
companion object {
|
||||
|
||||
const val EXTRA_ARTIST_ID = "extra_artist_id"
|
||||
const val REQUEST_CODE_SELECT_IMAGE = 9003
|
||||
}
|
||||
const val EXTRA_ARTIST_ID = "extra_artist_id"
|
||||
const val REQUEST_CODE_SELECT_IMAGE = 9003
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,39 @@
|
|||
package code.name.monkey.retromusic.adapter.song
|
||||
|
||||
import android.view.*
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import code.name.monkey.retromusic.interfaces.CabHolder
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import java.util.*
|
||||
|
||||
class SimpleSongAdapter(
|
||||
context: AppCompatActivity, songs: ArrayList<Song>, i: Int
|
||||
) : SongAdapter(context, songs, i, false, null) {
|
||||
context: AppCompatActivity,
|
||||
songs: ArrayList<Song>,
|
||||
i: Int,
|
||||
cabHolder: CabHolder?
|
||||
) : SongAdapter(context, songs, i, false, cabHolder) {
|
||||
|
||||
override fun swapDataSet(dataSet: ArrayList<Song>) {
|
||||
this.dataSet.clear()
|
||||
this.dataSet = dataSet
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
override fun swapDataSet(dataSet: ArrayList<Song>) {
|
||||
this.dataSet.clear()
|
||||
this.dataSet = dataSet
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return ViewHolder(LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false))
|
||||
}
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return ViewHolder(LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false))
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
super.onBindViewHolder(holder, position)
|
||||
val fixedTrackNumber = MusicUtil.getFixedTrackNumber(dataSet[position].trackNumber)
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
super.onBindViewHolder(holder, position)
|
||||
val fixedTrackNumber = MusicUtil.getFixedTrackNumber(dataSet[position].trackNumber)
|
||||
|
||||
holder.imageText?.text = if (fixedTrackNumber > 0) fixedTrackNumber.toString() else "-"
|
||||
holder.time?.text = MusicUtil.getReadableDurationString(dataSet[position].duration)
|
||||
}
|
||||
holder.imageText?.text = if (fixedTrackNumber > 0) fixedTrackNumber.toString() else "-"
|
||||
holder.time?.text = MusicUtil.getReadableDurationString(dataSet[position].duration)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return dataSet.size
|
||||
}
|
||||
override fun getItemCount(): Int {
|
||||
return dataSet.size
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde
|
|||
});
|
||||
getMainActivity().setSupportActionBar(toolbar);
|
||||
toolbar.setNavigationOnClickListener(v -> showMainMenu(OptionsSheetDialogFragment.LIBRARY));
|
||||
ToolbarContentTintHelper.colorBackButton(toolbar );
|
||||
ToolbarContentTintHelper.colorBackButton(toolbar);
|
||||
toolbar.setTitleTextColor(ATHUtil.INSTANCE.resolveColor(requireContext(), R.attr.colorOnSecondary));
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,9 @@ interface AlbumDetailsPresenter : Presenter<AlbumDetailsView> {
|
|||
) : PresenterImpl<AlbumDetailsView>(), AlbumDetailsPresenter {
|
||||
|
||||
private lateinit var album: Album
|
||||
|
||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||
|
||||
override fun loadMore(artistId: Int) {
|
||||
disposable += repository.getArtistByIdFlowable(artistId)
|
||||
.map {
|
||||
|
|
|
@ -14,16 +14,17 @@
|
|||
|
||||
package code.name.monkey.retromusic.mvp.presenter
|
||||
|
||||
import code.name.monkey.retromusic.Result
|
||||
import code.name.monkey.retromusic.model.Artist
|
||||
import code.name.monkey.retromusic.mvp.BaseView
|
||||
import code.name.monkey.retromusic.mvp.Presenter
|
||||
import code.name.monkey.retromusic.mvp.PresenterImpl
|
||||
import code.name.monkey.retromusic.providers.interfaces.Repository
|
||||
import code.name.monkey.retromusic.rest.model.LastFmArtist
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.coroutines.*
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
/**
|
||||
* Created by hemanths on 20/08/17.
|
||||
|
@ -38,38 +39,48 @@ interface ArtistDetailsPresenter : Presenter<ArtistDetailsView> {
|
|||
|
||||
fun loadArtist(artistId: Int)
|
||||
|
||||
fun loadBiography(name: String,
|
||||
lang: String? = Locale.getDefault().language,
|
||||
cache: String?)
|
||||
fun loadBiography(
|
||||
name: String, lang: String? = Locale.getDefault().language, cache: String?
|
||||
)
|
||||
|
||||
class ArtistDetailsPresenterImpl @Inject constructor(
|
||||
private val repository: Repository
|
||||
) : PresenterImpl<ArtistDetailsView>(), ArtistDetailsPresenter {
|
||||
) : PresenterImpl<ArtistDetailsView>(), ArtistDetailsPresenter, CoroutineScope {
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = Dispatchers.IO + job
|
||||
|
||||
override fun loadBiography(name: String,
|
||||
lang: String?,
|
||||
cache: String?) {
|
||||
disposable += repository.artistInfoFloable(name, lang, cache)
|
||||
.subscribe {
|
||||
view?.artistInfo(it)
|
||||
private val job = Job()
|
||||
|
||||
override fun loadBiography(name: String, lang: String?, cache: String?) {
|
||||
launch {
|
||||
when (val result = repository.artistInfo(name, lang, cache)) {
|
||||
is Result.Success -> withContext(Dispatchers.Main) {
|
||||
view?.artistInfo(result.data)
|
||||
}
|
||||
is Result.Error -> withContext(Dispatchers.Main) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var disposable = CompositeDisposable()
|
||||
|
||||
override fun loadArtist(artistId: Int) {
|
||||
disposable += repository.getArtistByIdFlowable(artistId)
|
||||
.doOnComplete {
|
||||
launch {
|
||||
when (val result = repository.artistById(artistId)) {
|
||||
is Result.Success -> withContext(Dispatchers.Main) {
|
||||
view?.artist(result.data)
|
||||
view?.complete()
|
||||
}
|
||||
.subscribe({
|
||||
view?.artist(it)
|
||||
}, { t -> println(t) })
|
||||
is Result.Error -> withContext(Dispatchers.Main) {
|
||||
view?.showEmptyView()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun detachView() {
|
||||
super.detachView()
|
||||
disposable.dispose()
|
||||
job.cancel()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ import code.name.monkey.retromusic.rest.model.LastFmArtist
|
|||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import java.io.IOException
|
||||
|
||||
class RepositoryImpl(private val context: Context) : Repository {
|
||||
|
||||
|
@ -98,14 +99,14 @@ class RepositoryImpl(private val context: Context) : Repository {
|
|||
|
||||
override suspend fun allSongs(): Result<ArrayList<Song>> {
|
||||
return try {
|
||||
val songs = SongLoader.getAllSongs(context);
|
||||
val songs = SongLoader.getAllSongs(context)
|
||||
if (songs.isEmpty()) {
|
||||
Error(Throwable("No items found"))
|
||||
} else {
|
||||
Success(songs);
|
||||
Success(songs)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Error(e);
|
||||
Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,7 +117,7 @@ class RepositoryImpl(private val context: Context) : Repository {
|
|||
} else {
|
||||
PlaylistSongsLoader.getPlaylistSongList(context, playlist.id)
|
||||
}
|
||||
Success(songs);
|
||||
Success(songs)
|
||||
} catch (e: Exception) {
|
||||
Error(e)
|
||||
}
|
||||
|
@ -128,7 +129,7 @@ class RepositoryImpl(private val context: Context) : Repository {
|
|||
if (songs.isEmpty()) {
|
||||
Error(Throwable("No items found"))
|
||||
} else {
|
||||
Success(songs);
|
||||
Success(songs)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Error(e)
|
||||
|
@ -165,7 +166,7 @@ class RepositoryImpl(private val context: Context) : Repository {
|
|||
albums,
|
||||
HomeAdapter.RECENT_ALBUMS,
|
||||
R.drawable.ic_album_white_24dp
|
||||
));
|
||||
))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Error(e)
|
||||
|
@ -184,7 +185,7 @@ class RepositoryImpl(private val context: Context) : Repository {
|
|||
albums,
|
||||
HomeAdapter.TOP_ALBUMS,
|
||||
R.drawable.ic_album_white_24dp
|
||||
));
|
||||
))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Error(e)
|
||||
|
@ -204,7 +205,7 @@ class RepositoryImpl(private val context: Context) : Repository {
|
|||
artists,
|
||||
HomeAdapter.TOP_ARTISTS,
|
||||
R.drawable.ic_artist_white_24dp
|
||||
));
|
||||
))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Error(e)
|
||||
|
@ -223,23 +224,33 @@ class RepositoryImpl(private val context: Context) : Repository {
|
|||
playlists,
|
||||
HomeAdapter.PLAYLISTS,
|
||||
R.drawable.ic_favorite_white_24dp
|
||||
));
|
||||
))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun artistInfoFloable(
|
||||
override suspend fun artistInfo(
|
||||
name: String,
|
||||
lang: String?,
|
||||
cache: String?
|
||||
): Observable<LastFmArtist> {
|
||||
return LastFMRestClient(context).apiService.getArtistInfoFloable(name, lang, cache)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
}
|
||||
): Result<LastFmArtist> = safeApiCall(
|
||||
call = {
|
||||
Success(LastFMRestClient(context).apiService.artistInfo(name, lang, cache))
|
||||
},
|
||||
errorMessage = "Error"
|
||||
|
||||
)
|
||||
|
||||
override suspend fun artistById(artistId: Int): Result<Artist> {
|
||||
return try {
|
||||
val artist = ArtistLoader.getArtist(context, artistId)
|
||||
return Success(artist)
|
||||
} catch (e: Exception) {
|
||||
Error(Throwable("Error loading artist"))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSongFlowable(id: Int): Observable<Song> {
|
||||
return SongLoader.getSongFlowable(context, id)
|
||||
|
@ -343,3 +354,9 @@ class RepositoryImpl(private val context: Context) : Repository {
|
|||
|
||||
|
||||
}
|
||||
|
||||
suspend fun <T : Any> safeApiCall(call: suspend () -> Result<T>, errorMessage: String): Result<T> = try {
|
||||
call.invoke()
|
||||
} catch (e: Exception) {
|
||||
Result.Error(IOException(errorMessage, e))
|
||||
}
|
||||
|
|
|
@ -51,6 +51,10 @@ interface Repository {
|
|||
|
||||
suspend fun favoritePlaylist(): Result<Home>
|
||||
|
||||
suspend fun artistInfo(name: String, lang: String?, cache: String?): Result<LastFmArtist>
|
||||
|
||||
suspend fun artistById(artistId: Int): Result<Artist>
|
||||
|
||||
val allSongsFlowable: Observable<ArrayList<Song>>
|
||||
|
||||
val suggestionSongsFlowable: Observable<ArrayList<Song>>
|
||||
|
@ -91,7 +95,4 @@ interface Repository {
|
|||
val favoritePlaylistFlowable: Observable<ArrayList<Playlist>>
|
||||
|
||||
|
||||
fun artistInfoFloable(name: String,
|
||||
lang: String?,
|
||||
cache: String?): Observable<LastFmArtist>
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Hemanth Savarala.
|
||||
*
|
||||
* Licensed under the GNU General Public License v3
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
package code.name.monkey.retromusic.rest.service;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import code.name.monkey.retromusic.rest.model.LastFmAlbum;
|
||||
import code.name.monkey.retromusic.rest.model.LastFmArtist;
|
||||
import io.reactivex.Observable;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Header;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
|
||||
public interface LastFMService {
|
||||
String API_KEY_BAK = "bd9c6ea4d55ec9ed3af7d276e5ece304";
|
||||
String API_KEY = "c679c8d3efa84613dc7dcb2e8d42da4c";
|
||||
String BASE_QUERY_PARAMETERS = "?format=json&autocorrect=1&api_key=" + API_KEY;
|
||||
String METHOD_TRACK = "track.getInfo";
|
||||
|
||||
@NonNull
|
||||
@GET(BASE_QUERY_PARAMETERS + "&method=album.getinfo")
|
||||
Observable<LastFmAlbum> getAlbumInfo(@Query("album") @NonNull String albumName, @Query("artist") @NonNull String artistName, @Nullable @Query("lang") String language);
|
||||
|
||||
@NonNull
|
||||
@GET(BASE_QUERY_PARAMETERS + "&method=artist.getinfo")
|
||||
Call<LastFmArtist> getArtistInfo(@Query("artist") @NonNull String artistName, @Nullable @Query("lang") String language, @Nullable @Header("Cache-Control") String cacheControl);
|
||||
|
||||
@NonNull
|
||||
@GET(BASE_QUERY_PARAMETERS + "&method=artist.getinfo")
|
||||
Observable<LastFmArtist> getArtistInfoFloable(@Query("artist") @NonNull String artistName, @Nullable @Query("lang") String language, @Nullable @Header("Cache-Control") String cacheControl);
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Hemanth Savarala.
|
||||
*
|
||||
* Licensed under the GNU General Public License v3
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
package code.name.monkey.retromusic.rest.service
|
||||
|
||||
import code.name.monkey.retromusic.rest.model.LastFmArtist
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
import retrofit2.http.Query
|
||||
|
||||
/**
|
||||
* Created by hemanths on 2019-11-26.
|
||||
*/
|
||||
|
||||
interface LastFMService {
|
||||
companion object {
|
||||
const val API_KEY = "c679c8d3efa84613dc7dcb2e8d42da4c"
|
||||
const val BASE_QUERY_PARAMETERS = "?format=json&autocorrect=1&api_key=$API_KEY"
|
||||
}
|
||||
|
||||
@GET("$BASE_QUERY_PARAMETERS&method=artist.getinfo")
|
||||
suspend fun artistInfo(@Query("artist") artistName: String,
|
||||
@Query("lang") language: String?,
|
||||
@Header("Cache-Control") cacheControl: String?
|
||||
): LastFmArtist
|
||||
}
|
|
@ -25,10 +25,21 @@
|
|||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
app:navigationIcon="@drawable/ic_keyboard_backspace_black_24dp" />
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
app:navigationIcon="@drawable/ic_keyboard_backspace_black_24dp" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/cab_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp" />
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -25,11 +25,20 @@
|
|||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
app:navigationIcon="@drawable/ic_keyboard_backspace_black_24dp" />
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
app:navigationIcon="@drawable/ic_keyboard_backspace_black_24dp" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/cab_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp" />
|
||||
</FrameLayout>
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
|
|
@ -36,9 +36,21 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal" />
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar" />
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
app:navigationIcon="@drawable/ic_keyboard_backspace_black_24dp" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/cab_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp" />
|
||||
</FrameLayout>
|
||||
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
|
|
|
@ -34,10 +34,21 @@
|
|||
android:layout_height="wrap_content"
|
||||
app:layout_collapseMode="parallax" />
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
app:layout_collapseMode="pin" />
|
||||
<FrameLayout
|
||||
app:layout_collapseMode="pin"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
app:navigationIcon="@drawable/ic_keyboard_backspace_black_24dp" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/cab_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp" />
|
||||
</FrameLayout>
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
|
@ -55,8 +66,8 @@
|
|||
android:id="@+id/contentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardElevation="8dp"
|
||||
android:layout_marginTop="6dp"
|
||||
app:cardElevation="8dp"
|
||||
app:shapeAppearanceOverlay="@style/TopCornerCardView">
|
||||
|
||||
<LinearLayout
|
||||
|
|
|
@ -36,11 +36,21 @@
|
|||
android:layout_width="320dp"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
app:layout_collapseMode="pin"
|
||||
app:title="" />
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
app:navigationIcon="@drawable/ic_keyboard_backspace_black_24dp" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/cab_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp" />
|
||||
</FrameLayout>
|
||||
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
|
|
|
@ -35,10 +35,21 @@
|
|||
android:layout_height="wrap_content"
|
||||
app:layout_collapseMode="parallax" />
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
app:layout_collapseMode="pin" />
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_collapseMode="pin">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
app:navigationIcon="@drawable/ic_keyboard_backspace_black_24dp" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/cab_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp" />
|
||||
</FrameLayout>
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
|
@ -56,8 +67,8 @@
|
|||
android:id="@+id/contentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardElevation="8dp"
|
||||
android:layout_marginTop="6dp"
|
||||
app:cardElevation="8dp"
|
||||
app:shapeAppearanceOverlay="@style/TopCornerCardView">
|
||||
|
||||
<LinearLayout
|
||||
|
@ -86,8 +97,8 @@
|
|||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:paddingTop="4dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="4dp"
|
||||
android:textAppearance="@style/TextViewHeadline6"
|
||||
tools:ignore="MissingPrefix"
|
||||
tools:text="Title" />
|
||||
|
|
|
@ -24,10 +24,20 @@
|
|||
android:layout_height="wrap_content"
|
||||
app:liftOnScroll="true">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
app:navigationIcon="@drawable/ic_keyboard_backspace_black_24dp" />
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
app:navigationIcon="@drawable/ic_keyboard_backspace_black_24dp" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/cab_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp" />
|
||||
</FrameLayout>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
|
|
|
@ -24,11 +24,20 @@
|
|||
android:layout_height="wrap_content"
|
||||
app:liftOnScroll="true">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
app:navigationIcon="@drawable/ic_keyboard_backspace_black_24dp" />
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
app:navigationIcon="@drawable/ic_keyboard_backspace_black_24dp" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/cab_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp" />
|
||||
</FrameLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
|
|
|
@ -22,11 +22,13 @@
|
|||
<item name="android:breakStrategy">simple</item>
|
||||
<item name="android:hyphenationFrequency">none</item>
|
||||
<item name="android:fontFamily">@font/circular</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
</style>
|
||||
|
||||
<style name="BottomSheetItemTextAppearanceActive" parent="Widget.MaterialComponents.BottomNavigationView.Colored">
|
||||
<item name="android:breakStrategy">simple</item>
|
||||
<item name="android:hyphenationFrequency">none</item>
|
||||
<item name="android:fontFamily">@font/circular</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
</style>
|
||||
</resources>
|
|
@ -169,7 +169,7 @@
|
|||
</style>
|
||||
|
||||
<style name="MaterialButtonTheme" parent="Widget.MaterialComponents.Button">
|
||||
<item name="cornerRadius">24dp</item>
|
||||
<item name="cornerRadius">8dp</item>
|
||||
<item name="android:textAppearance">@style/TextViewNormal</item>
|
||||
<item name="android:textAllCaps">false</item>
|
||||
<item name="android:paddingTop">@dimen/button_padding_vertical</item>
|
||||
|
|
Loading…
Reference in a new issue