Skip to content

Commit

Permalink
Use the Default Button Styles (Windows 11 Styles) (#3363)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattleibow committed Nov 17, 2021
1 parent 1465de8 commit da7787a
Show file tree
Hide file tree
Showing 15 changed files with 301 additions and 414 deletions.
Expand Up @@ -30,6 +30,12 @@
BackgroundColor="Red"
TextColor="White"
Text="Button"/>
<Label
Text="Character Spacing"
Style="{StaticResource Headline}"/>
<Button
CharacterSpacing="20"
Text="Button"/>
<Label
Text="Image Source"
Style="{StaticResource Headline}"/>
Expand Down
@@ -1,26 +1,19 @@
#nullable enable

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Imaging;
using WImage = Microsoft.UI.Xaml.Controls.Image;
using WStretch = Microsoft.UI.Xaml.Media.Stretch;
using WThickness = Microsoft.UI.Xaml.Thickness;
using WImageSource = Microsoft.UI.Xaml.Media.ImageSource;

namespace Microsoft.Maui.Controls.Platform
{
public static class ButtonExtensions
{
public static void UpdateContentLayout(this MauiButton mauiButton, Button button)
public static void UpdateContentLayout(this UI.Xaml.Controls.Button mauiButton, Button button)
{
// If the Content isn't the StackPanel setup by Maui.Core then
// The user has set a custom Content or the content isn't a mix of text/images
if (mauiButton.Content is not StackPanel container)
return;

var image = mauiButton.GetImage();
var textBlock = mauiButton.GetTextBlock();
var image = mauiButton.GetContent<UI.Xaml.Controls.Image>();
var textBlock = mauiButton.GetContent<UI.Xaml.Controls.TextBlock>();

// If either of these are null then the user has taken control of the content
// and we don't know how to apply our changes
Expand All @@ -31,14 +24,11 @@ public static void UpdateContentLayout(this MauiButton mauiButton, Button button
var layout = button.ContentLayout;
var spacing = layout.Spacing;

container.HorizontalAlignment = Microsoft.UI.Xaml.HorizontalAlignment.Center;
container.VerticalAlignment = Microsoft.UI.Xaml.VerticalAlignment.Center;

switch (layout.Position)
{
case Button.ButtonContentLayout.ImagePosition.Top:
container.Orientation = Orientation.Vertical;
image.Margin = WinUIHelpers.CreateThickness(0, 0, 0, spacing);
image.Margin = WinUIHelpers.CreateThickness(0, 0, 0, spacing);
container.Children.Add(image);
container.Children.Add(textBlock);
break;
Expand Down
77 changes: 48 additions & 29 deletions src/Core/src/Handlers/Button/ButtonHandler.Windows.cs
@@ -1,46 +1,65 @@
#nullable enable
using System.Threading.Tasks;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;

namespace Microsoft.Maui.Handlers
{
public partial class ButtonHandler : ViewHandler<IButton, MauiButton>
public partial class ButtonHandler : ViewHandler<IButton, Button>
{
static UI.Xaml.Thickness? DefaultPadding;
static UI.Xaml.Media.Brush? DefaultForeground;
static UI.Xaml.Media.Brush? DefaultBackground;

PointerEventHandler? _pointerPressedHandler;
PointerEventHandler? _pointerReleasedHandler;

protected override MauiButton CreateNativeView()
=> new MauiButton();

void SetupDefaults(MauiButton nativeView)
{
DefaultPadding = (UI.Xaml.Thickness)MauiWinUIApplication.Current.Resources["ButtonPadding"];
DefaultForeground = (UI.Xaml.Media.Brush)MauiWinUIApplication.Current.Resources["ButtonForegroundThemeBrush"];
DefaultBackground = (UI.Xaml.Media.Brush)MauiWinUIApplication.Current.Resources["ButtonBackgroundThemeBrush"];
}

protected override void ConnectHandler(MauiButton nativeView)
protected override Button CreateNativeView() =>
new Button
{
VerticalAlignment = VerticalAlignment.Stretch,
HorizontalAlignment = HorizontalAlignment.Stretch,
Content = new StackPanel
{
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Orientation = Orientation.Horizontal,
Margin = WinUIHelpers.CreateThickness(0),
Children =
{
new Image
{
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center,
Stretch = Stretch.Uniform,
Margin = WinUIHelpers.CreateThickness(0),
Visibility = UI.Xaml.Visibility.Collapsed,
},
new TextBlock
{
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center,
Margin = WinUIHelpers.CreateThickness(0),
Visibility = UI.Xaml.Visibility.Collapsed,
}
}
}
};

protected override void ConnectHandler(Button nativeView)
{
_pointerPressedHandler = new PointerEventHandler(OnPointerPressed);
_pointerReleasedHandler = new PointerEventHandler(OnPointerReleased);

nativeView.Click += OnClick;
nativeView.AddHandler(UI.Xaml.UIElement.PointerPressedEvent, _pointerPressedHandler, true);
nativeView.AddHandler(UI.Xaml.UIElement.PointerReleasedEvent, _pointerReleasedHandler, true);
nativeView.AddHandler(UIElement.PointerPressedEvent, _pointerPressedHandler, true);
nativeView.AddHandler(UIElement.PointerReleasedEvent, _pointerReleasedHandler, true);

base.ConnectHandler(nativeView);
}

protected override void DisconnectHandler(MauiButton nativeView)
protected override void DisconnectHandler(Button nativeView)
{
nativeView.Click -= OnClick;
nativeView.RemoveHandler(UI.Xaml.UIElement.PointerPressedEvent, _pointerPressedHandler);
nativeView.RemoveHandler(UI.Xaml.UIElement.PointerReleasedEvent, _pointerReleasedHandler);
nativeView.RemoveHandler(UIElement.PointerPressedEvent, _pointerPressedHandler);
nativeView.RemoveHandler(UIElement.PointerReleasedEvent, _pointerReleasedHandler);

_pointerPressedHandler = null;
_pointerReleasedHandler = null;
Expand All @@ -51,7 +70,7 @@ protected override void DisconnectHandler(MauiButton nativeView)
// This is a Windows-specific mapping
public static void MapBackground(IButtonHandler handler, IButton button)
{
handler.TypedNativeView?.UpdateBackground(button, DefaultBackground);
handler.TypedNativeView?.UpdateBackground(button);
}

public static void MapText(IButtonHandler handler, IText button)
Expand All @@ -61,12 +80,12 @@ public static void MapText(IButtonHandler handler, IText button)

public static void MapTextColor(IButtonHandler handler, ITextStyle button)
{
handler.TypedNativeView?.UpdateTextColor(button, DefaultForeground);
handler.TypedNativeView?.UpdateTextColor(button);
}

public static void MapCharacterSpacing(IButtonHandler handler, ITextStyle button)
{
handler.TypedNativeView?.UpdateCharacterSpacing(button.CharacterSpacing);
handler.TypedNativeView?.UpdateCharacterSpacing(button);
}

public static void MapFont(IButtonHandler handler, ITextStyle button)
Expand All @@ -78,7 +97,7 @@ public static void MapFont(IButtonHandler handler, ITextStyle button)

public static void MapPadding(IButtonHandler handler, IButton button)
{
handler.TypedNativeView?.UpdatePadding(button, DefaultPadding);
handler.TypedNativeView?.UpdatePadding(button);
}

public static void MapImageSource(IButtonHandler handler, IButton image) =>
Expand All @@ -87,12 +106,12 @@ public static void MapPadding(IButtonHandler handler, IButton button)
.UpdateImageSourceAsync()
.FireAndForget(handler);

void OnSetImageSource(ImageSource? obj)
void OnSetImageSource(ImageSource? nativeImageSource)
{
NativeView.UpdateImageSource(VirtualView, obj);
NativeView.UpdateImageSource(nativeImageSource);
}

void OnClick(object sender, UI.Xaml.RoutedEventArgs e)
void OnClick(object sender, RoutedEventArgs e)
{
VirtualView?.Clicked();
VirtualView?.Released();
Expand Down
2 changes: 1 addition & 1 deletion src/Core/src/Handlers/Button/ButtonHandler.cs
Expand Up @@ -3,7 +3,7 @@
#elif MONOANDROID
using NativeView = Google.Android.Material.Button.MaterialButton;
#elif WINDOWS
using NativeView = Microsoft.Maui.MauiButton;
using NativeView = Microsoft.UI.Xaml.Controls.Button;
#elif NETSTANDARD || (NET6_0 && !IOS && !ANDROID)
using NativeView = System.Object;
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/Core/src/Handlers/Button/IButtonHandler.cs
Expand Up @@ -3,7 +3,7 @@
#elif MONOANDROID
using NativeView = Google.Android.Material.Button.MaterialButton;
#elif WINDOWS
using NativeView = Microsoft.Maui.MauiButton;
using NativeView = Microsoft.UI.Xaml.Controls.Button;
#elif NETSTANDARD || (NET6_0 && !IOS && !ANDROID)
using NativeView = System.Object;
#endif
Expand Down
96 changes: 20 additions & 76 deletions src/Core/src/Handlers/ImageButton/ImageButtonHandler.Windows.cs
@@ -1,111 +1,55 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;

namespace Microsoft.Maui.Handlers
{
public partial class ImageButtonHandler : ViewHandler<IImageButton, MauiButton>
public partial class ImageButtonHandler : ViewHandler<IImageButton, Button>
{

PointerEventHandler? _pointerPressedHandler;
Image? _image;
protected override MauiButton CreateNativeView()
{
_image = new Image()
{
VerticalAlignment = Microsoft.UI.Xaml.VerticalAlignment.Center,
HorizontalAlignment = Microsoft.UI.Xaml.HorizontalAlignment.Center,
Stretch = Stretch.Uniform,
};

var mauiButton = new MauiButton()
protected override Button CreateNativeView() =>
new Button
{
Content = _image
VerticalAlignment = VerticalAlignment.Stretch,
HorizontalAlignment = HorizontalAlignment.Stretch,
Content = new Image
{
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center,
Stretch = Stretch.Uniform,
}
};

mauiButton.Padding = WinUIHelpers.CreateThickness(0);
mauiButton.BorderThickness = WinUIHelpers.CreateThickness(0);
mauiButton.Background = null;

return mauiButton;
}

protected override void ConnectHandler(MauiButton nativeView)
protected override void ConnectHandler(Button nativeView)
{
_pointerPressedHandler = new PointerEventHandler(OnPointerPressed);

nativeView.Click += OnClick;
nativeView.AddHandler(UI.Xaml.UIElement.PointerPressedEvent, _pointerPressedHandler, true);

if (_image != null)
{
_image.ImageFailed += OnImageFailed;
_image.ImageOpened += OnImageOpened;
}
nativeView.AddHandler(UIElement.PointerPressedEvent, _pointerPressedHandler, true);

base.ConnectHandler(nativeView);

nativeView.Loaded += OnNativeViewLoaded;
nativeView.Unloaded += OnNativeViewUnloaded;
}

protected override void DisconnectHandler(MauiButton nativeView)
protected override void DisconnectHandler(Button nativeView)
{
nativeView.Click -= OnClick;
nativeView.RemoveHandler(UI.Xaml.UIElement.PointerPressedEvent, _pointerPressedHandler);
nativeView.RemoveHandler(UIElement.PointerPressedEvent, _pointerPressedHandler);

_pointerPressedHandler = null;

base.DisconnectHandler(nativeView);

if (nativeView.XamlRoot != null)
nativeView.XamlRoot.Changed -= OnXamlRootChanged;

nativeView.Loaded -= OnNativeViewLoaded;
nativeView.Unloaded -= OnNativeViewUnloaded;

SourceLoader.Reset();
}

void OnImageOpened(object sender, RoutedEventArgs e)
{

}

void OnImageFailed(object sender, ExceptionRoutedEventArgs e)
{
}

void OnSetImageSource(ImageSource? obj)
{
if (NativeView.Content is Image i)
i.Source = obj;
}

void OnNativeViewLoaded(object sender = null!, RoutedEventArgs e = null!)
{
if (NativeView?.XamlRoot != null)
{
NativeView.XamlRoot.Changed += OnXamlRootChanged;
}
}

void OnNativeViewUnloaded(object sender = null!, RoutedEventArgs e = null!)
{
if (NativeView?.XamlRoot != null)
NativeView.XamlRoot.Changed -= OnXamlRootChanged;
}

void OnXamlRootChanged(XamlRoot sender, XamlRootChangedEventArgs args)
void OnSetImageSource(ImageSource? nativeImageSource)
{
UpdateValue(nameof(IImage.Source));
NativeView.UpdateImageSource(nativeImageSource);
}

void OnClick(object sender, UI.Xaml.RoutedEventArgs e)
void OnClick(object sender, RoutedEventArgs e)
{
VirtualView?.Clicked();
VirtualView?.Released();
Expand All @@ -116,4 +60,4 @@ void OnPointerPressed(object sender, PointerRoutedEventArgs e)
VirtualView?.Pressed();
}
}
}
}
19 changes: 10 additions & 9 deletions src/Core/src/Handlers/ImageButton/ImageButtonHandler.cs
@@ -1,18 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;
#if __IOS__ || MACCATALYST
using NativeImage = UIKit.UIImage;
using NativeImageView = UIKit.UIImageView;
using NativeView = UIKit.UIButton;
#elif MONOANDROID
using NativeImage = Android.Graphics.Drawables.Drawable;
using NativeImageView = Android.Widget.ImageView;
using NativeView = AndroidX.AppCompat.Widget.AppCompatImageButton;
#elif WINDOWS
using NativeImage = Microsoft.UI.Xaml.Media.ImageSource;
using NativeImageView = Microsoft.UI.Xaml.Controls.Image;
using NativeView = Microsoft.UI.Xaml.FrameworkElement;
#elif NETSTANDARD || (NET6_0 && !IOS && !ANDROID)
using NativeView = System.Object;
using NativeImage = System.Object;
using NativeImageView = System.Object;
using NativeView = System.Object;
#endif

namespace Microsoft.Maui.Handlers
Expand All @@ -38,15 +40,14 @@ public ImageButtonHandler(IPropertyMapper mapper) : base(mapper ?? Mapper)

IImage IImageHandler.TypedVirtualView => VirtualView;

NativeImageView IImageHandler.TypedNativeView =>
#if __IOS__
UIKit.UIImageView IImageHandler.TypedNativeView => NativeView.ImageView;
NativeView.ImageView;
#elif WINDOWS
UI.Xaml.Controls.Image IImageHandler.TypedNativeView => NativeView.GetImage() ?? (UI.Xaml.Controls.Image)NativeView.Content;
#elif __ANDROID__
Android.Widget.ImageView IImageHandler.TypedNativeView => NativeView;
NativeView.GetContent<NativeImageView>() ?? throw new InvalidOperationException("ImageButton did not contain an Image element.");
#else
object IImageHandler.TypedNativeView => NativeView;
NativeView;
#endif
ImageSourcePartLoader IImageHandler.SourceLoader => SourceLoader;
}
}
}

0 comments on commit da7787a

Please sign in to comment.