Windows Phone 8.1 自定义媒体播放器
Windows Phone 8.1 Custom Media Player
美好的一天,
我正在创建一个需要媒体播放器的应用程序。我尝试使用 AreTransportControlsEnabled,但它有点滞后,这是我不想要的。在我的 windows phone 上,我有一个应用程序 "Files"<-(Windows Phone 8.1 中的一个应用程序)我用它来播放我的一个视频,我看到了它的视频播放器。我在想我能不能做到这样的Player。任何关于如何实现此播放器的建议?
图片:http://s22.postimg.org/plu0oqxv5/wp_ss_20150329_0002.png
我尝试制作自定义控件,但在全屏模式下控件不显示。是否有 api 或其他方法可以做到这一点?
已回答问题
我的自定义媒体播放器
主要Page.xalm
<Page
x:Class="MediaPlayer.MainPage"
IsTabStop="false"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MediaPlayer"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Loaded="MainPage_Loaded">
<Page.Resources>
<Style x:Name="transportStyle" TargetType="Button">
<Setter Property="Height" Value="40" />
<Setter Property="Width" Value="75" />
<Setter Property="FontSize" Value="11" />
</Style>
<Thickness x:Key="PhoneBorderThickness">2.5</Thickness>
<FontFamily x:Key="PhoneFontFamilyNormal">Segoe WP</FontFamily>
<FontWeight x:Key="PhoneButtonFontWeight">Semibold</FontWeight>
<x:Double x:Key="TextStyleLargeFontSize">18.14</x:Double>
<x:Double x:Key="PhoneButtonMinHeight">0</x:Double>
<x:Double x:Key="PhoneButtonMinWidth">0</x:Double>
<Thickness x:Key="PhoneTouchTargetOverhang">0,0</Thickness>
<SolidColorBrush x:Key="ButtonDisabledBackgroundThemeBrush" Color="Transparent"/>
<Style x:Key="RoundButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="{ThemeResource PhoneForegroundBrush}"/>
<Setter Property="Foreground" Value="{ThemeResource PhoneForegroundBrush}"/>
<Setter Property="BorderThickness" Value="{ThemeResource PhoneBorderThickness}"/>
<Setter Property="FontFamily" Value="{ThemeResource PhoneFontFamilyNormal}"/>
<Setter Property="FontWeight" Value="{ThemeResource PhoneButtonFontWeight}"/>
<Setter Property="FontSize" Value="{ThemeResource TextStyleLargeFontSize}"/>
<Setter Property="Padding" Value="9.5,0"/>
<Setter Property="MinHeight" Value="{ThemeResource PhoneButtonMinHeight}"/>
<Setter Property="MinWidth" Value="{ThemeResource PhoneButtonMinWidth}"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Path Stretch="Uniform"
RenderTransformOrigin="0.5,0.5"
Margin="2,6,2,2"
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Data="{Binding Path=Content, RelativeSource={RelativeSource Mode=TemplatedParent}}"></Path>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="Grid" Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition From="Pressed" To="PointerOver">
<Storyboard>
<PointerUpThemeAnimation Storyboard.TargetName="Grid"/>
</Storyboard>
</VisualTransition>
<VisualTransition From="PointerOver" To="Normal">
<Storyboard>
<PointerUpThemeAnimation Storyboard.TargetName="Grid"/>
</Storyboard>
</VisualTransition>
<VisualTransition From="Pressed" To="Normal">
<Storyboard>
<PointerUpThemeAnimation Storyboard.TargetName="Grid"/>
</Storyboard>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver"/>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPressedForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Border">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPressedBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonDisabledForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="Border">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonDisabledBorderThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Border">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonDisabledBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="{ThemeResource PhoneTouchTargetOverhang}" Height="{Binding Path=Height, RelativeSource={RelativeSource Mode=TemplatedParent}}" Width="{Binding Path=Width, RelativeSource={RelativeSource Mode=TemplatedParent}}" CornerRadius="72">
<ContentPresenter x:Name="ContentPresenter" AutomationProperties.AccessibilityView="Raw" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<!--<RowDefinition Height="150"/>-->
</Grid.RowDefinitions>
<ContentControl x:Name="videoContainer"
KeyUp="VideoContainer_KeyUp"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
Grid.Row="0" >
<MediaElement Name="videoMediaElement"
Source="Media/video1.mp4"
MediaOpened="videoElement_MediaOpened"
MediaEnded="videoMediaElement_MediaEnded"
MediaFailed="videoMediaElement_MediaFailed"
CurrentStateChanged="videoMediaElement_CurrentStateChanged"
PosterSource="Media/Video1_Poster.png" PointerPressed="videoMediaElement_PointerPressed" />
</ContentControl>
<!-- Transport Controls -->
<StackPanel Name="TransportControlsPanel"
Grid.Row="0" VerticalAlignment="Bottom" Background="#CC000000" >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,15,0,0">
<Button HorizontalAlignment="Left" Click="btnReverse_Click" VerticalAlignment="Top" Style="{StaticResource RoundButtonStyle}" Height="72" Width="72" Content="M13.862404,0L17.667,3.8059161 10.879305,10.593651 17.6241,17.568752 13.861103,21.333 3.1840002,10.678149z M0,0L3.0719999,0 3.0719999,21.032 0,21.032z" Padding="20,5" Margin="20,0" BorderBrush="White" Background="#FFE6E6E6"/>
<Button x:Name="Play1" HorizontalAlignment="Left" Click="btnPlay_Click" VerticalAlignment="Top" Style="{StaticResource RoundButtonStyle}" Height="72" Width="72" Content="M27.270001,0L44.310001,0 44.310001,48.643002 27.270001,48.643002z M0,0L17.040001,0 17.040001,48.643002 0,48.643002z" Padding="20,10" Margin="20,0" BorderBrush="White" Background="#FFE6E6E6"/>
<Button HorizontalAlignment="Left" Click="btnForward_Click" VerticalAlignment="Top" Style="{StaticResource RoundButtonStyle}" Height="72" Width="72" Content="M14.595,0L17.668,0 17.668,21.032 14.595,21.032z M3.8059254,0L14.484001,10.67815 3.8059254,21.333 0.04431057,17.568752 6.7875929,10.593651 0,3.8059165z" Padding="20,5" Margin="20,0" BorderBrush="White" Background="#FFE6E6E6"/>
<Button HorizontalAlignment="Left" Click="btnFullScreenToggle_Click" VerticalAlignment="Top" Style="{StaticResource RoundButtonStyle}" Height="72" Width="72" Content="M0,2.3629998L11.63953,2.3629998 9.1447105,4.8564929 2.4934592,4.8564929 2.4934592,14.710437 12.712251,14.710437 12.712251,8.4683789 15.206,5.9748863 15.206,17.204 0,17.204z M11.741774,0L17.591398,0 17.591999,5.8514608 15.648591,3.9075235 7.7964079,11.759001 5.8289994,9.7914637 13.681183,1.9400271z" Padding="13,10,10,15" Margin="20,0" BorderBrush="White" Background="#FFE6E6E6"/>
</StackPanel>
<Slider Name="timelineSlider" HorizontalContentAlignment="Stretch" Margin="10,20,10,0"/>
<TextBlock x:Name="TextBlock1" Text="00:0 / 00:0" FontSize="18" Margin="20,0,20,40" Foreground="White"/>
</StackPanel>
</Grid>
MainPage.cs
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
// You should use the MediaElement.IsFullWindow property instead
// to enable and disable full window rendering.
private bool _isFullscreenToggle = false;
public bool IsFullscreen
{
get { return _isFullscreenToggle; }
set { _isFullscreenToggle = value; }
}
private Size _previousVideoContainerSize = new Size();
private async void FullscreenToggle()
{
this.IsFullscreen = !this.IsFullscreen;
if (this.IsFullscreen)
{
//TransportControlsPanel.Visibility = Visibility.Collapsed;
await Windows.UI.ViewManagement.StatusBar.GetForCurrentView().HideAsync();
DisplayInformation.AutoRotationPreferences = DisplayOrientations.Landscape | DisplayOrientations.LandscapeFlipped;
_previousVideoContainerSize.Width = videoContainer.ActualWidth;
_previousVideoContainerSize.Height = videoContainer.ActualHeight;
videoContainer.Width = Window.Current.Bounds.Width;
videoContainer.Height = Window.Current.Bounds.Height;
videoMediaElement.Width = Window.Current.Bounds.Width;
videoMediaElement.Height = Window.Current.Bounds.Height;
// Trigger the Visual State Manager
//VisualStateManager.GoToState(this, "Landscape", false);
}
else
{
//TransportControlsPanel.Visibility = Visibility.Visible;
await Windows.UI.ViewManagement.StatusBar.GetForCurrentView().ShowAsync();
DisplayInformation.AutoRotationPreferences = DisplayOrientations.None;
videoContainer.Width = _previousVideoContainerSize.Width;
videoContainer.Height = _previousVideoContainerSize.Height;
videoMediaElement.Width = _previousVideoContainerSize.Width;
videoMediaElement.Height = _previousVideoContainerSize.Height;
// Trigger the Visual State Manager
//VisualStateManager.GoToState(this, "Portrait",false);
}
}
private void btnFullScreenToggle_Click(object sender, RoutedEventArgs e)
{
FullscreenToggle();
}
private void VideoContainer_KeyUp(object sender, KeyRoutedEventArgs e)
{
if (IsFullscreen && e.Key == Windows.System.VirtualKey.Escape)
{
FullscreenToggle();
}
e.Handled = true;
}
private void btnPlay_Click(object sender, RoutedEventArgs e)
{
if (videoMediaElement.DefaultPlaybackRate != 1)
{
videoMediaElement.DefaultPlaybackRate = 1.0;
}
if (videoMediaElement.CurrentState == MediaElementState.Playing)
{
videoMediaElement.Pause();
Play1.Content = "M0,0L384.885,191.965 769.768,383.928 384.885,576.035 0,768 0,383.928z"; // Play
Play1.Padding = new Thickness(19, 5, 12, 5);
}
else if (videoMediaElement.CurrentState == MediaElementState.Paused)
{
videoMediaElement.Play();
Play1.Content = "M27.270001,0L44.310001,0 44.310001,48.643002 27.270001,48.643002z M0,0L17.040001,0 17.040001,48.643002 0,48.643002z";
Play1.Padding = new Thickness(20, 10, 20, 10);
}
}
DispatcherTimer timer = new DispatcherTimer();
public void Start_timer()
{
timer.Tick += timer_Tick;
timer.Interval = new TimeSpan(00, 0, 5);
bool enabled = timer.IsEnabled;
timer.Start();
}
void timer_Tick(object sender, object e)
{
//function to execute
if (TransportControlsPanel.Visibility == Windows.UI.Xaml.Visibility.Visible)
{
TransportControlsPanel.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
}
timer.Stop();
}
private void btnPause_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.Pause();
}
private void btnStop_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.Stop();
}
private void btnForward_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.DefaultPlaybackRate = 2.0;
videoMediaElement.Play();
}
private void btnReverse_Click(object sender, RoutedEventArgs e)
{
double Int1 = videoMediaElement.Position.TotalSeconds - 10;
if (Int1 > 0)
{
videoMediaElement.Position = TimeSpan.FromSeconds(videoMediaElement.Position.TotalSeconds - 10);
videoMediaElement.Play();
}
else
{
videoMediaElement.Position = TimeSpan.FromSeconds(0);
videoMediaElement.Play();
}
}
private void btnVolumeDown_Click(object sender, RoutedEventArgs e)
{
if (videoMediaElement.IsMuted)
{
videoMediaElement.IsMuted = false;
}
if (videoMediaElement.Volume < 1)
{
videoMediaElement.Volume += .1;
}
}
private void btnMute_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.IsMuted = !videoMediaElement.IsMuted;
}
private void btnVolumeUp_Click(object sender, RoutedEventArgs e)
{
if (videoMediaElement.IsMuted)
{
videoMediaElement.IsMuted = false;
}
if (videoMediaElement.Volume > 0)
{
videoMediaElement.Volume -= .1;
}
}
private void cbAudioTracks_SelectionChanged(
object sender, SelectionChangedEventArgs e)
{
//videoMediaElement.AudioStreamIndex = cbAudioTracks.SelectedIndex;
}
private void PopulateAudioTracks(
MediaElement media, ComboBox audioSelection)
{
if (media.AudioStreamCount > 0)
{
for (int index = 0; index < media.AudioStreamCount; index++)
{
ComboBoxItem track = new ComboBoxItem();
track.Content = media.GetAudioStreamLanguage(index);
audioSelection.Items.Add(track);
}
}
}
private async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
timelineSlider.ValueChanged += timelineSlider_ValueChanged;
PointerEventHandler pointerpressedhandler = new PointerEventHandler(slider_PointerEntered);
timelineSlider.AddHandler(Control.PointerPressedEvent, pointerpressedhandler, true);
PointerEventHandler pointerreleasedhandler = new PointerEventHandler(slider_PointerCaptureLost);
timelineSlider.AddHandler(Control.PointerCaptureLostEvent, pointerreleasedhandler, true);
}
void videoElement_MediaOpened(object sender, RoutedEventArgs e)
{
double absvalue = (int)Math.Round(
videoMediaElement.NaturalDuration.TimeSpan.TotalSeconds,
MidpointRounding.AwayFromZero);
timelineSlider.Maximum = absvalue;
timelineSlider.StepFrequency =
SliderFrequency(videoMediaElement.NaturalDuration.TimeSpan);
SetupTimer();
// Helper method to populate the combobox with audio tracks.
//PopulateAudioTracks(videoMediaElement, cbAudioTracks);
}
private bool _sliderpressed = false;
void slider_PointerEntered(object sender, PointerRoutedEventArgs e)
{
_sliderpressed = true;
}
void slider_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
{
videoMediaElement.Position = TimeSpan.FromSeconds(timelineSlider.Value);
_sliderpressed = false;
}
void timelineSlider_ValueChanged(object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e)
{
if (!_sliderpressed)
{
videoMediaElement.Position = TimeSpan.FromSeconds(e.NewValue);
}
}
void videoMediaElement_CurrentStateChanged(object sender, RoutedEventArgs e)
{
if (videoMediaElement.CurrentState == MediaElementState.Playing)
{
Play1.Content = "M27.270001,0L44.310001,0 44.310001,48.643002 27.270001,48.643002z M0,0L17.040001,0 17.040001,48.643002 0,48.643002z";
Play1.Padding = new Thickness(20, 10, 20, 10);
if (_sliderpressed)
{
_timer.Stop();
}
else
{
_timer.Start();
}
}
if (videoMediaElement.CurrentState == MediaElementState.Paused)
{
Play1.Content = "M0,0L384.885,191.965 769.768,383.928 384.885,576.035 0,768 0,383.928z"; // Play
Play1.Padding = new Thickness(19, 5, 12, 5);
_timer.Stop();
}
if (videoMediaElement.CurrentState == MediaElementState.Stopped)
{
_timer.Stop();
timelineSlider.Value = 0;
}
}
void videoMediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
StopTimer();
timelineSlider.Value = 0.0;
}
private void videoMediaElement_MediaFailed(object sender, ExceptionRoutedEventArgs e)
{
// get HRESULT from event args
string hr = GetHresultFromErrorMessage(e);
// Handle media failed event appropriately
}
private string GetHresultFromErrorMessage(ExceptionRoutedEventArgs e)
{
String hr = String.Empty;
String token = "HRESULT - ";
const int hrLength = 10; // eg "0xFFFFFFFF"
int tokenPos = e.ErrorMessage.IndexOf(token, StringComparison.Ordinal);
if (tokenPos != -1)
{
hr = e.ErrorMessage.Substring(tokenPos + token.Length, hrLength);
}
return hr;
}
private DispatcherTimer _timer;
private void SetupTimer()
{
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromSeconds(1);
StartTimer();
}
private void _timer_Tick(object sender, object e)
{
if (!_sliderpressed)
{
timelineSlider.Value = videoMediaElement.Position.TotalSeconds;
TimeSpan TS = new TimeSpan(videoMediaElement.Position.Hours, videoMediaElement.Position.Minutes, videoMediaElement.Position.Seconds);
TimeSpan TS1 = new TimeSpan(videoMediaElement.NaturalDuration.TimeSpan.Hours, videoMediaElement.NaturalDuration.TimeSpan.Minutes, videoMediaElement.NaturalDuration.TimeSpan.Seconds);
TextBlock1.Text = TS.Duration().ToString("c") + " / " + TS1.Duration().ToString("c");
}
}
private void StartTimer()
{
_timer.Tick += _timer_Tick;
_timer.Start();
}
private void StopTimer()
{
_timer.Stop();
_timer.Tick -= _timer_Tick;
}
private double SliderFrequency(TimeSpan timevalue)
{
double stepfrequency = -1;
double absvalue = (int)Math.Round(
timevalue.TotalSeconds, MidpointRounding.AwayFromZero);
stepfrequency = (int)(Math.Round(absvalue / 100));
if (timevalue.TotalMinutes >= 10 && timevalue.TotalMinutes < 30)
{
stepfrequency = 10;
}
else if (timevalue.TotalMinutes >= 30 && timevalue.TotalMinutes < 60)
{
stepfrequency = 30;
}
else if (timevalue.TotalHours >= 1)
{
stepfrequency = 60;
}
if (stepfrequency == 0) stepfrequency += 1;
if (stepfrequency == 1)
{
stepfrequency = absvalue / 100;
}
return stepfrequency;
}
private void videoMediaElement_PointerPressed(object sender, PointerRoutedEventArgs e)
{
if (TransportControlsPanel.Visibility == Windows.UI.Xaml.Visibility.Visible)
{
TransportControlsPanel.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
timer.Stop();
}
else
{
TransportControlsPanel.Visibility = Windows.UI.Xaml.Visibility.Visible;
Start_timer();
}
}
}
下次尝试给你代码,用这种方式展示你做了什么,这样更容易提供帮助。
您是否在 msdn 上看到了解释如何执行自定义媒体播放器控件的页面?
How to create custom media transport controls (XAML)
您提到了 AreTransportControlsEnabled 我不认为它有延迟,请记住,如果您尝试使用模拟器,它是一个运行 Windows [=43= 的虚拟机] 因此,如果您没有非常强大的计算机,您可能会看到一些延迟,例如在诺基亚 930 上看不到。
但是如果你还想自定义的话,我觉得你可以从msdn给的代码入手。
MainPage.xaml
<Page
x:Class="MediaPlayerQuickStart.MainPage"
IsTabStop="false"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MediaPlayerQuickStart"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Loaded="MainPage_Loaded">
<Page.Resources>
<Style x:Name="transportStyle" TargetType="Button">
<Setter Property="Height" Value="40" />
<Setter Property="Width" Value="75" />
<Setter Property="FontSize" Value="11" />
</Style>
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<ContentControl x:Name="videoContainer"
KeyUp="VideoContainer_KeyUp"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Height="400" Grid.Row="0" >
<MediaElement Name="videoMediaElement"
Source="Media/video1.mp4"
MediaOpened="videoElement_MediaOpened"
MediaEnded="videoMediaElement_MediaEnded"
MediaFailed="videoMediaElement_MediaFailed"
CurrentStateChanged="videoMediaElement_CurrentStateChanged"
PosterSource="Media/Video1_Poster.png"
AutoPlay="False" />
</ContentControl>
<!-- Transport Controls -->
<StackPanel Name="TransportControlsPanel"
HorizontalAlignment="Center"
Grid.Row="1" >
<Slider Name="timelineSlider" Margin="10,0" Width="200"/>
<StackPanel Orientation="Horizontal">
<Button Name="btnPlay" Click="btnPlay_Click"
Style="{StaticResource transportStyle}" Content="Play" />
<Button Name="btnPause" Click="btnPause_Click"
Style="{StaticResource transportStyle}" Content="Pause" />
<Button Name="btnStop" Click="btnStop_Click"
Style="{StaticResource transportStyle}" Content="Stop" />
<Button Name="btnReverse" Click="btnReverse_Click"
Style="{StaticResource transportStyle}" Content="Rewind" />
<Button Name="btnForward" Click="btnForward_Click"
Style="{StaticResource transportStyle}" Content="Forward" />
<Button Name="btnMute" Click="btnMute_Click"
Style="{StaticResource transportStyle}" Content="Mute" />
<Button Name="btnFullScreenToggle" Click="btnFullScreenToggle_Click"
Style="{StaticResource transportStyle}" Content="Full" />
<ComboBox Name="cbAudioTracks"
SelectionChanged="cbAudioTracks_SelectionChanged"
Width="75" />
<Button Name="btnVolumeUp" Click="btnVolumeUp_Click"
Style="{StaticResource transportStyle}" Content="-" />
<Button Name="btnVolumeDown" Click="btnVolumeDown_Click"
Style="{StaticResource transportStyle}" Content="+" />
<TextBlock Name="txtVolume" FontSize="14"
Text="{Binding Volume, ElementName=videoMediaElement}"
VerticalAlignment="Center" HorizontalAlignment="Right" />
</StackPanel>
</StackPanel>
</Grid>
</Page>
MainPage.xaml.cs
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
// You should use the MediaElement.IsFullWindow property instead
// to enable and disable full window rendering.
private bool _isFullscreenToggle = false;
public bool IsFullscreen
{
get { return _isFullscreenToggle; }
set { _isFullscreenToggle = value; }
}
private Size _previousVideoContainerSize = new Size();
private void FullscreenToggle()
{
this.IsFullscreen = !this.IsFullscreen;
if (this.IsFullscreen)
{
TransportControlsPanel.Visibility = Visibility.Collapsed;
_previousVideoContainerSize.Width = videoContainer.ActualWidth;
_previousVideoContainerSize.Height = videoContainer.ActualHeight;
videoContainer.Width = Window.Current.Bounds.Width;
videoContainer.Height = Window.Current.Bounds.Height;
videoMediaElement.Width = Window.Current.Bounds.Width;
videoMediaElement.Height = Window.Current.Bounds.Height;
}
else
{
TransportControlsPanel.Visibility = Visibility.Visible;
videoContainer.Width = _previousVideoContainerSize.Width;
videoContainer.Height = _previousVideoContainerSize.Height;
videoMediaElement.Width = _previousVideoContainerSize.Width;
videoMediaElement.Height = _previousVideoContainerSize.Height;
}
}
private void btnFullScreenToggle_Click(object sender, RoutedEventArgs e)
{
FullscreenToggle();
}
private void VideoContainer_KeyUp(object sender, KeyRoutedEventArgs e)
{
if (IsFullscreen && e.Key == Windows.System.VirtualKey.Escape)
{
FullscreenToggle();
}
e.Handled = true;
}
private void btnPlay_Click(object sender, RoutedEventArgs e)
{
if (videoMediaElement.DefaultPlaybackRate != 1)
{
videoMediaElement.DefaultPlaybackRate = 1.0;
}
videoMediaElement.Play();
}
private void btnPause_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.Pause();
}
private void btnStop_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.Stop();
}
private void btnForward_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.DefaultPlaybackRate = 2.0;
videoMediaElement.Play();
}
private void btnReverse_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.DefaultPlaybackRate = -2;
videoMediaElement.Play();;
}
private void btnVolumeDown_Click(object sender, RoutedEventArgs e)
{
if (videoMediaElement.IsMuted)
{
videoMediaElement.IsMuted = false;
}
if (videoMediaElement.Volume < 1)
{
videoMediaElement.Volume += .1;
}
}
private void btnMute_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.IsMuted = !videoMediaElement.IsMuted;
}
private void btnVolumeUp_Click(object sender, RoutedEventArgs e)
{
if (videoMediaElement.IsMuted)
{
videoMediaElement.IsMuted = false;
}
if (videoMediaElement.Volume > 0)
{
videoMediaElement.Volume -= .1;
}
}
private void cbAudioTracks_SelectionChanged(
object sender, SelectionChangedEventArgs e)
{
videoMediaElement.AudioStreamIndex = cbAudioTracks.SelectedIndex;
}
private void PopulateAudioTracks(
MediaElement media, ComboBox audioSelection)
{
if (media.AudioStreamCount > 0)
{
for (int index = 0; index < media.AudioStreamCount; index++)
{
ComboBoxItem track = new ComboBoxItem();
track.Content = media.GetAudioStreamLanguage(index);
audioSelection.Items.Add(track);
}
}
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
timelineSlider.ValueChanged += timelineSlider_ValueChanged;
PointerEventHandler pointerpressedhandler = new PointerEventHandler(slider_PointerEntered);
timelineSlider.AddHandler(Control.PointerPressedEvent, pointerpressedhandler, true);
PointerEventHandler pointerreleasedhandler = new PointerEventHandler(slider_PointerCaptureLost);
timelineSlider.AddHandler(Control.PointerCaptureLostEvent, pointerreleasedhandler, true);
}
void videoElement_MediaOpened(object sender, RoutedEventArgs e)
{
double absvalue = (int)Math.Round(
videoMediaElement.NaturalDuration.TimeSpan.TotalSeconds,
MidpointRounding.AwayFromZero);
timelineSlider.Maximum = absvalue;
timelineSlider.StepFrequency =
SliderFrequency(videoMediaElement.NaturalDuration.TimeSpan);
SetupTimer();
// Helper method to populate the combobox with audio tracks.
PopulateAudioTracks(videoMediaElement, cbAudioTracks);
}
private bool _sliderpressed = false;
void slider_PointerEntered(object sender, PointerRoutedEventArgs e)
{
_sliderpressed = true;
}
void slider_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
{
videoMediaElement.Position = TimeSpan.FromSeconds(timelineSlider.Value);
_sliderpressed = false;
}
void timelineSlider_ValueChanged(object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e)
{
if (!_sliderpressed)
{
videoMediaElement.Position = TimeSpan.FromSeconds(e.NewValue);
}
}
void videoMediaElement_CurrentStateChanged(object sender, RoutedEventArgs e)
{
if (videoMediaElement.CurrentState == MediaElementState.Playing)
{
if (_sliderpressed)
{
_timer.Stop();
}
else
{
_timer.Start();
}
}
if (videoMediaElement.CurrentState == MediaElementState.Paused)
{
_timer.Stop();
}
if (videoMediaElement.CurrentState == MediaElementState.Stopped)
{
_timer.Stop();
timelineSlider.Value = 0;
}
}
void videoMediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
StopTimer();
timelineSlider.Value = 0.0;
}
private void videoMediaElement_MediaFailed(object sender, ExceptionRoutedEventArgs e)
{
// get HRESULT from event args
string hr = GetHresultFromErrorMessage(e);
// Handle media failed event appropriately
}
private string GetHresultFromErrorMessage(ExceptionRoutedEventArgs e)
{
String hr = String.Empty;
String token = "HRESULT - ";
const int hrLength = 10; // eg "0xFFFFFFFF"
int tokenPos = e.ErrorMessage.IndexOf(token, StringComparison.Ordinal);
if (tokenPos != -1)
{
hr = e.ErrorMessage.Substring(tokenPos + token.Length, hrLength);
}
return hr;
}
private DispatcherTimer _timer;
private void SetupTimer()
{
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromSeconds(timelineSlider.StepFrequency);
StartTimer();
}
private void _timer_Tick(object sender, object e)
{
if (!_sliderpressed)
{
timelineSlider.Value = videoMediaElement.Position.TotalSeconds;
}
}
private void StartTimer()
{
_timer.Tick += _timer_Tick;
_timer.Start();
}
private void StopTimer()
{
_timer.Stop();
_timer.Tick -= _timer_Tick;
}
private double SliderFrequency(TimeSpan timevalue)
{
double stepfrequency = -1;
double absvalue = (int)Math.Round(
timevalue.TotalSeconds, MidpointRounding.AwayFromZero);
stepfrequency = (int)(Math.Round(absvalue / 100));
if (timevalue.TotalMinutes >= 10 && timevalue.TotalMinutes < 30)
{
stepfrequency = 10;
}
else if (timevalue.TotalMinutes >= 30 && timevalue.TotalMinutes < 60)
{
stepfrequency = 30;
}
else if (timevalue.TotalHours >= 1)
{
stepfrequency = 60;
}
if (stepfrequency == 0) stepfrequency += 1;
if (stepfrequency == 1)
{
stepfrequency = absvalue / 100;
}
return stepfrequency;
}
}
如果你想改变按钮的外观,你可以使用 AppBarButton 而不是普通按钮(给它们圆形 windows8 的外观)
要更改全屏行为,请查看 FullscreenToggle()。在此示例中,他们使用控件折叠 StackPanel,但您不必这样做并且可以实现您自己的逻辑。
美好的一天,
我正在创建一个需要媒体播放器的应用程序。我尝试使用 AreTransportControlsEnabled,但它有点滞后,这是我不想要的。在我的 windows phone 上,我有一个应用程序 "Files"<-(Windows Phone 8.1 中的一个应用程序)我用它来播放我的一个视频,我看到了它的视频播放器。我在想我能不能做到这样的Player。任何关于如何实现此播放器的建议?
图片:http://s22.postimg.org/plu0oqxv5/wp_ss_20150329_0002.png
我尝试制作自定义控件,但在全屏模式下控件不显示。是否有 api 或其他方法可以做到这一点?
已回答问题
我的自定义媒体播放器
主要Page.xalm
<Page
x:Class="MediaPlayer.MainPage"
IsTabStop="false"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MediaPlayer"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Loaded="MainPage_Loaded">
<Page.Resources>
<Style x:Name="transportStyle" TargetType="Button">
<Setter Property="Height" Value="40" />
<Setter Property="Width" Value="75" />
<Setter Property="FontSize" Value="11" />
</Style>
<Thickness x:Key="PhoneBorderThickness">2.5</Thickness>
<FontFamily x:Key="PhoneFontFamilyNormal">Segoe WP</FontFamily>
<FontWeight x:Key="PhoneButtonFontWeight">Semibold</FontWeight>
<x:Double x:Key="TextStyleLargeFontSize">18.14</x:Double>
<x:Double x:Key="PhoneButtonMinHeight">0</x:Double>
<x:Double x:Key="PhoneButtonMinWidth">0</x:Double>
<Thickness x:Key="PhoneTouchTargetOverhang">0,0</Thickness>
<SolidColorBrush x:Key="ButtonDisabledBackgroundThemeBrush" Color="Transparent"/>
<Style x:Key="RoundButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="{ThemeResource PhoneForegroundBrush}"/>
<Setter Property="Foreground" Value="{ThemeResource PhoneForegroundBrush}"/>
<Setter Property="BorderThickness" Value="{ThemeResource PhoneBorderThickness}"/>
<Setter Property="FontFamily" Value="{ThemeResource PhoneFontFamilyNormal}"/>
<Setter Property="FontWeight" Value="{ThemeResource PhoneButtonFontWeight}"/>
<Setter Property="FontSize" Value="{ThemeResource TextStyleLargeFontSize}"/>
<Setter Property="Padding" Value="9.5,0"/>
<Setter Property="MinHeight" Value="{ThemeResource PhoneButtonMinHeight}"/>
<Setter Property="MinWidth" Value="{ThemeResource PhoneButtonMinWidth}"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Path Stretch="Uniform"
RenderTransformOrigin="0.5,0.5"
Margin="2,6,2,2"
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Data="{Binding Path=Content, RelativeSource={RelativeSource Mode=TemplatedParent}}"></Path>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="Grid" Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition From="Pressed" To="PointerOver">
<Storyboard>
<PointerUpThemeAnimation Storyboard.TargetName="Grid"/>
</Storyboard>
</VisualTransition>
<VisualTransition From="PointerOver" To="Normal">
<Storyboard>
<PointerUpThemeAnimation Storyboard.TargetName="Grid"/>
</Storyboard>
</VisualTransition>
<VisualTransition From="Pressed" To="Normal">
<Storyboard>
<PointerUpThemeAnimation Storyboard.TargetName="Grid"/>
</Storyboard>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver"/>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPressedForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Border">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPressedBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonDisabledForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="Border">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonDisabledBorderThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="Border">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonDisabledBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="{ThemeResource PhoneTouchTargetOverhang}" Height="{Binding Path=Height, RelativeSource={RelativeSource Mode=TemplatedParent}}" Width="{Binding Path=Width, RelativeSource={RelativeSource Mode=TemplatedParent}}" CornerRadius="72">
<ContentPresenter x:Name="ContentPresenter" AutomationProperties.AccessibilityView="Raw" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<!--<RowDefinition Height="150"/>-->
</Grid.RowDefinitions>
<ContentControl x:Name="videoContainer"
KeyUp="VideoContainer_KeyUp"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
Grid.Row="0" >
<MediaElement Name="videoMediaElement"
Source="Media/video1.mp4"
MediaOpened="videoElement_MediaOpened"
MediaEnded="videoMediaElement_MediaEnded"
MediaFailed="videoMediaElement_MediaFailed"
CurrentStateChanged="videoMediaElement_CurrentStateChanged"
PosterSource="Media/Video1_Poster.png" PointerPressed="videoMediaElement_PointerPressed" />
</ContentControl>
<!-- Transport Controls -->
<StackPanel Name="TransportControlsPanel"
Grid.Row="0" VerticalAlignment="Bottom" Background="#CC000000" >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,15,0,0">
<Button HorizontalAlignment="Left" Click="btnReverse_Click" VerticalAlignment="Top" Style="{StaticResource RoundButtonStyle}" Height="72" Width="72" Content="M13.862404,0L17.667,3.8059161 10.879305,10.593651 17.6241,17.568752 13.861103,21.333 3.1840002,10.678149z M0,0L3.0719999,0 3.0719999,21.032 0,21.032z" Padding="20,5" Margin="20,0" BorderBrush="White" Background="#FFE6E6E6"/>
<Button x:Name="Play1" HorizontalAlignment="Left" Click="btnPlay_Click" VerticalAlignment="Top" Style="{StaticResource RoundButtonStyle}" Height="72" Width="72" Content="M27.270001,0L44.310001,0 44.310001,48.643002 27.270001,48.643002z M0,0L17.040001,0 17.040001,48.643002 0,48.643002z" Padding="20,10" Margin="20,0" BorderBrush="White" Background="#FFE6E6E6"/>
<Button HorizontalAlignment="Left" Click="btnForward_Click" VerticalAlignment="Top" Style="{StaticResource RoundButtonStyle}" Height="72" Width="72" Content="M14.595,0L17.668,0 17.668,21.032 14.595,21.032z M3.8059254,0L14.484001,10.67815 3.8059254,21.333 0.04431057,17.568752 6.7875929,10.593651 0,3.8059165z" Padding="20,5" Margin="20,0" BorderBrush="White" Background="#FFE6E6E6"/>
<Button HorizontalAlignment="Left" Click="btnFullScreenToggle_Click" VerticalAlignment="Top" Style="{StaticResource RoundButtonStyle}" Height="72" Width="72" Content="M0,2.3629998L11.63953,2.3629998 9.1447105,4.8564929 2.4934592,4.8564929 2.4934592,14.710437 12.712251,14.710437 12.712251,8.4683789 15.206,5.9748863 15.206,17.204 0,17.204z M11.741774,0L17.591398,0 17.591999,5.8514608 15.648591,3.9075235 7.7964079,11.759001 5.8289994,9.7914637 13.681183,1.9400271z" Padding="13,10,10,15" Margin="20,0" BorderBrush="White" Background="#FFE6E6E6"/>
</StackPanel>
<Slider Name="timelineSlider" HorizontalContentAlignment="Stretch" Margin="10,20,10,0"/>
<TextBlock x:Name="TextBlock1" Text="00:0 / 00:0" FontSize="18" Margin="20,0,20,40" Foreground="White"/>
</StackPanel>
</Grid>
MainPage.cs
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
// You should use the MediaElement.IsFullWindow property instead
// to enable and disable full window rendering.
private bool _isFullscreenToggle = false;
public bool IsFullscreen
{
get { return _isFullscreenToggle; }
set { _isFullscreenToggle = value; }
}
private Size _previousVideoContainerSize = new Size();
private async void FullscreenToggle()
{
this.IsFullscreen = !this.IsFullscreen;
if (this.IsFullscreen)
{
//TransportControlsPanel.Visibility = Visibility.Collapsed;
await Windows.UI.ViewManagement.StatusBar.GetForCurrentView().HideAsync();
DisplayInformation.AutoRotationPreferences = DisplayOrientations.Landscape | DisplayOrientations.LandscapeFlipped;
_previousVideoContainerSize.Width = videoContainer.ActualWidth;
_previousVideoContainerSize.Height = videoContainer.ActualHeight;
videoContainer.Width = Window.Current.Bounds.Width;
videoContainer.Height = Window.Current.Bounds.Height;
videoMediaElement.Width = Window.Current.Bounds.Width;
videoMediaElement.Height = Window.Current.Bounds.Height;
// Trigger the Visual State Manager
//VisualStateManager.GoToState(this, "Landscape", false);
}
else
{
//TransportControlsPanel.Visibility = Visibility.Visible;
await Windows.UI.ViewManagement.StatusBar.GetForCurrentView().ShowAsync();
DisplayInformation.AutoRotationPreferences = DisplayOrientations.None;
videoContainer.Width = _previousVideoContainerSize.Width;
videoContainer.Height = _previousVideoContainerSize.Height;
videoMediaElement.Width = _previousVideoContainerSize.Width;
videoMediaElement.Height = _previousVideoContainerSize.Height;
// Trigger the Visual State Manager
//VisualStateManager.GoToState(this, "Portrait",false);
}
}
private void btnFullScreenToggle_Click(object sender, RoutedEventArgs e)
{
FullscreenToggle();
}
private void VideoContainer_KeyUp(object sender, KeyRoutedEventArgs e)
{
if (IsFullscreen && e.Key == Windows.System.VirtualKey.Escape)
{
FullscreenToggle();
}
e.Handled = true;
}
private void btnPlay_Click(object sender, RoutedEventArgs e)
{
if (videoMediaElement.DefaultPlaybackRate != 1)
{
videoMediaElement.DefaultPlaybackRate = 1.0;
}
if (videoMediaElement.CurrentState == MediaElementState.Playing)
{
videoMediaElement.Pause();
Play1.Content = "M0,0L384.885,191.965 769.768,383.928 384.885,576.035 0,768 0,383.928z"; // Play
Play1.Padding = new Thickness(19, 5, 12, 5);
}
else if (videoMediaElement.CurrentState == MediaElementState.Paused)
{
videoMediaElement.Play();
Play1.Content = "M27.270001,0L44.310001,0 44.310001,48.643002 27.270001,48.643002z M0,0L17.040001,0 17.040001,48.643002 0,48.643002z";
Play1.Padding = new Thickness(20, 10, 20, 10);
}
}
DispatcherTimer timer = new DispatcherTimer();
public void Start_timer()
{
timer.Tick += timer_Tick;
timer.Interval = new TimeSpan(00, 0, 5);
bool enabled = timer.IsEnabled;
timer.Start();
}
void timer_Tick(object sender, object e)
{
//function to execute
if (TransportControlsPanel.Visibility == Windows.UI.Xaml.Visibility.Visible)
{
TransportControlsPanel.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
}
timer.Stop();
}
private void btnPause_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.Pause();
}
private void btnStop_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.Stop();
}
private void btnForward_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.DefaultPlaybackRate = 2.0;
videoMediaElement.Play();
}
private void btnReverse_Click(object sender, RoutedEventArgs e)
{
double Int1 = videoMediaElement.Position.TotalSeconds - 10;
if (Int1 > 0)
{
videoMediaElement.Position = TimeSpan.FromSeconds(videoMediaElement.Position.TotalSeconds - 10);
videoMediaElement.Play();
}
else
{
videoMediaElement.Position = TimeSpan.FromSeconds(0);
videoMediaElement.Play();
}
}
private void btnVolumeDown_Click(object sender, RoutedEventArgs e)
{
if (videoMediaElement.IsMuted)
{
videoMediaElement.IsMuted = false;
}
if (videoMediaElement.Volume < 1)
{
videoMediaElement.Volume += .1;
}
}
private void btnMute_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.IsMuted = !videoMediaElement.IsMuted;
}
private void btnVolumeUp_Click(object sender, RoutedEventArgs e)
{
if (videoMediaElement.IsMuted)
{
videoMediaElement.IsMuted = false;
}
if (videoMediaElement.Volume > 0)
{
videoMediaElement.Volume -= .1;
}
}
private void cbAudioTracks_SelectionChanged(
object sender, SelectionChangedEventArgs e)
{
//videoMediaElement.AudioStreamIndex = cbAudioTracks.SelectedIndex;
}
private void PopulateAudioTracks(
MediaElement media, ComboBox audioSelection)
{
if (media.AudioStreamCount > 0)
{
for (int index = 0; index < media.AudioStreamCount; index++)
{
ComboBoxItem track = new ComboBoxItem();
track.Content = media.GetAudioStreamLanguage(index);
audioSelection.Items.Add(track);
}
}
}
private async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
timelineSlider.ValueChanged += timelineSlider_ValueChanged;
PointerEventHandler pointerpressedhandler = new PointerEventHandler(slider_PointerEntered);
timelineSlider.AddHandler(Control.PointerPressedEvent, pointerpressedhandler, true);
PointerEventHandler pointerreleasedhandler = new PointerEventHandler(slider_PointerCaptureLost);
timelineSlider.AddHandler(Control.PointerCaptureLostEvent, pointerreleasedhandler, true);
}
void videoElement_MediaOpened(object sender, RoutedEventArgs e)
{
double absvalue = (int)Math.Round(
videoMediaElement.NaturalDuration.TimeSpan.TotalSeconds,
MidpointRounding.AwayFromZero);
timelineSlider.Maximum = absvalue;
timelineSlider.StepFrequency =
SliderFrequency(videoMediaElement.NaturalDuration.TimeSpan);
SetupTimer();
// Helper method to populate the combobox with audio tracks.
//PopulateAudioTracks(videoMediaElement, cbAudioTracks);
}
private bool _sliderpressed = false;
void slider_PointerEntered(object sender, PointerRoutedEventArgs e)
{
_sliderpressed = true;
}
void slider_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
{
videoMediaElement.Position = TimeSpan.FromSeconds(timelineSlider.Value);
_sliderpressed = false;
}
void timelineSlider_ValueChanged(object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e)
{
if (!_sliderpressed)
{
videoMediaElement.Position = TimeSpan.FromSeconds(e.NewValue);
}
}
void videoMediaElement_CurrentStateChanged(object sender, RoutedEventArgs e)
{
if (videoMediaElement.CurrentState == MediaElementState.Playing)
{
Play1.Content = "M27.270001,0L44.310001,0 44.310001,48.643002 27.270001,48.643002z M0,0L17.040001,0 17.040001,48.643002 0,48.643002z";
Play1.Padding = new Thickness(20, 10, 20, 10);
if (_sliderpressed)
{
_timer.Stop();
}
else
{
_timer.Start();
}
}
if (videoMediaElement.CurrentState == MediaElementState.Paused)
{
Play1.Content = "M0,0L384.885,191.965 769.768,383.928 384.885,576.035 0,768 0,383.928z"; // Play
Play1.Padding = new Thickness(19, 5, 12, 5);
_timer.Stop();
}
if (videoMediaElement.CurrentState == MediaElementState.Stopped)
{
_timer.Stop();
timelineSlider.Value = 0;
}
}
void videoMediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
StopTimer();
timelineSlider.Value = 0.0;
}
private void videoMediaElement_MediaFailed(object sender, ExceptionRoutedEventArgs e)
{
// get HRESULT from event args
string hr = GetHresultFromErrorMessage(e);
// Handle media failed event appropriately
}
private string GetHresultFromErrorMessage(ExceptionRoutedEventArgs e)
{
String hr = String.Empty;
String token = "HRESULT - ";
const int hrLength = 10; // eg "0xFFFFFFFF"
int tokenPos = e.ErrorMessage.IndexOf(token, StringComparison.Ordinal);
if (tokenPos != -1)
{
hr = e.ErrorMessage.Substring(tokenPos + token.Length, hrLength);
}
return hr;
}
private DispatcherTimer _timer;
private void SetupTimer()
{
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromSeconds(1);
StartTimer();
}
private void _timer_Tick(object sender, object e)
{
if (!_sliderpressed)
{
timelineSlider.Value = videoMediaElement.Position.TotalSeconds;
TimeSpan TS = new TimeSpan(videoMediaElement.Position.Hours, videoMediaElement.Position.Minutes, videoMediaElement.Position.Seconds);
TimeSpan TS1 = new TimeSpan(videoMediaElement.NaturalDuration.TimeSpan.Hours, videoMediaElement.NaturalDuration.TimeSpan.Minutes, videoMediaElement.NaturalDuration.TimeSpan.Seconds);
TextBlock1.Text = TS.Duration().ToString("c") + " / " + TS1.Duration().ToString("c");
}
}
private void StartTimer()
{
_timer.Tick += _timer_Tick;
_timer.Start();
}
private void StopTimer()
{
_timer.Stop();
_timer.Tick -= _timer_Tick;
}
private double SliderFrequency(TimeSpan timevalue)
{
double stepfrequency = -1;
double absvalue = (int)Math.Round(
timevalue.TotalSeconds, MidpointRounding.AwayFromZero);
stepfrequency = (int)(Math.Round(absvalue / 100));
if (timevalue.TotalMinutes >= 10 && timevalue.TotalMinutes < 30)
{
stepfrequency = 10;
}
else if (timevalue.TotalMinutes >= 30 && timevalue.TotalMinutes < 60)
{
stepfrequency = 30;
}
else if (timevalue.TotalHours >= 1)
{
stepfrequency = 60;
}
if (stepfrequency == 0) stepfrequency += 1;
if (stepfrequency == 1)
{
stepfrequency = absvalue / 100;
}
return stepfrequency;
}
private void videoMediaElement_PointerPressed(object sender, PointerRoutedEventArgs e)
{
if (TransportControlsPanel.Visibility == Windows.UI.Xaml.Visibility.Visible)
{
TransportControlsPanel.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
timer.Stop();
}
else
{
TransportControlsPanel.Visibility = Windows.UI.Xaml.Visibility.Visible;
Start_timer();
}
}
}
下次尝试给你代码,用这种方式展示你做了什么,这样更容易提供帮助。
您是否在 msdn 上看到了解释如何执行自定义媒体播放器控件的页面?
How to create custom media transport controls (XAML)
您提到了 AreTransportControlsEnabled 我不认为它有延迟,请记住,如果您尝试使用模拟器,它是一个运行 Windows [=43= 的虚拟机] 因此,如果您没有非常强大的计算机,您可能会看到一些延迟,例如在诺基亚 930 上看不到。
但是如果你还想自定义的话,我觉得你可以从msdn给的代码入手。
MainPage.xaml
<Page
x:Class="MediaPlayerQuickStart.MainPage"
IsTabStop="false"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MediaPlayerQuickStart"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Loaded="MainPage_Loaded">
<Page.Resources>
<Style x:Name="transportStyle" TargetType="Button">
<Setter Property="Height" Value="40" />
<Setter Property="Width" Value="75" />
<Setter Property="FontSize" Value="11" />
</Style>
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<ContentControl x:Name="videoContainer"
KeyUp="VideoContainer_KeyUp"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Height="400" Grid.Row="0" >
<MediaElement Name="videoMediaElement"
Source="Media/video1.mp4"
MediaOpened="videoElement_MediaOpened"
MediaEnded="videoMediaElement_MediaEnded"
MediaFailed="videoMediaElement_MediaFailed"
CurrentStateChanged="videoMediaElement_CurrentStateChanged"
PosterSource="Media/Video1_Poster.png"
AutoPlay="False" />
</ContentControl>
<!-- Transport Controls -->
<StackPanel Name="TransportControlsPanel"
HorizontalAlignment="Center"
Grid.Row="1" >
<Slider Name="timelineSlider" Margin="10,0" Width="200"/>
<StackPanel Orientation="Horizontal">
<Button Name="btnPlay" Click="btnPlay_Click"
Style="{StaticResource transportStyle}" Content="Play" />
<Button Name="btnPause" Click="btnPause_Click"
Style="{StaticResource transportStyle}" Content="Pause" />
<Button Name="btnStop" Click="btnStop_Click"
Style="{StaticResource transportStyle}" Content="Stop" />
<Button Name="btnReverse" Click="btnReverse_Click"
Style="{StaticResource transportStyle}" Content="Rewind" />
<Button Name="btnForward" Click="btnForward_Click"
Style="{StaticResource transportStyle}" Content="Forward" />
<Button Name="btnMute" Click="btnMute_Click"
Style="{StaticResource transportStyle}" Content="Mute" />
<Button Name="btnFullScreenToggle" Click="btnFullScreenToggle_Click"
Style="{StaticResource transportStyle}" Content="Full" />
<ComboBox Name="cbAudioTracks"
SelectionChanged="cbAudioTracks_SelectionChanged"
Width="75" />
<Button Name="btnVolumeUp" Click="btnVolumeUp_Click"
Style="{StaticResource transportStyle}" Content="-" />
<Button Name="btnVolumeDown" Click="btnVolumeDown_Click"
Style="{StaticResource transportStyle}" Content="+" />
<TextBlock Name="txtVolume" FontSize="14"
Text="{Binding Volume, ElementName=videoMediaElement}"
VerticalAlignment="Center" HorizontalAlignment="Right" />
</StackPanel>
</StackPanel>
</Grid>
</Page>
MainPage.xaml.cs
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
// You should use the MediaElement.IsFullWindow property instead
// to enable and disable full window rendering.
private bool _isFullscreenToggle = false;
public bool IsFullscreen
{
get { return _isFullscreenToggle; }
set { _isFullscreenToggle = value; }
}
private Size _previousVideoContainerSize = new Size();
private void FullscreenToggle()
{
this.IsFullscreen = !this.IsFullscreen;
if (this.IsFullscreen)
{
TransportControlsPanel.Visibility = Visibility.Collapsed;
_previousVideoContainerSize.Width = videoContainer.ActualWidth;
_previousVideoContainerSize.Height = videoContainer.ActualHeight;
videoContainer.Width = Window.Current.Bounds.Width;
videoContainer.Height = Window.Current.Bounds.Height;
videoMediaElement.Width = Window.Current.Bounds.Width;
videoMediaElement.Height = Window.Current.Bounds.Height;
}
else
{
TransportControlsPanel.Visibility = Visibility.Visible;
videoContainer.Width = _previousVideoContainerSize.Width;
videoContainer.Height = _previousVideoContainerSize.Height;
videoMediaElement.Width = _previousVideoContainerSize.Width;
videoMediaElement.Height = _previousVideoContainerSize.Height;
}
}
private void btnFullScreenToggle_Click(object sender, RoutedEventArgs e)
{
FullscreenToggle();
}
private void VideoContainer_KeyUp(object sender, KeyRoutedEventArgs e)
{
if (IsFullscreen && e.Key == Windows.System.VirtualKey.Escape)
{
FullscreenToggle();
}
e.Handled = true;
}
private void btnPlay_Click(object sender, RoutedEventArgs e)
{
if (videoMediaElement.DefaultPlaybackRate != 1)
{
videoMediaElement.DefaultPlaybackRate = 1.0;
}
videoMediaElement.Play();
}
private void btnPause_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.Pause();
}
private void btnStop_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.Stop();
}
private void btnForward_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.DefaultPlaybackRate = 2.0;
videoMediaElement.Play();
}
private void btnReverse_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.DefaultPlaybackRate = -2;
videoMediaElement.Play();;
}
private void btnVolumeDown_Click(object sender, RoutedEventArgs e)
{
if (videoMediaElement.IsMuted)
{
videoMediaElement.IsMuted = false;
}
if (videoMediaElement.Volume < 1)
{
videoMediaElement.Volume += .1;
}
}
private void btnMute_Click(object sender, RoutedEventArgs e)
{
videoMediaElement.IsMuted = !videoMediaElement.IsMuted;
}
private void btnVolumeUp_Click(object sender, RoutedEventArgs e)
{
if (videoMediaElement.IsMuted)
{
videoMediaElement.IsMuted = false;
}
if (videoMediaElement.Volume > 0)
{
videoMediaElement.Volume -= .1;
}
}
private void cbAudioTracks_SelectionChanged(
object sender, SelectionChangedEventArgs e)
{
videoMediaElement.AudioStreamIndex = cbAudioTracks.SelectedIndex;
}
private void PopulateAudioTracks(
MediaElement media, ComboBox audioSelection)
{
if (media.AudioStreamCount > 0)
{
for (int index = 0; index < media.AudioStreamCount; index++)
{
ComboBoxItem track = new ComboBoxItem();
track.Content = media.GetAudioStreamLanguage(index);
audioSelection.Items.Add(track);
}
}
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
timelineSlider.ValueChanged += timelineSlider_ValueChanged;
PointerEventHandler pointerpressedhandler = new PointerEventHandler(slider_PointerEntered);
timelineSlider.AddHandler(Control.PointerPressedEvent, pointerpressedhandler, true);
PointerEventHandler pointerreleasedhandler = new PointerEventHandler(slider_PointerCaptureLost);
timelineSlider.AddHandler(Control.PointerCaptureLostEvent, pointerreleasedhandler, true);
}
void videoElement_MediaOpened(object sender, RoutedEventArgs e)
{
double absvalue = (int)Math.Round(
videoMediaElement.NaturalDuration.TimeSpan.TotalSeconds,
MidpointRounding.AwayFromZero);
timelineSlider.Maximum = absvalue;
timelineSlider.StepFrequency =
SliderFrequency(videoMediaElement.NaturalDuration.TimeSpan);
SetupTimer();
// Helper method to populate the combobox with audio tracks.
PopulateAudioTracks(videoMediaElement, cbAudioTracks);
}
private bool _sliderpressed = false;
void slider_PointerEntered(object sender, PointerRoutedEventArgs e)
{
_sliderpressed = true;
}
void slider_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
{
videoMediaElement.Position = TimeSpan.FromSeconds(timelineSlider.Value);
_sliderpressed = false;
}
void timelineSlider_ValueChanged(object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e)
{
if (!_sliderpressed)
{
videoMediaElement.Position = TimeSpan.FromSeconds(e.NewValue);
}
}
void videoMediaElement_CurrentStateChanged(object sender, RoutedEventArgs e)
{
if (videoMediaElement.CurrentState == MediaElementState.Playing)
{
if (_sliderpressed)
{
_timer.Stop();
}
else
{
_timer.Start();
}
}
if (videoMediaElement.CurrentState == MediaElementState.Paused)
{
_timer.Stop();
}
if (videoMediaElement.CurrentState == MediaElementState.Stopped)
{
_timer.Stop();
timelineSlider.Value = 0;
}
}
void videoMediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
StopTimer();
timelineSlider.Value = 0.0;
}
private void videoMediaElement_MediaFailed(object sender, ExceptionRoutedEventArgs e)
{
// get HRESULT from event args
string hr = GetHresultFromErrorMessage(e);
// Handle media failed event appropriately
}
private string GetHresultFromErrorMessage(ExceptionRoutedEventArgs e)
{
String hr = String.Empty;
String token = "HRESULT - ";
const int hrLength = 10; // eg "0xFFFFFFFF"
int tokenPos = e.ErrorMessage.IndexOf(token, StringComparison.Ordinal);
if (tokenPos != -1)
{
hr = e.ErrorMessage.Substring(tokenPos + token.Length, hrLength);
}
return hr;
}
private DispatcherTimer _timer;
private void SetupTimer()
{
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromSeconds(timelineSlider.StepFrequency);
StartTimer();
}
private void _timer_Tick(object sender, object e)
{
if (!_sliderpressed)
{
timelineSlider.Value = videoMediaElement.Position.TotalSeconds;
}
}
private void StartTimer()
{
_timer.Tick += _timer_Tick;
_timer.Start();
}
private void StopTimer()
{
_timer.Stop();
_timer.Tick -= _timer_Tick;
}
private double SliderFrequency(TimeSpan timevalue)
{
double stepfrequency = -1;
double absvalue = (int)Math.Round(
timevalue.TotalSeconds, MidpointRounding.AwayFromZero);
stepfrequency = (int)(Math.Round(absvalue / 100));
if (timevalue.TotalMinutes >= 10 && timevalue.TotalMinutes < 30)
{
stepfrequency = 10;
}
else if (timevalue.TotalMinutes >= 30 && timevalue.TotalMinutes < 60)
{
stepfrequency = 30;
}
else if (timevalue.TotalHours >= 1)
{
stepfrequency = 60;
}
if (stepfrequency == 0) stepfrequency += 1;
if (stepfrequency == 1)
{
stepfrequency = absvalue / 100;
}
return stepfrequency;
}
}
如果你想改变按钮的外观,你可以使用 AppBarButton 而不是普通按钮(给它们圆形 windows8 的外观)
要更改全屏行为,请查看 FullscreenToggle()。在此示例中,他们使用控件折叠 StackPanel,但您不必这样做并且可以实现您自己的逻辑。