如何在Xamarin Forms中创建带左右滑动动画的简易工具栏
实现Xamarin.Forms可左右滑动的顶部工具栏
嗨,作为有iOS原生开发背景的Xamarin.Forms新手,你提到的可左右滑动的工具栏需求,原生的ToolbarItems确实满足不了——因为它在iOS和Android上的原生实现都是固定布局,不支持横向滑动。不过我们可以自定义一个顶部的滑动栏来实现这个效果,下面给你两种实用的方案:
方案一:基础滑动工具栏(切换内容)
这个方案用ScrollView包裹HorizontalStackLayout来实现横向滑动,搭配点击事件切换主内容,完全兼容iOS和Android。
XAML代码
<?xml version="1.0" encoding="UTF-8"?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="ToolBarDemo.Views.CustomToolBar"> <Grid> <!-- 顶部可滑动工具栏 --> <ScrollView Orientation="Horizontal" BackgroundColor="#f8f8f8" Padding="10,5"> <HorizontalStackLayout Spacing="20"> <Label Text="ONE" FontSize="16" TextColor="#333" Padding="10,5" x:Name="OneLabel"> <TapGestureRecognizer Tapped="OnToolbarItemTapped" CommandParameter="ONE"/> </Label> <Label Text="TWO" FontSize="16" TextColor="#333" Padding="10,5" x:Name="TwoLabel"> <TapGestureRecognizer Tapped="OnToolbarItemTapped" CommandParameter="TWO"/> </Label> <Label Text="THREE" FontSize="16" TextColor="#333" Padding="10,5" x:Name="ThreeLabel"> <TapGestureRecognizer Tapped="OnToolbarItemTapped" CommandParameter="THREE"/> </Label> <!-- 可添加更多选项 --> <Label Text="FOUR" FontSize="16" TextColor="#333" Padding="10,5"> <TapGestureRecognizer Tapped="OnToolbarItemTapped" CommandParameter="FOUR"/> </Label> </HorizontalStackLayout> </ScrollView> <!-- 主内容区域 --> <Frame Margin="0,60,0,0" Padding="10"> <Label x:Name="ContentLabel" Text="当前选中:ONE" FontSize="18"/> </Frame> </Grid> </ContentPage>
后台C#代码
using Xamarin.Forms; namespace ToolBarDemo.Views { public partial class CustomToolBar : ContentPage { public CustomToolBar() { InitializeComponent(); // 默认选中第一个选项 UpdateSelectedStyle(OneLabel); } private void OnToolbarItemTapped(object sender, EventArgs e) { if (sender is Label tappedLabel && e is TappedEventArgs tappedArgs) { var selectedItem = tappedArgs.Parameter as string; // 重置所有选项的样式 ResetAllLabelStyles(); // 设置当前选中项的高亮样式 UpdateSelectedStyle(tappedLabel); // 更新主内容显示 ContentLabel.Text = $"当前选中:{selectedItem}"; } } private void ResetAllLabelStyles() { // 统一重置所有标签的样式 foreach (var child in (ToolbarStack.Parent as ScrollView).Content as HorizontalStackLayout) { if (child is Label label) { label.TextColor = Color.FromHex("#333"); label.FontAttributes = FontAttributes.None; label.BackgroundColor = Color.Transparent; } } } private void UpdateSelectedStyle(Label label) { // 设置选中项的高亮样式(可根据需求调整) label.TextColor = Color.FromHex("#007AFF"); label.FontAttributes = FontAttributes.Bold; label.BackgroundColor = Color.FromHex("#E5F2FF"); } } }
方案二:联动内容轮播的滑动工具栏
如果需要点击工具栏选项时切换整个页面内容,可以搭配CarouselView实现工具栏和内容区的联动,体验更流畅。
XAML代码
<?xml version="1.0" encoding="UTF-8"?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="ToolBarDemo.Views.CarouselToolBarPage"> <Grid> <!-- 顶部滑动工具栏 --> <ScrollView Orientation="Horizontal" BackgroundColor="#f8f8f8" Padding="10,5"> <HorizontalStackLayout Spacing="20" x:Name="ToolbarStack"> <Label Text="ONE" FontSize="16" Padding="10,5" x:Name="OneLabel"> <TapGestureRecognizer Tapped="OnToolbarItemTapped" CommandParameter="0"/> </Label> <Label Text="TWO" FontSize="16" Padding="10,5" x:Name="TwoLabel"> <TapGestureRecognizer Tapped="OnToolbarItemTapped" CommandParameter="1"/> </Label> <Label Text="THREE" FontSize="16" Padding="10,5" x:Name="ThreeLabel"> <TapGestureRecognizer Tapped="OnToolbarItemTapped" CommandParameter="2"/> </Label> </HorizontalStackLayout> </ScrollView> <!-- 内容轮播区域 --> <CarouselView x:Name="ContentCarousel" Margin="0,60,0,0" CurrentItemChanged="OnCarouselCurrentItemChanged"> <CarouselView.ItemsSource> <x:Array Type="{x:Type ContentView}"> <ContentView> <Label Text="ONE页面专属内容" FontSize="20" HorizontalOptions="Center" VerticalOptions="Center"/> </ContentView> <ContentView> <Label Text="TWO页面专属内容" FontSize="20" HorizontalOptions="Center" VerticalOptions="Center"/> </ContentView> <ContentView> <Label Text="THREE页面专属内容" FontSize="20" HorizontalOptions="Center" VerticalOptions="Center"/> </ContentView> </x:Array> </CarouselView.ItemsSource> </CarouselView> </Grid> </ContentPage>
后台C#代码
using Xamarin.Forms; namespace ToolBarDemo.Views { public partial class CarouselToolBarPage : ContentPage { public CarouselToolBarPage() { InitializeComponent(); // 默认选中第一个选项 UpdateSelectedToolbarItem(0); } private void OnToolbarItemTapped(object sender, EventArgs e) { if (e is TappedEventArgs tappedArgs && int.TryParse(tappedArgs.Parameter.ToString(), out int index)) { // 切换轮播内容到对应索引 ContentCarousel.ScrollTo(index, position: ScrollToPosition.Center, animate: true); } } private void OnCarouselCurrentItemChanged(object sender, CurrentItemChangedEventArgs e) { // 当轮播内容切换时,同步更新工具栏选中状态 var currentIndex = ContentCarousel.ItemsSource.IndexOf(e.CurrentItem); UpdateSelectedToolbarItem(currentIndex); } private void UpdateSelectedToolbarItem(int index) { ResetAllLabelStyles(); // 根据索引设置对应标签的高亮样式 switch(index) { case 0: UpdateSelectedStyle(OneLabel); break; case 1: UpdateSelectedStyle(TwoLabel); break; case 2: UpdateSelectedStyle(ThreeLabel); break; } } private void ResetAllLabelStyles() { OneLabel.TextColor = Color.FromHex("#333"); OneLabel.FontAttributes = FontAttributes.None; OneLabel.BackgroundColor = Color.Transparent; TwoLabel.TextColor = Color.FromHex("#333"); TwoLabel.FontAttributes = FontAttributes.None; TwoLabel.BackgroundColor = Color.Transparent; ThreeLabel.TextColor = Color.FromHex("#333"); ThreeLabel.FontAttributes = FontAttributes.None; ThreeLabel.BackgroundColor = Color.Transparent; } private void UpdateSelectedStyle(Label label) { label.TextColor = Color.FromHex("#007AFF"); label.FontAttributes = FontAttributes.Bold; label.BackgroundColor = Color.FromHex("#E5F2FF"); } } }
额外优化建议
- 如果想让自定义工具栏和原生导航栏融合,可以设置
NavigationPage.HasNavigationBar="False",然后把滑动工具栏放在页面最顶部,模拟原生导航栏的视觉效果。 - 样式可以完全自定义,比如添加底部下划线、调整圆角等,适配你的App设计风格。
- 选项较多时,
ScrollView会自动在iOS和Android上启用横向滑动,无需额外处理平台差异。
内容的提问来源于stack exchange,提问作者Srikanth venigalla
相关产品推荐
相关产品推荐

