|
|
|
@ -1,5 +1,6 @@ |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Runtime.Versioning; |
|
|
|
using Android.App; |
|
|
|
using Android.Content; |
|
|
|
using Android.Graphics; |
|
|
|
@ -45,6 +46,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform |
|
|
|
private readonly AndroidInsetsManager _insetsManager; |
|
|
|
private readonly ClipboardImpl _clipboard; |
|
|
|
private ViewImpl _view; |
|
|
|
private WindowTransparencyLevel _transparencyLevel; |
|
|
|
|
|
|
|
public TopLevelImpl(AvaloniaView avaloniaView, bool placeOnTop = false) |
|
|
|
{ |
|
|
|
@ -68,6 +70,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform |
|
|
|
|
|
|
|
_nativeControlHost = new AndroidNativeControlHostImpl(avaloniaView); |
|
|
|
_storageProvider = new AndroidStorageProvider((Activity)avaloniaView.Context); |
|
|
|
_transparencyLevel = WindowTransparencyLevel.None; |
|
|
|
|
|
|
|
_systemNavigationManager = new AndroidSystemNavigationManagerImpl(avaloniaView.Context as IActivityNavigationService); |
|
|
|
} |
|
|
|
@ -103,9 +106,8 @@ namespace Avalonia.Android.Platform.SkiaPlatform |
|
|
|
|
|
|
|
public IEnumerable<object> Surfaces => new object[] { _gl, _framebuffer, Handle }; |
|
|
|
|
|
|
|
public IRenderer CreateRenderer(IRenderRoot root) => |
|
|
|
new CompositingRenderer(root, AndroidPlatform.Compositor, () => Surfaces); |
|
|
|
|
|
|
|
public Compositor Compositor => AndroidPlatform.Compositor; |
|
|
|
|
|
|
|
public virtual void Hide() |
|
|
|
{ |
|
|
|
_view.Visibility = ViewStates.Invisible; |
|
|
|
@ -274,7 +276,18 @@ namespace Avalonia.Android.Platform.SkiaPlatform |
|
|
|
public Action LostFocus { get; set; } |
|
|
|
public Action<WindowTransparencyLevel> TransparencyLevelChanged { get; set; } |
|
|
|
|
|
|
|
public WindowTransparencyLevel TransparencyLevel { get; private set; } |
|
|
|
public WindowTransparencyLevel TransparencyLevel |
|
|
|
{ |
|
|
|
get => _transparencyLevel; |
|
|
|
private set |
|
|
|
{ |
|
|
|
if (_transparencyLevel != value) |
|
|
|
{ |
|
|
|
_transparencyLevel = value; |
|
|
|
TransparencyLevelChanged?.Invoke(value); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) |
|
|
|
{ |
|
|
|
@ -299,91 +312,64 @@ namespace Avalonia.Android.Platform.SkiaPlatform |
|
|
|
|
|
|
|
public double Scaling => RenderScaling; |
|
|
|
|
|
|
|
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) |
|
|
|
public void SetTransparencyLevelHint(IReadOnlyList<WindowTransparencyLevel> transparencyLevels) |
|
|
|
{ |
|
|
|
if (TransparencyLevel != transparencyLevel) |
|
|
|
if (_view.Context is not AvaloniaMainActivity activity) |
|
|
|
return; |
|
|
|
|
|
|
|
foreach (var level in transparencyLevels) |
|
|
|
{ |
|
|
|
bool isBelowR = Build.VERSION.SdkInt < BuildVersionCodes.R; |
|
|
|
bool isAboveR = Build.VERSION.SdkInt > BuildVersionCodes.R; |
|
|
|
if (_view.Context is AvaloniaMainActivity activity) |
|
|
|
if (!IsSupported(level)) |
|
|
|
{ |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (level == TransparencyLevel) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (level == WindowTransparencyLevel.None) |
|
|
|
{ |
|
|
|
if (OperatingSystem.IsAndroidVersionAtLeast(30)) |
|
|
|
{ |
|
|
|
activity.SetTranslucent(false); |
|
|
|
} |
|
|
|
|
|
|
|
activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.White)); |
|
|
|
} |
|
|
|
else if (level == WindowTransparencyLevel.Transparent) |
|
|
|
{ |
|
|
|
if (OperatingSystem.IsAndroidVersionAtLeast(30)) |
|
|
|
{ |
|
|
|
activity.SetTranslucent(true); |
|
|
|
SetBlurBehind(activity, 0); |
|
|
|
activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (level == WindowTransparencyLevel.Blur) |
|
|
|
{ |
|
|
|
switch (transparencyLevel) |
|
|
|
if (OperatingSystem.IsAndroidVersionAtLeast(31)) |
|
|
|
{ |
|
|
|
case WindowTransparencyLevel.AcrylicBlur: |
|
|
|
case WindowTransparencyLevel.ForceAcrylicBlur: |
|
|
|
case WindowTransparencyLevel.Mica: |
|
|
|
case WindowTransparencyLevel.None: |
|
|
|
if (!isBelowR) |
|
|
|
{ |
|
|
|
activity.SetTranslucent(false); |
|
|
|
} |
|
|
|
if (isAboveR) |
|
|
|
{ |
|
|
|
activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); |
|
|
|
|
|
|
|
var attr = activity.Window?.Attributes; |
|
|
|
if (attr != null) |
|
|
|
{ |
|
|
|
attr.BlurBehindRadius = 0; |
|
|
|
|
|
|
|
activity.Window.Attributes = attr; |
|
|
|
} |
|
|
|
} |
|
|
|
activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White)); |
|
|
|
|
|
|
|
if(transparencyLevel != WindowTransparencyLevel.None) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
break; |
|
|
|
case WindowTransparencyLevel.Transparent: |
|
|
|
if (!isBelowR) |
|
|
|
{ |
|
|
|
activity.SetTranslucent(true); |
|
|
|
} |
|
|
|
if (isAboveR) |
|
|
|
{ |
|
|
|
activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); |
|
|
|
|
|
|
|
var attr = activity.Window?.Attributes; |
|
|
|
if (attr != null) |
|
|
|
{ |
|
|
|
attr.BlurBehindRadius = 0; |
|
|
|
|
|
|
|
activity.Window.Attributes = attr; |
|
|
|
} |
|
|
|
} |
|
|
|
activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); |
|
|
|
break; |
|
|
|
case WindowTransparencyLevel.Blur: |
|
|
|
if (isAboveR) |
|
|
|
{ |
|
|
|
activity.SetTranslucent(true); |
|
|
|
activity.Window?.AddFlags(WindowManagerFlags.BlurBehind); |
|
|
|
|
|
|
|
var attr = activity.Window?.Attributes; |
|
|
|
if (attr != null) |
|
|
|
{ |
|
|
|
attr.BlurBehindRadius = 120; |
|
|
|
|
|
|
|
activity.Window.Attributes = attr; |
|
|
|
} |
|
|
|
activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); |
|
|
|
activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White)); |
|
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
break; |
|
|
|
activity.SetTranslucent(true); |
|
|
|
SetBlurBehind(activity, 120); |
|
|
|
activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); |
|
|
|
} |
|
|
|
TransparencyLevel = transparencyLevel; |
|
|
|
} |
|
|
|
|
|
|
|
TransparencyLevel = level; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// If we get here, we didn't find a supported level. Use the default of None.
|
|
|
|
if (OperatingSystem.IsAndroidVersionAtLeast(30)) |
|
|
|
{ |
|
|
|
activity.SetTranslucent(false); |
|
|
|
} |
|
|
|
|
|
|
|
activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.White)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public virtual object TryGetFeature(Type featureType) |
|
|
|
{ |
|
|
|
if (featureType == typeof(IStorageProvider)) |
|
|
|
@ -418,6 +404,31 @@ namespace Avalonia.Android.Platform.SkiaPlatform |
|
|
|
|
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
private static bool IsSupported(WindowTransparencyLevel level) |
|
|
|
{ |
|
|
|
if (level == WindowTransparencyLevel.None) |
|
|
|
return true; |
|
|
|
if (level == WindowTransparencyLevel.Transparent) |
|
|
|
return OperatingSystem.IsAndroidVersionAtLeast(30); |
|
|
|
if (level == WindowTransparencyLevel.Blur) |
|
|
|
return OperatingSystem.IsAndroidVersionAtLeast(31); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
private static void SetBlurBehind(AvaloniaMainActivity activity, int radius) |
|
|
|
{ |
|
|
|
if (radius == 0) |
|
|
|
activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); |
|
|
|
else |
|
|
|
activity.Window?.AddFlags(WindowManagerFlags.BlurBehind); |
|
|
|
|
|
|
|
if (OperatingSystem.IsAndroidVersionAtLeast(31) && activity.Window?.Attributes is { } attr) |
|
|
|
{ |
|
|
|
attr.BlurBehindRadius = radius; |
|
|
|
activity.Window.Attributes = attr; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
internal class AvaloniaInputConnection : BaseInputConnection |
|
|
|
|