From 98a003727be1e9ed0e83032aa0418a4e6d0f4c2d Mon Sep 17 00:00:00 2001 From: Shihaam Abdul Rahman Date: Wed, 3 Jun 2026 02:21:39 +0500 Subject: [PATCH] customize circular nav --- .../basedbank/ui/home/CircularNavFragment.kt | 17 +++++++---- .../sar/basedbank/ui/home/NavCustomization.kt | 29 ++++++++++++++----- .../ui/home/SettingsAppearanceFragment.kt | 19 +++++++++++- .../layout/fragment_settings_appearance.xml | 25 ++++++++++++++++ app/src/main/res/values/strings.xml | 1 + 5 files changed, 76 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/CircularNavFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/CircularNavFragment.kt index 8a1ea10..6b81ef2 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/CircularNavFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/CircularNavFragment.kt @@ -78,13 +78,18 @@ class CircularNavFragment : Fragment() { } val wheelView = CircularWheelView(ctx).apply { layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT) + val prefs = ctx.getSharedPreferences("prefs", Context.MODE_PRIVATE) + val savedSlots = NavCustomization.getCircularSlots(prefs).map { id -> + val def = NavCustomization.ALL_SWAPPABLE.find { it.id == id }!! + CircularWheelView.WheelItem(def.id, def.iconRes, ctx.getString(def.titleRes)) + } items = listOf( - CircularWheelView.WheelItem(R.id.nav_dashboard, R.drawable.ic_nav_dashboard, "Dashboard"), // 12 - CircularWheelView.WheelItem(R.id.nav_transfer, R.drawable.ic_send, "Transfer"), // 2 - CircularWheelView.WheelItem(R.id.nav_pay_with_card, R.drawable.ic_nav_card, "Cards"), // 4 - CircularWheelView.WheelItem(R.id.nav_more, R.drawable.ic_nav_more, "More"), // 6 - CircularWheelView.WheelItem(R.id.nav_contacts, R.drawable.ic_contacts, "Contacts"), // 8 - CircularWheelView.WheelItem(R.id.nav_accounts, R.drawable.ic_nav_accounts, "Accounts"), // 10 + CircularWheelView.WheelItem(R.id.nav_dashboard, R.drawable.ic_nav_dashboard, ctx.getString(R.string.nav_dashboard)), + savedSlots[0], // 2 o'clock + savedSlots[1], // 4 o'clock + CircularWheelView.WheelItem(R.id.nav_more, R.drawable.ic_nav_more, ctx.getString(R.string.nav_more)), + savedSlots[2], // 8 o'clock + savedSlots[3], // 10 o'clock ) accentColor = colorPrimary surfaceColor = colorSurface diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/NavCustomization.kt b/app/src/main/java/sh/sar/basedbank/ui/home/NavCustomization.kt index 20221b9..c5be4ea 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/NavCustomization.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/NavCustomization.kt @@ -76,18 +76,31 @@ object NavCustomization { } /** Items that belong in the "More" screen — those not occupying a bottom nav slot. */ + fun getCircularSlots(prefs: SharedPreferences): List = listOf( + keyToId(prefs.getString("circular_slot_1_key", null), R.id.nav_transfer), + keyToId(prefs.getString("circular_slot_2_key", null), R.id.nav_pay_with_card), + keyToId(prefs.getString("circular_slot_3_key", null), R.id.nav_contacts), + keyToId(prefs.getString("circular_slot_4_key", null), R.id.nav_accounts), + ) + + fun saveCircularSlots(prefs: SharedPreferences, slots: List) { + prefs.edit() + .putString("circular_slot_1_key", idToKey(slots[0]) ?: "nav_transfer") + .putString("circular_slot_2_key", idToKey(slots[1]) ?: "nav_pay_with_card") + .putString("circular_slot_3_key", idToKey(slots[2]) ?: "nav_contacts") + .putString("circular_slot_4_key", idToKey(slots[3]) ?: "nav_accounts") + .apply() + } + fun getMoreItems(prefs: SharedPreferences): List { - if (getNavMode(prefs) == NAV_MODE_CIRCULAR) return getCircularMoreItems() + if (getNavMode(prefs) == NAV_MODE_CIRCULAR) return getCircularMoreItems(prefs) val slots = getSlots(prefs).toSet() return ALL_SWAPPABLE.filter { it.id !in slots } } - /** Items shown in More when circular nav is active — everything not directly on the wheel. */ - private fun getCircularMoreItems(): List { - val wheelIds = setOf( - R.id.nav_dashboard, R.id.nav_transfer, R.id.nav_pay_with_card, - R.id.nav_contacts, R.id.nav_accounts - ) - return ALL_SWAPPABLE.filter { it.id !in wheelIds } + /** Items shown in More when circular nav is active — everything not in the saved wheel slots. */ + private fun getCircularMoreItems(prefs: SharedPreferences): List { + val slotIds = getCircularSlots(prefs).toSet() + return ALL_SWAPPABLE.filter { it.id !in slotIds } } } diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/SettingsAppearanceFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/SettingsAppearanceFragment.kt index b9b7bee..0cd3231 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/SettingsAppearanceFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/SettingsAppearanceFragment.kt @@ -36,8 +36,10 @@ class SettingsAppearanceFragment : Fragment() { private lateinit var prefs: SharedPreferences private val slots = mutableListOf() private val quickActions = mutableListOf() + private val circularSlots = mutableListOf() private lateinit var slotAdapter: NavItemAdapter private lateinit var quickActionAdapter: NavItemAdapter + private lateinit var circularSlotAdapter: NavItemAdapter override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { _binding = FragmentSettingsAppearanceBinding.inflate(inflater, container, false) @@ -78,6 +80,18 @@ class SettingsAppearanceFragment : Fragment() { NavCustomization.getNavMode(prefs) != NavCustomization.NAV_MODE_BOTTOM } + // Circular nav shortcuts + circularSlots.clear() + circularSlots.addAll(NavCustomization.getCircularSlots(prefs)) + circularSlotAdapter = NavItemAdapter( + items = circularSlots, + onSave = { NavCustomization.saveCircularSlots(prefs, circularSlots) }, + isEnabled = { NavCustomization.getNavMode(prefs) == NavCustomization.NAV_MODE_CIRCULAR } + ) + setupNavItemRecyclerView(binding.rvCircularSlots, circularSlotAdapter, circularSlots) { + NavCustomization.getNavMode(prefs) == NavCustomization.NAV_MODE_CIRCULAR + } + // Bottom bar shortcuts slots.clear() slots.addAll(NavCustomization.getSlots(prefs)) @@ -202,11 +216,13 @@ class SettingsAppearanceFragment : Fragment() { private fun updateShortcutsVisibility() { val mode = NavCustomization.getNavMode(prefs) val isBottom = mode == NavCustomization.NAV_MODE_BOTTOM - val isDrawer = mode == NavCustomization.NAV_MODE_DRAWER + val isCircular = mode == NavCustomization.NAV_MODE_CIRCULAR binding.sectionQuickActions.alpha = if (!isBottom) 1f else 0.38f + binding.sectionCircularSlots.alpha = if (isCircular) 1f else 0.38f binding.sectionBottomBarShortcuts.alpha = if (isBottom) 1f else 0.38f binding.switchShowLabels.isClickable = isBottom quickActionAdapter.notifyDataSetChanged() + circularSlotAdapter.notifyDataSetChanged() slotAdapter.notifyDataSetChanged() } @@ -276,6 +292,7 @@ class SettingsAppearanceFragment : Fragment() { val mode = NavCustomization.getNavMode(prefs) if (items === slots && mode != NavCustomization.NAV_MODE_BOTTOM) return if (items === quickActions && mode == NavCustomization.NAV_MODE_BOTTOM) return + if (items === circularSlots && mode != NavCustomization.NAV_MODE_CIRCULAR) return val ctx = requireContext() val otherIds = items.filterIndexed { i, _ -> i != slotIndex }.toSet() val available = NavCustomization.ALL_SWAPPABLE.filter { it.id !in otherIds } diff --git a/app/src/main/res/layout/fragment_settings_appearance.xml b/app/src/main/res/layout/fragment_settings_appearance.xml index 1b4ced2..3399ca0 100644 --- a/app/src/main/res/layout/fragment_settings_appearance.xml +++ b/app/src/main/res/layout/fragment_settings_appearance.xml @@ -78,6 +78,31 @@ + + + + + + + + + Bottom Bar Circular Appearance + Circular Nav Shortcuts Bottom Bar Shortcuts Always show bottom bar labels Choose button