@apexnative/navigation 1.0.0-alpha.1 → 1.0.0-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ApexNavigation.podspec +2 -1
- package/CHANGELOG.md +132 -0
- package/README.md +147 -51
- package/android/CLAUDE.md +78 -25
- package/android/CORE.md +49 -25
- package/android/RECIPES.md +13 -6
- package/android/consumer-rules.pro +6 -0
- package/android/src/main/java/dev/apexnative/navigation/NavigationActivity.kt +85 -10
- package/android/src/main/java/dev/apexnative/navigation/NavigationApplication.kt +34 -13
- package/android/src/main/java/dev/apexnative/navigation/layout/LayoutChecks.kt +5 -1
- package/android/src/main/java/dev/apexnative/navigation/layout/LayoutNode.kt +6 -2
- package/android/src/main/java/dev/apexnative/navigation/nativescreen/NativeScreenContext.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/AnimationsOptions.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/BottomTabOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/BottomTabsOptions.kt +13 -8
- package/android/src/main/java/dev/apexnative/navigation/options/ButtonMenuOptions.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/ButtonOptions.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/options/HardwareBackButtonOptions.kt +9 -1
- package/android/src/main/java/dev/apexnative/navigation/options/LargeTitleOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/LayoutAnimation.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/OptionKey.kt +18 -0
- package/android/src/main/java/dev/apexnative/navigation/options/OptionPaths.kt +91 -0
- package/android/src/main/java/dev/apexnative/navigation/options/OptionsCache.kt +8 -4
- package/android/src/main/java/dev/apexnative/navigation/options/SheetOptions.kt +7 -4
- package/android/src/main/java/dev/apexnative/navigation/options/SideMenuOptions.kt +6 -1
- package/android/src/main/java/dev/apexnative/navigation/options/StackAnimationOptions.kt +40 -2
- package/android/src/main/java/dev/apexnative/navigation/options/StatusBarOptions.kt +7 -3
- package/android/src/main/java/dev/apexnative/navigation/options/TitleOptions.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/TopBarAppearanceOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/TopBarOptions.kt +16 -7
- package/android/src/main/java/dev/apexnative/navigation/options/UserChoices.kt +159 -0
- package/android/src/main/java/dev/apexnative/navigation/react/CommandAnswer.kt +29 -36
- package/android/src/main/java/dev/apexnative/navigation/react/CommandContract.kt +59 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ContentHeights.kt +95 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ContentMounts.kt +66 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ErrorTexts.kt +75 -60
- package/android/src/main/java/dev/apexnative/navigation/react/Hinge.kt +35 -23
- package/android/src/main/java/dev/apexnative/navigation/react/NavigationTurboModule.kt +12 -7
- package/android/src/main/java/dev/apexnative/navigation/react/OptionsCommands.kt +42 -4
- package/android/src/main/java/dev/apexnative/navigation/react/PendingCalls.kt +48 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ReactView.kt +54 -20
- package/android/src/main/java/dev/apexnative/navigation/react/ReloadCoordinator.kt +7 -6
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenEnvironment.kt +177 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenRegions.kt +19 -50
- package/android/src/main/java/dev/apexnative/navigation/react/ScrollEvents.kt +49 -128
- package/android/src/main/java/dev/apexnative/navigation/react/events/AppearanceDispatcher.kt +50 -81
- package/android/src/main/java/dev/apexnative/navigation/react/events/EventContract.kt +226 -0
- package/android/src/main/java/dev/apexnative/navigation/react/events/EventEmitter.kt +135 -94
- package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationState.kt +154 -0
- package/android/src/main/java/dev/apexnative/navigation/react/events/ScreenAppearance.kt +0 -6
- package/android/src/main/java/dev/apexnative/navigation/safearea/SafeAreaView.kt +12 -10
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotContainers.kt +10 -7
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotScreenView.kt +39 -19
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotView.kt +16 -4
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotViews.kt +40 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/ImageKey.kt +66 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/ImageLoader.kt +7 -89
- package/android/src/main/java/dev/apexnative/navigation/utils/ImageRequests.kt +76 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/MaterialTheme.kt +5 -6
- package/android/src/main/java/dev/apexnative/navigation/utils/OptionImages.kt +262 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/SystemAnimations.kt +36 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/UiUtils.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/utils/ViewController.kt +3 -1
- package/android/src/main/java/dev/apexnative/navigation/utils/ViewExtensions.kt +0 -13
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementController.kt +10 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementDefinition.kt +9 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementPlanner.kt +20 -15
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/SecondaryScreenPresenter.kt +13 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/AppliedTabCalls.kt +49 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsCollapseBehavior.kt +5 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsController.kt +108 -34
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsPresenter.kt +25 -24
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowGeometry.kt +22 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabItems.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabsRoom.kt +0 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentPresenter.kt +28 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentViewController.kt +12 -9
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ContentReadiness.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/RenderWait.kt +27 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenFrame.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenReadiness.kt +103 -56
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenSafeArea.kt +29 -11
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/externalcomponent/ExternalComponentViewController.kt +2 -6
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalAnimations.kt +22 -24
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalCoordinator.kt +109 -21
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalRecord.kt +21 -6
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalSheet.kt +476 -73
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalViews.kt +57 -25
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetBack.kt +42 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetStops.kt +83 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackCheck.kt +50 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackState.kt +49 -14
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/Navigator.kt +71 -12
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/RootCoordinator.kt +37 -11
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/overlay/OverlayCoordinator.kt +10 -8
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/Capabilities.kt +11 -4
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ContainerBackground.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ParentController.kt +6 -6
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuController.kt +42 -9
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +19 -8
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuPresenter.kt +16 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuRules.kt +43 -4
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitPanes.kt +23 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitViewController.kt +77 -17
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/BackPreview.kt +315 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/PreparedFrame.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackCommands.kt +30 -20
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +216 -18
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackDisplay.kt +26 -1
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +149 -41
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackTransitions.kt +26 -8
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +115 -6
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabMotion.kt +142 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt +222 -48
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/ScreenSearch.kt +3 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +30 -34
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarComponents.kt +5 -51
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarRowTransition.kt +3 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/ButtonPlaces.kt +11 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/MenuChecks.kt +13 -56
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +219 -54
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarVisibility.kt +9 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ScrollEventListener.kt +6 -9
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ViewController.kt +75 -21
- package/android/src/main/java/dev/apexnative/navigation/views/animations/AnimationLayer.kt +73 -0
- package/android/src/main/java/dev/apexnative/navigation/views/animations/Curves.kt +29 -11
- package/android/src/main/java/dev/apexnative/navigation/views/animations/ValueInterpolation.kt +14 -0
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabs.kt +9 -7
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabsLayout.kt +61 -2
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomBottomTabItemView.kt +0 -5
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomTabRow.kt +72 -10
- package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStep.kt +31 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/ElementTransitions.kt +143 -135
- package/android/src/main/java/dev/apexnative/navigation/views/element/TargetsWait.kt +13 -5
- package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionLayer.kt +37 -112
- package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionTargets.kt +9 -6
- package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionViews.kt +100 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ElementPictures.kt +112 -4
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/FlightGeometry.kt +346 -36
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMorph.kt +199 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/SharedAnimatorFactory.kt +56 -41
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextMorph.kt +176 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewMorph.kt +108 -0
- package/android/src/main/java/dev/apexnative/navigation/views/sidemenu/SideMenuView.kt +12 -3
- package/android/src/main/java/dev/apexnative/navigation/views/stack/ScreenEdge.kt +45 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/StackLayout.kt +140 -1
- package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/Fab.kt +14 -10
- package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabCopy.kt +85 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabMenu.kt +13 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TitleBar.kt +5 -17
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TopBar.kt +73 -34
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonComponentCell.kt +6 -6
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonView.kt +113 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarMenu.kt +219 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonBar.kt +125 -178
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonMenus.kt +34 -64
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonRow.kt +216 -0
- package/android/src/main/jni/ANNContentHeights.cpp +82 -0
- package/android/src/main/res/drawable/apex_navigation_ic_arrow_right.xml +14 -0
- package/android/src/main/res/layout/apex_navigation_menu_header.xml +19 -0
- package/android/src/main/res/layout/apex_navigation_menu_item.xml +68 -0
- package/android/src/main/res/values/styles.xml +1 -1
- package/android/src/main/res/values-night/styles.xml +1 -1
- package/cli/app.js +1 -1
- package/cli/doctor/checks/app.js +77 -14
- package/cli/doctor/checks/splash.js +4 -22
- package/cli/migrate/native.js +18 -0
- package/cli/project.js +10 -2
- package/cli/setup/index.js +18 -0
- package/cli/setup/source.js +2 -1
- package/cli/setup/steps/appDelegate.js +66 -11
- package/cli/setup/steps/mainApplication.js +134 -19
- package/cli/setup/steps/metro.js +46 -0
- package/cli/setup/steps/sceneDelegate.js +108 -0
- package/cli/splash/index.js +3 -1
- package/docs-md/architecture/native-screens.md +4 -0
- package/docs-md/architecture/theme-and-context.md +131 -12
- package/docs-md/architecture/transitions.md +58 -12
- package/docs-md/containers/arrangement.md +17 -1
- package/docs-md/containers/modals.md +8 -4
- package/docs-md/containers/overlays.md +3 -1
- package/docs-md/containers/side-menu.md +19 -2
- package/docs-md/containers/tabs.md +5 -1
- package/docs-md/flows/bottom-sheets.md +4 -2
- package/docs-md/flows/forms-in-a-modal.md +1 -1
- package/docs-md/fundamentals/screens-and-props.md +9 -1
- package/docs-md/fundamentals/starting-the-app.md +1 -1
- package/docs-md/guides/cli.md +4 -3
- package/docs-md/guides/deep-links.md +15 -33
- package/docs-md/help/glossary.md +4 -4
- package/docs-md/help/troubleshooting.md +44 -6
- package/docs-md/index.json +61 -1
- package/docs-md/migration/from-expo-router.md +1 -1
- package/docs-md/migration/from-react-native-navigation.md +9 -3
- package/docs-md/migration/from-react-navigation.md +2 -2
- package/docs-md/screen-ui/back-and-gestures.md +46 -2
- package/docs-md/screen-ui/bar-buttons.md +5 -5
- package/docs-md/screen-ui/search.md +1 -1
- package/docs-md/screen-ui/system-ui.md +17 -12
- package/docs-md/screen-ui/toolbar-and-fab.md +4 -2
- package/docs-md/screen-ui/top-bar.md +8 -4
- package/docs-md/start/installation.md +21 -3
- package/ios/Animations/ANNFrameDriver.h +55 -15
- package/ios/Animations/ANNFrameDriver.mm +216 -60
- package/ios/Animations/ANNTransitionAnimator.h +26 -5
- package/ios/Animations/ANNTransitionAnimator.mm +61 -13
- package/ios/Animations/ANNTransitionPlan.h +2 -2
- package/ios/Animations/ANNTransitionPlan.mm +10 -0
- package/ios/Animations/ANNTransitionWait.mm +6 -7
- package/ios/Animations/Elements/ANNElementFinder.h +57 -0
- package/ios/Animations/Elements/ANNElementFinder.mm +174 -2
- package/ios/Animations/Elements/ANNElementTransition.h +10 -8
- package/ios/Animations/Elements/ANNElementTransition.mm +19 -21
- package/ios/Animations/Elements/ANNSharedElementFlight.h +16 -11
- package/ios/Animations/Elements/ANNSharedElementFlight.mm +308 -69
- package/ios/Animations/Interpolators/ANNInterpolate.h +2 -30
- package/ios/Animations/Interpolators/ANNTransformParts.h +48 -0
- package/ios/Animations/Interpolators/ANNTransformParts.mm +507 -0
- package/ios/Animations/Interpolators/ANNViewTracks.h +9 -6
- package/ios/Animations/Interpolators/ANNViewTracks.mm +100 -30
- package/ios/CLAUDE.md +60 -24
- package/ios/CORE.md +44 -34
- package/ios/Contract/ANNCommandAnswer.h +13 -5
- package/ios/Contract/ANNCommandAnswer.mm +40 -32
- package/ios/Contract/ANNCommandContract.h +15 -0
- package/ios/Contract/ANNCommandContract.mm +78 -0
- package/ios/Contract/ANNCommandRunner.h +10 -9
- package/ios/Contract/ANNCommandRunner.mm +22 -28
- package/ios/Contract/ANNErrorTexts.h +6 -2
- package/ios/Contract/ANNErrorTexts.mm +18 -10
- package/ios/Contract/ANNLayoutNode.h +3 -3
- package/ios/Contract/ANNLayoutReader.h +3 -3
- package/ios/Core/ANNAppDelegate.mm +0 -2
- package/ios/Core/ANNAppearanceDispatcher.h +5 -4
- package/ios/Core/ANNAppearanceDispatcher.mm +12 -1
- package/ios/Core/ANNDeepLinkQueue.h +22 -2
- package/ios/Core/ANNDeepLinkQueue.mm +121 -14
- package/ios/Core/ANNErrorHandler.h +9 -4
- package/ios/Core/ANNErrorHandler.mm +20 -2
- package/ios/Core/ANNEventContract.h +246 -0
- package/ios/Core/ANNEventContract.mm +225 -0
- package/ios/Core/ANNEventEmitter.h +6 -2
- package/ios/Core/ANNEventEmitter.mm +117 -80
- package/ios/Core/ANNHinge.h +6 -0
- package/ios/Core/ANNHinge.mm +15 -4
- package/ios/Core/ANNJavaScriptCalls.h +33 -0
- package/ios/Core/ANNJavaScriptCalls.mm +52 -0
- package/ios/Core/ANNLayoutProtocol.h +5 -5
- package/ios/Core/ANNNavigationState.h +7 -5
- package/ios/Core/ANNNavigationState.mm +8 -7
- package/ios/Core/ANNNodeHelper.h +32 -12
- package/ios/Core/ANNNodeHelper.mm +100 -3
- package/ios/Core/ANNParking.h +5 -4
- package/ios/Core/ANNReloadCoordinator.mm +5 -12
- package/ios/Core/ANNRenderWait.h +20 -6
- package/ios/Core/ANNRenderWait.mm +143 -56
- package/ios/Core/ANNSceneDelegate.mm +25 -15
- package/ios/Core/ANNSystemUI.h +3 -2
- package/ios/Core/ANNSystemUI.mm +7 -0
- package/ios/Core/ANNUtils.h +7 -0
- package/ios/Core/ANNUtils.mm +10 -0
- package/ios/Core/ApexNavigation+Internal.h +1 -1
- package/ios/Core/ApexNavigation.mm +7 -6
- package/ios/Core/UIViewController+LayoutProtocol.h +9 -2
- package/ios/Core/UIViewController+LayoutProtocol.mm +8 -0
- package/ios/Layouts/Arrangement/ANNArrangementState.h +2 -17
- package/ios/Layouts/Arrangement/ANNArrangementState.mm +0 -38
- package/ios/Layouts/Arrangement/ANNArrangementViewController.mm +195 -21
- package/ios/Layouts/Modal/ANNModalCoordinator.h +1 -1
- package/ios/Layouts/Modal/ANNModalCoordinator.mm +57 -16
- package/ios/Layouts/Modal/ANNModalPresentation.h +8 -5
- package/ios/Layouts/Modal/ANNModalPresentation.mm +12 -12
- package/ios/Layouts/Modal/ANNSheetPresenter.mm +83 -1
- package/ios/Layouts/Overlay/ANNOverlayCoordinator.mm +2 -8
- package/ios/Layouts/Root/ANNRootCoordinator.mm +58 -19
- package/ios/Layouts/Root/ANNSplashViewController.h +5 -3
- package/ios/Layouts/Root/ANNSplashViewController.mm +147 -0
- package/ios/Layouts/Screen/ANNComponentPresenter.h +11 -3
- package/ios/Layouts/Screen/ANNComponentPresenter.mm +34 -6
- package/ios/Layouts/Screen/ANNComponentViewController.h +15 -13
- package/ios/Layouts/Screen/ANNComponentViewController.mm +130 -75
- package/ios/Layouts/Screen/ANNNativeScreenContext.mm +7 -5
- package/ios/Layouts/Screen/ANNPreviewInteraction.h +7 -4
- package/ios/Layouts/Screen/ANNPreviewInteraction.mm +72 -10
- package/ios/Layouts/Screen/ANNScreenEnvironment.h +63 -0
- package/ios/Layouts/Screen/ANNScreenEnvironment.mm +181 -0
- package/ios/Layouts/Screen/ANNScreenPlace.h +53 -0
- package/ios/Layouts/Screen/ANNScreenPlace.mm +205 -0
- package/ios/Layouts/Screen/ANNScreenRegions.h +3 -18
- package/ios/Layouts/Screen/ANNScreenRegions.mm +9 -44
- package/ios/Layouts/Screen/ANNScreenSafeArea.h +4 -9
- package/ios/Layouts/Screen/ANNScreenSafeArea.mm +14 -16
- package/ios/Layouts/Screen/ANNScreenSettling.h +34 -0
- package/ios/Layouts/Screen/ANNScreenSettling.mm +171 -0
- package/ios/Layouts/SideMenu/ANNSideMenuTypes.h +8 -0
- package/ios/Layouts/SideMenu/ANNSideMenuViewController.mm +83 -14
- package/ios/Layouts/SplitView/ANNSplitViewCommands.h +3 -2
- package/ios/Layouts/SplitView/ANNSplitViewCommands.mm +105 -39
- package/ios/Layouts/SplitView/ANNSplitViewController.mm +7 -8
- package/ios/Layouts/Stack/ANNPreviewPush.h +7 -6
- package/ios/Layouts/Stack/ANNPreviewPush.mm +142 -27
- package/ios/Layouts/Stack/ANNStackAnimatingDelegate.h +11 -2
- package/ios/Layouts/Stack/ANNStackAnimatingDelegate.mm +14 -7
- package/ios/Layouts/Stack/ANNStackCommands.mm +1 -0
- package/ios/Layouts/Stack/ANNStackController.h +8 -0
- package/ios/Layouts/Stack/ANNStackController.mm +184 -16
- package/ios/Layouts/Stack/ANNStackQueue.h +5 -2
- package/ios/Layouts/Stack/ANNStackQueue.mm +56 -43
- package/ios/Layouts/Stack/ANNSwipePopInteraction.h +26 -0
- package/ios/Layouts/Stack/ANNSwipePopInteraction.mm +185 -0
- package/ios/Layouts/Stack/InteractivePopGestureDelegate.mm +28 -4
- package/ios/Layouts/Stack/UINavigationController+ANNCommands.h +4 -2
- package/ios/Layouts/Stack/UINavigationController+ANNCommands.mm +2 -3
- package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.h +4 -0
- package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.mm +11 -0
- package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.h +12 -1
- package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.mm +23 -0
- package/ios/Layouts/Tabs/ANNBottomTabsController.h +3 -0
- package/ios/Layouts/Tabs/ANNBottomTabsController.mm +237 -57
- package/ios/Layouts/Tabs/ANNBottomTabsCustomRow.mm +8 -3
- package/ios/Layouts/Tabs/ANNBottomTabsPresenter.h +6 -2
- package/ios/Layouts/Tabs/ANNBottomTabsPresenter.mm +232 -43
- package/ios/Layouts/Tabs/ANNTabsDesign.h +6 -5
- package/ios/Layouts/Tabs/ANNTabsDesign.mm +9 -1
- package/ios/Layouts/Tabs/UITabBar+utils.h +5 -5
- package/ios/Layouts/Tabs/UITabBar+utils.mm +32 -13
- package/ios/Options/ANNAnimationOptions.h +2 -1
- package/ios/Options/ANNAnimationOptions.mm +1 -1
- package/ios/Options/ANNBottomTabsOptions.h +2 -0
- package/ios/Options/ANNBottomTabsOptions.mm +1 -0
- package/ios/Options/ANNOptions.h +25 -0
- package/ios/Options/ANNOptions.mm +157 -1
- package/ios/Options/ANNOptionsCache.h +7 -6
- package/ios/Options/ANNOptionsReader.mm +108 -0
- package/ios/Options/ANNSearchBarOptions.h +4 -3
- package/ios/Options/ANNSheetOptions.h +4 -1
- package/ios/Options/ANNSideMenuOptions.h +2 -0
- package/ios/Options/ANNSideMenuOptions.mm +2 -0
- package/ios/Options/ANNStackPopAnimationOptions.h +13 -0
- package/ios/Options/ANNStackPopAnimationOptions.mm +11 -0
- package/ios/Options/ANNUserChoice.h +57 -0
- package/ios/Options/ANNUserChoice.mm +44 -0
- package/ios/Options/Params/ANNImageSource.h +61 -0
- package/ios/Options/Params/ANNImageSource.mm +101 -0
- package/ios/Options/Params/ANNOptionImages.h +37 -0
- package/ios/Options/Params/ANNOptionImages.mm +284 -0
- package/ios/Options/Params/ANNParam.h +15 -0
- package/ios/Options/Params/ANNParam.mm +61 -0
- package/ios/Options/Params/Color.h +3 -0
- package/ios/Options/Params/Color.mm +21 -0
- package/ios/Options/Params/ColorParser.h +4 -3
- package/ios/Options/Params/ColorParser.mm +22 -4
- package/ios/Options/Params/Image.h +15 -2
- package/ios/Options/Params/Image.mm +35 -2
- package/ios/Options/Params/ImageParser.h +5 -5
- package/ios/Options/Params/ImageParser.mm +28 -46
- package/ios/Public/ApexNavigation/ANNSceneDelegate.h +3 -0
- package/ios/Public/ApexNavigation/ApexNavigation.h +1 -1
- package/ios/RECIPES.md +13 -6
- package/ios/React/ANNReactView.mm +6 -25
- package/ios/React/ANNSafeAreaViewComponentView.mm +28 -17
- package/ios/React/ANNSurfaceHostingView.h +14 -0
- package/ios/React/ANNSurfaceHostingView.mm +144 -1
- package/ios/React/Slots/ANNSlotComponentView.mm +24 -17
- package/ios/React/Slots/ANNSlotContainers.h +14 -6
- package/ios/React/Slots/ANNSlotContainers.mm +75 -2
- package/ios/React/Slots/ANNSlotHost.mm +1 -3
- package/ios/React/Slots/ANNSlotScreenView.mm +8 -2
- package/ios/TopBar/ANNBackButtonPresenter.mm +6 -5
- package/ios/TopBar/ANNBarAppearance.h +2 -1
- package/ios/TopBar/ANNBarAppearance.mm +111 -30
- package/ios/TopBar/ANNBarBackgroundComponent.mm +16 -0
- package/ios/TopBar/ANNBarButtonComponentView.h +4 -4
- package/ios/TopBar/ANNBarButtonComponentView.mm +1 -1
- package/ios/TopBar/ANNBarButtons.h +14 -8
- package/ios/TopBar/ANNBarButtons.mm +397 -80
- package/ios/TopBar/ANNIconButtonImage.h +1 -0
- package/ios/TopBar/ANNIconButtonImage.mm +34 -1
- package/ios/TopBar/ANNLargeTitlePresenter.h +13 -0
- package/ios/TopBar/ANNLargeTitlePresenter.mm +50 -7
- package/ios/TopBar/ANNMainList.h +3 -0
- package/ios/TopBar/ANNMainList.mm +4 -0
- package/ios/TopBar/ANNScrollEdgeEffects.h +22 -6
- package/ios/TopBar/ANNScrollEdgeEffects.mm +123 -16
- package/ios/TopBar/ANNSearchPresenter.mm +172 -21
- package/ios/TopBar/ANNSearchResultsViewController.mm +29 -6
- package/ios/TopBar/ANNTopBarPresenter.h +8 -2
- package/ios/TopBar/ANNTopBarPresenter.mm +155 -33
- package/ios/TurboModules/ANNTurboEventEmitter.mm +4 -35
- package/ios/TurboModules/ANNTurboModule.mm +104 -33
- package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.cpp +20 -0
- package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.h +5 -14
- package/lib/module/ARCHITECTURE.md +40 -27
- package/lib/module/adapters/NativeANNTurboModule.js.map +1 -1
- package/lib/module/api/app/AppRegistry.js +14 -2
- package/lib/module/api/app/AppRegistry.js.map +1 -1
- package/lib/module/api/app/createNavigation.js +190 -66
- package/lib/module/api/app/createNavigation.js.map +1 -1
- package/lib/module/api/commands/commands.js +54 -6
- package/lib/module/api/commands/commands.js.map +1 -1
- package/lib/module/api/events/navigationEvents.js +6 -2
- package/lib/module/api/events/navigationEvents.js.map +1 -1
- package/lib/module/api/hooks/useNavigation.js +8 -3
- package/lib/module/api/hooks/useNavigation.js.map +1 -1
- package/lib/module/api/hooks/useSafeAreaInsets.js +4 -3
- package/lib/module/api/hooks/useSafeAreaInsets.js.map +1 -1
- package/lib/module/api/linking/dispatchedLinks.js +23 -0
- package/lib/module/api/linking/dispatchedLinks.js.map +1 -0
- package/lib/module/api/linking/linking.js +11 -0
- package/lib/module/api/linking/linking.js.map +1 -1
- package/lib/module/api/navigation.js.map +1 -1
- package/lib/module/api/options/OptionsChain.js +2 -2
- package/lib/module/api/screens/arrangement.js +5 -2
- package/lib/module/api/screens/arrangement.js.map +1 -1
- package/lib/module/api/screens/defineScreen.js +45 -3
- package/lib/module/api/screens/defineScreen.js.map +1 -1
- package/lib/module/api/screens/nativeScreens.js +31 -6
- package/lib/module/api/screens/nativeScreens.js.map +1 -1
- package/lib/module/api/screens/registerScreens.js +193 -35
- package/lib/module/api/screens/registerScreens.js.map +1 -1
- package/lib/module/api/theme/theme.js +5 -0
- package/lib/module/api/theme/theme.js.map +1 -1
- package/lib/module/engine/commands.js +51 -9
- package/lib/module/engine/commands.js.map +1 -1
- package/lib/module/engine/layout.js +20 -11
- package/lib/module/engine/layout.js.map +1 -1
- package/lib/module/engine/nativeScreens.js +9 -0
- package/lib/module/engine/nativeScreens.js.map +1 -1
- package/lib/module/engine/options.js +49 -15
- package/lib/module/engine/options.js.map +1 -1
- package/lib/module/engine/optionsChange.js +102 -0
- package/lib/module/engine/optionsChange.js.map +1 -0
- package/lib/module/engine/places.js +52 -7
- package/lib/module/engine/places.js.map +1 -1
- package/lib/module/engine/props.js +30 -1
- package/lib/module/engine/props.js.map +1 -1
- package/lib/module/engine/refresh.js +85 -0
- package/lib/module/engine/refresh.js.map +1 -0
- package/lib/module/engine/rememberedOptions.js +61 -1
- package/lib/module/engine/rememberedOptions.js.map +1 -1
- package/lib/module/engine/screens.js +77 -16
- package/lib/module/engine/screens.js.map +1 -1
- package/lib/module/interfaces/contract/commands.json +101 -0
- package/lib/module/interfaces/contract/errors.json +275 -0
- package/lib/typescript/adapters/NativeANNTurboModule.d.ts +12 -2
- package/lib/typescript/adapters/NativeANNTurboModule.d.ts.map +1 -1
- package/lib/typescript/api/app/AppRegistry.d.ts.map +1 -1
- package/lib/typescript/api/app/createNavigation.d.ts +8 -3
- package/lib/typescript/api/app/createNavigation.d.ts.map +1 -1
- package/lib/typescript/api/commands/commands.d.ts.map +1 -1
- package/lib/typescript/api/commands/presentation.d.ts +4 -3
- package/lib/typescript/api/commands/presentation.d.ts.map +1 -1
- package/lib/typescript/api/events/navigationEvents.d.ts +3 -3
- package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
- package/lib/typescript/api/hooks/useNavigation.d.ts +1 -1
- package/lib/typescript/api/hooks/useNavigation.d.ts.map +1 -1
- package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts +4 -3
- package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts.map +1 -1
- package/lib/typescript/api/index.d.ts +1 -1
- package/lib/typescript/api/index.d.ts.map +1 -1
- package/lib/typescript/api/linking/dispatchedLinks.d.ts +7 -0
- package/lib/typescript/api/linking/dispatchedLinks.d.ts.map +1 -0
- package/lib/typescript/api/linking/linking.d.ts +8 -0
- package/lib/typescript/api/linking/linking.d.ts.map +1 -1
- package/lib/typescript/api/navigation.d.ts +4 -1
- package/lib/typescript/api/navigation.d.ts.map +1 -1
- package/lib/typescript/api/options/OptionsChain.d.ts +2 -2
- package/lib/typescript/api/screens/arrangement.d.ts +12 -2
- package/lib/typescript/api/screens/arrangement.d.ts.map +1 -1
- package/lib/typescript/api/screens/defineScreen.d.ts +23 -4
- package/lib/typescript/api/screens/defineScreen.d.ts.map +1 -1
- package/lib/typescript/api/screens/nativeScreens.d.ts +8 -1
- package/lib/typescript/api/screens/nativeScreens.d.ts.map +1 -1
- package/lib/typescript/api/screens/registerScreens.d.ts.map +1 -1
- package/lib/typescript/api/theme/theme.d.ts +2 -0
- package/lib/typescript/api/theme/theme.d.ts.map +1 -1
- package/lib/typescript/engine/commands.d.ts +5 -0
- package/lib/typescript/engine/commands.d.ts.map +1 -1
- package/lib/typescript/engine/layout.d.ts.map +1 -1
- package/lib/typescript/engine/nativeScreens.d.ts +5 -0
- package/lib/typescript/engine/nativeScreens.d.ts.map +1 -1
- package/lib/typescript/engine/options.d.ts +5 -2
- package/lib/typescript/engine/options.d.ts.map +1 -1
- package/lib/typescript/engine/optionsChange.d.ts +28 -0
- package/lib/typescript/engine/optionsChange.d.ts.map +1 -0
- package/lib/typescript/engine/places.d.ts +7 -2
- package/lib/typescript/engine/places.d.ts.map +1 -1
- package/lib/typescript/engine/props.d.ts +8 -1
- package/lib/typescript/engine/props.d.ts.map +1 -1
- package/lib/typescript/engine/refresh.d.ts +35 -0
- package/lib/typescript/engine/refresh.d.ts.map +1 -0
- package/lib/typescript/engine/rememberedOptions.d.ts +13 -0
- package/lib/typescript/engine/rememberedOptions.d.ts.map +1 -1
- package/lib/typescript/engine/screens.d.ts +27 -6
- package/lib/typescript/engine/screens.d.ts.map +1 -1
- package/lib/typescript/interfaces/ComponentEvents.d.ts +4 -4
- package/lib/typescript/interfaces/ComponentEvents.d.ts.map +1 -1
- package/lib/typescript/interfaces/Events.d.ts +28 -10
- package/lib/typescript/interfaces/Events.d.ts.map +1 -1
- package/lib/typescript/interfaces/Options.d.ts +1 -1
- package/lib/typescript/interfaces/Options.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/animations.d.ts +80 -22
- package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/bottomTabs.d.ts +21 -7
- package/lib/typescript/interfaces/options/bottomTabs.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/buttons.d.ts +23 -15
- package/lib/typescript/interfaces/options/buttons.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/modals.d.ts +34 -26
- package/lib/typescript/interfaces/options/modals.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/sideMenu.d.ts +23 -6
- package/lib/typescript/interfaces/options/sideMenu.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/stack.d.ts +17 -3
- package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/system.d.ts +18 -11
- package/lib/typescript/interfaces/options/system.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/toolbar.d.ts +2 -2
- package/lib/typescript/interfaces/options/topBar.d.ts +68 -38
- package/lib/typescript/interfaces/options/topBar.d.ts.map +1 -1
- package/metro/acceptPlugin.js +57 -0
- package/metro/babelTransformer.js +45 -0
- package/metro/index.js +36 -0
- package/package.json +3 -1
- package/src/ARCHITECTURE.md +40 -27
- package/src/adapters/NativeANNTurboModule.ts +12 -2
- package/src/api/app/AppRegistry.ts +16 -2
- package/src/api/app/createNavigation.ts +203 -69
- package/src/api/commands/commands.ts +48 -7
- package/src/api/commands/presentation.ts +4 -3
- package/src/api/events/navigationEvents.ts +10 -4
- package/src/api/hooks/useNavigation.ts +9 -4
- package/src/api/hooks/useSafeAreaInsets.ts +4 -3
- package/src/api/index.ts +1 -0
- package/src/api/linking/dispatchedLinks.ts +18 -0
- package/src/api/linking/linking.ts +22 -1
- package/src/api/navigation.ts +4 -1
- package/src/api/options/OptionsChain.ts +2 -2
- package/src/api/screens/arrangement.ts +17 -4
- package/src/api/screens/defineScreen.ts +49 -5
- package/src/api/screens/nativeScreens.ts +40 -4
- package/src/api/screens/registerScreens.tsx +185 -42
- package/src/api/theme/theme.ts +5 -0
- package/src/engine/commands.ts +70 -13
- package/src/engine/layout.ts +27 -11
- package/src/engine/nativeScreens.ts +10 -1
- package/src/engine/options.ts +45 -19
- package/src/engine/optionsChange.ts +107 -0
- package/src/engine/places.ts +65 -7
- package/src/engine/props.ts +30 -1
- package/src/engine/refresh.ts +97 -0
- package/src/engine/rememberedOptions.ts +74 -1
- package/src/engine/screens.tsx +76 -21
- package/src/interfaces/ComponentEvents.ts +4 -4
- package/src/interfaces/Events.ts +29 -10
- package/src/interfaces/Options.ts +1 -0
- package/src/interfaces/contract/commands.json +101 -0
- package/src/interfaces/contract/errors.json +275 -0
- package/src/interfaces/options/animations.ts +81 -22
- package/src/interfaces/options/bottomTabs.ts +21 -7
- package/src/interfaces/options/buttons.ts +23 -15
- package/src/interfaces/options/modals.ts +34 -26
- package/src/interfaces/options/sideMenu.ts +24 -6
- package/src/interfaces/options/stack.ts +17 -3
- package/src/interfaces/options/system.ts +18 -11
- package/src/interfaces/options/toolbar.ts +2 -2
- package/src/interfaces/options/topBar.ts +68 -38
- package/android/src/main/java/dev/apexnative/navigation/react/ArrangementStates.kt +0 -41
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenInsets.kt +0 -69
- package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationStateReporter.kt +0 -62
- package/android/src/main/java/dev/apexnative/navigation/react/events/StateHold.kt +0 -62
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowPlacer.kt +0 -223
- package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStub.kt +0 -31
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMatrixAnimator.kt +0 -138
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -88
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PropertyAnimatorCreator.kt +0 -33
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ReactImageAnimator.kt +0 -66
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextChangeAnimator.kt +0 -179
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -139
- package/ios/Layouts/Screen/ANNScreenInsets.h +0 -30
- package/ios/Layouts/Screen/ANNScreenInsets.mm +0 -68
- package/ios/Layouts/Tabs/ANNTabsPreloadWindow.h +0 -27
- package/ios/Layouts/Tabs/ANNTabsPreloadWindow.mm +0 -55
|
@@ -4,12 +4,11 @@ import android.content.Context
|
|
|
4
4
|
import android.content.res.ColorStateList
|
|
5
5
|
import android.content.res.Configuration
|
|
6
6
|
import android.graphics.Color
|
|
7
|
-
import android.graphics.drawable.Drawable
|
|
8
7
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
|
9
8
|
import dev.apexnative.navigation.options.params.ThemeColour
|
|
10
|
-
import dev.apexnative.navigation.utils.
|
|
11
|
-
import dev.apexnative.navigation.utils.ImageLoadingListenerAdapter
|
|
9
|
+
import dev.apexnative.navigation.utils.ImageRequests
|
|
12
10
|
import dev.apexnative.navigation.utils.MaterialTheme
|
|
11
|
+
import dev.apexnative.navigation.utils.OptionImages
|
|
13
12
|
import dev.apexnative.navigation.utils.UiUtils
|
|
14
13
|
import dev.apexnative.navigation.viewcontrollers.viewcontroller.ScrollEventListener
|
|
15
14
|
import androidx.appcompat.R as AppCompatR
|
|
@@ -29,6 +28,7 @@ class Fab(context: Context, val fabId: String) : FloatingActionButton(MaterialTh
|
|
|
29
28
|
// The icon's color of the options: a container color merged later kept the theme's icon color instead.
|
|
30
29
|
private var iconColor: Int? = null
|
|
31
30
|
private var optionRippleColor: Int? = null
|
|
31
|
+
private val icons = ImageRequests<Unit>(OptionImages.source(this.context))
|
|
32
32
|
|
|
33
33
|
init {
|
|
34
34
|
// Material's theme overlay of the button is a copy of the theme, made once: it follows a light/dark switch too.
|
|
@@ -36,14 +36,18 @@ class Fab(context: Context, val fabId: String) : FloatingActionButton(MaterialTh
|
|
|
36
36
|
MaterialTheme.followOverlay(this.context)
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
/**
|
|
40
|
+
* The icon of the options, with its color. [mayWait]: the button can show it when it is ready (it shows an icon
|
|
41
|
+
* already, it is hidden with `visible: false`, or it is an action of a closed menu), so an icon the cache doesn't
|
|
42
|
+
* have loads off the main thread; the last icon asked for wins. Otherwise it loads at once. An icon that doesn't
|
|
43
|
+
* load leaves the button without an icon.
|
|
44
|
+
*/
|
|
45
|
+
fun applyIcon(icon: String, color: ThemeColour, mayWait: Boolean) {
|
|
40
46
|
if (color.hasValue()) iconColor = color.get()
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
})
|
|
47
|
+
icons.request(Unit, icon, mayWait) { drawable ->
|
|
48
|
+
setImageDrawable(drawable)
|
|
49
|
+
iconColor?.let { imageTintList = ColorStateList.valueOf(it) }
|
|
50
|
+
}
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
/** iconColor alone, without a new icon: it did nothing in a merge. */
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
package dev.apexnative.navigation.views.stack.fab
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.graphics.Canvas
|
|
6
|
+
import android.graphics.Outline
|
|
7
|
+
import android.graphics.Picture
|
|
8
|
+
import android.os.Build
|
|
9
|
+
import android.view.Gravity
|
|
10
|
+
import android.view.View
|
|
11
|
+
import android.view.ViewGroup
|
|
12
|
+
import android.view.ViewOutlineProvider
|
|
13
|
+
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
14
|
+
import dev.apexnative.navigation.views.element.animators.recordPicture
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The picture of a FAB that leaves with its screen while the new top's FAB arrives: drawn as the button was, with the
|
|
18
|
+
* shadow of its shape, taking no touches and hidden from accessibility. The live button goes from its parent at once.
|
|
19
|
+
*/
|
|
20
|
+
@SuppressLint("ViewConstructor")
|
|
21
|
+
internal class FabCopy private constructor(
|
|
22
|
+
context: Context,
|
|
23
|
+
private val picture: Picture,
|
|
24
|
+
shape: Outline,
|
|
25
|
+
) : View(context) {
|
|
26
|
+
init {
|
|
27
|
+
importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
|
|
28
|
+
outlineProvider = object : ViewOutlineProvider() {
|
|
29
|
+
override fun getOutline(view: View, outline: Outline) = outline.set(shape)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
override fun onDraw(canvas: Canvas) {
|
|
34
|
+
canvas.drawPicture(picture)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
companion object {
|
|
38
|
+
/**
|
|
39
|
+
* A copy of [button] in [container], a child of [parent] (the button itself, or its menu), as it shows now: in
|
|
40
|
+
* its place in [parent], moved, scaled and faded as it is. None when it doesn't show or can't be recorded (a
|
|
41
|
+
* hardware bitmap in its icon before Android 9).
|
|
42
|
+
*/
|
|
43
|
+
fun of(button: View, container: View, parent: ViewGroup): FabCopy? {
|
|
44
|
+
if (container.parent !== parent || !button.isAttachedToWindow) return null
|
|
45
|
+
if (button.width <= 0 || button.height <= 0) return null
|
|
46
|
+
if (container.visibility != VISIBLE || button.visibility != VISIBLE) return null
|
|
47
|
+
val inner = button !== container
|
|
48
|
+
val alpha = container.alpha * if (inner) button.alpha else 1f
|
|
49
|
+
val scale = container.scaleX * if (inner) button.scaleX else 1f
|
|
50
|
+
if (alpha <= 0f || scale <= 0f) return null
|
|
51
|
+
val picture = recordPicture(button) ?: return null
|
|
52
|
+
val shape = Outline().apply {
|
|
53
|
+
// As the view counts its own outline: opaque unless the provider says otherwise.
|
|
54
|
+
this.alpha = 1f
|
|
55
|
+
button.outlineProvider?.getOutline(button, this)
|
|
56
|
+
}
|
|
57
|
+
val copy = FabCopy(button.context, picture, shape)
|
|
58
|
+
val left = container.left + if (inner) button.left else 0
|
|
59
|
+
val top = container.top + if (inner) button.top else 0
|
|
60
|
+
copy.translationX = container.translationX + if (inner) button.translationX else 0f
|
|
61
|
+
copy.translationY = container.translationY + if (inner) button.translationY else 0f
|
|
62
|
+
copy.scaleX = scale
|
|
63
|
+
copy.scaleY = scale
|
|
64
|
+
copy.alpha = alpha
|
|
65
|
+
copy.elevation = button.elevation
|
|
66
|
+
copy.translationZ = button.translationZ
|
|
67
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
68
|
+
copy.outlineAmbientShadowColor = button.outlineAmbientShadowColor
|
|
69
|
+
copy.outlineSpotShadowColor = button.outlineSpotShadowColor
|
|
70
|
+
}
|
|
71
|
+
parent.addView(copy, CoordinatorLayout.LayoutParams(button.width, button.height).apply {
|
|
72
|
+
gravity = Gravity.TOP or Gravity.LEFT
|
|
73
|
+
leftMargin = left
|
|
74
|
+
topMargin = top
|
|
75
|
+
})
|
|
76
|
+
// In its place before the next layout, so its first frame draws.
|
|
77
|
+
copy.measure(
|
|
78
|
+
MeasureSpec.makeMeasureSpec(button.width, MeasureSpec.EXACTLY),
|
|
79
|
+
MeasureSpec.makeMeasureSpec(button.height, MeasureSpec.EXACTLY),
|
|
80
|
+
)
|
|
81
|
+
copy.layout(left, top, left + button.width, top + button.height)
|
|
82
|
+
return copy
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -120,6 +120,19 @@ class FabMenu(context: Context, val fabId: String) : LinearLayout(context), FabA
|
|
|
120
120
|
(view.parent as? ViewGroup)?.removeView(view)
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
/**
|
|
124
|
+
* The menu closes and leaves its parent next: a scrim that shows fades out by itself and goes from the parent at
|
|
125
|
+
* the end of its fade, which the menu no longer owns; it takes no touches meanwhile, which belong to the new screen.
|
|
126
|
+
*/
|
|
127
|
+
fun closeToLeave() {
|
|
128
|
+
close()
|
|
129
|
+
scrim?.apply {
|
|
130
|
+
setOnClickListener(null)
|
|
131
|
+
isClickable = false
|
|
132
|
+
}
|
|
133
|
+
scrim = null
|
|
134
|
+
}
|
|
135
|
+
|
|
123
136
|
override fun show() = main.show()
|
|
124
137
|
|
|
125
138
|
override fun hide() {
|
|
@@ -7,15 +7,14 @@ import android.util.TypedValue
|
|
|
7
7
|
import android.view.View
|
|
8
8
|
import android.view.ViewGroup
|
|
9
9
|
import androidx.appcompat.widget.AppCompatTextView
|
|
10
|
-
import com.google.android.material.appbar.MaterialToolbar
|
|
11
|
-
import dev.apexnative.navigation.utils.MaterialTheme
|
|
12
10
|
import dev.apexnative.navigation.utils.UiUtils
|
|
11
|
+
import dev.apexnative.navigation.views.stack.topbar.titlebar.ButtonRow
|
|
13
12
|
import kotlin.math.max
|
|
14
13
|
import kotlin.math.min
|
|
15
14
|
|
|
16
15
|
/**
|
|
17
16
|
* The row of the bar: the left buttons with the back button at the start ([leftButtonBar]), the right buttons and "⋮"
|
|
18
|
-
* at the end ([rightButtonBar]),
|
|
17
|
+
* at the end ([rightButtonBar]), each a [ButtonRow], and between them the title and the subtitle, or a React
|
|
19
18
|
* title ([titleComponent]). It lays them out in its own coordinates, so a shift of the row (`topBar.title.topMargin`)
|
|
20
19
|
* moves them all; [sideInsets] keep them off the system bars and the cutout at the sides. Right to left, everything
|
|
21
20
|
* mirrors. Main thread only.
|
|
@@ -26,10 +25,10 @@ class TitleBar(context: Context) : ViewGroup(context) {
|
|
|
26
25
|
enum class Alignment { Start, Center, Fill }
|
|
27
26
|
|
|
28
27
|
/** The back button (its navigation button) and the left buttons. */
|
|
29
|
-
val leftButtonBar =
|
|
28
|
+
val leftButtonBar = ButtonRow(context)
|
|
30
29
|
|
|
31
30
|
/** The right buttons, the search's magnifier and "⋮". */
|
|
32
|
-
val rightButtonBar =
|
|
31
|
+
val rightButtonBar = ButtonRow(context)
|
|
33
32
|
|
|
34
33
|
/** The title's text: one line, cut with "…" at its end (`topBar.title.text`). */
|
|
35
34
|
val titleView = AppCompatTextView(context).apply {
|
|
@@ -152,7 +151,7 @@ class TitleBar(context: Context) : ViewGroup(context) {
|
|
|
152
151
|
view.layout(x, top, x + w, top + view.measuredHeight)
|
|
153
152
|
}
|
|
154
153
|
// The back button and the left buttons at the start of the line, the right buttons at its end: right to left
|
|
155
|
-
// the whole row mirrors, and each
|
|
154
|
+
// the whole row mirrors, and each side mirrors what it holds.
|
|
156
155
|
val startBar = leftButtonBar.measuredWidth
|
|
157
156
|
val endBar = rightButtonBar.measuredWidth
|
|
158
157
|
place(leftButtonBar, 0, 0)
|
|
@@ -192,17 +191,6 @@ class TitleBar(context: Context) : ViewGroup(context) {
|
|
|
192
191
|
return min(max(middle, startBar), max(inner - endBar - width, startBar))
|
|
193
192
|
}
|
|
194
193
|
|
|
195
|
-
// A toolbar that holds only buttons: no insets of its own around them (the row places them).
|
|
196
|
-
private fun plain(toolbar: MaterialToolbar) {
|
|
197
|
-
// Before the toolbar makes its menu, which takes the popup theme once: "⋮" in the current mode.
|
|
198
|
-
toolbar.popupTheme = MaterialTheme.popupTheme(toolbar.context)
|
|
199
|
-
toolbar.setContentInsetsRelative(0, 0)
|
|
200
|
-
toolbar.contentInsetStartWithNavigation = 0
|
|
201
|
-
toolbar.contentInsetEndWithActions = 0
|
|
202
|
-
toolbar.setPadding(0, 0, 0, 0)
|
|
203
|
-
toolbar.minimumHeight = 0
|
|
204
|
-
}
|
|
205
|
-
|
|
206
194
|
private companion object {
|
|
207
195
|
const val GAP_DP = 16
|
|
208
196
|
const val TITLE_SIZE_SP = 22f
|
|
@@ -2,11 +2,12 @@ package dev.apexnative.navigation.views.stack.topbar
|
|
|
2
2
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.content.Context
|
|
5
|
-
import android.graphics.Bitmap
|
|
6
5
|
import android.graphics.Canvas
|
|
7
6
|
import android.graphics.Color
|
|
7
|
+
import android.graphics.Picture
|
|
8
8
|
import android.graphics.Rect
|
|
9
9
|
import android.graphics.drawable.ColorDrawable
|
|
10
|
+
import android.graphics.drawable.PictureDrawable
|
|
10
11
|
import android.os.Build
|
|
11
12
|
import android.view.ContextThemeWrapper
|
|
12
13
|
import android.view.Gravity
|
|
@@ -16,10 +17,11 @@ import android.view.ViewGroup
|
|
|
16
17
|
import android.widget.FrameLayout
|
|
17
18
|
import android.widget.ImageView
|
|
18
19
|
import android.widget.LinearLayout
|
|
19
|
-
import
|
|
20
|
+
import androidx.appcompat.widget.AppCompatImageView
|
|
20
21
|
import dev.apexnative.navigation.R
|
|
21
22
|
import dev.apexnative.navigation.utils.MaterialTheme
|
|
22
23
|
import dev.apexnative.navigation.utils.UiUtils
|
|
24
|
+
import dev.apexnative.navigation.views.stack.topbar.titlebar.ButtonRow
|
|
23
25
|
|
|
24
26
|
/**
|
|
25
27
|
* The top bar of a stack: one per stack, showing what its screen on top sets. Top to bottom: the strip under the status
|
|
@@ -47,7 +49,7 @@ class TopBar(context: Context) : FrameLayout(themed(context)) {
|
|
|
47
49
|
private val largeTitleHolder = FrameLayout(this.context)
|
|
48
50
|
private val searchHolder = FrameLayout(this.context)
|
|
49
51
|
private val border = View(this.context)
|
|
50
|
-
private val snapshot =
|
|
52
|
+
private val snapshot = Snapshot(this.context)
|
|
51
53
|
private var searchArea: View? = null
|
|
52
54
|
private var barHeight = UiUtils.dpToPx(this.context, DEFAULT_HEIGHT_DP)
|
|
53
55
|
private var searchTakesBar = false
|
|
@@ -55,13 +57,15 @@ class TopBar(context: Context) : FrameLayout(themed(context)) {
|
|
|
55
57
|
private var heightChanged = false
|
|
56
58
|
// How far the large title is collapsed, in pixels.
|
|
57
59
|
private var largeTitleShift = 0
|
|
60
|
+
// `topBar.elevation`, in pixels: the bar's elevation unless it is flat.
|
|
61
|
+
private var shadow = 0f
|
|
58
62
|
|
|
59
|
-
/** The
|
|
60
|
-
val rightButtonBar:
|
|
63
|
+
/** The right buttons, the search's magnifier and "⋮". */
|
|
64
|
+
val rightButtonBar: ButtonRow
|
|
61
65
|
get() = titleBar.rightButtonBar
|
|
62
66
|
|
|
63
|
-
/** The
|
|
64
|
-
val leftButtonBar:
|
|
67
|
+
/** The back button and the left buttons. */
|
|
68
|
+
val leftButtonBar: ButtonRow
|
|
65
69
|
get() = titleBar.leftButtonBar
|
|
66
70
|
|
|
67
71
|
/** The strip under the status bar at the top of the bar, in pixels: the bar is under the status bar. */
|
|
@@ -187,14 +191,27 @@ class TopBar(context: Context) : FrameLayout(themed(context)) {
|
|
|
187
191
|
* The shadow of `topBar.elevation`, in pixels: its colors are black (Android 9 and later read them), none at 0.
|
|
188
192
|
*/
|
|
189
193
|
fun setShadow(elevation: Float) {
|
|
190
|
-
if (
|
|
191
|
-
|
|
194
|
+
if (shadow == elevation) return
|
|
195
|
+
shadow = elevation
|
|
196
|
+
if (!isFlat) this.elevation = elevation
|
|
192
197
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
193
198
|
outlineAmbientShadowColor = Color.BLACK
|
|
194
199
|
outlineSpotShadowColor = Color.BLACK
|
|
195
200
|
}
|
|
196
201
|
}
|
|
197
202
|
|
|
203
|
+
/**
|
|
204
|
+
* The bar draws without its shadow, at the level of the screens, in a transition that draws it with a screen: a
|
|
205
|
+
* screen drawn after it covers it, and an alpha layer around it fades it (with an elevation the renderer would draw
|
|
206
|
+
* the bar over every screen and out of the layer).
|
|
207
|
+
*/
|
|
208
|
+
var isFlat = false
|
|
209
|
+
set(value) {
|
|
210
|
+
if (field == value) return
|
|
211
|
+
field = value
|
|
212
|
+
elevation = if (value) 0f else shadow
|
|
213
|
+
}
|
|
214
|
+
|
|
198
215
|
/** The line under the bar: [height] pixels of [color]. */
|
|
199
216
|
fun setBorder(color: Int, height: Int) {
|
|
200
217
|
border.setBackgroundColor(color)
|
|
@@ -290,32 +307,27 @@ class TopBar(context: Context) : FrameLayout(themed(context)) {
|
|
|
290
307
|
layoutParams = params
|
|
291
308
|
}
|
|
292
309
|
|
|
293
|
-
// The row's picture in a transition.
|
|
310
|
+
// The row's picture in a transition: the drawing commands of the row as it is, not its pixels. Nothing as large
|
|
311
|
+
// as the bar is allocated or filled in on the main thread, and the renderer plays the commands each frame.
|
|
294
312
|
|
|
295
313
|
/**
|
|
296
|
-
* Lays a picture of the row and the large title over them, laid out at once; false when the bar can't be
|
|
297
|
-
*
|
|
314
|
+
* Lays a picture of the row and the large title over them, laid out at once; false when the bar can't be recorded:
|
|
315
|
+
* no picture then.
|
|
298
316
|
*/
|
|
299
317
|
fun takeRowSnapshot(withLargeTitle: Boolean = true): Boolean {
|
|
300
318
|
val width = rowArea.width
|
|
301
319
|
val large = withLargeTitle && isLargeTitleShown
|
|
302
320
|
val height = rowArea.height + if (large) largeTitleHolder.height else 0
|
|
303
321
|
if (width <= 0 || height <= 0) return false
|
|
304
|
-
val picture =
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
rowArea.
|
|
308
|
-
|
|
309
|
-
canvas.translate(0f, rowArea.height.toFloat())
|
|
310
|
-
largeTitleHolder.draw(canvas)
|
|
311
|
-
}
|
|
322
|
+
val picture = record(width, height) { canvas ->
|
|
323
|
+
rowArea.draw(canvas)
|
|
324
|
+
if (large) {
|
|
325
|
+
canvas.translate(0f, rowArea.height.toFloat())
|
|
326
|
+
largeTitleHolder.draw(canvas)
|
|
312
327
|
}
|
|
313
|
-
}
|
|
314
|
-
// A HARDWARE bitmap in the bar: it can't be drawn on a software canvas.
|
|
315
|
-
return false
|
|
316
|
-
}
|
|
328
|
+
} ?: return false
|
|
317
329
|
val top = content.top + rowArea.top
|
|
318
|
-
snapshot.
|
|
330
|
+
snapshot.setImageDrawable(PictureDrawable(picture))
|
|
319
331
|
snapshot.alpha = 1f
|
|
320
332
|
snapshot.translationX = 0f
|
|
321
333
|
snapshot.translationY = rowArea.translationY
|
|
@@ -333,22 +345,43 @@ class TopBar(context: Context) : FrameLayout(themed(context)) {
|
|
|
333
345
|
|
|
334
346
|
/**
|
|
335
347
|
* A picture of the bar under its row — the background, the large title, the search, the line — and where it starts
|
|
336
|
-
* in the bar, for a push to a screen without a large title; none when the bar can't be
|
|
348
|
+
* in the bar, for a push to a screen without a large title; none when the bar can't be recorded. Its intrinsic
|
|
349
|
+
* size is its size; it draws at the top left of its bounds.
|
|
337
350
|
*/
|
|
338
|
-
fun pictureUnderRow(): Pair<
|
|
339
|
-
|
|
351
|
+
fun pictureUnderRow(): Pair<PictureDrawable, Int>? = pictureFrom(content.top + rowArea.bottom)
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* A picture of the whole bar, for the screen it leaves with in a transition of the stack's own; none when the bar
|
|
355
|
+
* can't be recorded.
|
|
356
|
+
*/
|
|
357
|
+
fun picture(): PictureDrawable? = pictureFrom(0)?.first
|
|
358
|
+
|
|
359
|
+
private fun pictureFrom(top: Int): Pair<PictureDrawable, Int>? {
|
|
340
360
|
val width = width
|
|
341
361
|
val height = height - top
|
|
342
362
|
if (width <= 0 || height <= 0) return null
|
|
343
|
-
|
|
344
|
-
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
|
345
|
-
val canvas = Canvas(bitmap)
|
|
363
|
+
val picture = record(width, height) { canvas ->
|
|
346
364
|
canvas.translate(0f, -top.toFloat())
|
|
347
365
|
draw(canvas)
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
366
|
+
} ?: return null
|
|
367
|
+
return PictureDrawable(picture) to top
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// The commands [draw] gives, cut to [width] × [height]. A hardware bitmap in the bar is kept as it is from Android
|
|
371
|
+
// 9 on (the picture then plays only on the screen's hardware canvas, where the bar's pictures are drawn); Android 8
|
|
372
|
+
// can't record one, and there is no picture then.
|
|
373
|
+
private fun record(width: Int, height: Int, draw: (Canvas) -> Unit): Picture? = try {
|
|
374
|
+
Picture().also {
|
|
375
|
+
val canvas = it.beginRecording(width, height)
|
|
376
|
+
try {
|
|
377
|
+
canvas.clipRect(0, 0, width, height)
|
|
378
|
+
draw(canvas)
|
|
379
|
+
} finally {
|
|
380
|
+
it.endRecording()
|
|
381
|
+
}
|
|
351
382
|
}
|
|
383
|
+
} catch (e: IllegalArgumentException) {
|
|
384
|
+
null
|
|
352
385
|
}
|
|
353
386
|
|
|
354
387
|
/** The row's picture goes. */
|
|
@@ -388,6 +421,12 @@ class TopBar(context: Context) : FrameLayout(themed(context)) {
|
|
|
388
421
|
heightChanged = true
|
|
389
422
|
}
|
|
390
423
|
|
|
424
|
+
// The row's picture: it fades as one image. Its commands overlap (a button's background under its icon), and drawn
|
|
425
|
+
// one by one at the view's opacity each would show through the next.
|
|
426
|
+
private class Snapshot(context: Context) : AppCompatImageView(context) {
|
|
427
|
+
override fun hasOverlappingRendering(): Boolean = true
|
|
428
|
+
}
|
|
429
|
+
|
|
391
430
|
// The area of the row: it takes the touches without passing them on while the row is transparent.
|
|
392
431
|
private class RowArea(context: Context) : FrameLayout(context) {
|
|
393
432
|
var blocksTouches = false
|
|
@@ -8,12 +8,12 @@ import dev.apexnative.navigation.utils.UiUtils
|
|
|
8
8
|
import kotlin.math.max
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* The cell of a React button in the bar (`topBar.leftButtons[].component`)
|
|
12
|
-
*
|
|
13
|
-
* React root, or later a view of the screen's own tree) measures `AT_MOST` — the width at most what the row
|
|
14
|
-
* height at most the row's — or exactly its `component.width` / `component.height` when the options give
|
|
15
|
-
* ([contentWidth], [contentHeight], pixels). The cell takes the
|
|
16
|
-
* rejects a root with an id). It never looks inside the content.
|
|
11
|
+
* The cell of a React button in the bar (`topBar.leftButtons[].component`), in the row of its side as an icon button
|
|
12
|
+
* stands there: 12 dp on each side, at least 48 dp wide, as high as the row gives, the content in its middle. The
|
|
13
|
+
* content (a React root, or later a view of the screen's own tree) measures `AT_MOST` — the width at most what the row
|
|
14
|
+
* gives, the height at most the row's — or exactly its `component.width` / `component.height` when the options give
|
|
15
|
+
* them ([contentWidth], [contentHeight], pixels). The cell takes the button's `testID`; the content never gets one
|
|
16
|
+
* (React Native rejects a root with an id). It never looks inside the content.
|
|
17
17
|
*/
|
|
18
18
|
@SuppressLint("ViewConstructor")
|
|
19
19
|
internal class BarButtonComponentCell(context: Context) : ViewGroup(context) {
|
package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonView.kt
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
package dev.apexnative.navigation.views.stack.topbar.titlebar
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.content.res.TypedArray
|
|
6
|
+
import android.graphics.drawable.Drawable
|
|
7
|
+
import android.view.Gravity
|
|
8
|
+
import android.widget.Button
|
|
9
|
+
import androidx.appcompat.R as AppCompatR
|
|
10
|
+
import androidx.appcompat.widget.AppCompatTextView
|
|
11
|
+
import androidx.appcompat.widget.TooltipCompat
|
|
12
|
+
import androidx.core.widget.TextViewCompat
|
|
13
|
+
import dev.apexnative.navigation.utils.UiUtils
|
|
14
|
+
import kotlin.math.roundToInt
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A button of the bar with an icon or a text, drawn as a toolbar draws the items of its menu: the theme's
|
|
18
|
+
* `actionButtonStyle` (48 dp at least, 12 dp at the sides, the bar's ripple), its `actionMenuTextAppearance` and
|
|
19
|
+
* `actionMenuTextColor`, the icon at most 32 dp and in the middle. With an icon the text doesn't show; it labels the
|
|
20
|
+
* button for accessibility and is its tooltip instead, unless the button has a label of its own. Main thread only.
|
|
21
|
+
*/
|
|
22
|
+
@SuppressLint("ViewConstructor")
|
|
23
|
+
internal class BarButtonView(context: Context) :
|
|
24
|
+
AppCompatTextView(context, null, AppCompatR.attr.actionButtonStyle) {
|
|
25
|
+
private val minimumWidth = minWidth
|
|
26
|
+
private val maxIconSize = UiUtils.dpToPx(context, MAX_ICON_DP).roundToInt()
|
|
27
|
+
private val sidePadding = UiUtils.dpToPx(context, SIDE_DP).roundToInt()
|
|
28
|
+
private var icon: Drawable? = null
|
|
29
|
+
|
|
30
|
+
init {
|
|
31
|
+
gravity = Gravity.CENTER
|
|
32
|
+
isFocusable = true
|
|
33
|
+
val vertical = UiUtils.dpToPx(context, VERTICAL_DP).roundToInt()
|
|
34
|
+
setPaddingRelative(sidePadding, vertical, sidePadding, vertical)
|
|
35
|
+
restyle()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** The text appearance and color of the theme as it is now: a light/dark switch changes them. */
|
|
39
|
+
fun restyle() {
|
|
40
|
+
themed(AppCompatR.attr.actionMenuTextAppearance) { getResourceId(0, 0) }
|
|
41
|
+
.takeIf { it != 0 }
|
|
42
|
+
?.let { TextViewCompat.setTextAppearance(this, it) }
|
|
43
|
+
themed(AppCompatR.attr.actionMenuTextColor) { getColorStateList(0) }?.let(::setTextColor)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private fun <T> themed(attr: Int, read: TypedArray.() -> T): T {
|
|
47
|
+
val values = context.obtainStyledAttributes(intArrayOf(attr))
|
|
48
|
+
return try {
|
|
49
|
+
values.read()
|
|
50
|
+
} finally {
|
|
51
|
+
values.recycle()
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* What the button shows: [icon], or [title] without one. [label] is its accessibility label, else the title when
|
|
57
|
+
* only the icon shows; that title is its tooltip too. [tooltip] false leaves the long press to the caller.
|
|
58
|
+
*/
|
|
59
|
+
fun show(title: CharSequence, icon: Drawable?, label: CharSequence?, tooltip: Boolean) {
|
|
60
|
+
this.icon = icon?.also { fit(it) }
|
|
61
|
+
setCompoundDrawablesRelative(icon, null, null, null)
|
|
62
|
+
text = if (icon == null) title else null
|
|
63
|
+
val hidden = title.takeIf { icon != null && it.isNotEmpty() }
|
|
64
|
+
contentDescription = label?.takeIf { it.isNotEmpty() } ?: hidden
|
|
65
|
+
TooltipCompat.setTooltipText(this, if (tooltip) hidden else null)
|
|
66
|
+
requestLayout()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// TalkBack and UI tests see a button, as they see a toolbar's item.
|
|
70
|
+
override fun getAccessibilityClassName(): CharSequence = Button::class.java.name
|
|
71
|
+
|
|
72
|
+
// An icon larger than the bar's item takes keeps its shape at 32 dp.
|
|
73
|
+
private fun fit(icon: Drawable) {
|
|
74
|
+
var width = icon.intrinsicWidth.coerceAtLeast(0)
|
|
75
|
+
var height = icon.intrinsicHeight.coerceAtLeast(0)
|
|
76
|
+
if (width > maxIconSize) {
|
|
77
|
+
height = (height * maxIconSize.toFloat() / width).roundToInt()
|
|
78
|
+
width = maxIconSize
|
|
79
|
+
}
|
|
80
|
+
if (height > maxIconSize) {
|
|
81
|
+
width = (width * maxIconSize.toFloat() / height).roundToInt()
|
|
82
|
+
height = maxIconSize
|
|
83
|
+
}
|
|
84
|
+
icon.setBounds(0, 0, width, height)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
|
88
|
+
val centered = icon?.takeIf { text.isNullOrEmpty() }
|
|
89
|
+
if (centered == null) setPaddingRelative(sidePadding, paddingTop, sidePadding, paddingBottom)
|
|
90
|
+
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
|
91
|
+
// At least the theme's width, within what the row gives.
|
|
92
|
+
val mode = MeasureSpec.getMode(widthMeasureSpec)
|
|
93
|
+
val target = if (mode == MeasureSpec.AT_MOST) {
|
|
94
|
+
minOf(MeasureSpec.getSize(widthMeasureSpec), minimumWidth)
|
|
95
|
+
} else {
|
|
96
|
+
minimumWidth
|
|
97
|
+
}
|
|
98
|
+
if (mode != MeasureSpec.EXACTLY && minimumWidth > 0 && measuredWidth < target) {
|
|
99
|
+
super.onMeasure(MeasureSpec.makeMeasureSpec(target, MeasureSpec.EXACTLY), heightMeasureSpec)
|
|
100
|
+
}
|
|
101
|
+
// The icon alone stands in the middle of the button.
|
|
102
|
+
if (centered != null) {
|
|
103
|
+
val start = (measuredWidth - centered.bounds.width()) / 2
|
|
104
|
+
setPaddingRelative(start, paddingTop, paddingEnd, paddingBottom)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private companion object {
|
|
109
|
+
const val MAX_ICON_DP = 32f
|
|
110
|
+
const val SIDE_DP = 12f
|
|
111
|
+
const val VERTICAL_DP = 4f
|
|
112
|
+
}
|
|
113
|
+
}
|