зеркало из https://github.com/DeGsoft/maui-linux.git
Dualscreen updates to new apis and add hinge angle for UWP (#10244)
* Dual Screen sdk updates - update to newer windows sdk apis - Add Hinge Angle Events * - remove reflection call
This commit is contained in:
Родитель
8a458aebef
Коммит
723c4bc2f1
|
@ -1,11 +1,27 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">uap10.0.14393;uap10.0.16299;</TargetFrameworks>
|
||||
<PropertyGroup Condition=" '$(UwpMinTargetFrameworks)' != '' ">
|
||||
<TargetFrameworks>$(UwpMinTargetFrameworks)</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(UwpMinTargetFrameworks)' == '' ">
|
||||
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">uap10.0.14393;uap10.0.16299</TargetFrameworks>
|
||||
<!--<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">uap10.0.14393;uap10.0.16299;uap10.0.18362</TargetFrameworks>-->
|
||||
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard2.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetPlatformVersion Condition="'$(TargetFramework)' == 'uap10.0.14393'">10.0.16299.0</TargetPlatformVersion>
|
||||
<TargetPlatformVersion Condition="'$(TargetFramework)' == 'uap10.0.16299'">10.0.18362.0</TargetPlatformVersion>
|
||||
<TargetPlatformVersion Condition="'$(TargetFramework)' == 'uap10.0.18362'">10.0.19559.0</TargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(TargetFramework)' == 'uap10.0.14393'">
|
||||
<PropertyGroup Condition=" $(TargetFramework.StartsWith('uap10.0')) ">
|
||||
<DefineConstants>$(DefineConstants);UWP</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetPlatformVersion) == '10.0.16299.0'">
|
||||
<DefineConstants>$(DefineConstants);UWP_14393</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetPlatformVersion) == '10.0.18362.0'">
|
||||
<DefineConstants>$(DefineConstants);UWP_18362</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" $(TargetPlatformVersion.StartsWith('10.0.19')) ">
|
||||
<DefineConstants>$(DefineConstants);UWP_18362;UWP_19000</DefineConstants>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
@ -2,11 +2,16 @@
|
|||
<ItemGroup Condition="'$(TargetFramework)' == 'uap10.0.14393' AND '$(OS)' == 'Windows_NT' ">
|
||||
<PackageReference Include="NETStandard.Library" Version="2.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith('uap10.0')) AND '$(OS)' == 'Windows_NT' ">
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith('uap10.0')) AND '$(OS)' == 'Windows_NT' AND $(TargetPlatformMinVersion) <= '10.0.16299.0' ">
|
||||
<SDKReference Include="WindowsMobile, Version=10.0.18362.0">
|
||||
<Name>Windows Mobile Extensions for the UWP</Name>
|
||||
</SDKReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith('uap10.0')) AND '$(OS)' == 'Windows_NT' AND $(TargetPlatformMinVersion) >= '10.0.18362.0' ">
|
||||
<SDKReference Include="WindowsMobile, Version=10.0.19559.0">
|
||||
<Name>Windows Mobile Extensions for the UWP</Name>
|
||||
</SDKReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith('uap10.0')) AND '$(OS)' == 'Windows_NT' ">
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform" Version="6.0.15" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -56,7 +56,6 @@ using Android.Support.V4.Content;
|
|||
[assembly: ExportRenderer(typeof(ShellGestures.TouchTestView), typeof(ShellGesturesTouchTestViewRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Issue7249Switch), typeof(Issue7249SwitchRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Issue9360.Issue9360NavigationPage), typeof(Issue9360NavigationPageRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Xamarin.Forms.Controls.GalleryPages.TwoPaneViewGalleries.HingeAngleLabel), typeof(HingeAngleLabelRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Xamarin.Forms.Controls.Tests.TestClasses.CustomButton), typeof(CustomButtonRenderer))]
|
||||
[assembly: ExportRenderer(typeof(Issue8801.PopupStackLayout), typeof(CustomStackLayoutRenderer))]
|
||||
|
||||
|
@ -67,56 +66,6 @@ using Android.Support.V4.Content;
|
|||
#endif
|
||||
namespace Xamarin.Forms.ControlGallery.Android
|
||||
{
|
||||
public class HingeAngleLabelRenderer : Xamarin.Forms.Platform.Android.FastRenderers.LabelRenderer
|
||||
{
|
||||
System.Timers.Timer _hingeTimer;
|
||||
public HingeAngleLabelRenderer(Context context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
async void OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
if (_hingeTimer == null)
|
||||
return;
|
||||
|
||||
_hingeTimer.Stop();
|
||||
var hingeAngle = await DualScreen.DualScreenInfo.Current.GetHingeAngleAsync();
|
||||
|
||||
Device.BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
if (_hingeTimer != null)
|
||||
Element.Text = hingeAngle.ToString();
|
||||
});
|
||||
|
||||
if(_hingeTimer != null)
|
||||
_hingeTimer.Start();
|
||||
}
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
|
||||
{
|
||||
base.OnElementChanged(e);
|
||||
|
||||
if(_hingeTimer == null)
|
||||
{
|
||||
_hingeTimer = new System.Timers.Timer(100);
|
||||
_hingeTimer.Elapsed += OnTimerElapsed;
|
||||
_hingeTimer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_hingeTimer != null)
|
||||
{
|
||||
_hingeTimer.Elapsed -= OnTimerElapsed;
|
||||
_hingeTimer.Stop();
|
||||
_hingeTimer = null;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
|
||||
public class CustomStackLayoutRenderer : VisualElementRenderer<StackLayout>
|
||||
{
|
||||
public CustomStackLayoutRenderer(Context context) : base(context)
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
</Picker>
|
||||
<Picker Title="WideModeConfiguration" x:Name="WideModeConfiguration" SelectedIndex="1">
|
||||
</Picker>
|
||||
<Label Text="Hinge Angle (only works on Android):"></Label>
|
||||
<twoPaneGallery:HingeAngleLabel />
|
||||
<Label Text="Hinge Angle"></Label>
|
||||
<Label x:Name="lblHingeAngle" />
|
||||
</StackLayout>
|
||||
</local:TwoPaneView.Pane1>
|
||||
<local:TwoPaneView.Pane2>
|
||||
|
|
|
@ -33,11 +33,21 @@ namespace Xamarin.Forms.Controls.GalleryPages.TwoPaneViewGalleries
|
|||
|
||||
protected override void OnAppearing()
|
||||
{
|
||||
base.OnAppearing();
|
||||
|
||||
PanePriority.SelectedIndex = 0;
|
||||
TallModeConfiguration.SelectedIndex = 1;
|
||||
WideModeConfiguration.SelectedIndex = 1;
|
||||
|
||||
DualScreen.DualScreenInfo.Current.HingeAngleChanged += OnHingeAngleChanged;
|
||||
}
|
||||
|
||||
protected override void OnDisappearing()
|
||||
{
|
||||
DualScreen.DualScreenInfo.Current.HingeAngleChanged -= OnHingeAngleChanged;
|
||||
}
|
||||
|
||||
void OnHingeAngleChanged(object sender, DualScreen.HingeAngleChangedEventArgs e)
|
||||
{
|
||||
lblHingeAngle.Text = e.HingeAngleInDegrees.ToString();
|
||||
}
|
||||
|
||||
void Setup(double width, double height)
|
||||
|
@ -61,6 +71,4 @@ namespace Xamarin.Forms.Controls.GalleryPages.TwoPaneViewGalleries
|
|||
Pane2Length.Value = 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
public class HingeAngleLabel : Label { }
|
||||
}
|
|
@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
|||
using Windows.Foundation.Metadata;
|
||||
using Windows.UI.ViewManagement;
|
||||
|
||||
#if !UWP_14393
|
||||
#if UWP_18362
|
||||
using Windows.UI.WindowManagement;
|
||||
#endif
|
||||
|
||||
|
@ -18,7 +18,7 @@ namespace Xamarin.Forms.DualScreen
|
|||
public static class DualScreenHelper
|
||||
{
|
||||
|
||||
#if !UWP_14393
|
||||
#if UWP_18362
|
||||
|
||||
public static bool HasCompactModeSupport()
|
||||
{
|
||||
|
|
|
@ -3,12 +3,38 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Device.Display;
|
||||
|
||||
namespace Xamarin.Forms.DualScreen
|
||||
{
|
||||
public partial class DualScreenInfo : INotifyPropertyChanged
|
||||
{
|
||||
static object hingeAngleLock = new object();
|
||||
public Task<int> GetHingeAngleAsync() => DualScreenService.GetHingeAngleAsync();
|
||||
|
||||
void ProcessHingeAngleSubscriberCount(int newCount)
|
||||
{
|
||||
lock (hingeAngleLock)
|
||||
{
|
||||
if (newCount == 1)
|
||||
{
|
||||
DualScreen.DualScreenService.DualScreenServiceImpl.HingeAngleChanged += OnHingeAngleChanged;
|
||||
}
|
||||
else if (newCount == 0)
|
||||
{
|
||||
DualScreen.DualScreenService.DualScreenServiceImpl.HingeAngleChanged -= OnHingeAngleChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnHingeAngleChanged(object sender, HingeSensor.HingeSensorChangedEventArgs e)
|
||||
{
|
||||
Device.BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
_hingeAngleChanged?.Invoke(this, new HingeAngleChangedEventArgs(e.HingeAngle));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Forms.DualScreen
|
||||
{
|
||||
public partial class DualScreenInfo : INotifyPropertyChanged
|
||||
{
|
||||
public Task<int> GetHingeAngleAsync() => DualScreenService.GetHingeAngleAsync();
|
||||
|
||||
void ProcessHingeAngleSubscriberCount(int newCount) { }
|
||||
}
|
||||
}
|
|
@ -3,24 +3,37 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Forms.DualScreen
|
||||
{
|
||||
public class HingeAngleChangedEventArgs : EventArgs
|
||||
{
|
||||
public HingeAngleChangedEventArgs(double hingeAngleInDegrees)
|
||||
{
|
||||
HingeAngleInDegrees = hingeAngleInDegrees;
|
||||
}
|
||||
|
||||
public double HingeAngleInDegrees { get; }
|
||||
}
|
||||
|
||||
public partial class DualScreenInfo : INotifyPropertyChanged
|
||||
{
|
||||
static Lazy<DualScreenInfo> _dualScreenInfo { get; } = new Lazy<DualScreenInfo>(OnCreate);
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
Rectangle[] _spanningBounds;
|
||||
Rectangle _hingeBounds;
|
||||
bool _isLandscape;
|
||||
TwoPaneViewMode _spanMode;
|
||||
TwoPaneViewLayoutGuide _twoPaneViewLayoutGuide;
|
||||
IDualScreenService _dualScreenService;
|
||||
public static DualScreenInfo Current => _dualScreenInfo.Value;
|
||||
IDualScreenService _dualScreenService;
|
||||
IDualScreenService DualScreenService =>
|
||||
_dualScreenService ?? DependencyService.Get<IDualScreenService>() ?? NoDualScreenServiceImpl.Instance;
|
||||
|
||||
static Lazy<DualScreenInfo> _dualScreenInfo { get; } = new Lazy<DualScreenInfo>(OnCreate);
|
||||
|
||||
public static DualScreenInfo Current => _dualScreenInfo.Value;
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public DualScreenInfo(VisualElement layout) : this(layout, null)
|
||||
{
|
||||
}
|
||||
|
@ -35,10 +48,28 @@ namespace Xamarin.Forms.DualScreen
|
|||
else
|
||||
{
|
||||
_twoPaneViewLayoutGuide = new TwoPaneViewLayoutGuide(layout, dualScreenService);
|
||||
_twoPaneViewLayoutGuide.PropertyChanged += OnTwoPaneViewLayoutGuideChanged;
|
||||
_twoPaneViewLayoutGuide.PropertyChanged += OnTwoPaneViewLayoutGuideChanged;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EventHandler<HingeAngleChangedEventArgs> _hingeAngleChanged;
|
||||
int subscriberCount = 0;
|
||||
public event EventHandler<HingeAngleChangedEventArgs> HingeAngleChanged
|
||||
{
|
||||
add
|
||||
{
|
||||
ProcessHingeAngleSubscriberCount(Interlocked.Increment(ref subscriberCount));
|
||||
_hingeAngleChanged += value;
|
||||
}
|
||||
remove
|
||||
{
|
||||
ProcessHingeAngleSubscriberCount(Interlocked.Decrement(ref subscriberCount));
|
||||
_hingeAngleChanged -= value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Rectangle[] SpanningBounds
|
||||
{
|
||||
get => GetSpanningBounds();
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Devices.Sensors;
|
||||
|
||||
namespace Xamarin.Forms.DualScreen
|
||||
{
|
||||
public partial class DualScreenInfo : INotifyPropertyChanged
|
||||
{
|
||||
static object hingeAngleLock = new object();
|
||||
public Task<int> GetHingeAngleAsync() => DualScreenService.GetHingeAngleAsync();
|
||||
|
||||
#if UWP_18362
|
||||
Windows.Devices.Sensors.HingeAngleSensor _angleSensor;
|
||||
#endif
|
||||
|
||||
#if UWP_18362
|
||||
async void ProcessHingeAngleSubscriberCount(int newCount)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_angleSensor == null)
|
||||
_angleSensor = await Windows.Devices.Sensors.HingeAngleSensor.GetDefaultAsync();
|
||||
|
||||
if (_angleSensor == null)
|
||||
return;
|
||||
|
||||
lock (hingeAngleLock)
|
||||
{
|
||||
if (newCount == 1)
|
||||
{
|
||||
_angleSensor.ReadingChanged += OnReadingChanged;
|
||||
}
|
||||
else if(newCount == 0)
|
||||
{
|
||||
_angleSensor.ReadingChanged -= OnReadingChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Internals.Log.Warning(nameof(DualScreenInfo), $"Failed to retrieve Hinge Angle Sensor {e}");
|
||||
}
|
||||
|
||||
void OnReadingChanged(HingeAngleSensor sender, HingeAngleSensorReadingChangedEventArgs args)
|
||||
{
|
||||
Device.BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
_hingeAngleChanged?.Invoke(this, new HingeAngleChangedEventArgs(args.Reading.AngleInDegrees));
|
||||
});
|
||||
}
|
||||
}
|
||||
#else
|
||||
void ProcessHingeAngleSubscriberCount(int newCount)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Android.App;
|
||||
using Android.Util;
|
||||
|
@ -28,11 +29,10 @@ namespace Xamarin.Forms.DualScreen
|
|||
|
||||
internal class DualScreenServiceImpl : IDualScreenService, Platform.Android.DualScreen.IDualScreenService
|
||||
{
|
||||
public event EventHandler OnScreenChanged;
|
||||
ScreenHelper _helper;
|
||||
bool _isDuo = false;
|
||||
bool IsDuo => (_helper == null || _HingeService == null || _mainActivity == null || _hingeSensor == null) ? false : _isDuo;
|
||||
HingeSensor _hingeSensor;
|
||||
bool IsDuo => (_helper == null || _HingeService == null || _mainActivity == null || _singleUseHingeSensor == null) ? false : _isDuo;
|
||||
HingeSensor _singleUseHingeSensor;
|
||||
static Activity _mainActivity;
|
||||
static DualScreenServiceImpl _HingeService;
|
||||
bool _isLandscape;
|
||||
|
@ -40,6 +40,11 @@ namespace Xamarin.Forms.DualScreen
|
|||
object _hingeAngleLock = new object();
|
||||
TaskCompletionSource<int> _gettingHingeAngle;
|
||||
|
||||
internal static Activity MainActivity => _mainActivity;
|
||||
|
||||
static HingeSensor DefaultHingeSensor;
|
||||
public event EventHandler OnScreenChanged;
|
||||
|
||||
[Internals.Preserve(Conditional = true)]
|
||||
public DualScreenServiceImpl()
|
||||
{
|
||||
|
@ -77,51 +82,19 @@ namespace Xamarin.Forms.DualScreen
|
|||
|
||||
if (!isDuo)
|
||||
{
|
||||
_HingeService._helper = null;
|
||||
_HingeService._hingeSensor = null;
|
||||
_HingeService._helper = null;
|
||||
_HingeService.SetupHingeSensors(null);
|
||||
return;
|
||||
}
|
||||
|
||||
_HingeService._helper = screenHelper;
|
||||
_HingeService._hingeSensor = new HingeSensor(_mainActivity);
|
||||
_HingeService.SetupHingeSensors(_mainActivity);
|
||||
if (_mainActivity is IDeviceInfoProvider newDeviceInfoProvider)
|
||||
{
|
||||
newDeviceInfoProvider.ConfigurationChanged += _HingeService.ConfigurationChanged;
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigurationChanged(object sender, EventArgs e)
|
||||
{
|
||||
if(IsDuo)
|
||||
_helper?.Update();
|
||||
|
||||
bool screenChanged = false;
|
||||
if (_isLandscape != IsLandscape)
|
||||
{
|
||||
_isLandscape = IsLandscape;
|
||||
screenChanged = true;
|
||||
}
|
||||
|
||||
if (_mainActivity != null)
|
||||
{
|
||||
using (DisplayMetrics display = _mainActivity.Resources.DisplayMetrics)
|
||||
{
|
||||
var scalingFactor = display.Density;
|
||||
_pixelScreenSize = new Size(display.WidthPixels, display.HeightPixels);
|
||||
var newSize = new Size(_pixelScreenSize.Width / scalingFactor, _pixelScreenSize.Height / scalingFactor);
|
||||
|
||||
if (newSize != ScaledScreenSize)
|
||||
{
|
||||
ScaledScreenSize = newSize;
|
||||
screenChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(screenChanged)
|
||||
OnScreenChanged?.Invoke(this, e);
|
||||
}
|
||||
|
||||
public Size ScaledScreenSize
|
||||
{
|
||||
get;
|
||||
|
@ -131,43 +104,6 @@ namespace Xamarin.Forms.DualScreen
|
|||
public bool IsSpanned
|
||||
=> IsDuo && (_helper?.IsDualMode ?? false);
|
||||
|
||||
void StartListeningForHingeChanges()
|
||||
{
|
||||
if (!IsDuo)
|
||||
return;
|
||||
|
||||
_hingeSensor.OnSensorChanged += OnSensorChanged;
|
||||
_hingeSensor.StartListening();
|
||||
}
|
||||
|
||||
void StopListeningForHingeChanges()
|
||||
{
|
||||
if (!IsDuo)
|
||||
return;
|
||||
|
||||
_hingeSensor.OnSensorChanged -= OnSensorChanged;
|
||||
_hingeSensor.StopListening();
|
||||
}
|
||||
|
||||
void OnSensorChanged(object sender, HingeSensor.HingeSensorChangedEventArgs e)
|
||||
{
|
||||
SetHingeAngle(e.HingeAngle);
|
||||
}
|
||||
|
||||
void SetHingeAngle(int hingeAngle)
|
||||
{
|
||||
TaskCompletionSource<int> toSet = null;
|
||||
lock (_hingeAngleLock)
|
||||
{
|
||||
StopListeningForHingeChanges();
|
||||
toSet = _gettingHingeAngle;
|
||||
_gettingHingeAngle = null;
|
||||
}
|
||||
|
||||
if (toSet != null)
|
||||
toSet.SetResult(hingeAngle);
|
||||
}
|
||||
|
||||
public Task<int> GetHingeAngleAsync()
|
||||
{
|
||||
if (!IsDuo)
|
||||
|
@ -293,6 +229,145 @@ namespace Xamarin.Forms.DualScreen
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static EventHandler<HingeSensor.HingeSensorChangedEventArgs> _hingeAngleChanged;
|
||||
static int subscriberCount;
|
||||
static object hingeAngleLock = new object();
|
||||
|
||||
public static event EventHandler<HingeSensor.HingeSensorChangedEventArgs> HingeAngleChanged
|
||||
{
|
||||
add
|
||||
{
|
||||
if (DefaultHingeSensor == null)
|
||||
return;
|
||||
|
||||
ProcessHingeAngleSubscriberCount(Interlocked.Increment(ref subscriberCount));
|
||||
_hingeAngleChanged += value;
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (DefaultHingeSensor == null)
|
||||
return;
|
||||
|
||||
ProcessHingeAngleSubscriberCount(Interlocked.Decrement(ref subscriberCount));
|
||||
_hingeAngleChanged -= value;
|
||||
}
|
||||
}
|
||||
|
||||
static void ProcessHingeAngleSubscriberCount(int subscriberCount)
|
||||
{
|
||||
var sensor = DefaultHingeSensor;
|
||||
if (sensor == null)
|
||||
return;
|
||||
|
||||
lock(hingeAngleLock)
|
||||
{
|
||||
if (subscriberCount == 1)
|
||||
{
|
||||
sensor.StartListening();
|
||||
}
|
||||
else if (subscriberCount == 0)
|
||||
{
|
||||
sensor.StopListening();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultHingeSensorOnSensorChanged(object sender, HingeSensor.HingeSensorChangedEventArgs e)
|
||||
{
|
||||
_hingeAngleChanged?.Invoke(this, e);
|
||||
}
|
||||
|
||||
void SetupHingeSensors(global::Android.Content.Context context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
if (DefaultHingeSensor != null)
|
||||
DefaultHingeSensor.OnSensorChanged -= DefaultHingeSensorOnSensorChanged;
|
||||
|
||||
_singleUseHingeSensor = null;
|
||||
DefaultHingeSensor = null;
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
_singleUseHingeSensor = new HingeSensor(context);
|
||||
DefaultHingeSensor = new HingeSensor(context);
|
||||
DefaultHingeSensor.OnSensorChanged += DefaultHingeSensorOnSensorChanged;
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigurationChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (IsDuo)
|
||||
_helper?.Update();
|
||||
|
||||
bool screenChanged = false;
|
||||
if (_isLandscape != IsLandscape)
|
||||
{
|
||||
_isLandscape = IsLandscape;
|
||||
screenChanged = true;
|
||||
}
|
||||
|
||||
if (_mainActivity != null)
|
||||
{
|
||||
using (DisplayMetrics display = _mainActivity.Resources.DisplayMetrics)
|
||||
{
|
||||
var scalingFactor = display.Density;
|
||||
_pixelScreenSize = new Size(display.WidthPixels, display.HeightPixels);
|
||||
var newSize = new Size(_pixelScreenSize.Width / scalingFactor, _pixelScreenSize.Height / scalingFactor);
|
||||
|
||||
if (newSize != ScaledScreenSize)
|
||||
{
|
||||
ScaledScreenSize = newSize;
|
||||
screenChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (screenChanged)
|
||||
OnScreenChanged?.Invoke(this, e);
|
||||
}
|
||||
|
||||
|
||||
void StartListeningForHingeChanges()
|
||||
{
|
||||
if (!IsDuo)
|
||||
return;
|
||||
|
||||
_singleUseHingeSensor.OnSensorChanged += OnSensorChanged;
|
||||
_singleUseHingeSensor.StartListening();
|
||||
}
|
||||
|
||||
void StopListeningForHingeChanges()
|
||||
{
|
||||
if (!IsDuo)
|
||||
return;
|
||||
|
||||
_singleUseHingeSensor.OnSensorChanged -= OnSensorChanged;
|
||||
_singleUseHingeSensor.StopListening();
|
||||
}
|
||||
|
||||
void OnSensorChanged(object sender, HingeSensor.HingeSensorChangedEventArgs e)
|
||||
{
|
||||
SetHingeAngle(e.HingeAngle);
|
||||
}
|
||||
|
||||
void SetHingeAngle(int hingeAngle)
|
||||
{
|
||||
TaskCompletionSource<int> toSet = null;
|
||||
lock (_hingeAngleLock)
|
||||
{
|
||||
StopListeningForHingeChanges();
|
||||
toSet = _gettingHingeAngle;
|
||||
_gettingHingeAngle = null;
|
||||
}
|
||||
|
||||
if (toSet != null)
|
||||
toSet.SetResult(hingeAngle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Foundation.Metadata;
|
||||
using Windows.Graphics.Display;
|
||||
|
@ -25,32 +27,50 @@ namespace Xamarin.Forms.DualScreen
|
|||
|
||||
public DualScreenService()
|
||||
{
|
||||
if(Window.Current != null)
|
||||
if (Window.Current != null)
|
||||
{
|
||||
Window.Current.SizeChanged += OnCurrentSizeChanged;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<int> GetHingeAngleAsync() => Task.FromResult(0);
|
||||
public async Task<int> GetHingeAngleAsync()
|
||||
{
|
||||
if (!ApiInformation.IsMethodPresent("Windows.Devices.Sensors.HingeAngleSensor", "GetDefaultAsync"))
|
||||
{
|
||||
return await NoDualScreenServiceImpl.Instance.GetHingeAngleAsync();
|
||||
}
|
||||
|
||||
#if UWP_18362
|
||||
var sensor = await Windows.Devices.Sensors.HingeAngleSensor.GetDefaultAsync();
|
||||
|
||||
if (sensor == null)
|
||||
return await NoDualScreenServiceImpl.Instance.GetHingeAngleAsync();
|
||||
|
||||
var currentReading = await sensor.GetCurrentReadingAsync();
|
||||
return (int)currentReading.AngleInDegrees;
|
||||
#else
|
||||
return await NoDualScreenServiceImpl.Instance.GetHingeAngleAsync();
|
||||
#endif
|
||||
}
|
||||
|
||||
void OnCurrentSizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
|
||||
{
|
||||
OnScreenChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
bool IsDualScreenDevice => ApiInformation.IsMethodPresent("Windows.UI.ViewManagement.ApplicationView", "GetSpanningRects");
|
||||
|
||||
public bool IsSpanned
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!IsDualScreenDevice)
|
||||
return false;
|
||||
var viewMode = (int)ApplicationView.GetForCurrentView().ViewMode;
|
||||
|
||||
var visibleBounds = Window.Current.Bounds;
|
||||
|
||||
if (visibleBounds.Height > 1200 || visibleBounds.Width > 1200)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
switch (viewMode)
|
||||
{
|
||||
case 2:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,13 +79,33 @@ namespace Xamarin.Forms.DualScreen
|
|||
public bool IsLandscape
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsSpanned)
|
||||
return ApplicationView.GetForCurrentView().Orientation == ApplicationViewOrientation.Portrait;
|
||||
else
|
||||
return ApplicationView.GetForCurrentView().Orientation == ApplicationViewOrientation.Landscape;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (!IsSpanned)
|
||||
return ApplicationView.GetForCurrentView().Orientation == ApplicationViewOrientation.Landscape;
|
||||
|
||||
#if UWP_18362
|
||||
var displayRegions = ApplicationView.GetForCurrentView().GetDisplayRegions();
|
||||
if (displayRegions.Count == 2)
|
||||
{
|
||||
// We are split in two panes. Layout accordingly
|
||||
if (displayRegions[0].WorkAreaOffset.X != displayRegions[1].WorkAreaOffset.X)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (displayRegions[0].WorkAreaOffset.Y != displayRegions[1].WorkAreaOffset.Y)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ApplicationView.GetForCurrentView().Orientation == ApplicationViewOrientation.Landscape;
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ApplicationView.GetForCurrentView().Orientation == ApplicationViewOrientation.Landscape;
|
||||
}
|
||||
}
|
||||
|
||||
public Size ScaledScreenSize
|
||||
{
|
||||
|
@ -78,21 +118,56 @@ namespace Xamarin.Forms.DualScreen
|
|||
|
||||
public Rectangle GetHinge()
|
||||
{
|
||||
if (!IsDualScreenDevice)
|
||||
if (!ApiInformation.IsMethodPresent("Windows.UI.ViewManagement.ApplicationView", "GetSpanningRects"))
|
||||
return Rectangle.Zero;
|
||||
|
||||
var screen = DisplayInformation.GetForCurrentView();
|
||||
if (!IsSpanned)
|
||||
return Rectangle.Zero;
|
||||
|
||||
if (IsLandscape)
|
||||
{
|
||||
if (IsSpanned)
|
||||
return new Rectangle(0, 664 + 24, ScaledPixels(screen.ScreenWidthInRawPixels), 0);
|
||||
else
|
||||
return new Rectangle(0, 664, ScaledPixels(screen.ScreenWidthInRawPixels), 0);
|
||||
}
|
||||
else
|
||||
return new Rectangle(720, 0, 0, ScaledPixels(screen.ScreenHeightInRawPixels));
|
||||
}
|
||||
var screen = DisplayInformation.GetForCurrentView();
|
||||
|
||||
|
||||
#if UWP_18362
|
||||
var applicationView = ApplicationView.GetForCurrentView();
|
||||
List<Windows.Foundation.Rect> spanningRects = null;
|
||||
|
||||
#if UWP_19000
|
||||
spanningRects = applicationView.GetSpanningRects().ToList();
|
||||
#endif
|
||||
|
||||
if (spanningRects?.Count == 2)
|
||||
{
|
||||
if(!IsLandscape)
|
||||
{
|
||||
var x = spanningRects[0].Width;
|
||||
var hingeWidth = spanningRects[1].X - x;
|
||||
return new Rectangle(x, 0, hingeWidth, ScaledPixels(screen.ScreenHeightInRawPixels));
|
||||
}
|
||||
else
|
||||
{
|
||||
var y = spanningRects[0].Height;
|
||||
var hingeHeight = spanningRects[1].Y - y;
|
||||
return new Rectangle(0, y, ScaledPixels(screen.ScreenWidthInRawPixels), hingeHeight);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// fall back to hard coded
|
||||
Rectangle returnValue = Rectangle.Zero;
|
||||
|
||||
if (IsLandscape)
|
||||
{
|
||||
if (IsSpanned)
|
||||
returnValue = new Rectangle(0, 664 + 24, ScaledPixels(screen.ScreenWidthInRawPixels), 0);
|
||||
else
|
||||
returnValue = new Rectangle(0, 664, ScaledPixels(screen.ScreenWidthInRawPixels), 0);
|
||||
}
|
||||
else
|
||||
returnValue = new Rectangle(720, 0, 0, ScaledPixels(screen.ScreenHeightInRawPixels));
|
||||
|
||||
return returnValue;
|
||||
|
||||
}
|
||||
|
||||
double ScaledPixels(double n)
|
||||
=> n / DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel;
|
||||
|
|
|
@ -13,15 +13,6 @@
|
|||
<XamarinAndroidSupportSkipVerifyVersions>true</XamarinAndroidSupportSkipVerifyVersions>
|
||||
<GenerateLibraryLayout Condition=" $(TargetFramework.StartsWith('uap10.0')) ">false</GenerateLibraryLayout>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetPlatformVersion) == 'uap10.0.14393'">
|
||||
<DefineConstants>$(DefineConstants);UWP_14393</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetPlatformVersion) == 'uap10.0.16299'">
|
||||
<DefineConstants>$(DefineConstants);UWP_18362</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" $(TargetFramework.StartsWith('uap10.0')) ">
|
||||
<DefineConstants>$(DefineConstants);UWP</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" $(TargetFramework.StartsWith('MonoAndroid'))">
|
||||
<DefineConstants>$(DefineConstants);ANDROID</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -94,13 +94,13 @@
|
|||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework) == 'uap10.0.16299'">
|
||||
<ItemGroup Condition=" '$(OS)' == 'Windows_NT' AND $(TargetFramework.StartsWith('uap10.0')) AND $(TargetPlatformMinVersion) >= '10.0.16299.0'">
|
||||
<Page Include="Shell\ShellStyles.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework) == 'uap10.0.14393'">
|
||||
<ItemGroup Condition="'$(OS)' == 'Windows_NT' AND $(TargetFramework.StartsWith('uap10.0')) AND $(TargetPlatformMinVersion) < '10.0.16299.0'">
|
||||
<Page Remove="Shell\ShellStyles.xaml">
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
@ -114,11 +114,11 @@
|
|||
<ProjectReference Include="..\Xamarin.Forms.Xaml\Xamarin.Forms.Xaml.csproj">
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(OS)' == 'Windows_NT' ">
|
||||
<PackageReference Include="Microsoft.UI.Xaml" Condition="$(TargetFramework) == 'uap10.0.14393'">
|
||||
<ItemGroup Condition=" '$(OS)' == 'Windows_NT' AND $(TargetFramework.StartsWith('uap10.0')) ">
|
||||
<PackageReference Include="Microsoft.UI.Xaml" Condition="$(TargetPlatformMinVersion) < '10.0.16299.0'">
|
||||
<Version>2.1.190606001</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.UI.Xaml" Condition="$(TargetFramework) == 'uap10.0.16299'">
|
||||
<PackageReference Include="Microsoft.UI.Xaml" Condition="$(TargetPlatformMinVersion) >= '10.0.16299.0'">
|
||||
<Version>2.3.191211002</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Win2D.uwp">
|
||||
|
|
Загрузка…
Ссылка в новой задаче