Răsfoiți Sursa

Merge branch 'master' into fixes/win32-can-resize

Dan Walmsley 3 ani în urmă
părinte
comite
c45bb0ea30

+ 4 - 6
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<App>
     {
-        protected override void OnCreate(Bundle? savedInstanceState)
+        protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
         {
-            base.OnCreate(savedInstanceState);
-
-            Content = new MainView();
+            return base.CustomizeAppBuilder(builder);
         }
     }
 }

+ 0 - 10
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<App>()
-                    .UseAndroid()
-                    .SetupWithoutStarting();
-            }
-
             StartActivity(new Intent(Application.Context, typeof(MainActivity)));
         }
     }

+ 3 - 2
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<T>(this T builder) where T : AppBuilderBase<T>, new()
         {
             var options = AvaloniaLocator.Current.GetService<AndroidPlatformOptions>() ?? new AndroidPlatformOptions();
+
             return builder
                 .UseWindowingSubsystem(() => AndroidPlatform.Initialize(options), "Android")
                 .UseSkia();

+ 35 - 8
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<TApp> : 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<TApp>();
+            
+            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);
         }

+ 6 - 1
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();
         }

+ 12 - 3
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs

@@ -72,10 +72,19 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
 
         private static XamlIlBindingPathNode TransformForTargetTyping(XamlIlBindingPathNode transformed, AstTransformationContext context)
         {
-            if (context.ParentNodes().OfType<XamlPropertyAssignmentNode>().FirstOrDefault().Property.Getter.ReturnType == context.GetAvaloniaTypes().ICommand
-                && transformed.Elements[transformed.Elements.Count - 1] is XamlIlClrMethodPathElementNode method)
+            var parentNode = context.ParentNodes().OfType<XamlPropertyAssignmentNode>().FirstOrDefault();
+
+            if (parentNode == null)
+            {
+                return transformed;
+            }
+
+            var lastElement =
+                transformed.Elements[transformed.Elements.Count - 1];
+            
+            if (parentNode.Property?.Getter?.ReturnType == context.GetAvaloniaTypes().ICommand && lastElement is XamlIlClrMethodPathElementNode methodPathElement)
             {
-                IXamlMethod executeMethod = method.Method;
+                IXamlMethod executeMethod = methodPathElement.Method;
                 IXamlMethod canExecuteMethod = executeMethod.DeclaringType.FindMethod(new FindMethodMethodSignature($"Can{executeMethod.Name}", context.Configuration.WellKnownTypes.Boolean, context.Configuration.WellKnownTypes.Object));
                 List<string> dependsOnProperties = new();
                 if (canExecuteMethod is not null)

+ 16 - 12
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<TApp> : 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<TApp>();
             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;
-            }
-        }
     }
 }

+ 2 - 0
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<IPlatformOpenGlInterface>().ToConstant(GlFeature)
                 .Bind<ICursorFactory>().ToConstant(new CursorFactoryStub())
@@ -57,6 +58,7 @@ namespace Avalonia.iOS
                 .Bind<IRenderTimer>().ToConstant(Timer)
                 .Bind<IPlatformThreadingInterface>().ToConstant(new PlatformThreadingInterface())
                 .Bind<IKeyboardDevice>().ToConstant(keyboard);
+
             keyboard.PropertyChanged += (_, changed) =>
             {
                 if (changed.PropertyName == nameof(KeyboardDevice.FocusedElement))

+ 0 - 7
src/iOS/Avalonia.iOS/SingleViewLifetime.cs

@@ -1,7 +0,0 @@
-namespace Avalonia.iOS
-{
-    public class SingleViewLifetime
-    {
-        
-    }
-}