home: make tabs adaptive
Make tabs on the home page adapt to screen configuration changes, using only icons when the width is small and icons + text when the width is large.
This commit is contained in:
parent
331a06c6dc
commit
8e1da1bfc7
10 changed files with 106 additions and 36 deletions
|
@ -35,6 +35,8 @@ import org.oxycblt.auxio.playback.system.PlaybackService
|
|||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.util.isNight
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.replaceInsetsCompat
|
||||
import org.oxycblt.auxio.util.systemBarsCompat
|
||||
|
||||
/**
|
||||
* The single [AppCompatActivity] for Auxio.
|
||||
|
@ -126,16 +128,8 @@ class MainActivity : AppCompatActivity() {
|
|||
WindowInsets.Type.systemBars(),
|
||||
insets.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars())
|
||||
)
|
||||
.build().also {
|
||||
val bars = it.getInsets(WindowInsets.Type.systemBars())
|
||||
|
||||
// If left/right insets are present [implying phone landscape mode],
|
||||
// make sure that we apply them.
|
||||
binding.root.updatePadding(
|
||||
left = bars.left,
|
||||
right = bars.right
|
||||
)
|
||||
}
|
||||
.build()
|
||||
.applyLeftRightInsets(binding)
|
||||
}
|
||||
} else {
|
||||
// Do old edge-to-edge otherwise.
|
||||
|
@ -147,17 +141,23 @@ class MainActivity : AppCompatActivity() {
|
|||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
|
||||
setOnApplyWindowInsetsListener { _, insets ->
|
||||
updatePadding(
|
||||
left = insets.systemWindowInsetLeft,
|
||||
right = insets.systemWindowInsetRight
|
||||
)
|
||||
|
||||
insets
|
||||
insets.applyLeftRightInsets(binding)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun WindowInsets.applyLeftRightInsets(binding: ActivityMainBinding): WindowInsets {
|
||||
val bars = systemBarsCompat
|
||||
|
||||
binding.root.updatePadding(
|
||||
left = bars.left,
|
||||
right = bars.right
|
||||
)
|
||||
|
||||
return replaceInsetsCompat(0, bars.top, 0, bars.bottom)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_INTENT_USED = BuildConfig.APPLICATION_ID + ".key.FILE_INTENT_USED"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package org.oxycblt.auxio.home
|
||||
|
||||
import android.content.Context
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
class AdaptiveTabStrategy(
|
||||
context: Context,
|
||||
private val homeModel: HomeViewModel
|
||||
) : TabLayoutMediator.TabConfigurationStrategy {
|
||||
private val screenSize = context.resources.configuration.screenWidthDp
|
||||
|
||||
override fun onConfigureTab(tab: TabLayout.Tab, position: Int) {
|
||||
val tabMode = homeModel.tabs[position]
|
||||
|
||||
when {
|
||||
screenSize < 370 ->
|
||||
tab.setIcon(tabMode.icon)
|
||||
.setContentDescription(tabMode.string)
|
||||
|
||||
screenSize < 600 -> tab.setText(tabMode.string)
|
||||
|
||||
else ->
|
||||
tab.setIcon(tabMode.icon)
|
||||
.setText(tabMode.string)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -154,9 +154,9 @@ class HomeFragment : Fragment() {
|
|||
override fun onPageSelected(position: Int) = homeModel.updateCurrentTab(position)
|
||||
})
|
||||
|
||||
TabLayoutMediator(binding.homeTabs, this) { tab, pos ->
|
||||
tab.setText(homeModel.tabs[pos].string)
|
||||
}.attach()
|
||||
TabLayoutMediator(
|
||||
binding.homeTabs, this, AdaptiveTabStrategy(context, homeModel)
|
||||
).attach()
|
||||
}
|
||||
|
||||
binding.homeFab.setOnClickListener {
|
||||
|
|
|
@ -35,6 +35,7 @@ import android.widget.TextView
|
|||
import androidx.appcompat.widget.AppCompatTextView
|
||||
import androidx.core.math.MathUtils
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.core.widget.TextViewCompat
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
|
@ -316,7 +317,7 @@ class FastScrollRecyclerView @JvmOverloads constructor(
|
|||
override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
|
||||
val bars = insets.systemBarsCompat
|
||||
|
||||
setPadding(
|
||||
updatePadding(
|
||||
initialPadding.left, initialPadding.top, initialPadding.right,
|
||||
initialPadding.bottom + bars.bottom
|
||||
)
|
||||
|
|
|
@ -43,7 +43,7 @@ import org.oxycblt.auxio.excluded.ExcludedDatabase
|
|||
* blacklisting relies on a deprecated method, and the supposedly "modern" method is SLOWER and
|
||||
* causes even more problems since I have to manage databases across version boundaries. Sometimes
|
||||
* music will have a deformed clone that I can't filter out, sometimes Genres will just break for no
|
||||
* reason, sometimes this spaghetti parser just completely breaks down and is unable to get any
|
||||
* reason, sometimes this spaghetti parser just completely falls apart and is unable to get any
|
||||
* metadata. Everything is broken in it's own special unique way and I absolutely hate it.
|
||||
*
|
||||
* Is there anything we can do about it? No. Google has routinely shut down issues that begged google
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
package org.oxycblt.auxio.ui
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import org.oxycblt.auxio.R
|
||||
|
||||
/**
|
||||
|
@ -27,11 +26,25 @@ import org.oxycblt.auxio.R
|
|||
* changing them would also change the meaning of tab instances.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
enum class DisplayMode(@StringRes val string: Int) {
|
||||
SHOW_SONGS(R.string.lbl_songs),
|
||||
SHOW_ALBUMS(R.string.lbl_albums),
|
||||
SHOW_ARTISTS(R.string.lbl_artists),
|
||||
SHOW_GENRES(R.string.lbl_genres);
|
||||
enum class DisplayMode {
|
||||
SHOW_SONGS,
|
||||
SHOW_ALBUMS,
|
||||
SHOW_ARTISTS,
|
||||
SHOW_GENRES;
|
||||
|
||||
val string: Int get() = when (this) {
|
||||
SHOW_SONGS -> R.string.lbl_songs
|
||||
SHOW_ALBUMS -> R.string.lbl_albums
|
||||
SHOW_ARTISTS -> R.string.lbl_artists
|
||||
SHOW_GENRES -> R.string.lbl_genres
|
||||
}
|
||||
|
||||
val icon: Int get() = when (this) {
|
||||
SHOW_SONGS -> R.drawable.ic_song
|
||||
SHOW_ALBUMS -> R.drawable.ic_album
|
||||
SHOW_ARTISTS -> R.drawable.ic_artist
|
||||
SHOW_GENRES -> R.drawable.ic_genre
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val CONST_NULL = 0xA107
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.oxycblt.auxio.util
|
|||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Insets
|
||||
import android.graphics.Rect
|
||||
import android.os.Build
|
||||
import android.util.TypedValue
|
||||
|
@ -143,3 +144,24 @@ val WindowInsets.systemBarsCompat: Rect get() {
|
|||
}
|
||||
}
|
||||
|
||||
fun WindowInsets.replaceInsetsCompat(left: Int, top: Int, right: Int, bottom: Int): WindowInsets {
|
||||
return when {
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> {
|
||||
WindowInsets.Builder(this)
|
||||
.setInsets(
|
||||
WindowInsets.Type.systemBars(),
|
||||
Insets.of(left, top, right, bottom)
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 -> {
|
||||
@Suppress("DEPRECATION")
|
||||
replaceSystemWindowInsets(
|
||||
left, top, right, bottom
|
||||
)
|
||||
}
|
||||
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
|
11
app/src/main/res/drawable/ic_song.xml
Normal file
11
app/src/main/res/drawable/ic_song.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorPrimary">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,3v10.55c-0.59,-0.34 -1.27,-0.55 -2,-0.55 -2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4V7h4V3h-6z"/>
|
||||
</vector>
|
|
@ -7,17 +7,13 @@
|
|||
<org.oxycblt.auxio.ui.EdgeCoordinatorLayout
|
||||
android:id="@+id/main_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<org.oxycblt.auxio.ui.EdgeAppBarLayout
|
||||
android:id="@+id/home_appbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorSurface"
|
||||
android:clickable="true"
|
||||
android:clipChildren="true"
|
||||
android:focusable="true"
|
||||
app:liftOnScroll="true">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
|
@ -34,8 +30,7 @@
|
|||
app:tabContentStart="@dimen/spacing_medium"
|
||||
app:tabGravity="start"
|
||||
app:tabMode="scrollable"
|
||||
app:tabTextAppearance="@style/TextAppearance.Auxio.LabelLarger"
|
||||
app:tabTextColor="@color/sel_accented_primary" />
|
||||
app:tabTextAppearance="@style/TextAppearance.Auxio.LabelLarger" />
|
||||
|
||||
</org.oxycblt.auxio.ui.EdgeAppBarLayout>
|
||||
|
||||
|
@ -61,7 +56,6 @@
|
|||
android:layout_margin="@dimen/spacing_medium"
|
||||
android:contentDescription="@string/desc_shuffle_all"
|
||||
android:src="@drawable/ic_shuffle"
|
||||
app:fabSize="normal"
|
||||
app:tint="?attr/colorOnPrimaryContainer" />
|
||||
|
||||
</org.oxycblt.auxio.home.FloatingActionButtonContainer>
|
||||
|
|
|
@ -9,7 +9,7 @@ buildscript {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.0.3'
|
||||
classpath 'com.android.tools.build:gradle:7.0.4'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigation_version"
|
||||
|
||||
|
|
Loading…
Reference in a new issue