Added Material Cab for Album and Artist details

This commit is contained in:
h4h13 2019-11-26 20:57:28 +05:30
parent 72964be920
commit 0c5edf8ef6
21 changed files with 750 additions and 610 deletions

View file

@ -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'

View file

@ -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,11 +49,24 @@ import java.util.*
import javax.inject.Inject
import android.util.Pair as UtilPair
class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView {
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
}
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
@ -63,13 +95,7 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView {
setupRecyclerView()
artistImage.setOnClickListener {
val artistPairs = ActivityOptions.makeSceneTransitionAnimation(
this,
UtilPair.create(
artistImage,
getString(R.string.transition_artist_image)
)
)
val artistPairs = ActivityOptions.makeSceneTransitionAnimation(this, UtilPair.create(artistImage, getString(R.string.transition_artist_image)))
NavigationUtil.goToArtistOptions(this, album.artistId, artistPairs)
}
playAction.apply {
@ -90,7 +116,7 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView {
}
private fun setupRecyclerView() {
simpleSongAdapter = SimpleSongAdapter(this, ArrayList(), R.layout.item_song)
simpleSongAdapter = SimpleSongAdapter(this, ArrayList(), R.layout.item_song, this)
recyclerView.apply {
layoutManager = LinearLayoutManager(this@AlbumDetailsActivity)
itemAnimator = DefaultItemAnimator()
@ -118,28 +144,9 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView {
albumTitle.text = album.title
if (MusicUtil.getYearString(album.year) == "-") {
albumText.text = String.format(
"%s • %s",
album.artistName,
MusicUtil.getReadableDurationString(
MusicUtil.getTotalDuration(
this,
album.songs
)
)
)
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
)
)
)
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)

View file

@ -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,11 +43,22 @@ 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 cab: MaterialCab? = null
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
@ -58,8 +82,6 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView {
ActivityCompat.postponeEnterTransition(this)
lastFMRestClient = LastFMRestClient(this)
setUpViews()
playAction.apply {
@ -112,7 +134,7 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView {
layoutManager = GridLayoutManager(this.context, 1, GridLayoutManager.HORIZONTAL, false)
adapter = albumAdapter
}
songAdapter = SimpleSongAdapter(this, ArrayList(), R.layout.item_song)
songAdapter = SimpleSongAdapter(this, ArrayList(), R.layout.item_song, this)
recyclerView.apply {
itemAnimator = DefaultItemAnimator()
layoutManager = LinearLayoutManager(this.context)
@ -251,8 +273,7 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView {
intent.type = "image/*"
startActivityForResult(
Intent.createChooser(
intent,
getString(R.string.pick_from_local_storage)
intent, getString(R.string.pick_from_local_storage)
), REQUEST_CODE_SELECT_IMAGE
)
return true

View file

@ -1,14 +1,19 @@
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()

View file

@ -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 {

View file

@ -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
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) {
override fun loadBiography(name: String,
lang: String?,
cache: String?) {
disposable += repository.artistInfoFloable(name, lang, cache)
.subscribe {
view?.artistInfo(it)
}
}
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()
}
}
}

View file

@ -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))
}

View file

@ -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>
}

View file

@ -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);
}

View file

@ -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
}

View file

@ -25,11 +25,22 @@
android:layout_weight="1"
android:orientation="vertical">
<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"

View file

@ -25,11 +25,20 @@
android:layout_weight="1"
android:orientation="vertical">
<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"

View file

@ -36,9 +36,21 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
style="@style/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>

View file

@ -34,10 +34,21 @@
android:layout_height="wrap_content"
app:layout_collapseMode="parallax" />
<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:layout_collapseMode="pin" />
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

View file

@ -36,11 +36,21 @@
android:layout_width="320dp"
android:layout_height="wrap_content" />
<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:layout_collapseMode="pin"
app:title="" />
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>

View file

@ -35,10 +35,21 @@
android:layout_height="wrap_content"
app:layout_collapseMode="parallax" />
<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:layout_collapseMode="pin" />
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" />

View file

@ -24,11 +24,21 @@
android:layout_height="wrap_content"
app:liftOnScroll="true">
<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

View file

@ -24,11 +24,20 @@
android:layout_height="wrap_content"
app:liftOnScroll="true">
<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

View file

@ -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>

View file

@ -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>