.NET MAUI Flyout菜单跳转外部应用问题求助
解决方案:Shell Flyout菜单跳转外部应用的问题
方法1:给DataTemplate内的元素添加点击手势处理跳转
直接在Shell.ItemTemplate的布局容器上绑定点击手势,通过后台代码处理外部应用跳转逻辑。
修改XAML代码:
<Shell.ItemTemplate> <DataTemplate> <HorizontalStackLayout Spacing="55" Padding="5"> <HorizontalStackLayout.GestureRecognizers> <TapGestureRecognizer Tapped="FlyoutItem_Tapped"/> </HorizontalStackLayout.GestureRecognizers> <Label Text="{Binding Title}" FontSize="Small" TextColor="Orange" FontAttributes="Bold" /> <ImageButton Source="{Binding FlyoutIcon}" Aspect="AspectFit" HeightRequest="70" WidthRequest="150" HorizontalOptions="Center" /> </HorizontalStackLayout> </DataTemplate> </Shell.ItemTemplate>
在AppShell.xaml.cs中实现点击事件:
private async void FlyoutItem_Tapped(object sender, EventArgs e) { var layout = sender as HorizontalStackLayout; var flyoutItem = layout.BindingContext as FlyoutItem; if (flyoutItem?.Title == "Youtube") { // 优先打开本地Youtube应用,不存在则跳转网页版 var appUri = new Uri("vnd.youtube://"); if (await Launcher.Default.CanOpenAsync(appUri)) { await Launcher.Default.OpenAsync(appUri); } else { await Launcher.Default.OpenAsync(new Uri("https://www.youtube.com/")); } } // 可扩展其他菜单项的跳转逻辑 }
方法2:用MVVM绑定命令实现跳转
如果采用MVVM架构,可给每个菜单项绑定命令,把跳转逻辑封装到ViewModel中。
首先定义FlyoutItem的ViewModel:
public class FlyoutItemVm : INotifyPropertyChanged { public string Title { get; set; } public string FlyoutIcon { get; set; } public ICommand TapCommand { get; } public FlyoutItemVm() { TapCommand = new Command(ExecuteTap); } private async void ExecuteTap() { if (Title == "Youtube") { var appUri = new Uri("vnd.youtube://"); if (await Launcher.Default.CanOpenAsync(appUri)) { await Launcher.Default.OpenAsync(appUri); } else { await Launcher.Default.OpenAsync(new Uri("https://www.youtube.com/")); } } } // 实现INotifyPropertyChanged接口 public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName)); } }
在AppShell构造函数中绑定数据源:
public AppShell() { InitializeComponent(); BindingContext = new List<FlyoutItemVm> { new FlyoutItemVm { Title = "Youtube", FlyoutIcon = "logoyoutubesmall.png" } // 添加其他菜单项 }; }
修改XAML的Shell.ItemTemplate,绑定命令:
<Shell.ItemTemplate> <DataTemplate> <HorizontalStackLayout Spacing="55" Padding="5"> <HorizontalStackLayout.GestureRecognizers> <TapGestureRecognizer Command="{Binding TapCommand}"/> </HorizontalStackLayout.GestureRecognizers> <Label Text="{Binding Title}" FontSize="Small" TextColor="Orange" FontAttributes="Bold" /> <ImageButton Source="{Binding FlyoutIcon}" Aspect="AspectFit" HeightRequest="70" WidthRequest="150" HorizontalOptions="Center" /> </HorizontalStackLayout> </DataTemplate> </Shell.ItemTemplate>
方法3:给MenuItem添加自定义样式匹配DataTemplate外观
如果想保留MenuItem的Clicked事件,可通过自定义ControlTemplate让MenuItem外观和Shell.ItemTemplate一致。
创建MenuItem的自定义样式:
<Style x:Key="CustomMenuItemStyle" TargetType="MenuItem"> <Setter Property="ControlTemplate"> <ControlTemplate> <HorizontalStackLayout Spacing="55" Padding="5"> <Label Text="{TemplateBinding Text}" FontSize="Small" TextColor="Orange" FontAttributes="Bold" /> <Image Source="{TemplateBinding IconImageSource}" Aspect="AspectFit" HeightRequest="70" WidthRequest="150" HorizontalOptions="Center" /> </HorizontalStackLayout> </ControlTemplate> </Setter> </Style>
使用该样式的MenuItem:
<MenuItem Text="Youtube" IconImageSource="logoyoutubesmall.png" Clicked="Youtube_Clicked" Style="{StaticResource CustomMenuItemStyle}" />
后台实现Clicked事件:
private async void Youtube_Clicked(object sender, EventArgs e) { var appUri = new Uri("vnd.youtube://"); if (await Launcher.Default.CanOpenAsync(appUri)) { await Launcher.Default.OpenAsync(appUri); } else { await Launcher.Default.OpenAsync(new Uri("https://www.youtube.com/")); } }
内容的提问来源于stack exchange,提问作者Yayeiro
相关产品推荐
相关产品推荐

