3.3 KiB
Circular Nav
Radial wheel-style navigation. Activated by selecting Circular in Settings → Appearance → Navigation Mode. Replaces the drawer and bottom bar entirely.
Fragment — CircularNavFragment
File: ui/home/CircularNavFragment.kt. Becomes the root content fragment in HomeActivity when NavCustomization.getNavMode(prefs) == NAV_MODE_CIRCULAR (HomeActivity.kt:279-280). Inflates a LinearLayout with a CircularWheelView filling the available space and the app launcher icon at the bottom.
The toolbar collapses to a single centred title view ("wheel_title" tag) and the standard lock/eye/bell items are hidden via onPrepareOptionsMenu (HomeActivity.kt:646-650).
Wheel Layout
Six segments are populated in this order so the four user-configurable slots sit at the top of the wheel and the system items sit at the bottom:
| Clock position | Item |
|---|---|
| 10, 12, 2 | User wheel slots 0–2 (circular_slot_1_key–circular_slot_3_key) |
| 4 | User wheel slot 3 (circular_slot_4_key) |
| 6 | Dashboard (fixed) |
| 8 | More (fixed) — opens NavMoreSheetFragment with the remaining items |
Defaults (NavCustomization.kt:79-84): Transfer, Cards, Contacts, Accounts.
The wheel angle is persisted to circular_wheel_angle in SharedPreferences so the user's preferred rotation survives navigation away from the wheel.
Centre Lock
CircularWheelView has an isWheelLocked boolean that draws either ic_lock (locked) or ic_lock_open (unlocked) at the centre. The wheel starts unlocked.
| Action | Result |
|---|---|
| Tap a segment while unlocked | Spins the segment down to 6 o'clock, then fires onItemClick(navId) → HomeActivity.navigateTo() |
| Tap the centre while unlocked | Locks the wheel |
| Tap the centre while locked | Fires onWheelCenterLockedTap → HomeActivity.notifyWheelLockTap() (intended for user feedback / unlock guidance) |
| Tap a segment while locked | Animates the segment but shakes the lock icon and vibrates instead of navigating (vibrateDevice() + shakeLock()) |
HomeActivity exposes unlockWheelLock() on the fragment so external code can clear the locked state.
Gestures
CircularWheelView handles its own touch events:
| Gesture | Behaviour |
|---|---|
| Drag | Increments wheelAngle by the angular delta. Touch slop must be exceeded before drag mode engages |
| Fling | A 6-sample velocity buffer estimates angular velocity; fling(vel) decelerates at 0.0008 deg/ms² then snaps to the nearest segment |
| Release without dragging | Treated as a tap — the segment under the touch is centered and activated |
After every drag/fling settle, snapToNearest() aligns the wheel angle to a segment boundary using DecelerateInterpolator.
Visuals
- Disc fill:
colorSurface - Outer accent ring + inner centre ring:
colorPrimary - Icons: tinted with
colorPrimary(greyscale + 40% alpha while locked) - Labels: curved text on a per-segment arc (
drawTextOnPath); colour followscolorOnSurface(semi-transparent when locked)
Icon and centre bitmaps are regenerated on every size change via reloadBitmaps().