Reputation: 41638
In Xamarin.Forms, on iOS, how can I extend TabbedPage
so that in addition to changing pages using the tabs at the bottom, the user can swipe left or right to change pages? Ideally, the page transition should be animated when swiping.
None of the pages use left or right gestures within the pages themselves, so swiping left or right is available to unambiguously indicate a desire to change the current page.
Upvotes: 2
Views: 2437
Reputation: 41638
The following code responds to a user swipe gesture with a tab change animated with a cross dissolve. It creates a custom renderer for TabbedPage
that adds an iOS UISwipeGestureRecognizer
for each direction.
The gesture recognizer works simultaneously with other gestures on the page (otherwise, page gestures such as scrolling will prevent the swipe gesture from working unless the gesture is perfectly horizontal), but not itself (otherwise, one swipe will move across multiple pages).
[assembly: ExportRenderer(typeof(TabbedPage), typeof(SwipeTabbedRenderer))]
class SwipeTabbedRenderer : TabbedRenderer
{
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
NativeView.AddGestureRecognizer(new UISwipeGestureRecognizer(() => SelectNextTab(1)) { Direction = UISwipeGestureRecognizerDirection.Left, ShouldRecognizeSimultaneously = ShouldRecognizeSimultaneously });
NativeView.AddGestureRecognizer(new UISwipeGestureRecognizer(() => SelectNextTab(-1)) { Direction = UISwipeGestureRecognizerDirection.Right, ShouldRecognizeSimultaneously = ShouldRecognizeSimultaneously });
}
void SelectNextTab(int direction)
{
int nextIndex = TabbedPage.GetIndex(Tabbed.CurrentPage) + direction;
if (nextIndex < 0 || nextIndex >= Tabbed.Children.Count) return;
var nextPage = Tabbed.Children[nextIndex];
UIView.Transition(Platform.GetRenderer(Tabbed.CurrentPage).NativeView, Platform.GetRenderer(nextPage).NativeView, 0.15, UIViewAnimationOptions.TransitionCrossDissolve, null);
Tabbed.CurrentPage = nextPage;
}
static bool ShouldRecognizeSimultaneously(UIGestureRecognizer gestureRecognizer, UIGestureRecognizer otherGestureRecognizer) => gestureRecognizer != otherGestureRecognizer;
}
Opportunity for improvement: A slide gesture would be better than the cross dissolve, but when I tried to use CATransition to create one, the initial state of the animation was a blank page, rather than the page for the starting tab. This caused the animation to feel slightly jarring.
Upvotes: 6