Windows Phone Silverlight 音乐进度条简单实现

使用Slider实现音乐进度条,有两种思路:

1)使用数据绑定双向绑定Slider.Value与MediaElement.Position .

2) 使用Timer在适当的时间间隔间将MediaElement.Position代表的毫秒数同步到Slider.Value.


首先尝试第一种解决方案:

因为Slider.value与MediaElemen.position不能直接绑定,所以需要定义一个converter,双向绑定的Converter:

public class MyConverter:IValueConverter
    {

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
 return ((TimeSpan)value).TotalMilliseconds;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            int myvalue = (int)((double)value);
            return new TimeSpan(0, 0, 0, 0, myvalue);
        }
    }


在Xmal里引入Converter定义在的命名空间:

xmlns:myns="clr-namespace:PhoneApp_PlayMedia"

MyConverter作为Grid的静态资源:

<Grid.Resources>
            <myns:MyConverter x:Key="MyConverter"></myns:MyConverter>
        </Grid.Resources>

将Slider的value与MediaElement的Position双向绑定并指定converter:

<Slider x:Name="MediaSlider" Value="{Binding Path=Position,ElementName=MyMedia,Mode=TwoWay,Converter={StaticResource MyConverter}}"/>

调试之后发现播放卡顿,Slider不能更新,需要点击UI元素才能使slider继续跟随音乐播放滑动,手动滑动slider之后又继续停止重绘。


再考虑使用Time更新slider加上捕获slider的valuechangedevent来更新流位置的解决方案,这个比较简单,代码如下:

private Timer sliderTimer;

// 用来表示slider的滑动是否由Timer引起
private bool flag = false;public void DisposeSliderTimer()
        {
            if (this.sliderTimer != null)
            {
                this.sliderTimer.Dispose();
                this.sliderTimer = null;
            }
        }
public void sliderTimerCallback(object obj)
        {
            Dispatcher.BeginInvoke(() =>
            {
                flag = true;
                MediaSlider.Value = MyMedia.Position.TotalMilliseconds;
            });
        }private void MediaSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            // flag indicate wheather the valuechanged event was raised by the timer (wheather the slider was slide by the timer).
            if (flag)
            {
                flag = false;
                return;
            }
            
            // if not,seek to the position by slider's value (indicate the slider was slide by user).
            int sliderValue = (int)MediaSlider.Value;
            TimeSpan ts = new TimeSpan(0, 0, 0, 0, sliderValue);
            MyMedia.Position = ts;
        }
// 播放private void PlayMedia_Click(object sender, RoutedEventArgs e)
        {            MyMedia.Play();
    // 启动Timer       
            sliderTimer = new Timer(sliderTimerCallback,null,0,100);
        }
// 停止private void Stop_Click(object sender, RoutedEventArgs e)
        {
            DmonMedia.Stop();
            DisposeSliderTimer();
            MediaSlider.Value = 0.0;
        }
// App.xmal.cs中:private void Application_Closing(object sender, ClosingEventArgs e)
        {
            (this.RootVisual as MainPage).DisposeSliderTimer();
        }

注意定义一个flag辨别是否手动滑动slider,并在valuechanged中检查。

运行起来效果良好,可以通过slider定位音乐进度,slider还会跟随音乐播放而自动滑动,互不影响。



猜你喜欢

转载自blog.csdn.net/osirius123/article/details/47174461