diff --git a/UICompositionAnimations/CompositionExtensions.cs b/UICompositionAnimations/CompositionExtensions.cs index c1136f1..32e9ee6 100644 --- a/UICompositionAnimations/CompositionExtensions.cs +++ b/UICompositionAnimations/CompositionExtensions.cs @@ -926,7 +926,7 @@ public static SpriteVisual AttachVisualShadow( shadow.Opacity = opacity; sprite.Shadow = shadow; sprite.Size = new Vector2(width ?? (float)element.Width, height ?? (float)element.Height); - sprite.Offset = new Vector3(-0.5f, -0.5f, 0); + sprite.Offset = new Vector3(offsetX, offsetY, 0); // Clip it and add it to the visual tree InsetClip clip = compositor.CreateInsetClip( diff --git a/UICompositionAnimations/Helpers/ApiInformaitonHelper.cs b/UICompositionAnimations/Helpers/ApiInformaitonHelper.cs index a6fa1f4..f94d5e1 100644 --- a/UICompositionAnimations/Helpers/ApiInformaitonHelper.cs +++ b/UICompositionAnimations/Helpers/ApiInformaitonHelper.cs @@ -1,4 +1,6 @@ using System; +using Windows.ApplicationModel.Resources.Core; +using Windows.Foundation.Collections; using Windows.Foundation.Metadata; using Windows.System.Profile; using Windows.UI.Composition; @@ -184,5 +186,61 @@ public static bool AreBackdropEffectsAvailable public static bool IsRequiresPointerAvailable => ApiInformation.IsPropertyPresent("Windows.UI.Xaml.Controls.Control", nameof(Control.RequiresPointer)); #endregion + + #region Device family + + private static bool? _IsMobileDevice; + + /// + /// Gets whether or not the device is a mobile phone + /// + public static bool IsMobileDevice + { + get + { + if (_IsMobileDevice == null) + { + try + { + IObservableMap qualifiers = ResourceContext.GetForCurrentView().QualifierValues; + _IsMobileDevice = qualifiers.ContainsKey("DeviceFamily") && qualifiers["DeviceFamily"] == "Mobile"; + } + catch (UnauthorizedAccessException) + { + // No idea why this should happen + return ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"); + } + } + return _IsMobileDevice.Value; + } + } + + private static bool? _IsDesktop; + + /// + /// Gets whether or not the device is running Windows 10 Desktop + /// + public static bool IsDesktop + { + get + { + if (_IsDesktop == null) + { + try + { + IObservableMap qualifiers = ResourceContext.GetForCurrentView().QualifierValues; + _IsDesktop = qualifiers.ContainsKey("DeviceFamily") && qualifiers["DeviceFamily"] == "Desktop"; + } + catch (UnauthorizedAccessException) + { + // Weird crash, but still... + return false; + } + } + return _IsDesktop.Value; + } + } + + #endregion } } diff --git a/UICompositionAnimations/Helpers/PointerHelper.cs b/UICompositionAnimations/Helpers/PointerHelper.cs new file mode 100644 index 0000000..b885973 --- /dev/null +++ b/UICompositionAnimations/Helpers/PointerHelper.cs @@ -0,0 +1,84 @@ +using System; +using Windows.Devices.Input; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Input; + +namespace UICompositionAnimations.Helpers +{ + /// + /// A static class with some extension methods to manage different pointer states + /// + public static class PointerHelper + { + /// + /// Adds an event handler to all the pointer events of the target control + /// + /// The control to monitor + /// An action to call every time a pointer event is raised. The bool parameter + /// indicates whether the pointer is moving to or from the control + public static void ManageControlPointerStates(this UIElement control, Action action) + { + // Nested functions that adds the actual handlers + void AddHandler(RoutedEvent @event, bool state, Func predicate) + { + control.AddHandler(@event, new PointerEventHandler((_, e) => + { + if (predicate == null || predicate(e.Pointer.PointerDeviceType)) + { + action(e.Pointer.PointerDeviceType, state); + } + }), true); + } + + // Add handlers + AddHandler(UIElement.PointerExitedEvent, false, null); + AddHandler(UIElement.PointerCaptureLostEvent, false, null); + AddHandler(UIElement.PointerCanceledEvent, false, null); + AddHandler(UIElement.PointerEnteredEvent, true, p => p != PointerDeviceType.Touch); + AddHandler(UIElement.PointerReleasedEvent, false, p => p == PointerDeviceType.Touch); + } + + /// + /// Adds an event handler to all the pointer events of the target element + /// + /// The element to monitor + /// An action to call every time a pointer event is raised. The bool parameter + /// indicates whether the pointer is moving to or from the control + public static void ManageHostPointerStates(this UIElement element, Action action) + { + // Nested functions that adds the actual handlers + void AddHandler(RoutedEvent @event, bool state, Func predicate) + { + element.AddHandler(@event, new PointerEventHandler((_, e) => + { + if (predicate == null || predicate(e.Pointer.PointerDeviceType)) + { + action(e.Pointer.PointerDeviceType, state); + } + }), true); + } + + // Add handlers + AddHandler(UIElement.PointerExitedEvent, false, null); + AddHandler(UIElement.PointerMovedEvent, true, p => p != PointerDeviceType.Touch); + } + + /// + /// Adds the appropriate handlers to a control to help setup the light effects (skipped when on a mobile phone) + /// + /// The element to monitor + /// An action to call every time the light effects state should be changed + public static void ManageLightsPointerStates(this UIElement element, Action action) + { + // Platform check + if (ApiInformationHelper.IsMobileDevice) return; + + // Nested functions that adds the actual handlers + element.ManageHostPointerStates((pointer, value) => + { + if (pointer != PointerDeviceType.Mouse) return; + action(value); + }); + } + } +} diff --git a/UICompositionAnimations/Properties/AssemblyInfo.cs b/UICompositionAnimations/Properties/AssemblyInfo.cs index 02256ed..c2f335e 100644 --- a/UICompositionAnimations/Properties/AssemblyInfo.cs +++ b/UICompositionAnimations/Properties/AssemblyInfo.cs @@ -23,6 +23,6 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.7.0.0")] +[assembly: AssemblyVersion("2.8.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: ComVisible(false)] \ No newline at end of file diff --git a/UICompositionAnimations/UICompositionAnimations.csproj b/UICompositionAnimations/UICompositionAnimations.csproj index c5921b4..0f62907 100644 --- a/UICompositionAnimations/UICompositionAnimations.csproj +++ b/UICompositionAnimations/UICompositionAnimations.csproj @@ -133,6 +133,7 @@ + diff --git a/UICompositionAnimations/UICompositionAnimations.nuspec b/UICompositionAnimations/UICompositionAnimations.nuspec index cc9e01b..a37b6cd 100644 --- a/UICompositionAnimations/UICompositionAnimations.nuspec +++ b/UICompositionAnimations/UICompositionAnimations.nuspec @@ -2,14 +2,14 @@ Sergio0694.UWP.UICompositionAnimations - 2.7.0.0 + 2.8.0.0 UICompositionAnimations A wrapper UWP PCL to work with Windows.UI.Composition and XAML animations, and Win2D effects Sergio Pedri Sergio Pedri https://github.com/Sergio0694/UICompositionAnimations false - Added XAML custom acrylic brush + PointerHelper class added, minor bug fixes and improvements Copyright 2017 uwp composition animations xaml csharp windows winrt universal app ui win2d graphics