diff --git a/samples/ControlCatalog.Android/MainActivity.cs b/samples/ControlCatalog.Android/MainActivity.cs index b02083c39d..44290d9816 100644 --- a/samples/ControlCatalog.Android/MainActivity.cs +++ b/samples/ControlCatalog.Android/MainActivity.cs @@ -1,18 +1,16 @@ using Android.App; -using Android.OS; using Android.Content.PM; +using Avalonia; using Avalonia.Android; namespace ControlCatalog.Android { [Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleInstance, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)] - public class MainActivity : AvaloniaActivity + public class MainActivity : AvaloniaActivity { - protected override void OnCreate(Bundle? savedInstanceState) + protected override AppBuilder CustomizeAppBuilder(AppBuilder builder) { - base.OnCreate(savedInstanceState); - - Content = new MainView(); + return base.CustomizeAppBuilder(builder); } } } diff --git a/samples/ControlCatalog.Android/SplashActivity.cs b/samples/ControlCatalog.Android/SplashActivity.cs index 9729713833..dc292fd37b 100644 --- a/samples/ControlCatalog.Android/SplashActivity.cs +++ b/samples/ControlCatalog.Android/SplashActivity.cs @@ -1,9 +1,6 @@ using Android.App; using Android.Content; using Android.OS; -using Application = Android.App.Application; - -using Avalonia; namespace ControlCatalog.Android { @@ -19,13 +16,6 @@ namespace ControlCatalog.Android { base.OnResume(); - if (Avalonia.Application.Current == null) - { - AppBuilder.Configure() - .UseAndroid() - .SetupWithoutStarting(); - } - StartActivity(new Intent(Application.Context, typeof(MainActivity))); } } diff --git a/src/Android/Avalonia.Android/AndroidPlatform.cs b/src/Android/Avalonia.Android/AndroidPlatform.cs index 308be1325c..61aa6ce946 100644 --- a/src/Android/Avalonia.Android/AndroidPlatform.cs +++ b/src/Android/Avalonia.Android/AndroidPlatform.cs @@ -1,9 +1,9 @@ using System; - +using Avalonia.Controls; +using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Android; using Avalonia.Android.Platform; using Avalonia.Android.Platform.Input; -using Avalonia.Controls; using Avalonia.Controls.Platform; using Avalonia.Input; using Avalonia.Input.Platform; @@ -19,6 +19,7 @@ namespace Avalonia public static T UseAndroid(this T builder) where T : AppBuilderBase, new() { var options = AvaloniaLocator.Current.GetService() ?? new AndroidPlatformOptions(); + return builder .UseWindowingSubsystem(() => AndroidPlatform.Initialize(options), "Android") .UseSkia(); diff --git a/src/Android/Avalonia.Android/AvaloniaActivity.cs b/src/Android/Avalonia.Android/AvaloniaActivity.cs index fbadc257e2..f5d620a97a 100644 --- a/src/Android/Avalonia.Android/AvaloniaActivity.cs +++ b/src/Android/Avalonia.Android/AvaloniaActivity.cs @@ -1,28 +1,55 @@ -using Android.App; using Android.OS; -using Android.Views; -using Android.Content.PM; using AndroidX.AppCompat.App; using Android.Content.Res; using AndroidX.Lifecycle; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Controls; namespace Avalonia.Android { - public abstract class AvaloniaActivity : AppCompatActivity + public abstract class AvaloniaActivity : AppCompatActivity where TApp : Application, new() { + internal class SingleViewLifetime : ISingleViewApplicationLifetime + { + public AvaloniaView View { get; internal set; } + + public Control MainView + { + get => (Control)View.Content; + set => View.Content = value; + } + } + internal AvaloniaView View; internal AvaloniaViewModel _viewModel; + + protected virtual AppBuilder CustomizeAppBuilder(AppBuilder builder) => builder.UseAndroid(); + protected override void OnCreate(Bundle savedInstanceState) { + var builder = AppBuilder.Configure(); + + CustomizeAppBuilder(builder); + View = new AvaloniaView(this); SetContentView(View); - _viewModel = new ViewModelProvider(this).Get(Java.Lang.Class.FromType(typeof(AvaloniaViewModel))) as AvaloniaViewModel; + var lifetime = new SingleViewLifetime(); + lifetime.View = View; - if (_viewModel.Content != null) + builder.AfterSetup(x => { - View.Content = _viewModel.Content; - } + _viewModel = new ViewModelProvider(this).Get(Java.Lang.Class.FromType(typeof(AvaloniaViewModel))) as AvaloniaViewModel; + + if (_viewModel.Content != null) + { + View.Content = _viewModel.Content; + } + + View.Prepare(); + }); + + builder.SetupWithLifetime(lifetime); base.OnCreate(savedInstanceState); } diff --git a/src/Android/Avalonia.Android/AvaloniaView.cs b/src/Android/Avalonia.Android/AvaloniaView.cs index 8de3657283..8177cf1f69 100644 --- a/src/Android/Avalonia.Android/AvaloniaView.cs +++ b/src/Android/Avalonia.Android/AvaloniaView.cs @@ -12,7 +12,7 @@ namespace Avalonia.Android { public class AvaloniaView : FrameLayout { - private readonly EmbeddableControlRoot _root; + private EmbeddableControlRoot _root; private readonly ViewImpl _view; private IDisposable? _timerSubscription; @@ -21,6 +21,11 @@ namespace Avalonia.Android { _view = new ViewImpl(context); AddView(_view.View); + + } + + internal void Prepare () + { _root = new EmbeddableControlRoot(_view); _root.Prepare(); } diff --git a/src/iOS/Avalonia.iOS/AvaloniaAppDelegate.cs b/src/iOS/Avalonia.iOS/AvaloniaAppDelegate.cs index 65a6743f9d..f976b2feb4 100644 --- a/src/iOS/Avalonia.iOS/AvaloniaAppDelegate.cs +++ b/src/iOS/Avalonia.iOS/AvaloniaAppDelegate.cs @@ -1,6 +1,7 @@ +using Foundation; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; -using Foundation; + using UIKit; namespace Avalonia.iOS @@ -8,6 +9,17 @@ namespace Avalonia.iOS public class AvaloniaAppDelegate : UIResponder, IUIApplicationDelegate where TApp : Application, new() { + class SingleViewLifetime : ISingleViewApplicationLifetime + { + public AvaloniaView View; + + public Control MainView + { + get => View.Content; + set => View.Content = value; + } + } + protected virtual AppBuilder CustomizeAppBuilder(AppBuilder builder) => builder.UseiOS(); [Export("window")] @@ -18,7 +30,9 @@ namespace Avalonia.iOS { var builder = AppBuilder.Configure(); CustomizeAppBuilder(builder); - var lifetime = new Lifetime(); + + var lifetime = new SingleViewLifetime(); + builder.AfterSetup(_ => { Window = new UIWindow(); @@ -35,15 +49,5 @@ namespace Avalonia.iOS Window.Hidden = false; return true; } - - class Lifetime : ISingleViewApplicationLifetime - { - public AvaloniaView View; - public Control MainView - { - get => View.Content; - set => View.Content = value; - } - } } } diff --git a/src/iOS/Avalonia.iOS/Platform.cs b/src/iOS/Avalonia.iOS/Platform.cs index 57a86cbfd8..f8815e9030 100644 --- a/src/iOS/Avalonia.iOS/Platform.cs +++ b/src/iOS/Avalonia.iOS/Platform.cs @@ -45,6 +45,7 @@ namespace Avalonia.iOS Timer ??= new DisplayLinkTimer(); var keyboard = new KeyboardDevice(); var softKeyboard = new SoftKeyboardHelper(); + AvaloniaLocator.CurrentMutable .Bind().ToConstant(GlFeature) .Bind().ToConstant(new CursorFactoryStub()) @@ -57,6 +58,7 @@ namespace Avalonia.iOS .Bind().ToConstant(Timer) .Bind().ToConstant(new PlatformThreadingInterface()) .Bind().ToConstant(keyboard); + keyboard.PropertyChanged += (_, changed) => { if (changed.PropertyName == nameof(KeyboardDevice.FocusedElement)) diff --git a/src/iOS/Avalonia.iOS/SingleViewLifetime.cs b/src/iOS/Avalonia.iOS/SingleViewLifetime.cs deleted file mode 100644 index 914f0ba548..0000000000 --- a/src/iOS/Avalonia.iOS/SingleViewLifetime.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Avalonia.iOS -{ - public class SingleViewLifetime - { - - } -} \ No newline at end of file