Improve tablet layouts

Make the tablet layouts look much better
This commit is contained in:
OxygenCobalt 2021-01-18 10:27:54 -07:00
parent c4bc86cb05
commit bfa8a6d8f2
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
12 changed files with 462 additions and 19 deletions

View file

@ -13,6 +13,7 @@ import androidx.navigation.NavController
import androidx.navigation.NavOptions
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController
import com.google.android.material.bottomnavigation.LabelVisibilityMode
import org.oxycblt.auxio.databinding.FragmentMainBinding
import org.oxycblt.auxio.detail.DetailViewModel
import org.oxycblt.auxio.music.MusicStore
@ -20,6 +21,7 @@ import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.ui.Accent
import org.oxycblt.auxio.ui.isLandscape
import org.oxycblt.auxio.ui.isTablet
import org.oxycblt.auxio.ui.toColor
/**
@ -66,6 +68,15 @@ class MainFragment : Fragment() {
binding.lifecycleOwner = this
binding.navBar.apply {
itemIconTintList = navTints
itemTextColor = navTints
if (isTablet(resources)) {
labelVisibilityMode = LabelVisibilityMode.LABEL_VISIBILITY_LABELED
}
}
binding.navBar.itemIconTintList = navTints
binding.navBar.itemTextColor = navTints

View file

@ -19,8 +19,7 @@ import org.oxycblt.auxio.music.BaseModel
import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.ui.ActionMenu
import org.oxycblt.auxio.ui.getLandscapeSpans
import org.oxycblt.auxio.ui.isLandscape
import org.oxycblt.auxio.ui.getSpans
import org.oxycblt.auxio.ui.requireCompatActivity
/**
@ -64,9 +63,10 @@ class LibraryFragment : Fragment() {
binding.libraryRecycler.apply {
adapter = libraryAdapter
setHasFixedSize(true)
val spans = context.getSpans()
if (isLandscape(resources)) {
layoutManager = GridLayoutManager(requireContext(), getLandscapeSpans(resources))
if (spans != 1) {
layoutManager = GridLayoutManager(requireContext(), spans)
}
}

View file

@ -110,8 +110,8 @@ class LoadingFragment : Fragment(R.layout.fragment_loading) {
return binding.root
}
override fun onStart() {
super.onStart()
override fun onResume() {
super.onResume()
// If the music was already loaded, then don't do it again.
if (MusicStore.getInstance().loaded) {

View file

@ -25,8 +25,7 @@ import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.ui.Accent
import org.oxycblt.auxio.ui.ActionMenu
import org.oxycblt.auxio.ui.fixAnimationInfoMemoryLeak
import org.oxycblt.auxio.ui.getLandscapeSpans
import org.oxycblt.auxio.ui.isLandscape
import org.oxycblt.auxio.ui.getSpans
import org.oxycblt.auxio.ui.requireCompatActivity
import org.oxycblt.auxio.ui.toColor
@ -85,10 +84,9 @@ class SearchFragment : Fragment() {
binding.searchRecycler.apply {
adapter = searchAdapter
val spans = context.getSpans()
if (isLandscape(resources)) {
val spans = getLandscapeSpans(resources)
if (spans != -1) {
layoutManager = GridLayoutManager(requireContext(), spans).apply {
spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int =

View file

@ -19,8 +19,7 @@ import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.ui.Accent
import org.oxycblt.auxio.ui.ActionMenu
import org.oxycblt.auxio.ui.getLandscapeSpans
import org.oxycblt.auxio.ui.isLandscape
import org.oxycblt.auxio.ui.getSpans
import org.oxycblt.auxio.ui.requireCompatActivity
import kotlin.math.ceil
@ -70,8 +69,10 @@ class SongsFragment : Fragment() {
adapter = songAdapter
setHasFixedSize(true)
if (isLandscape(resources)) {
layoutManager = GridLayoutManager(requireContext(), getLandscapeSpans(resources))
val spans = context.getSpans()
if (spans != 1) {
layoutManager = GridLayoutManager(requireContext(), spans)
}
post {

View file

@ -139,11 +139,24 @@ fun isLandscape(resources: Resources): Boolean {
}
/**
* Get the span count for most RecyclerViews when in landscape mode.
* @return 3 if landscape mode is tablet, 2 if landscape mode is phone
* Determine if we are in tablet mode or not
*/
fun getLandscapeSpans(resources: Resources): Int {
return if (resources.configuration.screenLayout == Configuration.SCREENLAYOUT_SIZE_LARGE) 3 else 2
fun isTablet(resources: Resources): Boolean {
val layout = resources.configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK
return layout == Configuration.SCREENLAYOUT_SIZE_XLARGE ||
layout == Configuration.SCREENLAYOUT_SIZE_LARGE
}
/**
* Get the span count for most RecyclerViews
*/
fun Context.getSpans(): Int {
return if (isLandscape(resources)) {
if (isTablet(resources)) 3 else 2
} else {
if (isTablet(resources)) 2 else 1
}
}
/**

View file

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="album"
type="org.oxycblt.auxio.music.Album" />
<variable
name="detailModel"
type="org.oxycblt.auxio.detail.DetailViewModel" />
<variable
name="playbackModel"
type="org.oxycblt.auxio.playback.PlaybackViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">
<ImageView
android:id="@+id/album_cover"
android:layout_width="@dimen/size_cover_mid_huge"
android:layout_height="@dimen/size_cover_mid_huge"
android:layout_marginStart="@dimen/margin_medium"
android:layout_marginTop="@dimen/margin_medium"
android:outlineProvider="bounds"
android:elevation="@dimen/elevation_normal"
android:contentDescription="@{@string/description_album_cover(album.name)}"
app:coverArt="@{album}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_album" />
<TextView
android:id="@+id/album_name"
style="@style/DetailTitleText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:layout_marginEnd="@dimen/margin_medium"
android:text="@{album.name}"
app:layout_constraintBottom_toTopOf="@+id/album_artist"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/album_cover"
app:layout_constraintTop_toTopOf="@+id/album_cover"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Album Name" />
<TextView
android:id="@+id/album_artist"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:background="@drawable/ui_ripple"
android:clickable="true"
android:focusable="true"
android:onClick="@{() -> detailModel.navToItem(album.artist)}"
android:text="@{album.artist.name}"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintBottom_toTopOf="@+id/album_details"
app:layout_constraintStart_toEndOf="@+id/album_cover"
app:layout_constraintTop_toBottomOf="@+id/album_name"
tools:text="Artist Name" />
<TextView
android:id="@+id/album_details"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
app:albumDetails="@{album}"
app:layout_constraintBottom_toBottomOf="@+id/album_cover"
app:layout_constraintStart_toEndOf="@+id/album_cover"
app:layout_constraintTop_toBottomOf="@+id/album_artist"
tools:text="2020 / 10 Songs / 16:16" />
<com.google.android.material.button.MaterialButton
android:id="@+id/album_play_button"
style="@style/Widget.MaterialComponents.Button.Unimportant"
android:onClick="@{() -> playbackModel.playAlbum(album, false)}"
android:text="@string/label_play"
app:layout_constraintEnd_toStartOf="@+id/album_shuffle_button"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/album_cover"
tools:textColor="@color/blue" />
<com.google.android.material.button.MaterialButton
android:id="@+id/album_shuffle_button"
style="@style/Widget.MaterialComponents.Button.Highlighted"
android:onClick="@{() -> playbackModel.playAlbum(album, true)}"
android:text="@string/label_shuffle"
app:layout_constraintBottom_toBottomOf="@+id/album_play_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/album_play_button"
app:layout_constraintTop_toTopOf="@+id/album_play_button"
tools:backgroundTint="@color/blue" />
<TextView
android:id="@+id/album_song_header"
style="@style/HeaderText"
android:layout_marginTop="8dp"
android:text="@string/label_songs"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/album_play_button" />
<ImageButton
android:id="@+id/album_sort_button"
style="@style/HeaderAction"
android:contentDescription="@string/description_sort_button"
android:onClick="@{() -> detailModel.incrementAlbumSortMode()}"
app:layout_constraintBottom_toBottomOf="@+id/album_song_header"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/album_song_header"
app:sortIcon="@{detailModel.albumSortMode}"
tools:src="@drawable/ic_sort_numeric_down" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".detail.adapters.ArtistDetailAdapter.ArtistHeaderViewHolder">
<data>
<variable
name="artist"
type="org.oxycblt.auxio.music.Artist" />
<variable
name="detailModel"
type="org.oxycblt.auxio.detail.DetailViewModel" />
<variable
name="playbackModel"
type="org.oxycblt.auxio.playback.PlaybackViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/artist_image"
android:layout_width="@dimen/size_cover_mid_huge"
android:layout_height="@dimen/size_cover_mid_huge"
android:layout_margin="@dimen/margin_medium"
android:contentDescription="@{@string/description_artist_image(artist.name)}"
android:outlineProvider="bounds"
android:elevation="@dimen/elevation_normal"
app:artistImage="@{artist}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_artist" />
<TextView
android:id="@+id/artist_name"
style="@style/DetailTitleText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:layout_marginEnd="@dimen/margin_medium"
android:text="@{artist.name}"
app:layout_constraintBottom_toTopOf="@+id/artist_genre"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/artist_image"
app:layout_constraintTop_toTopOf="@+id/artist_image"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Artist Name" />
<TextView
android:id="@+id/artist_genre"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
app:artistGenre="@{artist}"
app:layout_constraintBottom_toTopOf="@+id/artist_counts"
app:layout_constraintStart_toEndOf="@+id/artist_image"
app:layout_constraintTop_toBottomOf="@+id/artist_name"
tools:text="Genre Name" />
<TextView
android:id="@+id/artist_counts"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
app:artistCounts="@{artist}"
app:layout_constraintBottom_toBottomOf="@+id/artist_image"
app:layout_constraintStart_toEndOf="@+id/artist_image"
app:layout_constraintTop_toBottomOf="@+id/artist_genre"
tools:text="2 Albums, 20 Songs" />
<com.google.android.material.button.MaterialButton
android:id="@+id/artist_play_button"
style="@style/Widget.MaterialComponents.Button.Unimportant"
android:onClick="@{() -> playbackModel.playArtist(artist, false)}"
android:text="@string/label_play"
app:layout_constraintEnd_toStartOf="@+id/artist_shuffle_button"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_image"
tools:textColor="@color/blue" />
<com.google.android.material.button.MaterialButton
android:id="@+id/artist_shuffle_button"
style="@style/Widget.MaterialComponents.Button.Highlighted"
android:onClick="@{() -> playbackModel.playArtist(artist, true)}"
android:text="@string/label_shuffle"
app:layout_constraintBottom_toBottomOf="@+id/artist_play_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/artist_play_button"
app:layout_constraintTop_toTopOf="@+id/artist_play_button"
tools:backgroundTint="@color/blue" />
<TextView
android:id="@+id/artist_album_header"
style="@style/HeaderText"
android:layout_marginTop="@dimen/margin_small"
android:text="@string/label_albums"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_play_button" />
<ImageButton
android:id="@+id/artist_sort_button"
style="@style/HeaderAction"
android:contentDescription="@string/description_sort_button"
android:onClick="@{() -> detailModel.incrementArtistSortMode()}"
app:layout_constraintBottom_toBottomOf="@+id/artist_album_header"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/artist_album_header"
app:sortIcon="@{detailModel.artistSortMode}"
tools:src="@drawable/ic_sort_numeric_down" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".detail.adapters.GenreDetailAdapter.GenreHeaderViewHolder">
<data>
<variable
name="genre"
type="org.oxycblt.auxio.music.Genre" />
<variable
name="detailModel"
type="org.oxycblt.auxio.detail.DetailViewModel" />
<variable
name="playbackModel"
type="org.oxycblt.auxio.playback.PlaybackViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/genre_image"
android:layout_width="@dimen/size_cover_mid_huge"
android:layout_height="@dimen/size_cover_mid_huge"
android:layout_margin="@dimen/margin_medium"
android:contentDescription="@{@string/description_genre_image(genre.name)}"
android:outlineProvider="bounds"
android:elevation="@dimen/elevation_normal"
app:genreImage="@{genre}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_genre" />
<TextView
android:id="@+id/genre_name"
style="@style/DetailTitleText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:layout_marginEnd="@dimen/margin_medium"
android:text="@{genre.displayName}"
app:layout_constraintBottom_toTopOf="@+id/genre_song_count"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/genre_image"
app:layout_constraintTop_toTopOf="@+id/genre_image"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Genre Name" />
<TextView
android:id="@+id/genre_song_count"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:text="@{@plurals/format_song_count(genre.songs.size(), genre.songs.size())}"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintBottom_toTopOf="@+id/genre_duration"
app:layout_constraintStart_toEndOf="@+id/genre_image"
app:layout_constraintTop_toBottomOf="@+id/genre_name"
tools:text="2 Artists, 4 Albums" />
<com.google.android.material.button.MaterialButton
android:id="@+id/genre_play_button"
style="@style/Widget.MaterialComponents.Button.Unimportant"
android:onClick="@{() -> playbackModel.playGenre(genre, false)}"
android:text="@string/label_play"
app:layout_constraintEnd_toStartOf="@+id/genre_shuffle_button"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/genre_image"
tools:textColor="@color/blue" />
<com.google.android.material.button.MaterialButton
android:id="@+id/genre_shuffle_button"
style="@style/Widget.MaterialComponents.Button.Highlighted"
android:onClick="@{() -> playbackModel.playGenre(genre, true)}"
android:text="@string/label_shuffle"
app:layout_constraintBottom_toBottomOf="@+id/genre_play_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/genre_play_button"
app:layout_constraintTop_toTopOf="@+id/genre_play_button"
tools:backgroundTint="@color/blue" />
<TextView
android:id="@+id/genre_duration"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:text="@{genre.totalDuration}"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintBottom_toBottomOf="@+id/genre_image"
app:layout_constraintStart_toEndOf="@+id/genre_image"
app:layout_constraintTop_toBottomOf="@+id/genre_song_count"
tools:text="16:16" />
<TextView
android:id="@+id/genre_song_header"
style="@style/HeaderText"
android:layout_marginTop="@dimen/margin_small"
android:text="@string/label_songs"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/genre_play_button" />
<ImageButton
android:id="@+id/genre_sort_button"
style="@style/HeaderAction"
android:contentDescription="@string/description_sort_button"
android:onClick="@{() -> detailModel.incrementGenreSortMode()}"
app:layout_constraintBottom_toBottomOf="@+id/genre_song_header"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/genre_song_header"
app:sortIcon="@{detailModel.genreSortMode}"
tools:src="@drawable/ic_sort_alpha_down" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="size_cover_mid_huge">200dp</dimen>
<dimen name="size_cover_huge">200dp</dimen>
</resources>

View file

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- An "Unimportant" material button, used for the "Play" button -->
<style name="Widget.MaterialComponents.Button.Unimportant" parent="@style/Widget.MaterialComponents.Button.OutlinedButton">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginTop">@dimen/margin_small</item>
<item name="android:layout_marginStart">@dimen/margin_medium</item>
<item name="android:layout_marginEnd">@dimen/margin_small</item>
<item name="android:clickable">true</item>
<item name="android:focusable">true</item>
<item name="android:padding">@dimen/padding_small</item>
<item name="android:textSize">@dimen/text_size_play_button_large</item>
<item name="android:theme">@style/Theme.MaterialComponents</item>
<item name="strokeColor">@color/divider_color</item>
<item name="strokeWidth">1dp</item>
<item name="rippleColor">@color/selection_color</item>
<item name="fontFamily">@font/inter_semibold</item>
<item name="textAllCaps">false</item>
<item name="cornerRadius">0dp</item>
</style>
<!-- An highlighted material button, used for the "Shuffle" button -->
<style name="Widget.MaterialComponents.Button.Highlighted" parent="@style/Widget.MaterialComponents.Button.TextButton">
<item name="android:layout_width">0dp</item>
<item name="android:clickable">true</item>
<item name="android:focusable">true</item>
<item name="android:padding">@dimen/padding_small</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginStart">@dimen/margin_small</item>
<item name="android:layout_marginEnd">@dimen/margin_medium</item>
<item name="android:theme">@style/Theme.MaterialComponents</item>
<item name="android:textSize">@dimen/text_size_play_button_large</item>
<item name="rippleColor">@color/selection_color</item>
<item name="fontFamily">@font/inter_semibold</item>
<item name="textAllCaps">false</item>
<item name="android:textColor">@color/background</item>
<item name="cornerRadius">0dp</item>
</style>
</resources>

View file

@ -44,6 +44,7 @@
<dimen name="text_size_detail_header_max">26sp</dimen>
<dimen name="text_size_thumb">18sp</dimen>
<dimen name="text_size_header">19sp</dimen>
<dimen name="text_size_play_button_large">16sp</dimen>
<!-- Misc -->
<dimen name="elevation_normal">4dp</dimen>