简体   繁体   中英

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

I am very new to 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. 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.

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. And when I envoke Pausetimer() and then Runtimer() one second gets skipped.

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()

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.

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();
                }
            });
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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