Xamarin.Forms如何显示实时时间?Android端DateTime.Now不更新如何解决
问题根因
DateTime.Now是.NET的静态属性,仅在被调用时返回当前系统时间。Xamarin.Forms中如果直接将其绑定到UI,因为没有主动的属性变更通知,UI只会在绑定初始化时读取一次值,后续不会自动刷新,所以看起来是时间没有实时更新。
可行解决方案
- 方案1:跨平台定时器定时刷新。用Xamarin.Forms内置的定时器按指定间隔更新时间属性,触发属性变更通知刷新UI,适配全平台,实现简单。
- 方案2:Android端监听系统时间广播。注册系统时间变更、分钟级心跳广播,系统时间变化时自动同步更新,比长时间运行定时器更省电。
- 方案3:绑定搭配值转换器。自定义
IValueConverter在绑定取值时实时读取DateTime.Now,适合对刷新精度要求不高的场景。
实现示例
跨平台通用实现(定时器方案,支持直接获取年/月/日/时/分)
首先实现带通知的ViewModel:
using System; using System.ComponentModel; using System.Runtime.CompilerServices; using Xamarin.Forms; public class TimeViewModel : INotifyPropertyChanged { private DateTime _currentTime; public DateTime CurrentTime { get => _currentTime; set { _currentTime = value; OnPropertyChanged(); // 同步通知单个时间字段变更 OnPropertyChanged(nameof(Year)); OnPropertyChanged(nameof(Month)); OnPropertyChanged(nameof(Day)); OnPropertyChanged(nameof(Hour)); OnPropertyChanged(nameof(Minute)); } } // 直接暴露各时间字段,可单独绑定使用 public int Year => CurrentTime.Year; public int Month => CurrentTime.Month; public int Day => CurrentTime.Day; public int Hour => CurrentTime.Hour; public int Minute => CurrentTime.Minute; public TimeViewModel() { CurrentTime = DateTime.Now; // 按1秒间隔刷新,不需要秒级精度可改为60000(1分钟)降低功耗 Device.StartTimer(TimeSpan.FromSeconds(1), () => { CurrentTime = DateTime.Now; return true; }); } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
XAML绑定示例:
<ContentPage.BindingContext> <local:TimeViewModel /> </ContentPage.BindingContext> <StackLayout Padding="20"> <Label Text="{Binding CurrentTime, StringFormat='完整时间:{0:yyyy-MM-dd HH:mm:ss}'}" FontSize="Large"/> <Label Text="{Binding Year, StringFormat='年:{0}'}" FontSize="Medium"/> <Label Text="{Binding Month, StringFormat='月:{0}'}" FontSize="Medium"/> <Label Text="{Binding Day, StringFormat='日:{0}'}" FontSize="Medium"/> <Label Text="{Binding Hour, StringFormat='时:{0}'}" FontSize="Medium"/> <Label Text="{Binding Minute, StringFormat='分:{0}'}" FontSize="Medium"/> </StackLayout>
Android端省电优化实现(可选)
在Android项目中注册系统时间广播接收器,不用常驻定时器:
[BroadcastReceiver] [IntentFilter(new[] { Intent.ActionTimeChanged, Intent.ActionTimeTick, Intent.ActionTimezoneChanged })] public class TimeUpdateReceiver : BroadcastReceiver { public override void OnReceive(Context context, Intent intent) { // 通知Forms层更新时间 MessagingCenter.Send<object, DateTime>(this, "SysTimeUpdated", DateTime.Now); } }
修改ViewModel逻辑,订阅广播消息更新时间:
public TimeViewModel() { CurrentTime = DateTime.Now; MessagingCenter.Subscribe<object, DateTime>(this, "SysTimeUpdated", (sender, newTime) => { CurrentTime = newTime; }); }
注意事项
- 页面销毁时需要主动停止定时器、取消
MessagingCenter订阅,避免内存泄漏 - 如果需要时间格式跟随系统地区设置,不要硬写格式化字符串,使用
CurrentTime.ToString("f")等系统预设格式即可
内容的提问来源于stack exchange,提问作者Daniel Flores
相关产品推荐
相关产品推荐

