Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/eighty-crews-exist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'react-native-bottom-tabs': patch
---

fix(ios): respect `disablePageAnimations` when switching tabs on iOS.
8 changes: 4 additions & 4 deletions apps/example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1246,7 +1246,7 @@ PODS:
- ReactCommon/turbomodule/core
- ReactNativeDependencies
- Yoga
- react-native-bottom-tabs (1.4.0):
- react-native-bottom-tabs (1.5.0):
- hermes-engine
- RCTRequired
- RCTTypeSafety
Expand All @@ -1259,7 +1259,7 @@ PODS:
- React-graphics
- React-ImageManager
- React-jsi
- react-native-bottom-tabs/common (= 1.4.0)
- react-native-bottom-tabs/common (= 1.5.0)
- React-NativeModulesApple
- React-RCTFabric
- React-renderercss
Expand All @@ -1270,7 +1270,7 @@ PODS:
- ReactNativeDependencies
- SwiftUIIntrospect (~> 1.0)
- Yoga
- react-native-bottom-tabs/common (1.4.0):
- react-native-bottom-tabs/common (1.5.0):
- hermes-engine
- RCTRequired
- RCTTypeSafety
Expand Down Expand Up @@ -2257,7 +2257,7 @@ SPEC CHECKSUMS:
React-Mapbuffer: 295203fc648a43acf7fba609ddf573aa9fca849f
React-microtasksnativemodule: 269f81deee27a2a9bedb6b2d1088c1ae93de9bd3
React-mutationobservernativemodule: 877e9f730e0d8175c2e952901b55c170fc3d372f
react-native-bottom-tabs: 919e0cce22b40003e716a11b1c81118afffec2aa
react-native-bottom-tabs: dbef12f7c74c8af648087ea11a16b20da93a399c
react-native-safe-area-context: f17f4ec987ecdd130820a4a850498b874fb70388
React-NativeModulesApple: adb1dd8361dff80e9f6652fb3fdbf033cfbe2a89
React-networking: c00b437c4408f0640ba0d4158357133488521eca
Expand Down
37 changes: 35 additions & 2 deletions packages/react-native-bottom-tabs/ios/TabItemEventModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,36 @@ import UIKit

#if !os(macOS) && !os(visionOS)

private final class ImmediateTabTransition: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
0
}

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let destination = transitionContext.viewController(forKey: .to),
let destinationView = transitionContext.view(forKey: .to)
else {
transitionContext.completeTransition(false)
return
}

destinationView.frame = transitionContext.finalFrame(for: destination)
transitionContext.containerView.addSubview(destinationView)
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
}

private final class TabBarDelegate: NSObject, UITabBarControllerDelegate {
var onClick: ((_ index: Int?, _ identifier: String?) -> Bool)?
var disablePageAnimations = false

func tabBarController(
_ tabBarController: UITabBarController,
animationControllerForTransitionFrom fromVC: UIViewController,
to toVC: UIViewController
) -> UIViewControllerAnimatedTransitioning? {
disablePageAnimations ? ImmediateTabTransition() : nil
}

func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if #available(iOS 27.0, *) {
Expand Down Expand Up @@ -74,6 +102,7 @@ private final class TabBarDelegate: NSObject, UITabBarControllerDelegate {
}

struct TabItemEventModifier: ViewModifier {
let disablePageAnimations: Bool
let onTabEvent: (_ index: Int?, _ identifier: String?, _ isLongPress: Bool) -> Bool
private let delegate = TabBarDelegate()

Expand All @@ -85,6 +114,7 @@ struct TabItemEventModifier: ViewModifier {
}

func handle(tabController: UITabBarController) {
delegate.disablePageAnimations = disablePageAnimations
delegate.onClick = { index, identifier in
onTabEvent(index, identifier, false)
}
Expand Down Expand Up @@ -155,8 +185,11 @@ extension View {
/**
Event for tab items. Returns true if should prevent default (switching tabs).
*/
func onTabItemEvent(_ handler: @escaping (Int?, String?, Bool) -> Bool) -> some View {
modifier(TabItemEventModifier(onTabEvent: handler))
func onTabItemEvent(
disablePageAnimations: Bool,
_ handler: @escaping (Int?, String?, Bool) -> Bool
) -> some View {
modifier(TabItemEventModifier(disablePageAnimations: disablePageAnimations, onTabEvent: handler))
}
}

Expand Down
4 changes: 2 additions & 2 deletions packages/react-native-bottom-tabs/ios/TabViewImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ struct TabViewImpl: View {
tabContent
.tabBarMinimizeBehavior(props.minimizeBehavior)
#if !os(tvOS) && !os(macOS) && !os(visionOS)
.onTabItemEvent { index, identifier, isLongPress in
.onTabItemEvent(disablePageAnimations: props.disablePageAnimations) { index, identifier, isLongPress in
let item = identifier.flatMap { props.filteredItems.findByKey($0) }
?? index.flatMap { props.filteredItems[safe: $0] }
guard let key = item?.key else { return false }
Expand Down Expand Up @@ -89,7 +89,7 @@ struct TabViewImpl: View {
.tintColor(props.selectedActiveTintColor)
.getSidebarAdaptable(enabled: props.sidebarAdaptable ?? false)
.onChange(of: props.selectedPage ?? "") { newValue in
#if !os(macOS)
#if os(tvOS) || os(visionOS)
if props.disablePageAnimations {
UIView.setAnimationsEnabled(false)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
Expand Down