From d5e6b813a9c84138a2ee1fc9fa45f86f882b6202 Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Mon, 31 Aug 2020 18:55:25 -0600 Subject: [PATCH] Add bottom menu Add a tab menu on the bottom of the screen that can switch between all fragments on the ViewPager. --- app/build.gradle | 3 + .../java/org/oxycblt/auxio/MainActivity.kt | 3 +- .../java/org/oxycblt/auxio/MainFragment.kt | 71 +++++++++++++++++-- .../org/oxycblt/auxio/music/MusicUtils.kt | 2 +- .../auxio/music/processing/MusicSorter.kt | 2 + .../oxycblt/auxio/recycler/RecyclerUtils.kt | 21 ++---- .../org/oxycblt/auxio/theme/ThemeUtils.kt | 33 +++++++++ app/src/main/res/drawable/ic_library.xml | 11 +++ .../drawable/{music_icon.xml => ic_music.xml} | 0 app/src/main/res/drawable/indicator.xml | 14 ++++ app/src/main/res/layout/fragment_main.xml | 29 ++++++-- app/src/main/res/values/dimens.xml | 2 + 12 files changed, 161 insertions(+), 30 deletions(-) create mode 100644 app/src/main/java/org/oxycblt/auxio/theme/ThemeUtils.kt create mode 100644 app/src/main/res/drawable/ic_library.xml rename app/src/main/res/drawable/{music_icon.xml => ic_music.xml} (100%) create mode 100644 app/src/main/res/drawable/indicator.xml diff --git a/app/build.gradle b/app/build.gradle index c01c37ab5..ab0320c3a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -66,6 +66,9 @@ dependencies { // Image loading implementation 'io.coil-kt:coil:0.12.0' + // Material + implementation 'com.google.android.material:material:1.3.0-alpha02' + // Lint ktlint "com.pinterest:ktlint:0.37.2" } diff --git a/app/src/main/java/org/oxycblt/auxio/MainActivity.kt b/app/src/main/java/org/oxycblt/auxio/MainActivity.kt index 6bc1b27f7..6c3992607 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainActivity.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainActivity.kt @@ -3,7 +3,6 @@ package org.oxycblt.auxio import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.app.AppCompatDelegate class MainActivity : AppCompatActivity() { @@ -11,7 +10,7 @@ class MainActivity : AppCompatActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) + // AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) Log.d(this::class.simpleName, "Activity Created.") } diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt index 899f4b988..d9cecbd49 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt @@ -5,13 +5,19 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.content.ContextCompat import androidx.databinding.DataBindingUtil import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import androidx.viewpager2.adapter.FragmentStateAdapter +import com.google.android.material.tabs.TabLayout +import com.google.android.material.tabs.TabLayoutMediator import org.oxycblt.auxio.databinding.FragmentMainBinding import org.oxycblt.auxio.library.LibraryFragment import org.oxycblt.auxio.songs.SongsFragment +import org.oxycblt.auxio.theme.getAccentTransparency +import org.oxycblt.auxio.theme.getDeselectedTransparency +import org.oxycblt.auxio.theme.toColor class MainFragment : Fragment() { @@ -20,6 +26,21 @@ class MainFragment : Fragment() { private val libraryFragment: LibraryFragment by lazy { LibraryFragment() } private val songsFragment: SongsFragment by lazy { SongsFragment() } + private val colorSelected: Int by lazy { + R.color.blue.toColor(requireContext()) + } + + private val colorDeselected: Int by lazy { + getAccentTransparency( + requireContext(), R.color.blue, getDeselectedTransparency(R.color.blue) + ) + } + + private val tabIcons = listOf( + R.drawable.ic_library, + R.drawable.ic_music + ) + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -32,11 +53,54 @@ class MainFragment : Fragment() { val adapter = PagerAdapter(requireActivity()) binding.viewPager.adapter = adapter + // Link the ViewPager & Tab View + TabLayoutMediator(binding.tabs, binding.viewPager) { tab, position -> + tab.icon = ContextCompat.getDrawable(requireContext(), tabIcons[position]) + + // Set the icon tint to deselected if its not the default tab + if (position > 0) { + tab.icon?.setTint(colorDeselected) + } + + // Init the fragment + fragmentAt(position) + }.attach() + + // Set up the selected/deselected colors + binding.tabs.addOnTabSelectedListener( + object : TabLayout.OnTabSelectedListener { + + override fun onTabSelected(tab: TabLayout.Tab) { + tab.icon?.setTint(colorSelected) + } + + override fun onTabUnselected(tab: TabLayout.Tab) { + tab.icon?.setTint(colorDeselected) + } + + override fun onTabReselected(tab: TabLayout.Tab?) { + } + } + ) + + binding.tabs.getTabAt( + binding.viewPager.offscreenPageLimit + ) + Log.d(this::class.simpleName, "Fragment Created.") return binding.root } + private fun fragmentAt(position: Int): Fragment { + return when (position) { + 0 -> libraryFragment + 1 -> songsFragment + + else -> libraryFragment + } + } + private inner class PagerAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) { override fun getItemCount(): Int = shownFragments.size @@ -44,12 +108,7 @@ class MainFragment : Fragment() { Log.d(this::class.simpleName, "Switching to fragment $position.") if (shownFragments.contains(position)) { - return when (position) { - 0 -> libraryFragment - 1 -> songsFragment - - else -> libraryFragment - } + return fragmentAt(position) } // Not sure how this would happen but it might diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicUtils.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicUtils.kt index a59897fcc..658ccd07f 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/MusicUtils.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicUtils.kt @@ -79,7 +79,7 @@ fun ImageView.getCoverArt(any: Any) { load(uri) { crossfade(true) placeholder(android.R.color.transparent) - error(R.drawable.music_icon) + error(R.drawable.ic_music) } } diff --git a/app/src/main/java/org/oxycblt/auxio/music/processing/MusicSorter.kt b/app/src/main/java/org/oxycblt/auxio/music/processing/MusicSorter.kt index 0cb378184..1ea473b7c 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/processing/MusicSorter.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/processing/MusicSorter.kt @@ -137,6 +137,8 @@ class MusicSorter( unknownGenre.numArtists = artists.size + genres.add(unknownGenre) + Log.d( this::class.simpleName, "${unknownArtists.size} albums were placed into an unknown genre." diff --git a/app/src/main/java/org/oxycblt/auxio/recycler/RecyclerUtils.kt b/app/src/main/java/org/oxycblt/auxio/recycler/RecyclerUtils.kt index 6a9b5dd5a..afd512815 100644 --- a/app/src/main/java/org/oxycblt/auxio/recycler/RecyclerUtils.kt +++ b/app/src/main/java/org/oxycblt/auxio/recycler/RecyclerUtils.kt @@ -1,12 +1,11 @@ package org.oxycblt.auxio.recycler import android.graphics.drawable.ColorDrawable -import androidx.appcompat.app.AppCompatDelegate -import androidx.core.content.ContextCompat -import androidx.core.graphics.ColorUtils import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.R +import org.oxycblt.auxio.theme.getAccentTransparency +import org.oxycblt.auxio.theme.getDayNightTransparency // Apply a custom vertical divider fun RecyclerView.applyDivider() { @@ -17,21 +16,11 @@ fun RecyclerView.applyDivider() { div.setDrawable( ColorDrawable( - getDividerDrawable(this) + getAccentTransparency( + context, R.color.divider_color, getDayNightTransparency() + ) ) ) addItemDecoration(div) } - -private fun getDividerDrawable(recycler: RecyclerView): Int { - val isDark = AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES - - // Depending on the theme use a different opacity for the divider - val alpha = if (isDark) 45 else 85 - - return ColorUtils.setAlphaComponent( - ContextCompat.getColor(recycler.context, R.color.divider_color), - alpha - ) -} diff --git a/app/src/main/java/org/oxycblt/auxio/theme/ThemeUtils.kt b/app/src/main/java/org/oxycblt/auxio/theme/ThemeUtils.kt new file mode 100644 index 000000000..375da8aa0 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/theme/ThemeUtils.kt @@ -0,0 +1,33 @@ +package org.oxycblt.auxio.theme + +import android.content.Context +import androidx.appcompat.app.AppCompatDelegate +import androidx.core.content.ContextCompat +import androidx.core.graphics.ColorUtils +import org.oxycblt.auxio.R + +fun getDayNightTransparency(): Int { + val isDark = AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES + + // Depending on the theme use a different opacity for the divider + return if (isDark) 45 else 85 +} + +fun getDeselectedTransparency(color: Int): Int { + return if (color == R.color.yellow) 100 else 150 +} + +fun getAccentTransparency(context: Context, color: Int, alpha: Int): Int { + return ColorUtils.setAlphaComponent( + ContextCompat.getColor(context, color), + alpha + ) +} + +fun Int.toColor(context: Context): Int { + return try { + ContextCompat.getColor(context, this) + } catch (e: Exception) { + ContextCompat.getColor(context, android.R.color.white) + } +} diff --git a/app/src/main/res/drawable/ic_library.xml b/app/src/main/res/drawable/ic_library.xml new file mode 100644 index 000000000..b17661a54 --- /dev/null +++ b/app/src/main/res/drawable/ic_library.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/music_icon.xml b/app/src/main/res/drawable/ic_music.xml similarity index 100% rename from app/src/main/res/drawable/music_icon.xml rename to app/src/main/res/drawable/ic_music.xml diff --git a/app/src/main/res/drawable/indicator.xml b/app/src/main/res/drawable/indicator.xml new file mode 100644 index 000000000..962155467 --- /dev/null +++ b/app/src/main/res/drawable/indicator.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_main.xml b/app/src/main/res/layout/fragment_main.xml index 6e947155e..1a3984ce0 100644 --- a/app/src/main/res/layout/fragment_main.xml +++ b/app/src/main/res/layout/fragment_main.xml @@ -1,13 +1,32 @@ - + - + android:layout_height="match_parent" + android:orientation="vertical"> - + android:layout_height="0dp" + android:layout_weight="1" /> + + + + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 631b7e2e7..eb898ac5f 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -10,5 +10,7 @@ 44dp 56dp + 38dp + 4dp \ No newline at end of file