XamarinでiOSアプリにタイマーを実装する方法を紹介します。
この記事では、System.Timers.Timer
は使わずに、Task.Delay()
を使用する方法を記載しています。
System.Timers.Timer
が動作しなかった人向けの代替策です。
0. この記事で実装したいイメージ
以下のツイートのように、1秒ずつカウントダウンしていきます。
「分:秒」で表示させています。
Xamarin でタイマーができた。
でも Task.Delay 使ってるから、ストップ押しても最大で1秒くらい遅延ができてしまうんだよなぁ。どうにかしたいが、なぜかtimer.Elapsedが動作せず。。。 pic.twitter.com/0OQ7dnZ4d4
— はる🐱 (@Harus0313) November 13, 2020
1. タイマーのカウントダウンロジック
System.Threading.Tasks.Task.Delay(1000)
で、1秒待つというロジックになります。
これを while でループさせています。
while ループを抜ける条件としては、「timeLimitSec
が0より大きい」としています。
private int timeLimitSec = 10;
async void StartTimer()
{
while(true && timeLimitSec > 0)
{
await System.Threading.Tasks.Task.Delay(1000);
timeLimitSec = timeLimitSec - 1;
}
}
2. 秒から「分:秒」の表示に変換する
秒(int型)から「分:秒」の表示に変換するには、TimeSpan
を使用します。
以下のコードでは、TimerCount
というラベルのテキストにセットしています。
TimerCount.Text = new TimeSpan(0, 0, timeLimitSec).ToString(@"mm\:ss");
TimerSpan
の第3引数に「秒」をセットし、ToString()
で文字列に変換します。
ちなみに、macでバックスラッシュを入力するには、「 option + ¥」です。
3. View部分(xaml)
タイマー表示用として、TimerCountという名前のラベルを設置します。
<Label x:Name="TimerCount"></Label>
4. 実行例
以下のように表示されれば成功です。
Xamarin でタイマーができた。
でも Task.Delay 使ってるから、ストップ押しても最大で1秒くらい遅延ができてしまうんだよなぁ。どうにかしたいが、なぜかtimer.Elapsedが動作せず。。。 pic.twitter.com/0OQ7dnZ4d4
— はる🐱 (@Harus0313) November 13, 2020
5. Task.Delay の問題点
タイマーカウントダウンのロジックは以下の通り Task.Delay
を使用しています。
while(true && timeLimitSec > 0)
{
await System.Threading.Tasks.Task.Delay(1000);
timeLimitSec = timeLimitSec - 1;
}
そのため、このタイマーを一時的にストップする場合は、最大で1秒の遅延が発生します。
Task.Delay(1000)
の部分で一秒待つためです。
6. タイマーの一時停止機能を実装する方法
タイマーの一時停止機能を実装してみましょう。
まず、View(xaml)にスタートとストップのボタンを設置します。
<Button x:Name="TimerStart" Clicked="TimerStart_Clicked" Text="TimerStart"></Button>
<Button x:Name="TimerStop" Clicked="TimerStop_Clicked" Text="TimerStop"></Button>
タイマーカウントダウンロジックを一部修正します。
ループ条件にtimerEnable
というbool変数を使用します。
private bool timerEnable = false;
async void StartTimer()
{
while(timerEnable && timeLimitSec > 0)
{
await System.Threading.Tasks.Task.Delay(1000);
timeLimitSec = timeLimitSec - 1;
TimerCount.Text = new TimeSpan(0, 0, timeLimitSec).ToString(@"mm\:ss");
}
}
TimerStart_Clicked
イベントトリガーで、タイマーを開始します。
void TimerStart_Clicked(System.Object sender, System.EventArgs e)
{
timerEnable = true;
StartTimer();
}
TimerStop_Clicked
イベントトリガーで、タイマーを停止します。
void TimerStop_Clicked(System.Object sender, System.EventArgs e)
{
timerEnable = false;
}
7. この記事で紹介したソースコード全文
- TaskTimer.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="todotimer.TaskTimer">
<ContentPage.Content>
<StackLayout>
<Button x:Name="TimerStart" Clicked="TimerStart_Clicked" Text="TimerStart"></Button>
<Button x:Name="TimerStop" Clicked="TimerStop_Clicked" Text="TimerStop"></Button>
<Label x:Name="TaskName"></Label>
<Label x:Name="TimerCount"></Label>
<Label x:Name="DeviceCount"></Label>
</StackLayout>
</ContentPage.Content>
</ContentPage>
- TaskTimer.xaml.cs
using System;
using System.Collections.Generic;
using Xamarin.Forms;
namespace todotimer
{
public partial class TaskTimer : ContentPage
{
private int count = 0;
private int timeLimitSec = 10;
private bool timerEnable = false;
public TaskTimer(string TodoName)
{
InitializeComponent();
TaskName.Text = TodoName;
TimerCount.Text = new TimeSpan(0, 0, timeLimitSec).ToString(@"mm\:ss");
}
async void StartTimer()
{
while(timerEnable && timeLimitSec > 0)
{
await System.Threading.Tasks.Task.Delay(1000);
timeLimitSec = timeLimitSec - 1;
TimerCount.Text = new TimeSpan(0, 0, timeLimitSec).ToString(@"mm\:ss");
}
}
void TimerStart_Clicked(System.Object sender, System.EventArgs e)
{
timerEnable = true;
StartTimer();
}
void TimerStop_Clicked(System.Object sender, System.EventArgs e)
{
timerEnable = false;
}
}
}
コメント