Browse Source

Add iOS implementation

pull/8110/head
Max Katz 5 years ago
parent
commit
d8d6fa5097
  1. 27
      Avalonia.sln
  2. 9
      samples/interop/NativeEmbedSample.iOS/AppDelegate.cs
  3. 117
      samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json
  4. BIN
      samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png
  5. BIN
      samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png
  6. BIN
      samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png
  7. BIN
      samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png
  8. BIN
      samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png
  9. BIN
      samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png
  10. BIN
      samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png
  11. BIN
      samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png
  12. BIN
      samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png
  13. BIN
      samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png
  14. BIN
      samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png
  15. BIN
      samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png
  16. BIN
      samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png
  17. 6
      samples/interop/NativeEmbedSample.iOS/Entitlements.plist
  18. 42
      samples/interop/NativeEmbedSample.iOS/Info.plist
  19. 6
      samples/interop/NativeEmbedSample.iOS/Main.cs
  20. 16
      samples/interop/NativeEmbedSample.iOS/NativeEmbedSample.iOS.csproj
  21. 43
      samples/interop/NativeEmbedSample.iOS/Resources/LaunchScreen.xib
  22. 4
      src/iOS/Avalonia.iOS/AvaloniaView.cs
  23. 183
      src/iOS/Avalonia.iOS/NativeControlHostImpl.cs

27
Avalonia.sln

@ -221,6 +221,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevAnalyzers", "src\tools\D
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NativeEmbedSample.Desktop", "samples\interop\NativeEmbedSample.Desktop\NativeEmbedSample.Desktop.csproj", "{F2389463-DDB4-4317-B894-D4DF9FF6B763}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NativeEmbedSample.iOS", "samples\interop\NativeEmbedSample.iOS\NativeEmbedSample.iOS.csproj", "{28DB5AD1-656D-4619-BE0B-5B475E138DF8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
@ -2015,6 +2017,30 @@ Global
{F2389463-DDB4-4317-B894-D4DF9FF6B763}.Release|iPhone.Build.0 = Release|Any CPU
{F2389463-DDB4-4317-B894-D4DF9FF6B763}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{F2389463-DDB4-4317-B894-D4DF9FF6B763}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.AppStore|iPhone.Build.0 = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Debug|iPhone.Build.0 = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Release|Any CPU.Build.0 = Release|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Release|iPhone.ActiveCfg = Release|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Release|iPhone.Build.0 = Release|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{28DB5AD1-656D-4619-BE0B-5B475E138DF8}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -2075,6 +2101,7 @@ Global
{CE910927-CE5A-456F-BC92-E4C757354A5C} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{2B390431-288C-435C-BB6B-A374033BD8D1} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{F2389463-DDB4-4317-B894-D4DF9FF6B763} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
{28DB5AD1-656D-4619-BE0B-5B475E138DF8} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}

9
samples/interop/NativeEmbedSample.iOS/AppDelegate.cs

@ -0,0 +1,9 @@
using Avalonia.iOS;
namespace NativeEmbedSample.iOS;
[Register("AppDelegate")]
public partial class AppDelegate : AvaloniaAppDelegate<App>
{
}

117
samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json

@ -0,0 +1,117 @@
{
"images": [
{
"scale": "2x",
"size": "20x20",
"idiom": "iphone",
"filename": "Icon40.png"
},
{
"scale": "3x",
"size": "20x20",
"idiom": "iphone",
"filename": "Icon60.png"
},
{
"scale": "2x",
"size": "29x29",
"idiom": "iphone",
"filename": "Icon58.png"
},
{
"scale": "3x",
"size": "29x29",
"idiom": "iphone",
"filename": "Icon87.png"
},
{
"scale": "2x",
"size": "40x40",
"idiom": "iphone",
"filename": "Icon80.png"
},
{
"scale": "3x",
"size": "40x40",
"idiom": "iphone",
"filename": "Icon120.png"
},
{
"scale": "2x",
"size": "60x60",
"idiom": "iphone",
"filename": "Icon120.png"
},
{
"scale": "3x",
"size": "60x60",
"idiom": "iphone",
"filename": "Icon180.png"
},
{
"scale": "1x",
"size": "20x20",
"idiom": "ipad",
"filename": "Icon20.png"
},
{
"scale": "2x",
"size": "20x20",
"idiom": "ipad",
"filename": "Icon40.png"
},
{
"scale": "1x",
"size": "29x29",
"idiom": "ipad",
"filename": "Icon29.png"
},
{
"scale": "2x",
"size": "29x29",
"idiom": "ipad",
"filename": "Icon58.png"
},
{
"scale": "1x",
"size": "40x40",
"idiom": "ipad",
"filename": "Icon40.png"
},
{
"scale": "2x",
"size": "40x40",
"idiom": "ipad",
"filename": "Icon80.png"
},
{
"scale": "1x",
"size": "76x76",
"idiom": "ipad",
"filename": "Icon76.png"
},
{
"scale": "2x",
"size": "76x76",
"idiom": "ipad",
"filename": "Icon152.png"
},
{
"scale": "2x",
"size": "83.5x83.5",
"idiom": "ipad",
"filename": "Icon167.png"
},
{
"scale": "1x",
"size": "1024x1024",
"idiom": "ios-marketing",
"filename": "Icon1024.png"
}
],
"properties": {},
"info": {
"version": 1,
"author": "xcode"
}
}

BIN
samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

BIN
samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 845 B

BIN
samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
samples/interop/NativeEmbedSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

6
samples/interop/NativeEmbedSample.iOS/Entitlements.plist

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
</dict>
</plist>

42
samples/interop/NativeEmbedSample.iOS/Info.plist

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>AvaloniaNative</string>
<key>CFBundleIdentifier</key>
<string>Avalonia.Native.Sample</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>XSAppIconAssets</key>
<string>Assets.xcassets/AppIcon.appiconset</string>
</dict>
</plist>

6
samples/interop/NativeEmbedSample.iOS/Main.cs

@ -0,0 +1,6 @@
using NativeEmbedSample.iOS;
// This is the main entry point of the application.
// If you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here.
UIApplication.Main(args, null, typeof(AppDelegate));

16
samples/interop/NativeEmbedSample.iOS/NativeEmbedSample.iOS.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-ios</TargetFramework>
<ProvisioningType>manual</ProvisioningType>
<OutputType>Exe</OutputType>
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
<SupportedOSPlatformVersion>11.2</SupportedOSPlatformVersion>
<RuntimeIdentifier>iossimulator-x64</RuntimeIdentifier>
<!-- <RuntimeIdentifier>ios-arm64</RuntimeIdentifier>-->
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\iOS\Avalonia.iOS\Avalonia.iOS.csproj" />
<ProjectReference Include="..\NativeEmbedSample\NativeEmbedSample.csproj" />
</ItemGroup>
</Project>

43
samples/interop/NativeEmbedSample.iOS/Resources/LaunchScreen.xib

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6214" systemVersion="14A314h" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6207" />
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1" />
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" />
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder" />
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480" />
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" />
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2017 " textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines"
minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="20" y="439" width="441" height="21" />
<fontDescription key="fontDescription" type="system" pointSize="17" />
<color key="textColor" cocoaTouchSystemColor="darkTextColor" />
<nil key="highlightedColor" />
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="NewApp" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines"
minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="140" width="441" height="43" />
<fontDescription key="fontDescription" type="boldSystem" pointSize="36" />
<color key="textColor" cocoaTouchSystemColor="darkTextColor" />
<nil key="highlightedColor" />
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite" />
<constraints>
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC" />
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk" />
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l" />
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0" />
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9" />
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g" />
</constraints>
<nil key="simulatedStatusBarMetrics" />
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics" />
<point key="canvasLocation" x="548" y="455" />
</view>
</objects>
</document>

4
src/iOS/Avalonia.iOS/AvaloniaView.cs

@ -43,7 +43,7 @@ namespace Avalonia.iOS
MultipleTouchEnabled = true;
}
internal class TopLevelImpl : ITopLevelImplWithTextInputMethod
internal class TopLevelImpl : ITopLevelImplWithTextInputMethod, ITopLevelImplWithNativeControlHost
{
private readonly AvaloniaView _view;
public AvaloniaView View => _view;
@ -51,6 +51,7 @@ namespace Avalonia.iOS
public TopLevelImpl(AvaloniaView view)
{
_view = view;
NativeControlHost = new NativeControlHostImpl(_view);
}
public void Dispose()
@ -112,6 +113,7 @@ namespace Avalonia.iOS
new AcrylicPlatformCompensationLevels();
public ITextInputMethodImpl? TextInputMethod => _view;
public INativeControlHostImpl NativeControlHost { get; }
}
[Export("layerClass")]

183
src/iOS/Avalonia.iOS/NativeControlHostImpl.cs

@ -0,0 +1,183 @@
#nullable enable
using System;
using System.Diagnostics.CodeAnalysis;
using Avalonia.Controls.Platform;
using Avalonia.Platform;
using CoreGraphics;
using ObjCRuntime;
using UIKit;
namespace Avalonia.iOS
{
internal class NativeControlHostImpl : INativeControlHostImpl
{
private readonly AvaloniaView _avaloniaView;
public NativeControlHostImpl(AvaloniaView avaloniaView)
{
_avaloniaView = avaloniaView;
}
public INativeControlHostDestroyableControlHandle CreateDefaultChild(IPlatformHandle parent)
{
return new UIViewControlHandle(new UIView());
}
public INativeControlHostControlTopLevelAttachment CreateNewAttachment(Func<IPlatformHandle, IPlatformHandle> create)
{
var holder = new UIViewControlHandle(_avaloniaView);
NativeControlAttachment? attachment = null;
try
{
var child = create(holder);
// It has to be assigned to the variable before property setter is called so we dispose it on exception
#pragma warning disable IDE0017 // Simplify object initialization
attachment = new NativeControlAttachment(holder, child);
#pragma warning restore IDE0017 // Simplify object initialization
attachment.AttachedTo = this;
return attachment;
}
catch
{
attachment?.Dispose();
holder?.Destroy();
throw;
}
}
public INativeControlHostControlTopLevelAttachment CreateNewAttachment(IPlatformHandle handle)
{
return new NativeControlAttachment(new UIViewControlHandle(_avaloniaView), handle)
{
AttachedTo = this
};
}
public bool IsCompatibleWith(IPlatformHandle handle) => handle.HandleDescriptor == UIViewControlHandle.UIViewDescriptor;
private class ViewHolder : UIView
{
public ViewHolder(IntPtr handle) : base(new NativeHandle(handle))
{
}
}
private class NativeControlAttachment : INativeControlHostControlTopLevelAttachment
{
// ReSharper disable once NotAccessedField.Local (keep GC reference)
private IPlatformHandle? _child;
private UIViewControlHandle? _holder;
private UIView? _view;
private NativeControlHostImpl? _attachedTo;
public NativeControlAttachment(UIViewControlHandle holder, IPlatformHandle child)
{
_holder = holder;
_child = child;
_view = (child as UIViewControlHandle)?.View ?? new ViewHolder(child.Handle);
_holder.View.AddSubview(_view);
}
[MemberNotNull(nameof(_view))]
private void CheckDisposed()
{
if (_view == null)
throw new ObjectDisposedException(nameof(NativeControlAttachment));
}
public void Dispose()
{
_view?.RemoveFromSuperview();
_holder = null;
_child = null;
_attachedTo = null;
_view?.Dispose();
_view = null;
}
public INativeControlHostImpl? AttachedTo
{
get => _attachedTo;
set
{
CheckDisposed();
_attachedTo = (NativeControlHostImpl?)value;
if (_attachedTo == null)
{
_view.RemoveFromSuperview();
}
else
{
_holder!.View.AddSubview(_view);
}
}
}
public bool IsCompatibleWith(INativeControlHostImpl host) => host is NativeControlHostImpl;
public void HideWithSize(Size size)
{
CheckDisposed();
_view.Hidden = true;
}
public void ShowInBounds(Rect bounds)
{
CheckDisposed();
if (_attachedTo == null)
throw new InvalidOperationException("The control isn't currently attached to a toplevel");
//bounds = _attachedTo._avaloniaView.ContentScaleFactor;
_view.Frame = new CGRect(bounds.X, bounds.Y, bounds.Width, bounds.Height);
_view.Hidden = false;
}
}
}
public class UIViewControlHandle : INativeControlHostDestroyableControlHandle, IDisposable
{
internal const string UIViewDescriptor = "UIView";
private UIView? _view;
public UIViewControlHandle(UIView view)
{
_view = view;
}
public UIView View => _view ?? throw new ObjectDisposedException(nameof(UIViewControlHandle));
public string HandleDescriptor => UIViewDescriptor;
IntPtr IPlatformHandle.Handle => _view?.Handle.Handle ?? default;
public void Destroy()
{
Dispose(true);
}
void IDisposable.Dispose()
{
Dispose(true);
}
~UIViewControlHandle()
{
Dispose(false);
}
private void Dispose(bool disposing)
{
_view?.Dispose();
_view = null;
if (disposing)
{
GC.SuppressFinalize(this);
}
}
}
}
Loading…
Cancel
Save