对于您的时间关键型操作,我想建议几个优化以供试验.第一个是避免不得不导航到新的视图.使用On Page体系 struct ,其中视图重叠在公共网格上,并且可见性由值OnePageState
控制.这应该会让您非常迅速地从主页视图切换到"看起来"导航的页面,但实际上并不是.
第二种方法是基于Stopwatch
进行计时,并使用异步Task.Delay调用来更新可见显示.即使切换视图需要几十毫秒,所用时间也是从调用启动命令的那一刻开始的,因此它仍然被考虑在内.你要求的是完美的同步,重要的是要注意,它不会达到用核同位素测量时间的原子精度,但它真的不坏.一百零二
首先创建一个IValueConverter
类,如果两个enum
值相等,则返回true
.在这里,如果绑定值OnePageState
不是OnePageState.Main
,则默认MAUI页面现在变为不可见.同样,当值变为OnePageState.Timer
时,替代虚拟页面变为可见.
IValueConverter个
class EnumToBoolConverter : IValueConverter
{
public object Convert(object unk, Type targetType, object parameter, CultureInfo culture)
{
if (unk is Enum enum1 && parameter is Enum @enum2)
{
return enum1.Equals(@enum2);
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
throw new NotImplementedException();
}
Timer Layout Overlaps Maui Default个
将Timer视图添加到公共网格中的Maui默认视图之上.
<!--1 x 1 Grid to contain overlapping virtual page representations-->
<Grid x:Name="OnePageGrid">
<!--Maui Default Virtual Page-->
<ScrollView
IsVisible="{Binding
OnePageState,
Converter={StaticResource EnumToBoolConverter},
ConverterParameter={x:Static local:OnePageState.Main}}">
<VerticalStackLayout
Spacing="25"
Padding="30,0"
VerticalOptions="Center">
.
.
.
</ScrollView>
接下来,在Maui默认视图之上,我们为MainPage.Content堆叠了一个完全不同的"外观".
<!--Timer Virtual Page-->
<Grid
IsVisible="{Binding
OnePageState,
Converter={StaticResource EnumToBoolConverter},
ConverterParameter={x:Static local:OnePageState.Timer}}"
RowDefinitions="50,*,50"
BackgroundColor="MidnightBlue">
<HorizontalStackLayout
HorizontalOptions="Fill"
BackgroundColor="White">
<Button
Text ="<--- Main Page"
TextColor="CornflowerBlue"
BackgroundColor="White"
FontSize="Medium"
HorizontalOptions="Start"
Command="{Binding SetOnePageStateCommand}"
CommandParameter="{x:Static local:OnePageState.Main}"/>
</HorizontalStackLayout>
<Label
Grid.Row="1"
Text="{Binding TimerDisplay}"
TextColor="White"
FontSize="48"
FontAttributes="Bold"
HorizontalOptions="Center"
VerticalOptions="Center"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
BackgroundColor="Transparent">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding StartTimerCommand}"/>
</Label.GestureRecognizers>
</Label>
<Grid
Grid.Row="2"
BackgroundColor="White">
<Button
Text ="Reset"
TextColor="CornflowerBlue"
BackgroundColor="White"
FontSize="Medium"
HorizontalOptions="CenterAndExpand"
Command="{Binding ResetTimerCommand}"/>
</Grid>
</Grid>
</Grid>
Suggestion: Avoid using a Timer个
这里有一种方法可以简化更新所用时间,而不使用Timer
个实例和由此产生的负担.
Task _pollingTask;
private Stopwatch _stopwatch = new Stopwatch();
private async void OnStartTimer(object o)
{
if (!_stopwatch.IsRunning)
{
OnePageState = OnePageState.Timer;
try
{
if (_cts != null)
{
_cts.Cancel();
}
_cts = new CancellationTokenSource();
var token = _cts.Token;
_stopwatch.Restart();
while (!token.IsCancellationRequested)
{
var elapsed = _stopwatch.Elapsed;
MainThread.BeginInvokeOnMainThread(() =>
{
TimerDisplay =
elapsed < TimeSpan.FromSeconds(1) ?
elapsed.ToString(@"hh\:mm\:ss\.ff") :
elapsed.ToString(@"hh\:mm\:ss");
});
await Task.Delay(TimeSpan.FromSeconds(0.1), token);
}
}
catch { }
finally
{
_stopwatch.Stop();
_pollingTask?.Dispose();
}
}
}