Browse Source

iOS and Android implementations

pull/9913/head
Max Katz 3 years ago
parent
commit
a4bffbf660
  1. 2
      src/Android/Avalonia.Android/AndroidPlatform.cs
  2. 16
      src/Android/Avalonia.Android/AvaloniaView.cs
  3. 73
      src/Android/Avalonia.Android/Platform/AndroidPlatformSettings.cs
  4. 6
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  5. 27
      src/iOS/Avalonia.iOS/AvaloniaView.cs
  6. 6
      src/iOS/Avalonia.iOS/AvaloniaViewController.cs
  7. 2
      src/iOS/Avalonia.iOS/Platform.cs
  8. 34
      src/iOS/Avalonia.iOS/PlatformSettings.cs

2
src/Android/Avalonia.Android/AndroidPlatform.cs

@ -43,7 +43,7 @@ namespace Avalonia.Android
.Bind<ICursorFactory>().ToTransient<CursorFactory>()
.Bind<IWindowingPlatform>().ToConstant(new WindowingPlatformStub())
.Bind<IKeyboardDevice>().ToSingleton<AndroidKeyboardDevice>()
.Bind<IPlatformSettings>().ToSingleton<DefaultPlatformSettings>()
.Bind<IPlatformSettings>().ToSingleton<AndroidPlatformSettings>()
.Bind<IPlatformThreadingInterface>().ToConstant(new AndroidThreadingInterface())
.Bind<IPlatformIconLoader>().ToSingleton<PlatformIconLoaderStub>()
.Bind<IRenderTimer>().ToConstant(new ChoreographerTimer())

16
src/Android/Avalonia.Android/AvaloniaView.cs

@ -1,11 +1,14 @@
using System;
using Android.Content;
using Android.Content.Res;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Avalonia.Android.Platform;
using Avalonia.Android.Platform.SkiaPlatform;
using Avalonia.Controls;
using Avalonia.Controls.Embedding;
using Avalonia.Platform;
using Avalonia.Rendering;
namespace Avalonia.Android
@ -26,6 +29,7 @@ namespace Avalonia.Android
_root.Prepare();
this.SetBackgroundColor(global::Android.Graphics.Color.Transparent);
OnConfigurationChanged();
}
internal TopLevelImpl TopLevelImpl => _view;
@ -70,6 +74,18 @@ namespace Avalonia.Android
_timerSubscription?.Dispose();
}
}
protected override void OnConfigurationChanged(Configuration newConfig)
{
base.OnConfigurationChanged(newConfig);
OnConfigurationChanged();
}
private void OnConfigurationChanged()
{
var settings = AvaloniaLocator.Current.GetRequiredService<IPlatformSettings>() as AndroidPlatformSettings;
settings?.OnViewConfigurationChanged(Context);
}
class ViewImpl : TopLevelImpl
{

73
src/Android/Avalonia.Android/Platform/AndroidPlatformSettings.cs

@ -0,0 +1,73 @@
using System;
using Android;
using Android.Content;
using Android.Content.Res;
using Android.Graphics;
using AndroidX.Core.Content.Resources;
using Avalonia.Media;
using Avalonia.Platform;
using Color = Avalonia.Media.Color;
namespace Avalonia.Android.Platform;
// TODO: ideally should be created per view/activity.
internal class AndroidPlatformSettings : DefaultPlatformSettings
{
private PlatformColorValues _latestValues;
public AndroidPlatformSettings()
{
_latestValues = base.GetColorValues();
}
public override PlatformColorValues GetColorValues()
{
return _latestValues;
}
internal void OnViewConfigurationChanged(Context context)
{
if (context.Resources?.Configuration is null)
{
return;
}
var systemTheme = (context.Resources.Configuration.UiMode & UiMode.NightMask) switch
{
UiMode.NightYes => PlatformThemeVariant.Dark,
UiMode.NightNo => PlatformThemeVariant.Light,
_ => throw new ArgumentOutOfRangeException()
};
if (OperatingSystem.IsAndroidVersionAtLeast(31))
{
// See https://developer.android.com/reference/android/R.color
var accent1 = context.Resources.GetColor(17170494, context.Theme); // Resource.Color.SystemAccent1500
var accent2 = context.Resources.GetColor(17170507, context.Theme); // Resource.Color.SystemAccent2500
var accent3 = context.Resources.GetColor(17170520, context.Theme); // Resource.Color.SystemAccent3500
_latestValues = new PlatformColorValues(
systemTheme,
new Color(accent1.A, accent1.R, accent1.G, accent1.B),
new Color(accent2.A, accent2.R, accent2.G, accent2.B),
new Color(accent3.A, accent3.R, accent3.G, accent3.B));
}
else if (OperatingSystem.IsAndroidVersionAtLeast(23))
{
// See https://developer.android.com/reference/android/R.attr
var array = context.Theme.ObtainStyledAttributes(new[] { 16843829 }); // Resource.Attribute.ColorAccent
var accent = array.GetColor(0, 0);
_latestValues = new PlatformColorValues(
systemTheme,
new Color(accent.A, accent.R, accent.G, accent.B));
array.Recycle();
}
else
{
_latestValues = _latestValues with { ThemeVariant = systemTheme };
}
OnColorValuesChanged(_latestValues);
}
}

6
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -26,6 +26,7 @@ using Avalonia.Rendering.Composition;
using Java.Lang;
using Math = System.Math;
using AndroidRect = Android.Graphics.Rect;
using Window = Android.Views.Window;
using Android.Graphics.Drawables;
namespace Avalonia.Android.Platform.SkiaPlatform
@ -286,6 +287,11 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public WindowTransparencyLevel TransparencyLevel { get; private set; }
public void SetFrameThemeVariant(PlatformThemeVariant themeVariant)
{
// TODO adjust status bar depending on full screen mode.
}
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels => new AcrylicPlatformCompensationLevels(1, 1, 1);
IntPtr EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Handle => ((IPlatformHandle)_view).Handle;

27
src/iOS/Avalonia.iOS/AvaloniaView.cs

@ -52,6 +52,14 @@ namespace Avalonia.iOS
public override bool CanResignFirstResponder => true;
public override void TraitCollectionDidChange(UITraitCollection previousTraitCollection)
{
base.TraitCollectionDidChange(previousTraitCollection);
var settings = AvaloniaLocator.Current.GetRequiredService<IPlatformSettings>() as PlatformSettings;
settings?.TraitCollectionDidChange();
}
internal class TopLevelImpl : ITopLevelImplWithTextInputMethod, ITopLevelImplWithNativeControlHost,
ITopLevelImplWithStorageProvider
{
@ -120,7 +128,24 @@ namespace Avalonia.iOS
// legacy no-op
public IMouseDevice MouseDevice { get; } = new MouseDevice();
public WindowTransparencyLevel TransparencyLevel { get; }
public void SetFrameThemeVariant(PlatformThemeVariant themeVariant)
{
// TODO adjust status bar depending on full screen mode.
if (OperatingSystem.IsIOSVersionAtLeast(13))
{
var uiStatusBarStyle = themeVariant switch
{
PlatformThemeVariant.Light => UIStatusBarStyle.DarkContent,
PlatformThemeVariant.Dark => UIStatusBarStyle.LightContent,
_ => throw new ArgumentOutOfRangeException(nameof(themeVariant), themeVariant, null)
};
// Consider using UIViewController.PreferredStatusBarStyle in the future.
UIApplication.SharedApplication.SetStatusBarStyle(uiStatusBarStyle, true);
}
}
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } =
new AcrylicPlatformCompensationLevels();

6
src/iOS/Avalonia.iOS/AvaloniaViewController.cs

@ -0,0 +1,6 @@
namespace Avalonia.iOS;
public class AvaloniaViewController
{
}

2
src/iOS/Avalonia.iOS/Platform.cs

@ -40,7 +40,7 @@ namespace Avalonia.iOS
.Bind<ICursorFactory>().ToConstant(new CursorFactoryStub())
.Bind<IWindowingPlatform>().ToConstant(new WindowingPlatformStub())
.Bind<IClipboard>().ToConstant(new ClipboardImpl())
.Bind<IPlatformSettings>().ToSingleton<DefaultPlatformSettings>()
.Bind<IPlatformSettings>().ToSingleton<PlatformSettings>()
.Bind<IPlatformIconLoader>().ToConstant(new PlatformIconLoaderStub())
.Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>()
.Bind<IRenderLoop>().ToSingleton<RenderLoop>()

34
src/iOS/Avalonia.iOS/PlatformSettings.cs

@ -0,0 +1,34 @@
using System;
using System.Linq;
using Avalonia.Media;
using Avalonia.Platform;
using Foundation;
using UIKit;
namespace Avalonia.iOS;
// TODO: ideally should be created per view/activity.
internal class PlatformSettings : DefaultPlatformSettings
{
private PlatformColorValues _lastColorValues;
public override PlatformColorValues GetColorValues()
{
var themeVariant = UITraitCollection.CurrentTraitCollection.UserInterfaceStyle == UIUserInterfaceStyle.Dark ?
PlatformThemeVariant.Dark :
PlatformThemeVariant.Light;
return _lastColorValues = new PlatformColorValues(themeVariant);
}
public void TraitCollectionDidChange()
{
var oldColorValues = _lastColorValues;
var colorValues = GetColorValues();
if (oldColorValues != colorValues)
{
OnColorValuesChanged(colorValues);
}
}
}
Loading…
Cancel
Save