Add landscape support to list fragments

Add a landscape mode for LibraryFragment & SongsFragment.
This commit is contained in:
OxygenCobalt 2020-12-14 12:01:24 -07:00
parent fca42f2cb0
commit 07e7e1ae5b
9 changed files with 38 additions and 23 deletions

View file

@ -12,6 +12,7 @@ import androidx.core.view.forEach
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import androidx.transition.Fade
import androidx.transition.TransitionManager
import org.oxycblt.auxio.R
@ -23,10 +24,12 @@ import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.BaseModel
import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.Header
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.settings.SettingsManager
import org.oxycblt.auxio.utils.applyColor
import org.oxycblt.auxio.utils.isLandscape
import org.oxycblt.auxio.utils.resolveAttr
import org.oxycblt.auxio.utils.setupAlbumActions
import org.oxycblt.auxio.utils.setupArtistActions
@ -92,7 +95,6 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
searchView.maxWidth = Int.MAX_VALUE
searchView.setOnQueryTextListener(this@LibraryFragment)
searchView.setOnQueryTextFocusChangeListener { _, hasFocus ->
libraryModel.updateSearchFocusStatus(hasFocus)
item.isVisible = !hasFocus
}
@ -100,6 +102,7 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
binding.libraryRecycler.adapter = searchAdapter
setGroupVisible(R.id.group_sorting, false)
libraryModel.resetQuery()
return true
@ -108,6 +111,7 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
binding.libraryRecycler.adapter = libraryAdapter
setGroupVisible(R.id.group_sorting, true)
libraryModel.resetQuery()
return true
@ -119,6 +123,19 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
binding.libraryRecycler.apply {
adapter = libraryAdapter
setHasFixedSize(true)
if (isLandscape(resources)) {
layoutManager = GridLayoutManager(requireContext(), GridLayoutManager.VERTICAL).apply {
spanCount = 3
spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return if (binding.libraryRecycler.adapter == searchAdapter) {
if (searchAdapter.currentList[position] is Header) 3 else 1
} else 1
}
}
}
}
}
// --- VIEWMODEL SETUP ---
@ -128,7 +145,7 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
}
libraryModel.searchResults.observe(viewLifecycleOwner) {
if (libraryModel.searchHasFocus) {
if (binding.libraryRecycler.adapter == searchAdapter) {
searchAdapter.submitList(it) {
binding.libraryRecycler.scrollToPosition(0)
}

View file

@ -34,10 +34,6 @@ class LibraryViewModel : ViewModel(), SettingsManager.Callback {
private var mIsNavigating = false
val isNavigating: Boolean get() = mIsNavigating
private var mSearchHasFocus = false
val searchHasFocus: Boolean get() = mSearchHasFocus
private val settingsManager = SettingsManager.getInstance()
private val musicStore = MusicStore.getInstance()
@ -111,10 +107,6 @@ class LibraryViewModel : ViewModel(), SettingsManager.Callback {
}
}
fun updateSearchFocusStatus(value: Boolean) {
mSearchHasFocus = value
}
fun resetQuery() {
mSearchResults.value = listOf()
}

View file

@ -45,7 +45,7 @@ class MusicStore private constructor() {
*/
suspend fun load(app: Application): MusicLoaderResponse {
return withContext(Dispatchers.IO) {
logD("Starting initial music load...")
this@MusicStore.logD("Starting initial music load...")
val start = System.currentTimeMillis()
@ -83,7 +83,7 @@ class MusicStore private constructor() {
val elapsed = System.currentTimeMillis() - start
logD("Music load completed successfully in ${elapsed}ms.")
this@MusicStore.logD("Music load completed successfully in ${elapsed}ms.")
loaded = true
}

View file

@ -144,6 +144,7 @@ class MusicLoader(
}.toMutableList()
// Then try to associate any genres with their respective artists.
// TODO: This is already querying all genre songs, just move it.
for (genre in genres) {
val artistGenreCursor = resolver.query(
Genres.Members.getContentUri("external", genre.id),
@ -155,7 +156,6 @@ class MusicLoader(
artistGenreCursor?.let { cursor ->
val idIndex = cursor.getColumnIndexOrThrow(Genres.Members.ARTIST_ID)
while (cursor.moveToNext()) {
val id = cursor.getLong(idIndex)

View file

@ -8,6 +8,7 @@ import android.view.ViewGroup
import androidx.appcompat.widget.PopupMenu
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.reddit.indicatorfastscroll.FastScrollItemIndicator
import com.reddit.indicatorfastscroll.FastScrollerView
@ -17,6 +18,7 @@ import org.oxycblt.auxio.logD
import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.settings.SettingsManager
import org.oxycblt.auxio.utils.isLandscape
import org.oxycblt.auxio.utils.setupSongActions
import kotlin.math.ceil
@ -70,6 +72,12 @@ class SongsFragment : Fragment() {
adapter = songAdapter
setHasFixedSize(true)
if (isLandscape(resources)) {
layoutManager = GridLayoutManager(requireContext(), GridLayoutManager.VERTICAL).also {
it.spanCount = 3
}
}
post {
if (computeVerticalScrollRange() < height) {
binding.songFastScroll.visibility = View.GONE

View file

@ -28,7 +28,7 @@
android:layout_width="0dp"
android:layout_height="0dp"
android:background="?android:attr/windowBackground"
android:elevation="@dimen/elevation_weird"
android:elevation="@dimen/elevation_high"
android:outlineProvider="bounds"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
@ -41,7 +41,6 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/background"
app:elevation="@dimen/elevation_normal"
app:labelVisibilityMode="selected"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"

View file

@ -27,7 +27,6 @@
<androidx.appcompat.widget.Toolbar
android:id="@+id/playback_toolbar"
style="@style/Toolbar.Style.Icon"
android:elevation="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:menu="@menu/menu_playback"
@ -38,13 +37,13 @@
android:id="@+id/playback_cover"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="@dimen/margin_mid_large"
android:layout_margin="@dimen/margin_large"
android:contentDescription="@{@string/description_album_cover(song.name)}"
android:elevation="@dimen/elevation_normal"
android:outlineProvider="bounds"
app:coverArt="@{song}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintDimensionRatio="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/playback_toolbar"
tools:src="@drawable/ic_song" />

View file

@ -193,13 +193,13 @@
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="@dimen/size_play_pause_compact"
android:layout_height="@dimen/size_play_pause_compact"
android:layout_marginEnd="@dimen/margin_mid_large"
android:layout_marginStart="@dimen/margin_mid_large"
android:background="@drawable/ui_unbounded_ripple"
android:contentDescription="@{playbackModel.isShuffling() ? @string/description_shuffle_off : @string/description_shuffle_on"
android:onClick="@{() -> playbackModel.invertShuffleStatus()}"
android:src="@drawable/ic_shuffle_large"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/playback_skip_next"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
<ImageButton
@ -207,13 +207,13 @@
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="@dimen/size_play_pause_compact"
android:layout_height="@dimen/size_play_pause_compact"
android:layout_marginStart="@dimen/margin_mid_large"
android:layout_marginEnd="@dimen/margin_mid_large"
android:background="@drawable/ui_unbounded_ripple"
android:contentDescription="@string/description_change_loop"
android:onClick="@{() -> playbackModel.incrementLoopStatus()}"
android:src="@drawable/ic_loop_large"
app:layout_constraintBottom_toBottomOf="@+id/playback_play_pause"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/playback_skip_prev"
app:layout_constraintTop_toTopOf="@+id/playback_play_pause" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -10,6 +10,7 @@
<dimen name="margin_mid_small">10dp</dimen>
<dimen name="margin_medium">16dp</dimen>
<dimen name="margin_mid_large">24dp</dimen>
<dimen name="margin_large">32dp</dimen>
<!-- Height Namespace | Height for UI elements -->
<dimen name="height_compact_progress">2dp</dimen>
@ -39,7 +40,6 @@
<!-- Misc -->
<dimen name="elevation_normal">4dp</dimen>
<dimen name="elevation_weird">4.2dp</dimen>
<dimen name="elevation_high">8dp</dimen>
<dimen name="offset_thumb">4dp</dimen>
</resources>