uwp多媒体应用

作业要求

  • 使用MediaElement或MediaPlayer打造一个播放器,可播放视频和音乐
  • 实现暂停,播放,停止等操作
  • 实现进度条,实时显示媒体的播放速度;同时,拖动进度条,可以使媒体快速前进,后退到相应的位置
  • 播放视频时,可全屏显示、退出全屏
  • 可手动选择本地的媒体资源进行播放
  • 实现封面旋转:播放音乐时,封面开始旋转,播放结束,封面复位,暂停时,封面的旋转动作暂停,播放视频的时候封面隐藏

具体实现

MainPage.xaml

<Page
    x:Class="week8.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:week8"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.Resources>
        <local:PositionSliderConverter x:Key="converter" />
        <Storyboard x:Name="AvrilStoryboard" RepeatBehavior="Forever">
            <DoubleAnimation Duration="0:0:20" 
                             To="360" 
                             Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)" 
                             Storyboard.TargetName="Picture" 
                             d:IsOptimized="True"/>
        </Storyboard>
    </Page.Resources>
    <Page.BottomAppBar>
        <CommandBar>
            <AppBarButton x:Name="ButtonPlay" Icon="Play" Click="ButtonPlay_Click"/>
            <AppBarButton x:Name="ButtonPause" Icon="Pause" Click="ButtonPause_Click"/>
            <AppBarButton x:Name="ButtonStop" Icon="Stop" Click="ButtonStop_Click"/>
            <AppBarButton x:Name="ButtonFullScreen" Icon="FullScreen" Click="ButtonFullScreen_Click"/>
            <AppBarButton x:Name="ButtonFolder" Icon="Folder" Click="ButtonFolder_Click"/>
            <AppBarButton x:Name="ButtonVolume" Icon="Volume" Click="ButtonVolume_Click"/>
        </CommandBar>
    </Page.BottomAppBar>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="100"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="100"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Ellipse Grid.Row="1" Grid.Column="1"  x:Name="Picture" Height="250" Width="250" Visibility="Collapsed" RenderTransformOrigin="0.5, 0.5">
            <Ellipse.RenderTransform>
                <CompositeTransform />
            </Ellipse.RenderTransform>
            <Ellipse.Fill>
                <ImageBrush ImageSource="Assets/1.jpg"/>
            </Ellipse.Fill>
        </Ellipse>
        <MediaPlayerElement x:Name="_mediaPlayerElement" HorizontalAlignment="Stretch" Grid.Row="1" Grid.Column="1"/>
        <StackPanel Grid.Row="2" Grid.Column="1">
            <Slider x:Name="sliderLine" Value="{x:Bind _mediaTimelineController.Position, Converter={StaticResource converter},Mode=TwoWay}"/>
        </StackPanel>
        <Slider Grid.Row="2" Grid.Column="2" Minimum="0" Maximum="1" x:Name="Volumn" Width="100" Value="0.5" StepFrequency="0.1" ValueChanged="Volumn_ValueChanged" Orientation="Vertical" HorizontalAlignment="Right" Visibility="Collapsed"/>
    </Grid>
</Page>
  • <local:PositionSliderConverter x:Key="converter" />,转换器,用于拖动Slider进度的时候,改变视频或音乐的进度。
  • Storyboard,实现动画的控件,这定义了一个旋转的动画。
  • <Slider Grid.Row="2" Grid.Column="2" Minimum="0" Maximum="1" x:Name="Volumn" Width="100" Value="0.5" StepFrequency="0.1" ValueChanged="Volumn_ValueChanged" Orientation="Vertical" HorizontalAlignment="Right" Visibility="Collapsed"/>这个是用来做声音的,没找到可以和声音图片绑定的方法,所以就直接用宽度调节到相应的位置上,用的是垂直方向的Slider,当点声音按钮的时候,就会出现,再点击就会消失。

MainPage.xaml.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Media;
using Windows.Media.Core;
using Windows.Media.Playback;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x804 上介绍了“空白页”项模板

namespace week8
{
    /// <summary>
    /// 可用于自身或导航至 Frame 内部的空白页。
    /// </summary>
    public sealed partial class MainPage : Page
    {
        MediaPlayer _mediaPlayer = new MediaPlayer();
        MediaTimelineController _mediaTimelineController = new MediaTimelineController();
        TimeSpan _duration;
        public MainPage()
        {
            this.InitializeComponent();
            _mediaPlayer = new MediaPlayer();
            var mediaSource = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/DarkSouls.mp4"));
            mediaSource.OpenOperationCompleted += MediaSource_OpenOperationCompleted;
            _mediaPlayer.Source = mediaSource;
            _mediaPlayer.CommandManager.IsEnabled = false;
            _mediaPlayer.TimelineController = _mediaTimelineController;
            _mediaPlayerElement.SetMediaPlayer(_mediaPlayer);
        }

        private void ButtonPlay_Click(object sender, RoutedEventArgs e)
        {
            DispatcherTimer timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromSeconds(1);
            timer.Tick += timer_Tick;
            timer.Start();
            AvrilStoryboard.Begin();
            if (_mediaTimelineController.State == MediaTimelineControllerState.Paused)
            {
                _mediaTimelineController.Resume();
            }
            else
            {
                _mediaTimelineController.Start();
            }
        }

        void timer_Tick(object sender, object e)
        {
            sliderLine.Value = ((TimeSpan)_mediaTimelineController.Position).TotalSeconds;
            if (sliderLine.Value == sliderLine.Maximum)
            {
                _mediaTimelineController.Position = TimeSpan.FromSeconds(0);
            }
        }

        private void ButtonPause_Click(object sender, RoutedEventArgs e)
        {
                _mediaTimelineController.Pause();
            AvrilStoryboard.Pause();
        }

        private void ButtonStop_Click(object sender, RoutedEventArgs e)
        {
            AvrilStoryboard.Stop();
            _mediaTimelineController.Position = TimeSpan.FromSeconds(0);
            _mediaTimelineController.Start();
            _mediaTimelineController.Pause();
        }

        private void ButtonFullScreen_Click(object sender, RoutedEventArgs e)
        {
            ApplicationView view = ApplicationView.GetForCurrentView();
            bool isInFullScreenMode = view.IsFullScreenMode;
            if (isInFullScreenMode)
            {
                view.ExitFullScreenMode();
            }
            else
            {
                view.TryEnterFullScreenMode();
            }
            _mediaPlayerElement.IsFullWindow = !_mediaPlayerElement.IsFullWindow;
        }

        private async void MediaSource_OpenOperationCompleted(MediaSource sender, MediaSourceOpenOperationCompletedEventArgs args)
        {
            _duration = sender.Duration.GetValueOrDefault();

            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                sliderLine.Minimum = 0;
                sliderLine.Maximum = _duration.TotalSeconds;
                sliderLine.StepFrequency = 1;
            });
        }

        private async void ButtonFolder_Click(object sender, RoutedEventArgs e)
        {
            var openPicker = new FileOpenPicker();

            openPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.VideosLibrary;
            openPicker.FileTypeFilter.Add(".wmv");
            openPicker.FileTypeFilter.Add(".mp4");
            openPicker.FileTypeFilter.Add(".mp3");
            openPicker.FileTypeFilter.Add(".wma");

            StorageFile file = await openPicker.PickSingleFileAsync();
            if (file != null)
            {
                var mediaSource = MediaSource.CreateFromStorageFile(file);
                mediaSource.OpenOperationCompleted += MediaSource_OpenOperationCompleted;
                _mediaPlayer.Source = mediaSource;
                if (file.FileType == ".mp3" || file.FileType == ".wma")
                {
                    Picture.Visibility = Visibility.Visible;
                }
                else
                {
                    Picture.Visibility = Visibility.Collapsed;
                }
            }
        }
        private void Volumn_ValueChanged(object sender, RoutedEventArgs e)
        {
            _mediaPlayer.Volume = (double)Volumn.Value;
        }

        private void ButtonVolume_Click(object sender, RoutedEventArgs e)
        {
            if(Volumn.Visibility == Visibility.Collapsed)
            {
                Volumn.Visibility = Visibility.Visible;
            }
            else
            {
                Volumn.Visibility = Visibility.Collapsed;
            }
        }
    }
}
  • MediaTimelineController用来调节时间线,因为直接用MediaPlayer来调节有很大的局限性,所以用MediaTimelineController来代替。
  • MediaTimelineController几个函数的解释,Resume,从当前位置继续播放,Start从开始位置播放,所以即使是正在播放,按下播放按钮还是重头播放,Pause暂定在现在的位置,所以在暂定之后,点击播放按钮的时候要判断是否是暂定状态,否则就会从头播放。如果要实现Stop功能直接Start再接Pause就可以了。
  • DispatcherTimer这个作用是随着时间,进度条会前进,如果没有相关的设置,虽然可以用进度条控制视频的进度,但是进度条是不会自己动的,所以还要把视频的进度赋给Slider的value。
  • AvrilStoryboard是之前Storyboard的名字,因为我用的是Avril的封面,所以就取了这个名字,AvrilStoryboardBegin,Pause,Stop是对应的。
  • MediaPlayer全屏,这个是比较难受的,因为实现方法是_mediaPlayerElement.IsFullWindow = !_mediaPlayerElement.IsFullWindow;,这个必须要吐槽一下,用一个返回值是bool类型的函数控制是否全屏,不是太奇怪了吗,我本来还想找set前缀的函数,真是太年轻了。

PositionSliderConverter.cs

用于Slider位置转换成视频进度条的转换器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml.Data;

namespace week8
{
    class PositionSliderConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            return ((TimeSpan)value).TotalSeconds;
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            return TimeSpan.FromSeconds((double)value);
        }
    }
}

参考链接

可能是师兄的项目,大部分参考这个

资源以及演示视频

资源以及演示视频

猜你喜欢

转载自blog.csdn.net/yaoxh6/article/details/80139805