简体   繁体   English

从 30 秒倒计时到 0 秒,在最后一秒使用 Xamarin.Forms c# 显示 2 位小数

[英]Countdown from 30 seconds to 0 seconds, showing 2 decimals in the last second with Xamarin.Forms c#

I am very new to Xamarin.我对 Xamarin 很陌生。 What I want to make is a shot clock.我想做的是一个计时表。 It needs to countdown from 30 seconds to 0 seconds, and in the last second it needs to show 2 decimals.它需要从 30 秒倒数到 0 秒,最后一秒需要显示 2 位小数。 I also need it to Pause when I click BtnPause, and if I click the BtnStart I want it to restart at the exact moment I paused it, so the countdown has to be paused and started with the timer paused, not reset.当我单击 BtnPause 时,我还需要它暂停,如果我单击 BtnStart,我希望它在我暂停它的那一刻重新启动,因此倒计时必须暂停并在计时器暂停而不是重置的情况下开始。

This is my code, excuse my mistakes and bad programming skills.这是我的代码,请原谅我的错误和糟糕的编程技巧。

  public partial class MainPage : ContentPage
    {
        private static System.Timers.Timer _timer;
        private double _shotClock = 30;

        public MainPage()
        {
            InitializeComponent();
            _timer = new Timer();

        }

        private void BtnStart_Clicked(object sender, EventArgs e)
        {
            RunTimer();

        }
        private void BtnPause_Clicked(object sender, EventArgs e)
        {
            PauseTimer();
        }

        private void RunTimer()
        {
            if (_shotClock < 1.00)
            {
                _timer.Interval = 10;
            }
            else 
            {
                _timer.Interval = 1000;
            }

            _timer.Start();
            _timer.Elapsed += OnTimedEvent;          

        }

        private void PauseTimer()
        {
            _timer.Stop();
        }

        private void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
        {
            Device.BeginInvokeOnMainThread(() => {

                if (_shotClock > 1.00)
                {

                    _shotClock -= 1.00;
                    _shotClock = Math.Round(_shotClock, 2);
                    lblTimer.Text = _shotClock.ToString();
                } 
                else if (_shotClock <= 1.00 && _shotClock > 0.00)
                {
                    _shotClock -= 0.01;
                    _timer.Interval = 10;
                    _shotClock = Math.Round(_shotClock, 2);
                    lblTimer.Text = _shotClock.ToString();
                }
                else
                {
                    lblTimer.Text = "0";
                    _timer.Stop();
                }
            });          
        }
    }

What is going wrong:出了什么问题:

I do not believe it counts exact seconds, especially when I envoke Runtimer() the first few seconds are off and I'm not sure one countdown is one second.我不相信它会计算精确的秒数,尤其是当我调用Runtimer()时,前几秒关闭并且我不确定倒计时是一秒。 And when I envoke Pausetimer() and then Runtimer() one second gets skipped.当我调用Pausetimer()然后Runtimer()时,会跳过一秒钟。

Is there a better way to code this?有没有更好的编码方式?

Haven't compiled this, so I'm not sure if it will work without some tweaking, but I hope you get the idea.还没有编译这个,所以我不确定它是否会在没有一些调整的情况下工作,但我希望你明白了。 Basically, you'll have to calculate the elapsed time manually.基本上,您必须手动计算经过的时间。 The seconds being off in your case was probably because of using Round() instead of Floor()在您的情况下关闭秒数可能是因为使用 Round() 而不是 Floor()

public partial class MainPage : ContentPage
{
    private static System.Timers.Timer _timer;
    private double _shotClock = 30;
    private DateTime _startTime;

    public MainPage()
    {
        InitializeComponent();
        _timer = new Timer();
        _timer.Interval = 10;
        _timer.Elapsed += OnTimedEvent;  
    }

    private void BtnStart_Clicked(object sender, EventArgs e)
    {
        _startTime = DateTime.UtcNow;
        _timer.Start();
    }
    private void BtnPause_Clicked(object sender, EventArgs e)
    {
        _shotClock -= (DateTime.UtcNow - _startTime).TotalSeconds;
        _shotClock = Math.Floor(_shotClock);
        _timer.Stop();
    }        

    private void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
    {
        Device.BeginInvokeOnMainThread(() => {
            var elapsedSinceBtnStartPressed = (DateTime.UtcNow - _startTime).TotalSeconds;
            var remaining = _shotClock - elapsedSinceBtnStartPressed;

            if (remaining > 1.00)
            {
                lblTimer.Text = Math.Floor(remaining).ToString();
            } 
            else if (remaining <= 1.00 && remaining > 0.00)
            {
                lblTimer.Text = Math.Round(remaining, 2).ToString();
            }
            else
            {
                lblTimer.Text = "0";
                _timer.Stop();
            }
        });          
    }
}

You might also want to try Math.Ceiling() instead of Math.Floor() if you want 12.53 displayed as 13 instead of 12.如果您希望 12.53 显示为 13 而不是 12,您可能还想尝试使用 Math.Ceiling()而不是 Math.Floor()。

with the help of the accepted answer I got the basics working:在接受的答案的帮助下,我得到了基本的工作:

public partial class MainPage : ContentPage
    {
        private static System.Timers.Timer _timer;
        private double _shotClock;
        private DateTime _startTime;



        public MainPage()
        {
            InitializeComponent();
            _timer = new Timer();
            _timer.Interval = 10;
            _timer.Elapsed += OnTimedEvent;
            _shotClock = 30.00;
        }

        private void BtnStart_Clicked(object sender, EventArgs e)
        {
            _startTime = DateTime.UtcNow;     
            _timer.Start();
        }

        private void BtnPause_Clicked(object sender, EventArgs e)
        {


            _timer.Stop();
            var elapsedSinceBtnPausePressed = (DateTime.UtcNow - _startTime).TotalSeconds;
            _shotClock -= elapsedSinceBtnPausePressed;


        }

        private void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
        {
            var elapsedSinceBtnStartPressed = (DateTime.UtcNow - _startTime).TotalSeconds;
            var remaining = _shotClock - elapsedSinceBtnStartPressed;

            Device.BeginInvokeOnMainThread(() => {


                if (remaining > 1.00)
                {
                    lblTimer.Text = Math.Floor(remaining).ToString();
                }
                else if (remaining <= 1.00 && remaining > 0.00)
                {
                    lblTimer.Text = Math.Round(remaining, 2).ToString();
                }
                else
                {
                    lblTimer.Text = "0";
                    _timer.Stop();
                }
            });
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM