【发布时间】:2022-06-30 00:03:33
【问题描述】:
我已经使用 ScrollView 控件和 Bindable StackLayout 控件创建了自定义选项卡控件。
我首先在 Xamarin.Forms(VS for Mac 2019)中创建了这个解决方案,它在两个平台上都可以正常工作,但是在 .Net MAUI(VS for Mac 2022 Prev)中开发的相同解决方案在 Android 中无法正常工作.
这是我到目前为止所做的:
MainPage.xaml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:poc_maui.ViewModels"
x:Class="poc_maui.Views.HomePage"
xmlns:tabs="clr-namespace:poc_maui.Views.SubViews"
Title="HomePage">
<ContentPage.BindingContext>
<vm:MainPageViewModel />
</ContentPage.BindingContext>
<Grid RowDefinitions="50, *" RowSpacing="0">
<ScrollView Grid.Row="0" Orientation="Horizontal" VerticalOptions="Start" HorizontalScrollBarVisibility="Never"
Scrolled="ScrollView_Scrolled">
<StackLayout x:Name="TabsView"
Orientation="Horizontal"
BindableLayout.ItemsSource="{Binding Tabs}" Spacing="0">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Grid RowDefinitions="*, 4" RowSpacing="0">
<Label Grid.Row="0"
Text="{Binding TabTitle}"
TextColor="White"
BackgroundColor="navy"
Padding="20,0"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Center"
FontSize="12"
HeightRequest="40"/>
<BoxView Grid.Row="1"
Color="Yellow"
IsVisible="{Binding IsSelected}"/>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.TabChangedCommand,
Source={x:Reference TabsView}}"
CommandParameter="{Binding .}"/>
</Grid.GestureRecognizers>
</Grid>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ScrollView>
<tabs:ParentRecordTabView Grid.Row="1" IsVisible="{Binding IsParentRecordTabVisible}"
VerticalOptions="FillAndExpand"/>
<tabs:AdditionalInfoTabView Grid.Row="1" IsVisible="{Binding IsAdditionalInfoTabVisible}"
VerticalOptions="FillAndExpand" />
</Grid>
</ContentPage>
MainPageViewModel
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows.Input;
using poc_maui.Models;
namespace poc_maui.ViewModels
{
public class MainPageViewModel : BaseViewModel
{
#region Constructor
public MainPageViewModel()
{
GetTabs();
}
#endregion
#region Private Properties
private bool _isParentRecordTabVisible = true;
private bool _isAdditionalInfoTabVisible;
private ObservableCollection<TabViewModel> _tabs { get; set; }
#endregion
#region Public Properties
public bool IsParentRecordTabVisible
{
get => _isParentRecordTabVisible;
set { _isParentRecordTabVisible = value; OnPropertyChanged(nameof(IsParentRecordTabVisible)); }
}
public bool IsAdditionalInfoTabVisible
{
get => _isAdditionalInfoTabVisible;
set { _isAdditionalInfoTabVisible = value; OnPropertyChanged(nameof(IsAdditionalInfoTabVisible)); }
}
public ObservableCollection<TabViewModel> Tabs
{
get => _tabs;
set { _tabs = value; OnPropertyChanged(nameof(Tabs)); }
}
#endregion
#region Commands
public ICommand TabChangedCommand { get { return new Command<TabViewModel>(ChangeTabClick); } }
#endregion
#region Private Methods
private void GetTabs()
{
Tabs = new ObservableCollection<TabViewModel>();
Tabs.Add(new TabViewModel { TabId = 1, IsSelected = true, TabTitle = "Parent record" });
Tabs.Add(new TabViewModel { TabId = 2, TabTitle = "Additional Info" });
Tabs.Add(new TabViewModel { TabId = 3, TabTitle = "Contacts" });
Tabs.Add(new TabViewModel { TabId = 4, TabTitle = "Previous inspections" });
Tabs.Add(new TabViewModel { TabId = 5, TabTitle = "Attachments" });
SelectedTab = Tabs.FirstOrDefault();
}
private void ChangeTabClick(TabViewModel tab)
{
try
{
var tabs = new ObservableCollection<TabViewModel>(Tabs);
foreach (var item in tabs)
{
if (item.TabId == tab.TabId)
{
item.IsSelected = true;
}
else
{
item.IsSelected = false;
}
}
Tabs.Clear();
Tabs = new ObservableCollection<TabViewModel>(tabs);
switch (tab.TabId)
{
case 1:
IsParentRecordTabVisible = true;
IsAdditionalInfoTabVisible = false;
break;
case 2:
IsParentRecordTabVisible = false;
IsAdditionalInfoTabVisible = true;
break;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
#endregion
}
}
#ParentTabView.xaml
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="poc_maui.Views.SubViews.ParentTabView">
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand" >
<Label
Text="Welcome to Parent tab!"
VerticalOptions="Center"
HorizontalOptions="Center" />
</StackLayout>
</ContentView>
#AdditionalInfoTabView.xaml
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="poc_maui.Views.SubViews.AdditionalInfoTabView">
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand" >
<Label
Text="Welcome to Additiona info tab!"
VerticalOptions="Center"
HorizontalOptions="Center" />
</StackLayout>
</ContentView>
所以在 Android 中发生的情况是,当我单击 AdditionalInfo 选项卡时,它会显示一个空白的白色屏幕,如果您按下硬件后退按钮并再次打开应用程序,它将显示 AdditionalTab 已被选中,并且它的视图内容也会显示.
如果我从 ViewModel 中删除 switch() 代码部分,它会正常工作,但选项卡不会改变。有人知道 MAUI 中滚动视图的这种行为吗?
完整的源代码在这里:maui_sample
【问题讨论】:
-
这可能是两个选项卡通用的 ScrollView 的问题,您是否尝试将其保留在选项卡内容视图中?
-
不,滚动视图对于两个选项卡都不常见,如果您检查代码就会明白。同样的事情在 iOS 中运行良好,所以这很奇怪吧?
-
快速提问,如果你只有两个选项卡,为什么需要那个 ScrollView?另外,我猜问题是您的可绑定布局不确定谁应该响应 android 上的调用,我建议您将事件放在布局级别并让您的孩子将 InputTransparent 视为 true
-
不明白你的意思,但它不仅仅是两个标签,还有五个标签。我只对 2 个标签进行了隐藏/显示。如果您可以下载代码并运行,您将能够看到有 5 个选项卡。
标签: c# xamarin xamarin.forms maui .net-maui