From a55e4561e3e184b51b8f1d7f355a601ca9a06a6b Mon Sep 17 00:00:00 2001 From: James Crutchley Date: Fri, 27 Sep 2024 13:14:09 -0700 Subject: [PATCH 1/6] Add custom transport controls and resource dictionary Introduced a new embedded resource, `ResourceDictionary.windows.xaml`, in the `CommunityToolkit.Maui.MediaElement.csproj` project file. Updated `MauiMediaElement.windows.cs`: - Imported new namespaces. - Added `CustomTransportControls` field and methods for loading resource dictionary and applying custom styles. - Updated constructor to load resource dictionary and set custom transport controls. - Added `LoadResourceDictionary`, `ApplyCustomStyle`, and `SetTransportControls` methods. - Updated `Dispose` method to handle custom transport controls. - Removed `OnMediaPlayerElementPointerMoved` method and related code. - Updated `OnFullScreenButtonClick` method to remove fullscreen button references. Updated `MediaManager.windows.cs`: - Disabled `SystemMediaTransportControls` in `CreatePlatformView`. Added `CustomTransportControls` class in `CommunityToolkit.Maui.Primitives`: - Imported necessary namespaces. - Defined `FullScreenButton` property. - Implemented `OnTemplateLoaded` event. - Overrode `OnApplyTemplate` method to add full-screen button. - Added `FullScreenButton_Click` event handler. - Introduced `isFullScreen` field to track full-screen state. --- .../CommunityToolkit.Maui.MediaElement.csproj | 5 + .../CustomTransportControls.windows.cs | 65 ++ .../ResourceDictionary.windows.xaml | 791 ++++++++++++++++++ .../Views/MauiMediaElement.windows.cs | 128 +-- .../Views/MediaManager.windows.cs | 2 + 5 files changed, 932 insertions(+), 59 deletions(-) create mode 100644 src/CommunityToolkit.Maui.MediaElement/Primitives/CustomTransportControls.windows.cs create mode 100644 src/CommunityToolkit.Maui.MediaElement/ResourceDictionary.windows.xaml diff --git a/src/CommunityToolkit.Maui.MediaElement/CommunityToolkit.Maui.MediaElement.csproj b/src/CommunityToolkit.Maui.MediaElement/CommunityToolkit.Maui.MediaElement.csproj index 8fab04e6d9..09adf0dfe1 100644 --- a/src/CommunityToolkit.Maui.MediaElement/CommunityToolkit.Maui.MediaElement.csproj +++ b/src/CommunityToolkit.Maui.MediaElement/CommunityToolkit.Maui.MediaElement.csproj @@ -68,4 +68,9 @@ + + + ResourceDictionary.windows.xaml + + \ No newline at end of file diff --git a/src/CommunityToolkit.Maui.MediaElement/Primitives/CustomTransportControls.windows.cs b/src/CommunityToolkit.Maui.MediaElement/Primitives/CustomTransportControls.windows.cs new file mode 100644 index 0000000000..fc2502348d --- /dev/null +++ b/src/CommunityToolkit.Maui.MediaElement/Primitives/CustomTransportControls.windows.cs @@ -0,0 +1,65 @@ +using CommunityToolkit.Maui.Core; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Button = Microsoft.UI.Xaml.Controls.Button; +namespace CommunityToolkit.Maui.Primitives; + +/// +/// A class that provides a way to create custom transport controls for a . +/// +public sealed class CustomTransportControls : MediaTransportControls +{ + /// + /// An event that triggers when the template is loaded. + /// + public event EventHandler? OnTemplateLoaded; + + /// + /// A button for Full screen controls. + /// + public AppBarButton? FullScreenButton { get; private set; } + bool isFullScreen = false; + + /// + /// A for a . + /// + public CustomTransportControls() + { + this.DefaultStyleKey = typeof(CustomTransportControls); + } + + /// + /// Add full screen button to the template. + /// + protected override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + var temp = GetTemplateChild("FullWindowButton") as AppBarButton; + if(temp is not null) + { + FullScreenButton = temp; + FullScreenButton.Visibility = Microsoft.UI.Xaml.Visibility.Visible; + OnTemplateLoaded?.Invoke(this, EventArgs.Empty); + FullScreenButton.Click += FullScreenButton_Click; + } + } + + void FullScreenButton_Click(object sender, RoutedEventArgs e) + { + if (FullScreenButton is null) + { + return; + } + if (isFullScreen) + { + FullScreenButton.Icon = new FontIcon { Glyph = "\uE740" }; + isFullScreen = false; + } + else + { + FullScreenButton.Icon = new SymbolIcon(Symbol.BackToWindow); + isFullScreen = true; + } + } +} diff --git a/src/CommunityToolkit.Maui.MediaElement/ResourceDictionary.windows.xaml b/src/CommunityToolkit.Maui.MediaElement/ResourceDictionary.windows.xaml new file mode 100644 index 0000000000..6a797dfa35 --- /dev/null +++ b/src/CommunityToolkit.Maui.MediaElement/ResourceDictionary.windows.xaml @@ -0,0 +1,791 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/CommunityToolkit.Maui.MediaElement/Views/MauiMediaElement.windows.cs b/src/CommunityToolkit.Maui.MediaElement/Views/MauiMediaElement.windows.cs index edac52be68..e11df11b35 100644 --- a/src/CommunityToolkit.Maui.MediaElement/Views/MauiMediaElement.windows.cs +++ b/src/CommunityToolkit.Maui.MediaElement/Views/MauiMediaElement.windows.cs @@ -1,20 +1,17 @@ +using System.Reflection; using CommunityToolkit.Maui.Extensions; +using CommunityToolkit.Maui.Primitives; using CommunityToolkit.Maui.Views; using Microsoft.UI; using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls.Primitives; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; +using Microsoft.UI.Xaml.Markup; using WinRT.Interop; using Application = Microsoft.Maui.Controls.Application; -using Button = Microsoft.UI.Xaml.Controls.Button; -using Colors = Microsoft.UI.Colors; using Grid = Microsoft.UI.Xaml.Controls.Grid; using Page = Microsoft.Maui.Controls.Page; -using SolidColorBrush = Microsoft.UI.Xaml.Media.SolidColorBrush; -using Thickness = Microsoft.UI.Xaml.Thickness; namespace CommunityToolkit.Maui.Core.Views; @@ -26,12 +23,8 @@ public class MauiMediaElement : Grid, IDisposable static readonly AppWindow appWindow = GetAppWindowForCurrentWindow(); readonly Popup popup = new(); readonly Grid fullScreenGrid = new(); - readonly Grid buttonContainer; - readonly Button fullScreenButton; readonly MediaPlayerElement mediaPlayerElement; - // Cannot be static readonly because we need to be able to add icon to multiple instances of the button - readonly FontIcon fullScreenIcon = new() { Glyph = "\uE740", FontFamily = new FontFamily("Segoe Fluent Icons") }; - readonly FontIcon exitFullScreenIcon = new() { Glyph = "\uE73F", FontFamily = new FontFamily("Segoe Fluent Icons") }; + readonly CustomTransportControls? customTransportControls; bool doesNavigationBarExistBeforeFullScreen; bool isDisposed; @@ -41,33 +34,73 @@ public class MauiMediaElement : Grid, IDisposable /// public MauiMediaElement(MediaPlayerElement mediaPlayerElement) { + LoadResourceDictionary(); this.mediaPlayerElement = mediaPlayerElement; + customTransportControls = SetTransportControls(); + Children.Add(this.mediaPlayerElement); + } - fullScreenButton = new Button + void LoadResourceDictionary() + { + var assembly = Assembly.GetExecutingAssembly(); + using Stream? stream = assembly.GetManifestResourceStream("ResourceDictionary.windows.xaml"); + if (stream is null) { - Content = fullScreenIcon, - Background = new SolidColorBrush(Colors.Transparent), - Width = 45, - Height = 45 - }; + return; + } + using StreamReader reader = new(stream); + var xaml = reader.ReadToEnd(); + var resourceDictionary = (Microsoft.UI.Xaml.ResourceDictionary)XamlReader.Load(xaml); + if (resourceDictionary is null) + { + return; + } + this.Resources.MergedDictionaries.Add(resourceDictionary); + } + void ApplyCustomStyle() + { + if (this.Resources.TryGetValue("customTransportcontrols", out object styleObj) && + styleObj is Microsoft.UI.Xaml.Style customStyle && mediaPlayerElement is not null && mediaPlayerElement.TransportControls is not null) + { + mediaPlayerElement.TransportControls.Style = customStyle; + } + } - buttonContainer = new Grid + CustomTransportControls SetTransportControls() + { + mediaPlayerElement.TransportControls.IsEnabled = false; + var temp = new CustomTransportControls() { - HorizontalAlignment = Microsoft.UI.Xaml.HorizontalAlignment.Right, - VerticalAlignment = Microsoft.UI.Xaml.VerticalAlignment.Top, - Visibility = mediaPlayerElement.TransportControls.Visibility, - Width = 45, - Height = 45, - Margin = new Thickness(0, 20, 30, 0) + IsZoomButtonVisible = true, + IsZoomEnabled = true, + IsVolumeButtonVisible = true, + IsVolumeEnabled = true, + IsSeekBarVisible = true, + IsSeekEnabled = true, + IsEnabled = true, + IsRepeatButtonVisible = true, + IsRepeatEnabled = true, + IsNextTrackButtonVisible = true, + IsPreviousTrackButtonVisible = true, + IsFastForwardButtonVisible = true, + IsFastForwardEnabled = true, + IsFastRewindButtonVisible = true, + IsFastRewindEnabled = true, + IsPlaybackRateButtonVisible = true, + IsPlaybackRateEnabled = true, + IsCompact = false, }; - - fullScreenButton.Click += OnFullScreenButtonClick; - buttonContainer.Children.Add(fullScreenButton); - - Children.Add(this.mediaPlayerElement); - Children.Add(buttonContainer); - - mediaPlayerElement.PointerMoved += OnMediaPlayerElementPointerMoved; + temp.OnTemplateLoaded += (s, e) => + { + if (temp.FullScreenButton is null) + { + return; + } + temp.FullScreenButton.Click += OnFullScreenButtonClick; + }; + mediaPlayerElement.TransportControls = temp; + ApplyCustomStyle(); + return temp; } /// @@ -99,9 +132,10 @@ protected virtual void Dispose(bool disposing) { return; } - - fullScreenButton.Click -= OnFullScreenButtonClick; - mediaPlayerElement.PointerMoved -= OnMediaPlayerElementPointerMoved; + if (customTransportControls?.FullScreenButton is not null) + { + customTransportControls.FullScreenButton.Click -= OnFullScreenButtonClick; + } if (disposing) { @@ -128,29 +162,9 @@ static AppWindow GetAppWindowForCurrentWindow() return AppWindow.GetFromWindowId(id); } - async void OnMediaPlayerElementPointerMoved(object sender, PointerRoutedEventArgs e) - { - e.Handled = true; - buttonContainer.Visibility = mediaPlayerElement.TransportControls.Visibility; - - if (mediaPlayerElement.TransportControls.Visibility == Microsoft.UI.Xaml.Visibility.Collapsed) - { - buttonContainer.Visibility = mediaPlayerElement.TransportControls.Visibility; - return; - } - - mediaPlayerElement.PointerMoved -= OnMediaPlayerElementPointerMoved; - buttonContainer.Visibility = Microsoft.UI.Xaml.Visibility.Visible; - await Task.Delay(TimeSpan.FromSeconds(5)); - - buttonContainer.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed; - mediaPlayerElement.PointerMoved += OnMediaPlayerElementPointerMoved; - } - void OnFullScreenButtonClick(object sender, RoutedEventArgs e) { var currentPage = CurrentPage; - if (appWindow.Presenter.Kind is AppWindowPresenterKind.FullScreen) { appWindow.SetPresenter(AppWindowPresenterKind.Default); @@ -162,9 +176,7 @@ void OnFullScreenButtonClick(object sender, RoutedEventArgs e) popup.Child = null; fullScreenGrid.Children.Clear(); } - fullScreenButton.Content = fullScreenIcon; Children.Add(mediaPlayerElement); - Children.Add(buttonContainer); var parent = mediaPlayerElement.Parent as FrameworkElement; mediaPlayerElement.Width = parent?.Width ?? mediaPlayerElement.Width; @@ -181,9 +193,7 @@ void OnFullScreenButtonClick(object sender, RoutedEventArgs e) mediaPlayerElement.Height = displayInfo.Height / displayInfo.Density; Children.Clear(); - fullScreenButton.Content = exitFullScreenIcon; fullScreenGrid.Children.Add(mediaPlayerElement); - fullScreenGrid.Children.Add(buttonContainer); popup.XamlRoot = mediaPlayerElement.XamlRoot; popup.HorizontalOffset = 0; diff --git a/src/CommunityToolkit.Maui.MediaElement/Views/MediaManager.windows.cs b/src/CommunityToolkit.Maui.MediaElement/Views/MediaManager.windows.cs index 0f8dd0c6f3..5d5bc80d8d 100644 --- a/src/CommunityToolkit.Maui.MediaElement/Views/MediaManager.windows.cs +++ b/src/CommunityToolkit.Maui.MediaElement/Views/MediaManager.windows.cs @@ -60,7 +60,9 @@ public PlatformMediaElement CreatePlatformView() Player.MediaPlayer.VolumeChanged += OnMediaElementVolumeChanged; Player.MediaPlayer.IsMutedChanged += OnMediaElementIsMutedChanged; + Player.MediaPlayer.SystemMediaTransportControls.IsEnabled = false; systemMediaControls = Player.MediaPlayer.SystemMediaTransportControls; + return Player; } From 21881308438eb0086fbd8929b6e2ed0fc9adace8 Mon Sep 17 00:00:00 2001 From: James Crutchley Date: Fri, 27 Sep 2024 23:03:19 -0700 Subject: [PATCH 2/6] Reorder AppBarSeparator in ResourceDictionary.xaml Moved RightSeparator before PlaybackRateButton in ResourceDictionary.windows.xaml. Added RightSeparator with Height='0', Width='0', and Margin='0,0'. Reordered properties of PlaybackRateButton without changing values. Removed original RightSeparator after PlaybackRateButton. --- .../ResourceDictionary.windows.xaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/CommunityToolkit.Maui.MediaElement/ResourceDictionary.windows.xaml b/src/CommunityToolkit.Maui.MediaElement/ResourceDictionary.windows.xaml index 6a797dfa35..c922ce67cd 100644 --- a/src/CommunityToolkit.Maui.MediaElement/ResourceDictionary.windows.xaml +++ b/src/CommunityToolkit.Maui.MediaElement/ResourceDictionary.windows.xaml @@ -735,18 +735,18 @@ + + Style='{StaticResource AppBarButtonStyle}' + MediaTransportControlsHelper.DropoutOrder='10' + Visibility='Collapsed'> - Date: Sat, 28 Sep 2024 00:13:02 -0700 Subject: [PATCH 3/6] Re-add and enhance media control styles and templates Re-added various properties and elements to styles and templates in `ResourceDictionary.windows.xaml` to ensure consistent UI appearance and behavior. Added new buttons like `ZoomButton` and `CastButton` to the media controls command bar. Enhanced `customTransportcontrols` and `CommandBarStyle` with additional properties. --- .../ResourceDictionary.windows.xaml | 469 +++++++++--------- 1 file changed, 238 insertions(+), 231 deletions(-) diff --git a/src/CommunityToolkit.Maui.MediaElement/ResourceDictionary.windows.xaml b/src/CommunityToolkit.Maui.MediaElement/ResourceDictionary.windows.xaml index c922ce67cd..a8ae58a754 100644 --- a/src/CommunityToolkit.Maui.MediaElement/ResourceDictionary.windows.xaml +++ b/src/CommunityToolkit.Maui.MediaElement/ResourceDictionary.windows.xaml @@ -6,6 +6,10 @@ + + + + @@ -30,6 +34,7 @@