react-native-screens 5.0.0-alpha.2 → 5.0.0-alpha.3
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/Package.swift +87 -0
- package/README.md +0 -7
- package/android/src/main/cpp/NativeProxy.cpp +30 -6
- package/android/src/main/cpp/NativeProxy.h +7 -1
- package/android/src/main/java/com/swmansion/rnscreens/common/container/Container.kt +8 -0
- package/android/src/main/java/com/swmansion/rnscreens/common/container/ContainerItem.kt +13 -1
- package/android/src/main/java/com/swmansion/rnscreens/common/text/ReactTextAppearance.kt +62 -0
- package/android/src/main/java/com/swmansion/rnscreens/common/text/TextAppearance.kt +20 -0
- package/android/src/main/java/com/swmansion/rnscreens/common/text/TextAppearanceDefaults.kt +65 -0
- package/android/src/main/java/com/swmansion/rnscreens/helpers/PropIconResolver.kt +17 -23
- package/android/src/main/java/com/swmansion/rnscreens/legacy/Screen.kt +3 -1
- package/android/src/main/java/com/swmansion/rnscreens/legacy/ScreenStack.kt +2 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetBehaviorController.kt +49 -18
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetDimensionsCoordinator.kt +65 -40
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetKeyboardCoordinator.kt +101 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetNativeDismissCoordinator.kt +0 -6
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/core/FormSheetAvailableHeightProvider.kt +44 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/core/FormSheetDialog.kt +35 -3
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/core/FormSheetDialogManager.kt +33 -106
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/interfaces/FormSheetDialogEventEmitter.kt +2 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/model/FormSheetDetents.kt +61 -15
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetAnimatorFactory.kt +8 -9
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetDimmingManager.kt +115 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetDismissalOrigin.kt +22 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetPresentation.kt +173 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetPresentationManager.kt +141 -49
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetPresentationState.kt +1 -1
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetStackRegistry.kt +28 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/react/event/FormSheetDismissEvent.kt +29 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/react/host/FormSheetHostEventEmitter.kt +7 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/react/host/FormSheetHostViewManager.kt +2 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderApplicator.kt +369 -58
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderBackPressHandler.kt +11 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderCoordinatorLayout.kt +143 -98
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/appbar/StackHeaderAppBarLayout.kt +155 -23
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/appbar/StackHeaderContentScrimDrawable.kt +36 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderCollapsedTitleGravityMode.kt +6 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfig.kt +170 -167
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigViewManager.kt +385 -12
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigurationObserver.kt +0 -4
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigurationProviding.kt +32 -3
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderDelegate.kt +0 -7
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderInvalidationFlags.kt +7 -2
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuApplicator.kt +27 -280
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuController.kt +448 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuDelegate.kt +10 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuMapper.kt +28 -20
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuConfig.kt +3 -55
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuGroupMetadata.kt +1 -10
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuItemConfig.kt +1 -3
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuModel.kt +180 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementOptions.kt +57 -6
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementRawUpdate.kt +3 -1
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementUpdate.kt +1 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuIconResolver.kt +4 -3
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuUpdateQueue.kt +23 -9
- package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackContainer.kt +103 -3
- package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackHost.kt +13 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackHostViewManager.kt +14 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreen.kt +4 -0
- package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreenFragment.kt +20 -1
- package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreenFragmentDelegate.kt +12 -0
- package/android/src/main/java/com/swmansion/rnscreens/tabs/appearance/TabsAppearanceCoordinator.kt +2 -4
- package/android/src/main/java/com/swmansion/rnscreens/tabs/container/MenuHelpers.kt +5 -23
- package/android/src/main/java/com/swmansion/rnscreens/tabs/container/TabsContainer.kt +46 -25
- package/android/src/main/java/com/swmansion/rnscreens/tabs/host/TabsHost.kt +10 -0
- package/android/src/main/java/com/swmansion/rnscreens/tabs/host/TabsHostA11yCoordinator.kt +23 -2
- package/android/src/main/java/com/swmansion/rnscreens/tabs/screen/TabsScreen.kt +17 -0
- package/android/src/main/java/com/swmansion/rnscreens/tabs/screen/TabsScreenFragment.kt +3 -0
- package/android/src/main/java/com/swmansion/rnscreens/utils/DimensionUtils.kt +7 -0
- package/android/src/main/java/com/swmansion/rnscreens/utils/StyleUtils.kt +22 -0
- package/android/src/main/res/base/layout/rns_collapsing_toolbar_large_available_space.xml +8 -0
- package/android/src/main/res/base/layout/rns_collapsing_toolbar_large_entire_space.xml +8 -0
- package/android/src/main/res/base/layout/rns_collapsing_toolbar_medium_available_space.xml +8 -0
- package/android/src/main/res/base/layout/rns_collapsing_toolbar_medium_entire_space.xml +8 -0
- package/cpp/legacy/RNSScreenRemovalListener.cpp +31 -1
- package/cpp/legacy/RNSScreenRemovalListener.h +18 -3
- package/ios/RNSEnums.h +2 -0
- package/ios/conversion/RNSConversions.h +7 -108
- package/ios/legacy/RNSFullWindowOverlay.mm +1 -1
- package/ios/legacy/RNSModalScreen.mm +1 -1
- package/ios/legacy/RNSScreen.mm +8 -19
- package/ios/legacy/RNSScreenStackHeaderConfig.mm +3 -1
- package/ios/legacy/RNSScreenStackHeaderSubview.mm +1 -1
- package/ios/legacy/RNSScreenWindowTraits.mm +5 -13
- package/ios/modals/form-sheet/RNSFormSheetConfigurationApplicator.h +1 -3
- package/ios/modals/form-sheet/RNSFormSheetConfigurationApplicator.mm +11 -22
- package/ios/modals/form-sheet/RNSFormSheetContentController.h +1 -1
- package/ios/modals/form-sheet/RNSFormSheetContentController.mm +7 -18
- package/ios/modals/form-sheet/RNSFormSheetHostComponentView.mm +4 -4
- package/ios/modals/form-sheet/RNSFormSheetHostShadowStateProxy.mm +2 -2
- package/ios/modals/form-sheet/RNSFormSheetUpdateFlags.h +3 -0
- package/ios/safe-area/RNSSafeAreaViewComponentView.mm +2 -2
- package/ios/{conversion → scroll-view-marker/conversion}/RNSConversions-ScrollViewMarker.mm +2 -3
- package/ios/split/RNSSplitAppearanceApplicator.h +4 -4
- package/ios/split/RNSSplitAppearanceApplicator.mm +53 -56
- package/ios/split/RNSSplitHostComponentEventEmitter.h +1 -0
- package/ios/split/RNSSplitHostComponentEventEmitter.mm +1 -1
- package/ios/split/RNSSplitHostComponentView.h +5 -15
- package/ios/split/RNSSplitHostComponentView.mm +55 -6
- package/ios/split/RNSSplitHostController.h +25 -6
- package/ios/split/RNSSplitHostController.mm +24 -92
- package/ios/split/RNSSplitHostProviders.h +67 -0
- package/ios/split/RNSSplitScreenComponentView.h +0 -39
- package/ios/split/RNSSplitScreenComponentView.mm +27 -10
- package/ios/split/RNSSplitScreenController.h +26 -3
- package/ios/split/RNSSplitScreenController.mm +13 -30
- package/ios/split/RNSSplitScreenShadowStateProxy.h +1 -40
- package/ios/split/RNSSplitScreenShadowStateProxy.mm +1 -26
- package/ios/split/conversion/RNSConversions-SplitView.h +56 -0
- package/ios/{conversion → split/conversion}/RNSConversions-SplitView.mm +4 -1
- package/ios/stack/conversion/RNSConversions-Stack.h +32 -0
- package/ios/stack/conversion/RNSConversions-Stack.mm +55 -0
- package/ios/stack/header/RNSStackHeaderAppearanceMapper.h +26 -0
- package/ios/stack/header/RNSStackHeaderAppearanceMapper.mm +88 -0
- package/ios/stack/header/RNSStackHeaderConfigComponentView.h +10 -1
- package/ios/stack/header/RNSStackHeaderConfigComponentView.mm +67 -35
- package/ios/stack/header/RNSStackHeaderConfigDataProviding.h +6 -0
- package/ios/stack/header/RNSStackHeaderConfigShadowStateProxy.mm +1 -1
- package/ios/stack/header/RNSStackHeaderIconResolver.mm +7 -0
- package/ios/stack/header/RNSStackHeaderItemComponentView.h +3 -1
- package/ios/stack/header/RNSStackHeaderItemComponentView.mm +15 -2
- package/ios/stack/header/RNSStackHeaderItemDataProviding.h +2 -0
- package/ios/stack/header/RNSStackHeaderItemShadowStateProxy.mm +1 -1
- package/ios/stack/header/RNSStackHeaderItemSpacerComponentView.mm +2 -1
- package/ios/stack/header/RNSStackHeaderMenuMapper.mm +4 -0
- package/ios/stack/host/RNSStackNavigationBar.h +25 -0
- package/ios/stack/host/RNSStackNavigationBar.mm +80 -0
- package/ios/stack/host/RNSStackNavigationBarCoordinator.h +8 -0
- package/ios/stack/host/RNSStackNavigationBarCoordinator.mm +11 -0
- package/ios/stack/host/RNSStackNavigationController.mm +13 -5
- package/ios/stack/host/RNSStackOperation.h +0 -2
- package/ios/stack/screen/RNSStackScreenComponentView.mm +9 -2
- package/ios/stack/screen/RNSStackScreenController.mm +12 -0
- package/ios/stack/screen/RNSStackScreenHeaderCoordinator.h +8 -0
- package/ios/stack/screen/RNSStackScreenHeaderCoordinator.mm +98 -16
- package/ios/tabs/RNSTabBarAppearanceCoordinator.mm +40 -9
- package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.h +1 -1
- package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.mm +1 -1
- package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryContentComponentView.mm +1 -1
- package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryEventEmitter.mm +1 -1
- package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryShadowStateProxy.mm +1 -1
- package/ios/tabs/conversion/RNSConversions-Tabs.h +78 -0
- package/ios/{conversion → tabs/conversion}/RNSConversions-Tabs.mm +8 -71
- package/ios/tabs/extensions/RNSTabsHostComponentView+RNSImageLoader.h +1 -1
- package/ios/tabs/host/RNSTabsHostComponentView.h +2 -0
- package/ios/tabs/host/RNSTabsHostComponentView.mm +10 -3
- package/ios/tabs/host/RNSTabsHostEventEmitter.mm +1 -1
- package/ios/tabs/screen/RNSTabsScreenComponentView.mm +20 -5
- package/ios/utils/RNSDefines.h +3 -0
- package/lib/commonjs/components/stack/header/StackHeaderConfig.android.js +34 -19
- package/lib/commonjs/components/stack/header/StackHeaderConfig.android.js.map +1 -1
- package/lib/commonjs/components/stack/header/StackHeaderConfig.ios.js +33 -1
- package/lib/commonjs/components/stack/header/StackHeaderConfig.ios.js.map +1 -1
- package/lib/commonjs/components/stack/host/StackHost.js +9 -6
- package/lib/commonjs/components/stack/host/StackHost.js.map +1 -1
- package/lib/commonjs/components/stack/index.js.map +1 -1
- package/lib/commonjs/components/tabs/host/TabsHost.ios.js +1 -0
- package/lib/commonjs/components/tabs/host/TabsHost.ios.js.map +1 -1
- package/lib/commonjs/fabric/stack/StackHeaderConfigAndroidNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/stack/StackHeaderConfigIOSNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/stack/StackHeaderItemIOSNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/stack/StackHostNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/tabs/TabsHostIOSNativeComponent.js.map +1 -1
- package/lib/module/components/stack/header/StackHeaderConfig.android.js +35 -20
- package/lib/module/components/stack/header/StackHeaderConfig.android.js.map +1 -1
- package/lib/module/components/stack/header/StackHeaderConfig.ios.js +34 -2
- package/lib/module/components/stack/header/StackHeaderConfig.ios.js.map +1 -1
- package/lib/module/components/stack/host/StackHost.js +9 -6
- package/lib/module/components/stack/host/StackHost.js.map +1 -1
- package/lib/module/components/stack/index.js.map +1 -1
- package/lib/module/components/tabs/host/TabsHost.ios.js +1 -0
- package/lib/module/components/tabs/host/TabsHost.ios.js.map +1 -1
- package/lib/module/fabric/stack/StackHeaderConfigAndroidNativeComponent.js.map +1 -1
- package/lib/module/fabric/stack/StackHeaderConfigIOSNativeComponent.js.map +1 -1
- package/lib/module/fabric/stack/StackHeaderItemIOSNativeComponent.js.map +1 -1
- package/lib/module/fabric/stack/StackHostNativeComponent.js.map +1 -1
- package/lib/module/fabric/tabs/TabsHostIOSNativeComponent.js.map +1 -1
- package/lib/typescript/components/modals/form-sheet/FormSheet.types.d.ts +1 -1
- package/lib/typescript/components/stack/header/StackHeaderConfig.android.d.ts.map +1 -1
- package/lib/typescript/components/stack/header/StackHeaderConfig.android.types.d.ts +616 -21
- package/lib/typescript/components/stack/header/StackHeaderConfig.android.types.d.ts.map +1 -1
- package/lib/typescript/components/stack/header/StackHeaderConfig.ios.d.ts.map +1 -1
- package/lib/typescript/components/stack/header/StackHeaderConfig.ios.types.d.ts +226 -2
- package/lib/typescript/components/stack/header/StackHeaderConfig.ios.types.d.ts.map +1 -1
- package/lib/typescript/components/stack/header/StackHeaderConfig.types.d.ts +2 -2
- package/lib/typescript/components/stack/header/ios/StackHeaderItem.ios.types.d.ts +2 -0
- package/lib/typescript/components/stack/header/ios/StackHeaderItem.ios.types.d.ts.map +1 -1
- package/lib/typescript/components/stack/host/StackHost.d.ts +1 -1
- package/lib/typescript/components/stack/host/StackHost.d.ts.map +1 -1
- package/lib/typescript/components/stack/host/StackHost.types.d.ts +24 -0
- package/lib/typescript/components/stack/host/StackHost.types.d.ts.map +1 -1
- package/lib/typescript/components/stack/index.d.ts +2 -2
- package/lib/typescript/components/stack/index.d.ts.map +1 -1
- package/lib/typescript/components/tabs/host/TabsHost.ios.d.ts.map +1 -1
- package/lib/typescript/components/tabs/host/TabsHost.ios.types.d.ts +16 -0
- package/lib/typescript/components/tabs/host/TabsHost.ios.types.d.ts.map +1 -1
- package/lib/typescript/components/tabs/host/TabsHost.types.d.ts +3 -0
- package/lib/typescript/components/tabs/host/TabsHost.types.d.ts.map +1 -1
- package/lib/typescript/fabric/stack/StackHeaderConfigAndroidNativeComponent.d.ts +52 -0
- package/lib/typescript/fabric/stack/StackHeaderConfigAndroidNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/stack/StackHeaderConfigIOSNativeComponent.d.ts +25 -1
- package/lib/typescript/fabric/stack/StackHeaderConfigIOSNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/stack/StackHeaderItemIOSNativeComponent.d.ts +2 -0
- package/lib/typescript/fabric/stack/StackHeaderItemIOSNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/stack/StackHostNativeComponent.d.ts +3 -1
- package/lib/typescript/fabric/stack/StackHostNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/tabs/TabsHostIOSNativeComponent.d.ts +1 -0
- package/lib/typescript/fabric/tabs/TabsHostIOSNativeComponent.d.ts.map +1 -1
- package/package.json +8 -7
- package/react-native.config.js +3 -0
- package/src/components/modals/form-sheet/FormSheet.types.ts +1 -1
- package/src/components/stack/header/StackHeaderConfig.android.tsx +48 -23
- package/src/components/stack/header/StackHeaderConfig.android.types.ts +637 -21
- package/src/components/stack/header/StackHeaderConfig.ios.tsx +45 -1
- package/src/components/stack/header/StackHeaderConfig.ios.types.ts +238 -2
- package/src/components/stack/header/StackHeaderConfig.types.ts +2 -2
- package/src/components/stack/header/ios/StackHeaderItem.ios.types.ts +2 -0
- package/src/components/stack/host/StackHost.tsx +4 -2
- package/src/components/stack/host/StackHost.types.ts +26 -0
- package/src/components/stack/index.ts +6 -1
- package/src/components/tabs/host/TabsHost.ios.tsx +1 -0
- package/src/components/tabs/host/TabsHost.ios.types.ts +16 -0
- package/src/components/tabs/host/TabsHost.types.ts +3 -0
- package/src/fabric/stack/StackHeaderConfigAndroidNativeComponent.ts +78 -0
- package/src/fabric/stack/StackHeaderConfigIOSNativeComponent.ts +32 -0
- package/src/fabric/stack/StackHeaderItemIOSNativeComponent.ts +2 -0
- package/src/fabric/stack/StackHostNativeComponent.ts +11 -2
- package/src/fabric/tabs/TabsHostIOSNativeComponent.ts +1 -0
- package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingView.kt +0 -83
- package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingViewManager.kt +0 -89
- package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingViewPointerEvents.kt +0 -18
- package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuSelectionController.kt +0 -83
- package/ios/conversion/RNSConversions-Stack.h +0 -32
- package/ios/conversion/RNSConversions-Stack.mm +0 -41
- package/ios/conversion/always_false.h +0 -31
- /package/ios/{conversion → scroll-view-marker/conversion}/RNSConversions-ScrollViewMarker.h +0 -0
|
@@ -4,63 +4,56 @@ import android.view.ViewGroup
|
|
|
4
4
|
import android.widget.FrameLayout
|
|
5
5
|
import androidx.core.view.ViewCompat
|
|
6
6
|
import androidx.core.view.WindowInsetsCompat
|
|
7
|
-
import
|
|
8
|
-
import com.google.android.material.bottomsheet.BottomSheetDialog
|
|
7
|
+
import com.swmansion.rnscreens.modals.formsheet.native.core.FormSheetAvailableHeightProvider
|
|
9
8
|
import com.swmansion.rnscreens.modals.formsheet.native.core.FormSheetContainer
|
|
9
|
+
import com.swmansion.rnscreens.modals.formsheet.native.core.FormSheetDialog
|
|
10
10
|
import com.swmansion.rnscreens.modals.formsheet.native.interfaces.FormSheetContentSizeChangeDelegate
|
|
11
11
|
import com.swmansion.rnscreens.modals.formsheet.native.model.FormSheetDetents
|
|
12
12
|
|
|
13
13
|
internal class FormSheetDimensionsCoordinator(
|
|
14
|
-
private val dialog:
|
|
14
|
+
private val dialog: FormSheetDialog,
|
|
15
15
|
private val container: FormSheetContainer,
|
|
16
|
-
private val bottomSheetView: FrameLayout?,
|
|
17
16
|
private val behaviorController: FormSheetBehaviorController?,
|
|
18
|
-
) : FormSheetContentSizeChangeDelegate
|
|
17
|
+
) : FormSheetContentSizeChangeDelegate,
|
|
18
|
+
FormSheetAvailableHeightProvider.OnAvailableHeightMeasuredListener {
|
|
19
19
|
private var lastTopInset = 0
|
|
20
20
|
private var lastBottomInset = 0
|
|
21
|
+
private var lastImeInset = 0
|
|
21
22
|
private var currentDetents: FormSheetDetents? = null
|
|
22
23
|
private var currentInitialDetentIndex: Int = 0
|
|
23
24
|
private var shouldApplyInitialDetent: Boolean = false
|
|
24
25
|
|
|
25
26
|
private var currentContentHeight: Int = 0
|
|
26
27
|
|
|
28
|
+
// Height the metrics were last resolved against. Any other value reported by the measure pass
|
|
29
|
+
// means the window has been resized and metrics have to be recomputed.
|
|
30
|
+
private var resolvedAvailableSpace: Int = 0
|
|
31
|
+
private var isGeometryDirty: Boolean = false
|
|
32
|
+
|
|
27
33
|
internal fun setup() {
|
|
34
|
+
dialog.availableHeightProvider.availableHeightListener = this
|
|
28
35
|
setupWindowInsetsListener()
|
|
29
|
-
|
|
30
|
-
bottomSheetView?.let { view ->
|
|
31
|
-
disableMaterialInsetsAnimationCallback(view)
|
|
32
|
-
}
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
private fun setupWindowInsetsListener() {
|
|
36
39
|
ViewCompat.setOnApplyWindowInsetsListener(container) { _, insets ->
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
val topInset = getTopInset(insets)
|
|
41
|
+
val bottomInset = getBottomInset(insets)
|
|
42
|
+
val imeInset = getImeInset(insets)
|
|
43
|
+
if (topInset != lastTopInset || bottomInset != lastBottomInset || imeInset != lastImeInset) {
|
|
44
|
+
lastTopInset = topInset
|
|
45
|
+
lastBottomInset = bottomInset
|
|
46
|
+
lastImeInset = imeInset
|
|
47
|
+
invalidateGeometry()
|
|
48
|
+
}
|
|
40
49
|
insets
|
|
41
50
|
}
|
|
42
51
|
}
|
|
43
52
|
|
|
44
|
-
/**
|
|
45
|
-
* BottomSheetBehavior registers an internal `WindowInsetsAnimationCallback` on the
|
|
46
|
-
* sheet view during its first `onLayoutChild`. That callback drives `translationY` to follow
|
|
47
|
-
* animated inset changes, what interferes with our slide-in custom animation.
|
|
48
|
-
*
|
|
49
|
-
* We manage insets ourselves by setting a fixed height for FormSheetContainer, so we can
|
|
50
|
-
* clear the Material's callback to remove the conflict entirely.
|
|
51
|
-
*
|
|
52
|
-
* This method must run after the first layout pass.
|
|
53
|
-
*/
|
|
54
|
-
private fun disableMaterialInsetsAnimationCallback(view: FrameLayout) {
|
|
55
|
-
view.doOnLayout {
|
|
56
|
-
ViewCompat.setWindowInsetsAnimationCallback(it, null)
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
53
|
override fun onContentHeightChanged(newHeight: Int) {
|
|
61
54
|
if (currentContentHeight != newHeight) {
|
|
62
55
|
currentContentHeight = newHeight
|
|
63
|
-
|
|
56
|
+
invalidateGeometry()
|
|
64
57
|
}
|
|
65
58
|
}
|
|
66
59
|
|
|
@@ -72,7 +65,25 @@ internal class FormSheetDimensionsCoordinator(
|
|
|
72
65
|
currentDetents = detents
|
|
73
66
|
currentInitialDetentIndex = initialDetentIndex
|
|
74
67
|
shouldApplyInitialDetent = applyInitialDetent
|
|
75
|
-
|
|
68
|
+
invalidateGeometry()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Schedules a measure pass; the metrics are resolved from there. The provider is a sibling of the sheet
|
|
72
|
+
// subtree, not an ancestor, so it has to be asked for a re-measure explicitly. No-op while the dialog
|
|
73
|
+
// is not shown - the first traversal after `show()` measures everything anyway.
|
|
74
|
+
private fun invalidateGeometry() {
|
|
75
|
+
isGeometryDirty = true
|
|
76
|
+
dialog.availableHeightProvider.requestLayout()
|
|
77
|
+
container.requestLayout()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
override fun onAvailableHeightMeasured(height: Int) {
|
|
81
|
+
if (!isGeometryDirty && height == resolvedAvailableSpace) {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
isGeometryDirty = false
|
|
85
|
+
resolvedAvailableSpace = height
|
|
86
|
+
resolveGeometry(height)
|
|
76
87
|
}
|
|
77
88
|
|
|
78
89
|
/**
|
|
@@ -81,20 +92,18 @@ internal class FormSheetDimensionsCoordinator(
|
|
|
81
92
|
* status bar or display cutout. This causes Yoga to recalculate the layout, resulting in UI flickering
|
|
82
93
|
* during the drag gesture. By calculating and enforcing a static height that explicitly subtracts
|
|
83
94
|
* the system insets, we completely bypass these redundant layout passes.
|
|
95
|
+
*
|
|
96
|
+
* Runs inside the measure pass of `FormSheetAvailableHeightProvider`, i.e. before Material's container, the sheet and
|
|
97
|
+
* our container are measured, so the values applied here are picked up by the very same traversal.
|
|
84
98
|
*/
|
|
85
|
-
private fun
|
|
86
|
-
val dialogDecorHeight = dialog.window?.decorView?.height ?: 0
|
|
87
|
-
|
|
88
|
-
if (dialogDecorHeight <= 0) {
|
|
89
|
-
return
|
|
90
|
-
}
|
|
91
|
-
|
|
99
|
+
private fun resolveGeometry(sheetAvailableSpace: Int) {
|
|
92
100
|
currentDetents?.let { detents ->
|
|
93
101
|
behaviorController?.updateSheetBehavior(
|
|
94
102
|
detents = detents,
|
|
95
|
-
sheetAvailableSpace =
|
|
103
|
+
sheetAvailableSpace = sheetAvailableSpace,
|
|
96
104
|
contentHeightForFitToContents = currentContentHeight,
|
|
97
105
|
nativeContainerPaddingBottom = lastBottomInset,
|
|
106
|
+
keyboardLift = keyboardLift,
|
|
98
107
|
initialDetentIndex = currentInitialDetentIndex,
|
|
99
108
|
applyInitialDetent = shouldApplyInitialDetent,
|
|
100
109
|
)
|
|
@@ -102,8 +111,13 @@ internal class FormSheetDimensionsCoordinator(
|
|
|
102
111
|
}
|
|
103
112
|
|
|
104
113
|
val sheetContainerHeight =
|
|
105
|
-
currentDetents?.sheetContainerHeight(
|
|
106
|
-
|
|
114
|
+
currentDetents?.sheetContainerHeight(
|
|
115
|
+
sheetAvailableSpace,
|
|
116
|
+
lastTopInset,
|
|
117
|
+
lastBottomInset,
|
|
118
|
+
currentContentHeight,
|
|
119
|
+
keyboardLift,
|
|
120
|
+
) ?: (sheetAvailableSpace - lastTopInset - lastBottomInset - keyboardLift).coerceAtLeast(0)
|
|
107
121
|
|
|
108
122
|
val layoutParams =
|
|
109
123
|
container.layoutParams
|
|
@@ -116,6 +130,16 @@ internal class FormSheetDimensionsCoordinator(
|
|
|
116
130
|
}
|
|
117
131
|
}
|
|
118
132
|
|
|
133
|
+
/**
|
|
134
|
+
* The part of the keyboard inset that sticks out above the bottom system inset. Material pads the sheet by
|
|
135
|
+
* the larger of the two, so this is exactly how much the sheet has to be extended to keep its detent-sized
|
|
136
|
+
* part above the keyboard.
|
|
137
|
+
*/
|
|
138
|
+
private val keyboardLift: Int
|
|
139
|
+
get() = (lastImeInset - lastBottomInset).coerceAtLeast(0)
|
|
140
|
+
|
|
141
|
+
private fun getImeInset(insetsCompat: WindowInsetsCompat): Int = insetsCompat.getInsets(WindowInsetsCompat.Type.ime()).bottom
|
|
142
|
+
|
|
119
143
|
private fun getTopInset(insetsCompat: WindowInsetsCompat): Int =
|
|
120
144
|
insetsCompat
|
|
121
145
|
.getInsets(
|
|
@@ -129,6 +153,7 @@ internal class FormSheetDimensionsCoordinator(
|
|
|
129
153
|
).bottom
|
|
130
154
|
|
|
131
155
|
internal fun destroy() {
|
|
156
|
+
dialog.availableHeightProvider.availableHeightListener = null
|
|
132
157
|
ViewCompat.setOnApplyWindowInsetsListener(container, null)
|
|
133
158
|
}
|
|
134
159
|
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
package com.swmansion.rnscreens.modals.formsheet.native.coordinator
|
|
2
|
+
|
|
3
|
+
import android.widget.FrameLayout
|
|
4
|
+
import androidx.core.view.ViewCompat
|
|
5
|
+
import androidx.core.view.WindowInsetsAnimationCompat
|
|
6
|
+
import androidx.core.view.WindowInsetsCompat
|
|
7
|
+
import androidx.core.view.doOnLayout
|
|
8
|
+
|
|
9
|
+
internal class FormSheetKeyboardCoordinator(
|
|
10
|
+
private val bottomSheetView: FrameLayout,
|
|
11
|
+
) {
|
|
12
|
+
/**
|
|
13
|
+
* Whether the sheet should track the keyboard animation. Kept `false` while an enter / exit
|
|
14
|
+
* transition owns `translationY`. Tracking the keyboard (`true`) should be allowed only when
|
|
15
|
+
* the sheet is in PRESENTED state.
|
|
16
|
+
*/
|
|
17
|
+
internal var isTrackingEnabled: Boolean = false
|
|
18
|
+
|
|
19
|
+
private val insetsAnimationCallback = KeyboardInsetsAnimationCallback()
|
|
20
|
+
|
|
21
|
+
internal fun setup() {
|
|
22
|
+
// BottomSheetBehavior registers an internal `WindowInsetsAnimationCallback` on the
|
|
23
|
+
// sheet view during its first `onLayoutChild`. That callback drives `translationY` to track
|
|
24
|
+
// animated inset changes, what interferes with our slide-in custom animation.
|
|
25
|
+
//
|
|
26
|
+
// We manage insets ourselves by setting a fixed height for FormSheetContainer, so we can
|
|
27
|
+
// clear the Material's callback to remove the conflict entirely.
|
|
28
|
+
//
|
|
29
|
+
// This method must run after the first layout pass.
|
|
30
|
+
bottomSheetView.doOnLayout {
|
|
31
|
+
ViewCompat.setWindowInsetsAnimationCallback(it, insetsAnimationCallback)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
internal fun destroy() {
|
|
36
|
+
ViewCompat.setWindowInsetsAnimationCallback(bottomSheetView, null)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private inner class KeyboardInsetsAnimationCallback : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_STOP) {
|
|
40
|
+
private var startTop = 0
|
|
41
|
+
private var startTranslationY = 0f
|
|
42
|
+
|
|
43
|
+
// Decided once per keyboard animation, in `onPrepare`. Tracking can't be picked up mid-animation
|
|
44
|
+
// because of no start position to translate from.
|
|
45
|
+
private var isTracking = false
|
|
46
|
+
|
|
47
|
+
private val isActive: Boolean
|
|
48
|
+
get() = isTracking && isTrackingEnabled
|
|
49
|
+
|
|
50
|
+
override fun onPrepare(animation: WindowInsetsAnimationCompat) {
|
|
51
|
+
if (!animation.isKeyboardAnimation() || !isTrackingEnabled) {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Saving sheet's position before applying keyboard insets.
|
|
56
|
+
startTop = bottomSheetView.top
|
|
57
|
+
isTracking = true
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
override fun onStart(
|
|
61
|
+
animation: WindowInsetsAnimationCompat,
|
|
62
|
+
bounds: WindowInsetsAnimationCompat.BoundsCompat,
|
|
63
|
+
): WindowInsetsAnimationCompat.BoundsCompat {
|
|
64
|
+
if (!animation.isKeyboardAnimation() || !isActive) {
|
|
65
|
+
return bounds
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// The end sheet position is known - move the sheet and let the animation progress
|
|
69
|
+
// bring it to the new position.
|
|
70
|
+
startTranslationY = (startTop - bottomSheetView.top).toFloat()
|
|
71
|
+
bottomSheetView.translationY = startTranslationY
|
|
72
|
+
return bounds
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
override fun onProgress(
|
|
76
|
+
insets: WindowInsetsCompat,
|
|
77
|
+
runningAnimations: List<WindowInsetsAnimationCompat>,
|
|
78
|
+
): WindowInsetsCompat {
|
|
79
|
+
if (!isActive) {
|
|
80
|
+
return insets
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
val keyboardAnimation = runningAnimations.firstOrNull { it.isKeyboardAnimation() } ?: return insets
|
|
84
|
+
bottomSheetView.translationY = startTranslationY * (1f - keyboardAnimation.interpolatedFraction)
|
|
85
|
+
return insets
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
override fun onEnd(animation: WindowInsetsAnimationCompat) {
|
|
89
|
+
if (!animation.isKeyboardAnimation()) {
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (isActive) {
|
|
94
|
+
bottomSheetView.translationY = 0f
|
|
95
|
+
}
|
|
96
|
+
isTracking = false
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private fun WindowInsetsAnimationCompat.isKeyboardAnimation(): Boolean = typeMask and WindowInsetsCompat.Type.ime() != 0
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
package com.swmansion.rnscreens.modals.formsheet.native.coordinator
|
|
2
2
|
|
|
3
3
|
import androidx.activity.OnBackPressedCallback
|
|
4
|
-
import com.swmansion.rnscreens.modals.dimmingview.DimmingViewManager
|
|
5
4
|
import com.swmansion.rnscreens.modals.formsheet.native.core.FormSheetDialog
|
|
6
5
|
|
|
7
6
|
internal class FormSheetNativeDismissCoordinator(
|
|
8
7
|
private val dialog: FormSheetDialog,
|
|
9
8
|
private val behaviorController: FormSheetBehaviorController?,
|
|
10
|
-
private val dimmingManager: DimmingViewManager,
|
|
11
9
|
private val onDismissAllowed: () -> Unit,
|
|
12
10
|
private val onDismissPrevented: () -> Unit,
|
|
13
11
|
) : FormSheetDialog.CancelRequestInterceptor {
|
|
@@ -27,15 +25,11 @@ internal class FormSheetNativeDismissCoordinator(
|
|
|
27
25
|
internal fun setup() {
|
|
28
26
|
dialog.cancelRequestInterceptor = this
|
|
29
27
|
dialog.onBackPressedDispatcher.addCallback(preventNativeDismissBackPressCallback)
|
|
30
|
-
// Backdrop taps go through `cancel()` rather than dismissing directly, so that they are
|
|
31
|
-
// subject to the very same interception as the back press and the swipe down.
|
|
32
|
-
dimmingManager.setOnBackdropClickListener { dialog.cancel() }
|
|
33
28
|
}
|
|
34
29
|
|
|
35
30
|
internal fun destroy() {
|
|
36
31
|
dialog.cancelRequestInterceptor = null
|
|
37
32
|
preventNativeDismissBackPressCallback.remove()
|
|
38
|
-
dimmingManager.setOnBackdropClickListener(null)
|
|
39
33
|
}
|
|
40
34
|
|
|
41
35
|
override fun handleCancelRequest() {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
package com.swmansion.rnscreens.modals.formsheet.native.core
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.view.View
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* View installed as the first child of the window's `android.R.id.content`, as a sibling
|
|
8
|
+
* of Material's dialog `container` - nothing in Material's hierarchy is moved.
|
|
9
|
+
*
|
|
10
|
+
* Every metric we hand to `BottomSheetBehavior` and the height of [FormSheetContainer] is derived from
|
|
11
|
+
* the height the sheet is measured against. The measure pass is the only point where that height is known
|
|
12
|
+
* *before* the sheet gets measured. `FrameLayout` measures its children in index order, so the provider reports
|
|
13
|
+
* the height right before Material's `container`, the coordinator and the sheet are measured in the same
|
|
14
|
+
* traversal, keeping those values in sync with window resizes, e.g. orientation change.
|
|
15
|
+
*/
|
|
16
|
+
internal class FormSheetAvailableHeightProvider(
|
|
17
|
+
context: Context,
|
|
18
|
+
) : View(context) {
|
|
19
|
+
internal fun interface OnAvailableHeightMeasuredListener {
|
|
20
|
+
/**
|
|
21
|
+
* Invoked at the beginning of every measure pass with the height the sheet is about
|
|
22
|
+
* to be measured against.
|
|
23
|
+
*/
|
|
24
|
+
fun onAvailableHeightMeasured(height: Int)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
internal var availableHeightListener: OnAvailableHeightMeasuredListener? = null
|
|
28
|
+
|
|
29
|
+
init {
|
|
30
|
+
visibility = INVISIBLE
|
|
31
|
+
importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_NO
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
override fun onMeasure(
|
|
35
|
+
widthMeasureSpec: Int,
|
|
36
|
+
heightMeasureSpec: Int,
|
|
37
|
+
) {
|
|
38
|
+
val height = MeasureSpec.getSize(heightMeasureSpec)
|
|
39
|
+
if (MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.UNSPECIFIED && height > 0) {
|
|
40
|
+
availableHeightListener?.onAvailableHeightMeasured(height)
|
|
41
|
+
}
|
|
42
|
+
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -2,6 +2,7 @@ package com.swmansion.rnscreens.modals.formsheet.native.core
|
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
4
|
import android.os.Bundle
|
|
5
|
+
import android.util.Log
|
|
5
6
|
import android.view.View
|
|
6
7
|
import android.view.ViewGroup
|
|
7
8
|
import android.view.Window
|
|
@@ -14,8 +15,8 @@ import com.google.android.material.bottomsheet.BottomSheetDialog
|
|
|
14
15
|
* A custom BottomSheetDialog override used to render the FormSheet native component.
|
|
15
16
|
*
|
|
16
17
|
* We enforce edge-to-edge rendering, bypassing standard Material checks.
|
|
17
|
-
* This
|
|
18
|
-
* The FormSheetContainer is sized manually against the system insets.
|
|
18
|
+
* This is required because our custom dimming logic needs the Dialog to span
|
|
19
|
+
* the entire screen. The FormSheetContainer is sized manually against the system insets.
|
|
19
20
|
*/
|
|
20
21
|
internal class FormSheetDialog(
|
|
21
22
|
context: Context,
|
|
@@ -33,6 +34,12 @@ internal class FormSheetDialog(
|
|
|
33
34
|
|
|
34
35
|
internal var cancelRequestInterceptor: CancelRequestInterceptor? = null
|
|
35
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Installed next to Material's content once the dialog is created. Reports the height the sheet
|
|
39
|
+
* is measured against so the sheet metrics can be resolved before the sheet itself is measured.
|
|
40
|
+
*/
|
|
41
|
+
internal val availableHeightProvider = FormSheetAvailableHeightProvider(context)
|
|
42
|
+
|
|
36
43
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
37
44
|
super.onCreate(savedInstanceState)
|
|
38
45
|
|
|
@@ -40,6 +47,7 @@ internal class FormSheetDialog(
|
|
|
40
47
|
disableNativeWindowAnimation(window)
|
|
41
48
|
|
|
42
49
|
setupBottomSheetHeight()
|
|
50
|
+
installAvailableHeightProvider()
|
|
43
51
|
}
|
|
44
52
|
|
|
45
53
|
override fun onAttachedToWindow() {
|
|
@@ -63,7 +71,8 @@ internal class FormSheetDialog(
|
|
|
63
71
|
* `enableEdgeToEdge` attribute AND the navigation bar is translucent (see
|
|
64
72
|
* `BottomSheetDialog#onAttachedToWindow`).
|
|
65
73
|
*
|
|
66
|
-
* We force edge-to-edge on every API level so the
|
|
74
|
+
* We force edge-to-edge on every API level so the window content always spans the whole
|
|
75
|
+
* screen.
|
|
67
76
|
*/
|
|
68
77
|
private fun forceEdgeToEdge() {
|
|
69
78
|
val window = window ?: return
|
|
@@ -80,4 +89,27 @@ internal class FormSheetDialog(
|
|
|
80
89
|
val bottomSheetView = findViewById<FrameLayout>(com.google.android.material.R.id.design_bottom_sheet)
|
|
81
90
|
bottomSheetView?.layoutParams?.height = ViewGroup.LayoutParams.MATCH_PARENT
|
|
82
91
|
}
|
|
92
|
+
|
|
93
|
+
private fun installAvailableHeightProvider() {
|
|
94
|
+
if (availableHeightProvider.parent != null) {
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
val contentParent = findViewById<ViewGroup>(android.R.id.content)
|
|
99
|
+
if (contentParent == null) {
|
|
100
|
+
Log.e(TAG, "[RNScreens] Window content view not found; the sheet dimensions won't be resolved.")
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// FrameLayout measures its children in order, so the provider reports the height before Material's container
|
|
105
|
+
contentParent.addView(
|
|
106
|
+
availableHeightProvider,
|
|
107
|
+
0,
|
|
108
|
+
FrameLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT),
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
companion object {
|
|
113
|
+
private const val TAG = "FormSheetDialog"
|
|
114
|
+
}
|
|
83
115
|
}
|
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
package com.swmansion.rnscreens.modals.formsheet.native.core
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
|
-
import android.util.Log
|
|
5
4
|
import android.view.ContextThemeWrapper
|
|
6
5
|
import android.view.View
|
|
7
|
-
import android.widget.FrameLayout
|
|
8
|
-
import com.swmansion.rnscreens.modals.dimmingview.DimmingViewManager
|
|
9
|
-
import com.swmansion.rnscreens.modals.formsheet.native.coordinator.FormSheetAppearanceCoordinator
|
|
10
|
-
import com.swmansion.rnscreens.modals.formsheet.native.coordinator.FormSheetBehaviorController
|
|
11
|
-
import com.swmansion.rnscreens.modals.formsheet.native.coordinator.FormSheetDimensionsCoordinator
|
|
12
|
-
import com.swmansion.rnscreens.modals.formsheet.native.coordinator.FormSheetNativeDismissCoordinator
|
|
13
6
|
import com.swmansion.rnscreens.modals.formsheet.native.interfaces.FormSheetContentSizeChangeDelegate
|
|
14
7
|
import com.swmansion.rnscreens.modals.formsheet.native.interfaces.FormSheetDialogEventEmitter
|
|
15
8
|
import com.swmansion.rnscreens.modals.formsheet.native.model.FormSheetConfig
|
|
16
|
-
import com.swmansion.rnscreens.modals.formsheet.native.
|
|
9
|
+
import com.swmansion.rnscreens.modals.formsheet.native.presentation.FormSheetDimmingManager
|
|
10
|
+
import com.swmansion.rnscreens.modals.formsheet.native.presentation.FormSheetPresentation
|
|
17
11
|
import com.swmansion.rnscreens.modals.formsheet.native.presentation.FormSheetPresentationManager
|
|
18
12
|
import kotlin.properties.Delegates
|
|
19
13
|
|
|
@@ -32,131 +26,64 @@ class FormSheetDialogManager(
|
|
|
32
26
|
// Eagerly create the container so it's always ready for the provided content view
|
|
33
27
|
private val container = FormSheetContainer(themedContext, contentView)
|
|
34
28
|
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
setContentView(container)
|
|
39
|
-
setCanceledOnTouchOutside(false)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
private val bottomSheetView = dialog.findViewById<FrameLayout>(com.google.android.material.R.id.design_bottom_sheet)
|
|
29
|
+
// The React content only reports height changes, so a new presentation is seeded with the
|
|
30
|
+
// last known value.
|
|
31
|
+
private var lastContentHeight = 0
|
|
43
32
|
|
|
44
|
-
private val
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
33
|
+
private val presentationCallbacks =
|
|
34
|
+
object : FormSheetPresentation.Callbacks {
|
|
35
|
+
override fun onDetentChanged(index: Int) {
|
|
36
|
+
eventEmitter?.emitOnDetentChanged(index)
|
|
37
|
+
}
|
|
48
38
|
|
|
49
|
-
|
|
39
|
+
override fun onNativeDismissAllowed() {
|
|
40
|
+
presentationManager.handleNativeDismiss()
|
|
41
|
+
}
|
|
50
42
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
43
|
+
override fun onNativeDismissPrevented() {
|
|
44
|
+
eventEmitter?.emitOnNativeDismissPreventedEvent()
|
|
45
|
+
}
|
|
46
|
+
}
|
|
55
47
|
|
|
56
|
-
private val
|
|
57
|
-
FormSheetDimensionsCoordinator(
|
|
58
|
-
dialog = dialog,
|
|
59
|
-
container = container,
|
|
60
|
-
bottomSheetView = bottomSheetView,
|
|
61
|
-
behaviorController = behaviorController,
|
|
62
|
-
)
|
|
48
|
+
private val dimmingManager = FormSheetDimmingManager(context)
|
|
63
49
|
|
|
64
50
|
private val presentationManager =
|
|
65
51
|
FormSheetPresentationManager(
|
|
66
|
-
|
|
67
|
-
bottomSheetView = bottomSheetView,
|
|
52
|
+
presentationFactory = ::createPresentation,
|
|
68
53
|
dimmingManager = dimmingManager,
|
|
69
54
|
onNativeDismiss = { eventEmitter?.emitOnNativeDismissEvent() },
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
private val nativeDismissCoordinator =
|
|
73
|
-
FormSheetNativeDismissCoordinator(
|
|
74
|
-
dialog = dialog,
|
|
75
|
-
behaviorController = behaviorController,
|
|
76
|
-
dimmingManager = dimmingManager,
|
|
77
|
-
onDismissAllowed = { presentationManager.handleNativeDismiss() },
|
|
78
|
-
onDismissPrevented = { eventEmitter?.emitOnNativeDismissPreventedEvent() },
|
|
55
|
+
onDismiss = { eventEmitter?.emitOnDismissEvent() },
|
|
79
56
|
)
|
|
80
57
|
|
|
81
58
|
internal var eventEmitter: FormSheetDialogEventEmitter? by Delegates.observable(null) { _, _, newValue ->
|
|
82
59
|
presentationManager.appearanceEventEmitter = newValue
|
|
83
60
|
}
|
|
84
61
|
|
|
85
|
-
internal val contentSizeChangeDelegate: FormSheetContentSizeChangeDelegate
|
|
86
|
-
|
|
62
|
+
internal val contentSizeChangeDelegate: FormSheetContentSizeChangeDelegate =
|
|
63
|
+
object : FormSheetContentSizeChangeDelegate {
|
|
64
|
+
override fun onContentHeightChanged(newHeight: Int) {
|
|
65
|
+
lastContentHeight = newHeight
|
|
66
|
+
presentationManager.currentPresentation?.onContentHeightChanged(newHeight)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
87
69
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
dimensionsCoordinator.setup()
|
|
93
|
-
behaviorController?.setup()
|
|
94
|
-
}
|
|
70
|
+
private fun createPresentation(): FormSheetPresentation =
|
|
71
|
+
FormSheetPresentation(themedContext, container, presentationCallbacks).also {
|
|
72
|
+
it.applyInitialConfig(formSheetConfig, lastContentHeight)
|
|
73
|
+
}
|
|
95
74
|
|
|
96
75
|
internal fun applyConfig(newConfig: FormSheetConfig) {
|
|
97
76
|
val oldConfig = formSheetConfig
|
|
98
77
|
formSheetConfig = newConfig
|
|
99
78
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
// ALWAYS refresh dimensions when reopening to ensure that BottomSheet
|
|
103
|
-
// state and layout are synchronized with native behavior.
|
|
104
|
-
val dimensionsChanged = oldConfig.detents != newConfig.detents
|
|
105
|
-
if (dimensionsChanged || reopened) {
|
|
106
|
-
dimensionsCoordinator.updateFormSheetDimensions(
|
|
107
|
-
resolveDetents(newConfig.detents),
|
|
108
|
-
newConfig.initialDetentIndex,
|
|
109
|
-
reopened,
|
|
110
|
-
)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (oldConfig.prefersGrabberVisible != newConfig.prefersGrabberVisible) {
|
|
114
|
-
container.setGrabberVisible(newConfig.prefersGrabberVisible)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (oldConfig.preferredCornerRadius != newConfig.preferredCornerRadius) {
|
|
118
|
-
appearanceCoordinator.updateCornerRadius(newConfig.preferredCornerRadius)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (oldConfig.nativeContainerBackgroundColor != newConfig.nativeContainerBackgroundColor) {
|
|
122
|
-
appearanceCoordinator.updateBackgroundColor(newConfig.nativeContainerBackgroundColor)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (oldConfig.shouldPreventNativeDismiss != newConfig.shouldPreventNativeDismiss) {
|
|
126
|
-
nativeDismissCoordinator.shouldPreventDismiss = newConfig.shouldPreventNativeDismiss
|
|
127
|
-
}
|
|
79
|
+
presentationManager.currentPresentation?.applyConfigUpdate(oldConfig, newConfig)
|
|
128
80
|
|
|
129
81
|
if (oldConfig.isOpen != newConfig.isOpen) {
|
|
130
|
-
presentationManager.
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
private fun resolveDetents(rawDetents: List<Double>): FormSheetDetents {
|
|
135
|
-
if (rawDetents.isEmpty()) {
|
|
136
|
-
return FormSheetDetents(listOf(LARGE_DETENT_FRACTION))
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return try {
|
|
140
|
-
FormSheetDetents(rawDetents)
|
|
141
|
-
} catch (e: IllegalArgumentException) {
|
|
142
|
-
Log.e(
|
|
143
|
-
"[RNScreens]",
|
|
144
|
-
"Invalid FormSheet detents: $rawDetents. Falling back to large detent.",
|
|
145
|
-
e,
|
|
146
|
-
)
|
|
147
|
-
FormSheetDetents(listOf(LARGE_DETENT_FRACTION))
|
|
82
|
+
presentationManager.requestProgrammaticStateUpdate(newConfig.isOpen)
|
|
148
83
|
}
|
|
149
84
|
}
|
|
150
85
|
|
|
151
86
|
internal fun destroy() {
|
|
152
|
-
behaviorController?.destroy()
|
|
153
|
-
nativeDismissCoordinator.destroy()
|
|
154
87
|
presentationManager.destroy()
|
|
155
|
-
dimensionsCoordinator.destroy()
|
|
156
|
-
dialog.dismiss()
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
companion object {
|
|
160
|
-
private const val LARGE_DETENT_FRACTION = 1.0
|
|
161
88
|
}
|
|
162
89
|
}
|
|
@@ -3,6 +3,8 @@ package com.swmansion.rnscreens.modals.formsheet.native.interfaces
|
|
|
3
3
|
import com.swmansion.rnscreens.common.event.ViewAppearanceEventEmitter
|
|
4
4
|
|
|
5
5
|
internal interface FormSheetDialogEventEmitter : ViewAppearanceEventEmitter {
|
|
6
|
+
fun emitOnDismissEvent()
|
|
7
|
+
|
|
6
8
|
fun emitOnNativeDismissEvent()
|
|
7
9
|
|
|
8
10
|
fun emitOnNativeDismissPreventedEvent()
|