Xamarin.Forms 中的计时器

Posted

技术标签:

【中文标题】Xamarin.Forms 中的计时器【英文标题】:Timer in Xamarin.Forms 【发布时间】:2016-09-09 06:13:20 【问题描述】:

我想构建自己的音频播放器(因为没有可用的插件)。我使用了一个滑块来显示播放器的进度。当滑块移动时,我可以允许用户转到特定位置,但我无法将其与正在播放的录音同步。

表格

int i = 1;
Button btnPlay = new Button

    Text = "Play/Pause",
    Command = new Command(() =>
    
        DependencyService.Get<IAudio>().PlayMp3File();
        TimeSpan tmspan = new TimeSpan(00, 00, 00);
        label.Text = String.Format("0:hh\\:mm\\:ss", tmspan.Add(TimeSpan.FromMilliseconds(i)));
        i++;
        return true;
    )
;
Button btnStop = new Button  Text = "Stop" ;
TimeSpan timeSpan = DependencyService.Get<IAudio>().GetInfo();
Label lblDuration = new Label  Text = String.Format("0:hh\\:mm\\:ss", timeSpan) ;

var slider = new Slider 
    Minimum = 0,
    Maximum = timeSpan.TotalHours,
;
var label = new Label 
    Text = "Slider value is 0",
    FontSize = 25,
    HorizontalOptions = LayoutOptions.Start,
;
slider.ValueChanged += 
    (sender, e) => 
    
        label.Text = String.Format("Slider value is 0:hh\\:mm\\:ss", TimeSpan.FromMilliseconds(e.NewValue));
        DependencyService.Get<IAudio>().SeekTo(Convert.ToInt32(e.NewValue));
    ;
MainPage = new ContentPage

    Content = new StackLayout 
    
        Children = 
        
            btnPlay,
            btnStop,
            slider,
            lblDuration,
            label
        
    ,  
    Padding = new Thickness (10, Device.OnPlatform (20, 0, 0), 10, 5)
;

服务

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using AudioTest.Droid;
using Xamarin.Forms;
using Android.Media;
using System.Threading.Tasks;

[assembly: Dependency(typeof(Audioservice))]

namespace AudioTest.Droid

    public class AudioService : IAudio
    
        public AudioService()  

        MediaPlayer player = null;

        public async Task StartPlayerAsync()
        
            try
            
                if (player == null)
                
                    player = new MediaPlayer();
                    player = MediaPlayer.Create(global::Android.App.Application.Context, Resource.Raw.test);
                    player.Start();
                
                else
                
                    if (player.IsPlaying == true)
                    
                        player.Pause();
                    
                    else
                    
                        player.Start();
                    
                
            
            catch (Exception ex)
            
                Console.Out.WriteLine(ex.StackTrace);
            
        

        public void StopPlayer()
        
            if ((player != null))
            
                if (player.IsPlaying)
                
                    player.Stop();
                
                player.Release();
                player = null;
            
        

        public async Task PlayMp3File()
        
            await StartPlayerAsync();
        

        public void Stop()
        
            this.StopPlayer();
        

        public async Task SeekTo( int s)
        
            await seekTo(s);
        

        public double CurrentPosition()
        
            if ((player != null))
            
                return player.CurrentPosition;
            
            else
             return 0; 
        

        private async Task seekTo(int mseconds)
        
            if (player == null)
            
                player = new MediaPlayer();
                player = MediaPlayer.Create(global::Android.App.Application.Context, Resource.Raw.test);

            

            player.SeekTo(mseconds);
            player.Start();
        



        public TimeSpan GetInfo()
        
            int arr;
            if (player == null)
            
                player = new MediaPlayer();
                player = MediaPlayer.Create(global::Android.App.Application.Context, Resource.Raw.test);

            
            arr = player.Duration;

            return TimeSpan.FromMilliseconds(arr);//TimeSpan.FromMilliseconds(arr).TotalMinutes;
        
    

有人知道怎么做吗?

编辑 屏幕截图

在播放时,计时器应该开始,我的滑块值也应该增加。暂停时,计时器和滑块应暂停,停止时应停止。

【问题讨论】:

【参考方案1】:

查看Xamarin.Forms 中的Device 类,尤其是StartTimer 方法。

鉴于此,您可以设置计时器:

Device.StartTimer(TimeSpan.FromMilliseconds(300.0), TimerElapsed);

private bool TimerElapsed()

    Device.BeginInvokeOnMainThread(() => 
    
        //put here your code which updates the view
    );
    //return true to keep timer reccurring
    //return false to stop timer

大约每 300 毫秒触发一次(取决于设备功能)

关于您的代码,您可以从以下内容开始:

1.将以下内容添加到您的播放命令中:

Device.StartTimer(TimeSpan.FromSeconds(1.0), CheckPositionAndUpdateSlider);

2.添加CheckPositionAndUpdateSlider方法:

private bool CheckPositionAndUpdateSlider()

    var position = DependencyService.Get<IAudio>().GetCurrentPosition();
    Device.BeginInvokeOnMainThread(() => 
    
         slider.Value = position;
    );
    return true;

【讨论】:

有没有办法暂停或停止计时器? 只需从TimerElapsed 方法返回false 即可停止它。当您想暂停计时器时,您必须自己编写此逻辑。我的意思是停止计时器,然后在您想恢复它时再次启动计时器。 我无法让我的滑块按照录制进度移动。有什么想法吗? 你测试过你的定时器是否被触发了吗?我看不到您的计时器代码,但也许您忘记通知 Slider 的属性已更改? 点击播放按钮我想启动一个计时器(它在标签中显示)也启动我的滑块(即根据录音移动滑块值。)让我的滑块移动因为录制继续不起作用。

以上是关于Xamarin.Forms 中的计时器的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin.Forms之异步

Xamarin Forms error MSB6006: “java.exe”已退出,代码为 2 解决办法

Xamarin Forms - 从 2017 年到 2019 年更新 Visual Studio 后 iOS 上的奇怪行为

Xamarin.Forms.Forms.Init(e) Onlaunched 中的 FileNotFoundExeception

xamarin.forms 中的页面生命周期事件

ScrollView 问题中的 Xamarin.Forms 捏手势