home: make toolbar collapse

Make the home toolbar collapse on scroll.

I was planning to implement this back in 2.0.0, but visual bugs stopped
me. Now, knowing how much space the the Toolbar + Tab combination takes
up on smaller devices, I think it would be better to have this in
general.
This commit is contained in:
OxygenCobalt 2022-06-08 09:31:57 -06:00
parent cc2561f20f
commit a6c321cfa5
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
25 changed files with 82 additions and 51 deletions

View file

@ -67,6 +67,10 @@
</intent-filter> </intent-filter>
</activity> </activity>
<!--
IndexerService handles querying the media database,
extracting metadata, and constructing the music library.
-->
<service <service
android:name=".music.IndexerService" android:name=".music.IndexerService"
android:foregroundServiceType="dataSync" android:foregroundServiceType="dataSync"
@ -74,6 +78,9 @@
android:exported="false" android:exported="false"
android:roundIcon="@mipmap/ic_launcher" /> android:roundIcon="@mipmap/ic_launcher" />
<!--
PlaybackService handles music playback, system components, and state saving.
-->
<service <service
android:name=".playback.system.PlaybackService" android:name=".playback.system.PlaybackService"
android:foregroundServiceType="mediaPlayback" android:foregroundServiceType="mediaPlayback"
@ -81,7 +88,6 @@
android:exported="false" android:exported="false"
android:roundIcon="@mipmap/ic_launcher" /> android:roundIcon="@mipmap/ic_launcher" />
<!-- <!--
Work around apps that blindly query for ACTION_MEDIA_BUTTON working. Work around apps that blindly query for ACTION_MEDIA_BUTTON working.
See the class for more info. See the class for more info.
@ -94,7 +100,7 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
<!-- Auxio's one and only AppWidget --> <!-- Auxio's one and only AppWidget. -->
<receiver <receiver
android:name=".widgets.WidgetProvider" android:name=".widgets.WidgetProvider"
android:exported="false" android:exported="false"

View file

@ -34,7 +34,9 @@ import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2 import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator
import kotlin.math.abs
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.FragmentHomeBinding import org.oxycblt.auxio.databinding.FragmentHomeBinding
import org.oxycblt.auxio.home.list.AlbumListFragment import org.oxycblt.auxio.home.list.AlbumListFragment
@ -86,6 +88,18 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
indexerModel.reindex() indexerModel.reindex()
} }
binding.homeAppbar.apply {
addOnOffsetChangedListener(
AppBarLayout.OnOffsetChangedListener { _, offset ->
val range = binding.homeAppbar.totalScrollRange
binding.homeToolbar.alpha = 1f - (abs(offset.toFloat()) / (range.toFloat() / 2))
binding.homePager.updatePadding(
bottom = binding.homeAppbar.totalScrollRange + offset)
})
}
binding.homeToolbar.apply { binding.homeToolbar.apply {
sortItem = menu.findItem(R.id.submenu_sorting) sortItem = menu.findItem(R.id.submenu_sorting)
setOnMenuItemClickListener(this@HomeFragment) setOnMenuItemClickListener(this@HomeFragment)

View file

@ -29,6 +29,7 @@ import org.oxycblt.auxio.ui.Item
import org.oxycblt.auxio.ui.MenuItemListener import org.oxycblt.auxio.ui.MenuItemListener
import org.oxycblt.auxio.ui.NavigationViewModel import org.oxycblt.auxio.ui.NavigationViewModel
import org.oxycblt.auxio.ui.ViewBindingFragment import org.oxycblt.auxio.ui.ViewBindingFragment
import org.oxycblt.auxio.util.applySpans
/** /**
* A Base [Fragment] implementing the base features shared across all list fragments in the home UI. * A Base [Fragment] implementing the base features shared across all list fragments in the home UI.
@ -49,6 +50,7 @@ abstract class HomeListFragment<T : Item> :
override fun onBindingCreated(binding: FragmentHomeListBinding, savedInstanceState: Bundle?) { override fun onBindingCreated(binding: FragmentHomeListBinding, savedInstanceState: Bundle?) {
binding.homeRecycler.popupProvider = this binding.homeRecycler.popupProvider = this
binding.homeRecycler.listener = this binding.homeRecycler.listener = this
binding.homeRecycler.applySpans()
} }
override fun onDestroyBinding(binding: FragmentHomeListBinding) { override fun onDestroyBinding(binding: FragmentHomeListBinding) {

View file

@ -36,8 +36,11 @@ import org.oxycblt.auxio.ui.Sort
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
/** /**
* The [ViewModel] for the search functionality * The [ViewModel] for search functionality
* @author OxygenCobalt * @author OxygenCobalt
*
* TODO: Add a context to this ViewModel, not because I want to, but because it just makes the code
* easier to work with.
*/ */
class SearchViewModel : ViewModel() { class SearchViewModel : ViewModel() {
private val musicStore = MusicStore.getInstance() private val musicStore = MusicStore.getInstance()
@ -143,9 +146,9 @@ class SearchViewModel : ViewModel() {
*/ */
private fun <T : Music> List<T>.filterByOrNull(context: Context, value: String): List<T>? { private fun <T : Music> List<T>.filterByOrNull(context: Context, value: String): List<T>? {
val filtered = filter { val filtered = filter {
// First see if the normal item name will work. If that fails, try the "normalized" // Compare normalized names, which are names with unicode characters that are
// [e.g all accented/unicode chars become latin chars] instead. Hopefully this // normalized to their non-unicode forms. This is just for quality-of-life,
// shouldn't break other language's search functionality. // and I hope it doesn't bork search functionality for other languages.
it.resolveNameNormalized(context).contains(value, ignoreCase = true) || it.resolveNameNormalized(context).contains(value, ignoreCase = true) ||
it.resolveNameNormalized(context).contains(value, ignoreCase = true) it.resolveNameNormalized(context).contains(value, ignoreCase = true)
} }

View file

@ -74,23 +74,26 @@ class AboutFragment : ViewBindingFragment<FragmentAboutBinding>() {
private fun updateSongCount(songs: List<Song>) { private fun updateSongCount(songs: List<Song>) {
val binding = requireBinding() val binding = requireBinding()
binding.aboutSongCount.textSafe = getString(R.string.fmt_song_count, songs.size) binding.aboutSongCount.textSafe = getString(R.string.fmt_lib_song_count, songs.size)
binding.aboutTotalDuration.textSafe = binding.aboutTotalDuration.textSafe =
getString( getString(
R.string.fmt_total_duration, songs.sumOf { it.durationSecs }.formatDuration(false)) R.string.fmt_lib_total_duration,
songs.sumOf { it.durationSecs }.formatDuration(false))
} }
private fun updateAlbumCount(albums: List<Album>) { private fun updateAlbumCount(albums: List<Album>) {
requireBinding().aboutAlbumCount.textSafe = getString(R.string.fmt_album_count, albums.size) requireBinding().aboutAlbumCount.textSafe =
getString(R.string.fmt_lib_album_count, albums.size)
} }
private fun updateArtistCount(artists: List<Artist>) { private fun updateArtistCount(artists: List<Artist>) {
requireBinding().aboutArtistCount.textSafe = requireBinding().aboutArtistCount.textSafe =
getString(R.string.fmt_artist_count, artists.size) getString(R.string.fmt_lib_artist_count, artists.size)
} }
private fun updateGenreCount(genres: List<Genre>) { private fun updateGenreCount(genres: List<Genre>) {
requireBinding().aboutGenreCount.textSafe = getString(R.string.fmt_genre_count, genres.size) requireBinding().aboutGenreCount.textSafe =
getString(R.string.fmt_lib_genre_count, genres.size)
} }
/** Go through the process of opening a [link] in a browser. */ /** Go through the process of opening a [link] in a browser. */

View file

@ -218,8 +218,8 @@ class SyncBackingData<T>(adapter: RecyclerView.Adapter<*>, diffCallback: DiffUti
/** /**
* Like [AsyncListDiffer], but synchronous. This may seem like it would be inefficient, but in * Like [AsyncListDiffer], but synchronous. This may seem like it would be inefficient, but in
* practice Auxio's lists tend to be small enough to the point where this does not matter, * practice Auxio's lists tend to be small enough to the point where this does not matter, and
* and situations that would be inefficient are ruled out with [SyncBackingData.replaceList]. * situations that would be inefficient are ruled out with [SyncBackingData.replaceList].
*/ */
private class SyncListDiffer<T>( private class SyncListDiffer<T>(
adapter: RecyclerView.Adapter<*>, adapter: RecyclerView.Adapter<*>,
@ -301,7 +301,7 @@ private class SyncListDiffer<T>(
} }
} }
}) })
_currentList = newList _currentList = newList
result.dispatchUpdatesTo(updateCallback) result.dispatchUpdatesTo(updateCallback)
} }

View file

@ -39,6 +39,8 @@ import org.oxycblt.auxio.util.getDrawableSafe
* useful for the playback buttons, as at times highlighting them is not enough to differentiate * useful for the playback buttons, as at times highlighting them is not enough to differentiate
* them. * them.
* @author OxygenCobalt * @author OxygenCobalt
*
* TODO: Remove this for Material Buttons (I hope)
*/ */
class StyledImageButton class StyledImageButton
@JvmOverloads @JvmOverloads

View file

@ -183,7 +183,7 @@ class WidgetProvider : AppWidgetProvider() {
logW("No good widget layout found") logW("No good widget layout found")
val minimum = val minimum =
unlikelyToBeNull(views.minByOrNull { it.key.width * it.key.height }?.value) unlikelyToBeNull(views.minByOrNull { it.key.width * it.key.height }).value
updateAppWidget(id, minimum) updateAppWidget(id, minimum)
} }

View file

@ -14,6 +14,7 @@
android:id="@+id/home_toolbar" android:id="@+id/home_toolbar"
style="@style/Widget.Auxio.Toolbar" style="@style/Widget.Auxio.Toolbar"
app:menu="@menu/menu_home" app:menu="@menu/menu_home"
app:layout_scrollFlags="scroll|enterAlways"
app:title="@string/info_app_name" /> app:title="@string/info_app_name" />
<com.google.android.material.tabs.TabLayout <com.google.android.material.tabs.TabLayout

View file

@ -161,7 +161,7 @@
<string name="clr_grey">رمادي</string> <string name="clr_grey">رمادي</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_song_count">الاغنية المُحملة: %d</string> <string name="fmt_lib_song_count">الاغنية المُحملة: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="zero">%d اغاني</item> <item quantity="zero">%d اغاني</item>

View file

@ -190,11 +190,11 @@
<string name="fmt_indexing">Načítání hudební knihovny… (%1$d/%2$d)</string> <string name="fmt_indexing">Načítání hudební knihovny… (%1$d/%2$d)</string>
<string name="fmt_song_count">Načtených skladeb: %d</string> <string name="fmt_lib_song_count">Načtených skladeb: %d</string>
<string name="fmt_album_count">Načtených alb: %d</string> <string name="fmt_lib_album_count">Načtených alb: %d</string>
<string name="fmt_artist_count">Načtených umělců: %d</string> <string name="fmt_lib_artist_count">Načtených umělců: %d</string>
<string name="fmt_genre_count">Načtených žánrů: %d</string> <string name="fmt_lib_genre_count">Načtených žánrů: %d</string>
<string name="fmt_total_duration">Celková doba trvání: %s</string> <string name="fmt_lib_total_duration">Celková doba trvání: %s</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">"%d skladba"</item> <item quantity="one">"%d skladba"</item>

View file

@ -146,7 +146,7 @@
<string name="clr_grey">Grau</string> <string name="clr_grey">Grau</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_song_count">Geladene Lieder: %d</string> <string name="fmt_lib_song_count">Geladene Lieder: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Lied</item> <item quantity="one">%d Lied</item>
@ -191,8 +191,8 @@
<string name="fmt_disc_no">Schallplatte %d</string> <string name="fmt_disc_no">Schallplatte %d</string>
<string name="fmt_db_pos">+%.1f dB</string> <string name="fmt_db_pos">+%.1f dB</string>
<string name="fmt_db_neg">-%.1f dB</string> <string name="fmt_db_neg">-%.1f dB</string>
<string name="fmt_album_count">Geladene Alben: %d</string> <string name="fmt_lib_album_count">Geladene Alben: %d</string>
<string name="fmt_artist_count">Geladene Künstler: %d</string> <string name="fmt_lib_artist_count">Geladene Künstler: %d</string>
<string name="fmt_genre_count">Geladene Genres: %d</string> <string name="fmt_lib_genre_count">Geladene Genres: %d</string>
<string name="fmt_total_duration">Gesamtdauer: %s</string> <string name="fmt_lib_total_duration">Gesamtdauer: %s</string>
</resources> </resources>

View file

@ -74,7 +74,7 @@
<string name="clr_grey">Γκρί</string> <string name="clr_grey">Γκρί</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_song_count">Τραγούδια φορτώθηκε: %d</string> <string name="fmt_lib_song_count">Τραγούδια φορτώθηκε: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Τραγούδι</item> <item quantity="one">%d Τραγούδι</item>

View file

@ -165,7 +165,7 @@
<string name="clr_grey">Gris</string> <string name="clr_grey">Gris</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_song_count">Canciones cargadas: %d</string> <string name="fmt_lib_song_count">Canciones cargadas: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Canción</item> <item quantity="one">%d Canción</item>

View file

@ -80,7 +80,7 @@
<string name="clr_grey">Gris</string> <string name="clr_grey">Gris</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_song_count">Titres chargés: %d</string> <string name="fmt_lib_song_count">Titres chargés: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%s Titre</item> <item quantity="one">%s Titre</item>

View file

@ -168,11 +168,11 @@
<string name="clr_grey">Grigio</string> <string name="clr_grey">Grigio</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_song_count">Canzoni trovate: %d</string> <string name="fmt_lib_song_count">Canzoni trovate: %d</string>
<string name="fmt_album_count">Dischi trovati: %d</string> <string name="fmt_lib_album_count">Dischi trovati: %d</string>
<string name="fmt_artist_count">Artisti trovati: %d</string> <string name="fmt_lib_artist_count">Artisti trovati: %d</string>
<string name="fmt_genre_count">Generi trovati: %d</string> <string name="fmt_lib_genre_count">Generi trovati: %d</string>
<string name="fmt_total_duration">Durata totale: %s</string> <string name="fmt_lib_total_duration">Durata totale: %s</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d canzone</item> <item quantity="one">%d canzone</item>

View file

@ -186,11 +186,11 @@
<string name="fmt_db_pos">+%.1f dB</string> <string name="fmt_db_pos">+%.1f dB</string>
<string name="fmt_db_neg">-%.1f dB</string> <string name="fmt_db_neg">-%.1f dB</string>
<string name="fmt_song_count">불러온 음악: %d</string> <string name="fmt_lib_song_count">불러온 음악: %d</string>
<string name="fmt_album_count">불러온 앨범: %d</string> <string name="fmt_lib_album_count">불러온 앨범: %d</string>
<string name="fmt_artist_count">불러온 아티스트: %d</string> <string name="fmt_lib_artist_count">불러온 아티스트: %d</string>
<string name="fmt_genre_count">불러온 장르: %d</string> <string name="fmt_lib_genre_count">불러온 장르: %d</string>
<string name="fmt_total_duration">총 길이: %s</string> <string name="fmt_lib_total_duration">총 길이: %s</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="other">%d 곡</item> <item quantity="other">%d 곡</item>

View file

@ -133,7 +133,7 @@
<string name="clr_grey">Grijis</string> <string name="clr_grey">Grijis</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_song_count">Nummers geladen: %d</string> <string name="fmt_lib_song_count">Nummers geladen: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Nummer</item> <item quantity="one">%d Nummer</item>

View file

@ -78,7 +78,7 @@
<string name="clr_grey">Szary</string> <string name="clr_grey">Szary</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_song_count">Utwory uruchamia się: %d</string> <string name="fmt_lib_song_count">Utwory uruchamia się: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Utwór</item> <item quantity="one">%d Utwór</item>

View file

@ -79,7 +79,7 @@
<string name="clr_grey">Grisalho</string> <string name="clr_grey">Grisalho</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_song_count">Músicas carregado: %d</string> <string name="fmt_lib_song_count">Músicas carregado: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Música</item> <item quantity="one">%d Música</item>

View file

@ -80,7 +80,7 @@
<string name="clr_grey">Grisalho</string> <string name="clr_grey">Grisalho</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_song_count">Músicas carregado: %d</string> <string name="fmt_lib_song_count">Músicas carregado: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Música</item> <item quantity="one">%d Música</item>

View file

@ -166,7 +166,7 @@
<string name="clr_grey">Серый</string> <string name="clr_grey">Серый</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_song_count">Всего треков: %d</string> <string name="fmt_lib_song_count">Всего треков: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d трек</item> <item quantity="one">%d трек</item>

View file

@ -60,7 +60,7 @@
<string name="desc_play_pause">Відтворити/Зупинити</string> <string name="desc_play_pause">Відтворити/Зупинити</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_song_count">Пісні завантажено: %d</string> <string name="fmt_lib_song_count">Пісні завантажено: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Пісня</item> <item quantity="one">%d Пісня</item>

View file

@ -167,7 +167,7 @@
<string name="clr_grey">灰色</string> <string name="clr_grey">灰色</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_song_count">已加载 %d 首曲目</string> <string name="fmt_lib_song_count">已加载 %d 首曲目</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="other">"%d 首歌曲"</item> <item quantity="other">"%d 首歌曲"</item>

View file

@ -192,11 +192,11 @@
<string name="fmt_indexing">Loading your music library… (%1$d/%2$d)</string> <string name="fmt_indexing">Loading your music library… (%1$d/%2$d)</string>
<string name="fmt_song_count">Songs loaded: %d</string> <string name="fmt_lib_song_count">Songs loaded: %d</string>
<string name="fmt_album_count">Albums loaded: %d</string> <string name="fmt_lib_album_count">Albums loaded: %d</string>
<string name="fmt_artist_count">Artists loaded: %d</string> <string name="fmt_lib_artist_count">Artists loaded: %d</string>
<string name="fmt_genre_count">Genres loaded: %d</string> <string name="fmt_lib_genre_count">Genres loaded: %d</string>
<string name="fmt_total_duration">Total duration: %s</string> <string name="fmt_lib_total_duration">Total duration: %s</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Song</item> <item quantity="one">%d Song</item>