Browse Source

Merge pull request #868 from kekekeks/droid-fixes

Make android support great-ish again
pull/872/head
Steven Kirk 10 years ago
committed by GitHub
parent
commit
2be56cde1d
  1. 35
      Avalonia.sln
  2. 5
      samples/ControlCatalog.Android/ControlCatalog.Android.csproj
  3. 24
      samples/ControlCatalog.Android/MainActivity.cs
  4. 25
      src/Android/Avalonia.Android/AndroidPlatform.cs
  5. 12
      src/Android/Avalonia.Android/AndroidThreadingInterface.cs
  6. 9
      src/Android/Avalonia.Android/Avalonia.Android.csproj
  7. 50
      src/Android/Avalonia.Android/AvaloniaActivity.cs
  8. 59
      src/Android/Avalonia.Android/AvaloniaView.cs
  9. 101
      src/Android/Avalonia.Android/Platform/SkiaPlatform/AndroidFramebuffer.cs
  10. 8
      src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
  11. 44
      src/Android/Avalonia.Android/Platform/SkiaPlatform/MainWindowImpl.cs
  12. 32
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  13. 60
      src/Android/Avalonia.Android/Platform/Specific/AvaloniaActivity.cs
  14. 2
      src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs
  15. 2
      src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs
  16. 12
      src/Android/Avalonia.Android/Platform/Specific/IAndroidActivity.cs
  17. 12
      src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
  18. 32
      src/Android/Avalonia.AndroidTestApplication/MainActivity.cs
  19. 7
      src/Skia/Avalonia.Skia.Android.TestApp/App.cs
  20. 138
      src/Skia/Avalonia.Skia.Android.TestApp/Avalonia.Skia.Android.TestApp.csproj
  21. 26
      src/Skia/Avalonia.Skia.Android.TestApp/Avalonia.Skia.Android.TestApp.v2.ncrunchproject
  22. 78
      src/Skia/Avalonia.Skia.Android.TestApp/MainActivity.cs
  23. 5
      src/Skia/Avalonia.Skia.Android.TestApp/Properties/AndroidManifest.xml
  24. 30
      src/Skia/Avalonia.Skia.Android.TestApp/Properties/AssemblyInfo.cs
  25. 114
      src/Skia/Avalonia.Skia.Android.TestApp/Resources/Resource.Designer.cs
  26. BIN
      src/Skia/Avalonia.Skia.Android.TestApp/Resources/drawable/Icon.png
  27. 13
      src/Skia/Avalonia.Skia.Android.TestApp/Resources/layout/Main.axml
  28. 5
      src/Skia/Avalonia.Skia.Android.TestApp/Resources/values/Strings.xml
  29. 9
      src/Skia/Avalonia.Skia.Android/AndroidPlatformRenderInterface.cs
  30. 24
      src/Skia/Avalonia.Skia.Android/AndroidRenderTarget.cs
  31. 4
      src/Skia/Avalonia.Skia.Android/Avalonia.Skia.Android.csproj
  32. 106
      src/Skia/Avalonia.Skia.Android/RenderTarget.cs
  33. 39
      src/Skia/Avalonia.Skia.Android/SkiaRenderView.cs
  34. 1
      src/Skia/Avalonia.Skia.iOS/Avalonia.Skia.iOS.csproj
  35. 0
      src/Skia/Avalonia.Skia.iOS/WindowDrawingContextImpl.cs
  36. 1
      src/Skia/Avalonia.Skia/Avalonia.Skia.projitems

35
Avalonia.sln

@ -99,8 +99,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.Desktop", "sr
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.Android", "src\Skia\Avalonia.Skia.Android\Avalonia.Skia.Android.csproj", "{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.Android", "src\Skia\Avalonia.Skia.Android\Avalonia.Skia.Android.csproj", "{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.Android.TestApp", "src\Skia\Avalonia.Skia.Android.TestApp\Avalonia.Skia.Android.TestApp.csproj", "{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.iOS.TestApp", "src\Skia\Avalonia.Skia.iOS.TestApp\Avalonia.Skia.iOS.TestApp.csproj", "{DA49C5F3-BE95-461C-B999-072128CCF59E}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.iOS.TestApp", "src\Skia\Avalonia.Skia.iOS.TestApp\Avalonia.Skia.iOS.TestApp.csproj", "{DA49C5F3-BE95-461C-B999-072128CCF59E}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.iOS", "src\Skia\Avalonia.Skia.iOS\Avalonia.Skia.iOS.csproj", "{47BE08A7-5985-410B-9FFC-2264B8EA595F}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.iOS", "src\Skia\Avalonia.Skia.iOS\Avalonia.Skia.iOS.csproj", "{47BE08A7-5985-410B-9FFC-2264B8EA595F}"
@ -1469,38 +1467,6 @@ Global
{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|Mono.ActiveCfg = Release|Any CPU {BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|Mono.ActiveCfg = Release|Any CPU
{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|x86.ActiveCfg = Release|Any CPU {BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|x86.ActiveCfg = Release|Any CPU
{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|x86.Build.0 = Release|Any CPU {BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|x86.Build.0 = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|Mono.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|x86.Deploy.0 = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|Mono.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|x86.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|x86.Build.0 = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|x86.Deploy.0 = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|Mono.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|x86.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|x86.Build.0 = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|x86.Deploy.0 = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|Any CPU.Build.0 = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|Any CPU.Deploy.0 = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|iPhone.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|Mono.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|x86.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|x86.Build.0 = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|x86.Deploy.0 = Release|Any CPU
{DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone {DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone
{DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone {DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
{DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone {DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
@ -2359,7 +2325,6 @@ Global
{2F59F3D0-748D-4652-B01E-E0D954756308} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E} {2F59F3D0-748D-4652-B01E-E0D954756308} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{925DD807-B651-475F-9F7C-CBEB974CE43D} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E} {925DD807-B651-475F-9F7C-CBEB974CE43D} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E} {BD43F7C0-396B-4AA1-BAD9-DFDE54D51298} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{DA49C5F3-BE95-461C-B999-072128CCF59E} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E} {DA49C5F3-BE95-461C-B999-072128CCF59E} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{47BE08A7-5985-410B-9FFC-2264B8EA595F} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E} {47BE08A7-5985-410B-9FFC-2264B8EA595F} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{7B92AF71-6287-4693-9DCB-BD5B6E927E23} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F} {7B92AF71-6287-4693-9DCB-BD5B6E927E23} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}

5
samples/ControlCatalog.Android/ControlCatalog.Android.csproj

@ -32,9 +32,12 @@
<EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk> <EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
<BundleAssemblies>False</BundleAssemblies> <BundleAssemblies>False</BundleAssemblies>
<AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi> <AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
<AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis> <AndroidSupportedAbis>armeabi;armeabi-v7a;x86</AndroidSupportedAbis>
<Debugger>Xamarin</Debugger> <Debugger>Xamarin</Debugger>
<AndroidEnableMultiDex>False</AndroidEnableMultiDex> <AndroidEnableMultiDex>False</AndroidEnableMultiDex>
<AotAssemblies>False</AotAssemblies>
<EnableLLVM>False</EnableLLVM>
<EnableProguard>False</EnableProguard>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>

24
samples/ControlCatalog.Android/MainActivity.cs

@ -1,9 +1,8 @@
using System; using System;
using Android.App; using Android.App;
using Android.OS; using Android.OS;
using Android.Content.PM; using Android.Content.PM;
using Avalonia.Android.Platform.Specific; using Avalonia.Android;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
@ -17,29 +16,16 @@ namespace ControlCatalog.Android
[Activity(Label = "ControlCatalog.Android", MainLauncher = true, Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleInstance)] [Activity(Label = "ControlCatalog.Android", MainLauncher = true, Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleInstance)]
public class MainActivity : AvaloniaActivity public class MainActivity : AvaloniaActivity
{ {
public MainActivity() : base(typeof (App))
{
}
protected override void OnCreate(Bundle savedInstanceState) protected override void OnCreate(Bundle savedInstanceState)
{ {
base.OnCreate(savedInstanceState); if (Avalonia.Application.Current == null)
App app;
if (Avalonia.Application.Current != null)
app = (App)Avalonia.Application.Current;
else
{ {
app = new App(); AppBuilder.Configure(new App())
AppBuilder.Configure(app)
.UseAndroid() .UseAndroid()
.UseSkia()
.SetupWithoutStarting(); .SetupWithoutStarting();
Content = new MainView();
} }
base.OnCreate(savedInstanceState);
var mainWindow = new MainWindow();
app.Run(mainWindow);
} }
} }
} }

25
src/Android/Avalonia.Android/AndroidPlatform.cs

@ -1,5 +1,8 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq;
using Android.Content;
using Android.Views;
using Avalonia.Android.Platform; using Avalonia.Android.Platform;
using Avalonia.Android.Platform.Input; using Avalonia.Android.Platform.Input;
using Avalonia.Android.Platform.SkiaPlatform; using Avalonia.Android.Platform.SkiaPlatform;
@ -8,6 +11,7 @@ using Avalonia.Controls.Platform;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Input.Platform; using Avalonia.Input.Platform;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Shared.PlatformSupport; using Avalonia.Shared.PlatformSupport;
using Avalonia.Skia; using Avalonia.Skia;
@ -17,7 +21,8 @@ namespace Avalonia
{ {
public static T UseAndroid<T>(this T builder) where T : AppBuilderBase<T>, new() public static T UseAndroid<T>(this T builder) where T : AppBuilderBase<T>, new()
{ {
builder.UseWindowingSubsystem(Android.AndroidPlatform.Initialize, "Android"); builder.UseWindowingSubsystem(() => Android.AndroidPlatform.Initialize(builder.Instance), "Android");
builder.UseSkia();
return builder; return builder;
} }
} }
@ -25,7 +30,7 @@ namespace Avalonia
namespace Avalonia.Android namespace Avalonia.Android
{ {
public class AndroidPlatform : IPlatformSettings, IWindowingPlatform class AndroidPlatform : IPlatformSettings, IWindowingPlatform
{ {
public static readonly AndroidPlatform Instance = new AndroidPlatform(); public static readonly AndroidPlatform Instance = new AndroidPlatform();
public Size DoubleClickSize => new Size(4, 4); public Size DoubleClickSize => new Size(4, 4);
@ -40,7 +45,7 @@ namespace Avalonia.Android
_scalingFactor = global::Android.App.Application.Context.Resources.DisplayMetrics.ScaledDensity; _scalingFactor = global::Android.App.Application.Context.Resources.DisplayMetrics.ScaledDensity;
} }
public static void Initialize() public static void Initialize(Avalonia.Application app)
{ {
AvaloniaLocator.CurrentMutable AvaloniaLocator.CurrentMutable
.Bind<IClipboard>().ToTransient<ClipboardImpl>() .Bind<IClipboard>().ToTransient<ClipboardImpl>()
@ -51,24 +56,22 @@ namespace Avalonia.Android
.Bind<IPlatformThreadingInterface>().ToConstant(new AndroidThreadingInterface()) .Bind<IPlatformThreadingInterface>().ToConstant(new AndroidThreadingInterface())
.Bind<ISystemDialogImpl>().ToTransient<SystemDialogImpl>() .Bind<ISystemDialogImpl>().ToTransient<SystemDialogImpl>()
.Bind<IWindowingPlatform>().ToConstant(Instance) .Bind<IWindowingPlatform>().ToConstant(Instance)
.Bind<IPlatformIconLoader>().ToSingleton<PlatformIconLoader>(); .Bind<IPlatformIconLoader>().ToSingleton<PlatformIconLoader>()
.Bind<IRenderLoop>().ToConstant(new DefaultRenderLoop(60))
SkiaPlatform.Initialize(); .Bind<IAssetLoader>().ToConstant(new AssetLoader(app.GetType().Assembly));
}
public void Init(Type applicationType) SkiaPlatform.Initialize();
{
StandardRuntimePlatformServices.Register(applicationType.Assembly);
} }
public IWindowImpl CreateWindow() public IWindowImpl CreateWindow()
{ {
return new WindowImpl(); throw new NotSupportedException();
} }
public IEmbeddableWindowImpl CreateEmbeddableWindow() public IEmbeddableWindowImpl CreateEmbeddableWindow()
{ {
throw new NotImplementedException(); throw new NotSupportedException();
} }
public IPopupImpl CreatePopup() public IPopupImpl CreatePopup()

12
src/Android/Avalonia.Android/AndroidThreadingInterface.cs

@ -51,10 +51,16 @@ namespace Avalonia.Android
scheduled = true; scheduled = true;
EnsureInvokeOnMainThread(() => EnsureInvokeOnMainThread(() =>
{ {
tick(); try
lock (l)
{ {
scheduled = false; tick();
}
finally
{
lock (l)
{
scheduled = false;
}
} }
}); });
} }

9
src/Android/Avalonia.Android/Avalonia.Android.csproj

@ -63,16 +63,17 @@
<ItemGroup> <ItemGroup>
<Compile Include="AndroidPlatform.cs" /> <Compile Include="AndroidPlatform.cs" />
<Compile Include="AndroidThreadingInterface.cs" /> <Compile Include="AndroidThreadingInterface.cs" />
<Compile Include="AvaloniaActivity.cs" />
<Compile Include="AvaloniaView.cs" />
<Compile Include="PlatformIconLoader.cs" /> <Compile Include="PlatformIconLoader.cs" />
<Compile Include="Platform\ClipboardImpl.cs" /> <Compile Include="Platform\ClipboardImpl.cs" />
<Compile Include="CursorFactory.cs" /> <Compile Include="CursorFactory.cs" />
<Compile Include="Platform\Input\AndroidKeyboardDevice.cs" /> <Compile Include="Platform\Input\AndroidKeyboardDevice.cs" />
<Compile Include="Platform\Input\AndroidMouseDevice.cs" /> <Compile Include="Platform\Input\AndroidMouseDevice.cs" />
<Compile Include="Platform\SkiaPlatform\MainWindowImpl.cs" /> <Compile Include="Platform\SkiaPlatform\AndroidFramebuffer.cs" />
<Compile Include="Platform\SkiaPlatform\WindowImpl.cs" /> <Compile Include="Platform\SkiaPlatform\InvalidationAwareSurfaceView.cs" />
<Compile Include="Platform\SkiaPlatform\TopLevelImpl.cs" />
<Compile Include="Platform\Specific\IAndroidView.cs" /> <Compile Include="Platform\Specific\IAndroidView.cs" />
<Compile Include="Platform\Specific\IAndroidActivity.cs" />
<Compile Include="Platform\Specific\AvaloniaActivity.cs" />
<Compile Include="Platform\Specific\Helpers\AndroidTouchEventsHelper.cs" /> <Compile Include="Platform\Specific\Helpers\AndroidTouchEventsHelper.cs" />
<Compile Include="Platform\Specific\Helpers\AndroidKeyboardEventsHelper.cs" /> <Compile Include="Platform\Specific\Helpers\AndroidKeyboardEventsHelper.cs" />
<Compile Include="Resources\Resource.Designer.cs" /> <Compile Include="Resources\Resource.Designer.cs" />

50
src/Android/Avalonia.Android/AvaloniaActivity.cs

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace Avalonia.Android
{
public abstract class AvaloniaActivity : Activity
{
AvaloniaView _view;
object _content;
protected override void OnCreate(Bundle savedInstanceState)
{
RequestWindowFeature(WindowFeatures.NoTitle);
_view = new AvaloniaView(this);
if(_content != null)
_view.Content = _content;
SetContentView(_view);
TakeKeyEvents(true);
base.OnCreate(savedInstanceState);
}
public object Content
{
get
{
return _content;
}
set
{
_content = value;
if (_view != null)
_view.Content = value;
}
}
public override bool DispatchKeyEvent(KeyEvent e)
{
return _view.DispatchKeyEvent(e);
}
}
}

59
src/Android/Avalonia.Android/AvaloniaView.cs

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Avalonia.Android.Platform.SkiaPlatform;
using Avalonia.Controls.Embedding;
using Avalonia.Platform;
namespace Avalonia.Android
{
public class AvaloniaView : FrameLayout
{
private readonly EmbeddableControlRoot _root;
private readonly ViewImpl _view;
public AvaloniaView(Context context) : base(context)
{
_view = new ViewImpl(context);
AddView(_view);
_root = new EmbeddableControlRoot(_view);
_root.Prepare();
}
public object Content
{
get { return _root.Content; }
set { _root.Content = value; }
}
public override bool DispatchKeyEvent(KeyEvent e)
{
return _view.DispatchKeyEvent(e);
}
class ViewImpl : TopLevelImpl, IEmbeddableWindowImpl
{
public event Action LostFocus;
public ViewImpl(Context context) : base(context)
{
Focusable = true;
FocusChange += ViewImpl_FocusChange;
}
private void ViewImpl_FocusChange(object sender, FocusChangeEventArgs e)
{
if(!e.HasFocus)
LostFocus?.Invoke();
}
}
}
}

101
src/Android/Avalonia.Android/Platform/SkiaPlatform/AndroidFramebuffer.cs

@ -0,0 +1,101 @@
using System;
using System.Runtime.InteropServices;
using Android.Runtime;
using Android.Views;
using Avalonia.Controls.Platform.Surfaces;
namespace Avalonia.Android.Platform.SkiaPlatform
{
class AndroidFramebuffer : ILockedFramebuffer
{
private IntPtr _window;
public AndroidFramebuffer(Surface surface)
{
_window = ANativeWindow_fromSurface(JNIEnv.Handle, surface.Handle);
ANativeWindow_Buffer buffer;
var rc = new ARect()
{
right = Width = ANativeWindow_getWidth(_window),
bottom = Height = ANativeWindow_getHeight(_window)
};
ANativeWindow_lock(_window, out buffer, ref rc);
Format = buffer.format == AndroidPixelFormat.WINDOW_FORMAT_RGB_565
? PixelFormat.Rgb565 : PixelFormat.Rgba8888;
RowBytes = buffer.stride * (Format == PixelFormat.Rgb565 ? 2 : 4);
Address = buffer.bits;
}
public void Dispose()
{
ANativeWindow_unlockAndPost(_window);
ANativeWindow_release(_window);
_window = IntPtr.Zero;
Address = IntPtr.Zero;
}
public IntPtr Address { get; set; }
public int Width { get; }
public int Height { get; }
public int RowBytes { get; }
public Size Dpi { get; } = new Size(96, 96);
public PixelFormat Format { get; }
[DllImport("android")]
internal static extern IntPtr ANativeWindow_fromSurface(IntPtr jniEnv, IntPtr handle);
[DllImport("android")]
internal static extern int ANativeWindow_getWidth(IntPtr window);
[DllImport("android")]
internal static extern int ANativeWindow_getHeight(IntPtr window);
[DllImport("android")]
internal static extern void ANativeWindow_release(IntPtr window);
[DllImport("android")]
internal static extern void ANativeWindow_unlockAndPost(IntPtr window);
[DllImport("android")]
internal static extern int ANativeWindow_lock(IntPtr window, out ANativeWindow_Buffer outBuffer, ref ARect inOutDirtyBounds);
public enum AndroidPixelFormat
{
WINDOW_FORMAT_RGBA_8888 = 1,
WINDOW_FORMAT_RGBX_8888 = 2,
WINDOW_FORMAT_RGB_565 = 4,
}
internal struct ARect
{
public int left;
public int top;
public int right;
public int bottom;
}
internal struct ANativeWindow_Buffer
{
// The number of pixels that are show horizontally.
public int width;
// The number of pixels that are shown vertically.
public int height;
// The number of *pixels* that a line in the buffer takes in
// memory. This may be >= width.
public int stride;
// The format of the buffer. One of WINDOW_FORMAT_*
public AndroidPixelFormat format;
// The actual bits.
public IntPtr bits;
// Do not touch.
uint reserved1;
uint reserved2;
uint reserved3;
uint reserved4;
uint reserved5;
uint reserved6;
}
}
}

8
src/Skia/Avalonia.Skia.Android/SkiaView.cs → src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs

@ -14,16 +14,16 @@ using Android.Widget;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Platform; using Avalonia.Platform;
namespace Avalonia.Skia.Android namespace Avalonia.Android
{ {
public abstract class SkiaView : SurfaceView, ISurfaceHolderCallback, IPlatformHandle public abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, IPlatformHandle
{ {
private readonly Activity _context; private readonly Context _context;
bool _invalidateQueued; bool _invalidateQueued;
readonly object _lock = new object(); readonly object _lock = new object();
private readonly Handler _handler; private readonly Handler _handler;
public SkiaView(Activity context) : base(context) public InvalidationAwareSurfaceView(Context context) : base(context)
{ {
_context = context; _context = context;
Holder.AddCallback(this); Holder.AddCallback(this);

44
src/Android/Avalonia.Android/Platform/SkiaPlatform/MainWindowImpl.cs

@ -1,44 +0,0 @@
using Android.Views;
using Avalonia.Android.Platform.Specific;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Platform;
namespace Avalonia.Android.Platform.SkiaPlatform
{
public class MainWindowImpl :
WindowImpl
, IWindowImpl
{
public MainWindowImpl()
{
}
public new WindowState WindowState
{
get { return WindowState.Normal; }
set { }
}
protected override void Init()
{
base.Init();
HandleEvents = true;
_keyboardHelper.ActivateAutoShowKeybord();
}
void ITopLevelImpl.Show()
{
(Parent as ViewGroup)?.RemoveAllViews();
AvaloniaLocator.Current.GetService<IAndroidActivity>().ContentView = this;
//this.Visibility = ViewStates.Visible;
}
void ITopLevelImpl.SetInputRoot(IInputRoot inputRoot)
{
base.SetInputRoot(inputRoot);
_keyboardHelper.UpdateKeyboardState(inputRoot);
}
}
}

32
src/Android/Avalonia.Android/Platform/SkiaPlatform/WindowImpl.cs → src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -7,32 +7,30 @@ using Avalonia.Android.Platform.Specific.Helpers;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Input.Raw; using Avalonia.Input.Raw;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Skia.Android;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Platform.Surfaces;
namespace Avalonia.Android.Platform.SkiaPlatform namespace Avalonia.Android.Platform.SkiaPlatform
{ {
public class WindowImpl : SkiaView, IAndroidView, IWindowImpl, ISurfaceHolderCallback class TopLevelImpl : InvalidationAwareSurfaceView, IAndroidView, ITopLevelImpl,
ISurfaceHolderCallback, IFramebufferPlatformSurface
{ {
protected AndroidKeyboardEventsHelper<WindowImpl> _keyboardHelper; protected AndroidKeyboardEventsHelper<TopLevelImpl> _keyboardHelper;
private AndroidTouchEventsHelper<WindowImpl> _touchHelper; private AndroidTouchEventsHelper<TopLevelImpl> _touchHelper;
public WindowImpl(Context context) : base((Activity)context) public TopLevelImpl(Context context) : base(context)
{ {
_keyboardHelper = new AndroidKeyboardEventsHelper<WindowImpl>(this); _keyboardHelper = new AndroidKeyboardEventsHelper<TopLevelImpl>(this);
_touchHelper = new AndroidTouchEventsHelper<WindowImpl>(this, () => InputRoot, p => GetAvaloniaPointFromEvent(p)); _touchHelper = new AndroidTouchEventsHelper<TopLevelImpl>(this, () => InputRoot, p => GetAvaloniaPointFromEvent(p));
MaxClientSize = new Size(Resources.DisplayMetrics.WidthPixels, Resources.DisplayMetrics.HeightPixels); MaxClientSize = new Size(Resources.DisplayMetrics.WidthPixels, Resources.DisplayMetrics.HeightPixels);
ClientSize = MaxClientSize; ClientSize = MaxClientSize;
Init();
}
public WindowImpl() : this(AvaloniaLocator.Current.GetService<IAndroidActivity>().Activity)
{
} }
void ISurfaceHolderCallback.SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height) void ISurfaceHolderCallback.SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height)
{ {
@ -46,11 +44,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
base.SurfaceChanged(holder, format, width, height); base.SurfaceChanged(holder, format, width, height);
} }
protected virtual void Init()
{
}
private bool _handleEvents; private bool _handleEvents;
public bool HandleEvents public bool HandleEvents
@ -191,5 +185,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
{ {
// No window icons for mobile platforms // No window icons for mobile platforms
} }
}
ILockedFramebuffer IFramebufferPlatformSurface.Lock()=>new AndroidFramebuffer(Holder.Surface);
}
} }

60
src/Android/Avalonia.Android/Platform/Specific/AvaloniaActivity.cs

@ -1,60 +0,0 @@
using System;
using Android.App;
using Android.OS;
using Android.Views;
using Android.Widget;
namespace Avalonia.Android.Platform.Specific
{
public class AvaloniaActivity : Activity, IAndroidActivity
{
private IAndroidView _contentView;
public AvaloniaActivity(Type applicationType)
{
AndroidPlatform.Instance.Init(applicationType);
}
public Activity Activity => this;
public IAndroidView ContentView
{
get
{
return this._contentView;
}
set
{
this._contentView = value;
var fl = new FrameLayout(this);
fl.AddView(this._contentView.View);
//this.SetContentView(value.View);
this.SetContentView(fl);
}
}
protected override void OnCreate(Bundle savedInstanceState)
{
AvaloniaLocator.CurrentMutable.Bind<IAndroidActivity>().ToConstant(this);
RequestWindowFeature(WindowFeatures.NoTitle);
base.OnCreate(savedInstanceState);
}
public override void SetContentView(View view)
{
base.SetContentView(view);
TakeKeyEvents(true);
}
public override bool DispatchKeyEvent(KeyEvent e)
{
if (_contentView != null)
{
_contentView.View.DispatchKeyEvent(e);
}
return base.DispatchKeyEvent(e);
}
}
}

2
src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs

@ -12,7 +12,7 @@ using System.ComponentModel;
namespace Avalonia.Android.Platform.Specific.Helpers namespace Avalonia.Android.Platform.Specific.Helpers
{ {
public class AndroidKeyboardEventsHelper<TView> : IDisposable where TView : View, IWindowImpl, IAndroidView public class AndroidKeyboardEventsHelper<TView> : IDisposable where TView : View, ITopLevelImpl, IAndroidView
{ {
private TView _view; private TView _view;
private IInputElement _lastFocusedElement; private IInputElement _lastFocusedElement;

2
src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs

@ -8,7 +8,7 @@ using System;
namespace Avalonia.Android.Platform.Specific.Helpers namespace Avalonia.Android.Platform.Specific.Helpers
{ {
public class AndroidTouchEventsHelper<TView> : IDisposable where TView : View, IWindowImpl, IAndroidView public class AndroidTouchEventsHelper<TView> : IDisposable where TView : View, ITopLevelImpl, IAndroidView
{ {
private TView _view; private TView _view;
public bool HandleEvents { get; set; } public bool HandleEvents { get; set; }

12
src/Android/Avalonia.Android/Platform/Specific/IAndroidActivity.cs

@ -1,12 +0,0 @@
using Android.App;
using Android.Views;
namespace Avalonia.Android.Platform.Specific
{
public interface IAndroidActivity
{
Activity Activity { get; }
IAndroidView ContentView { get; set; }
}
}

12
src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj

@ -20,7 +20,7 @@
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest> <AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>True</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath> <OutputPath>bin\Debug\</OutputPath>
@ -29,16 +29,16 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime> <AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
<AndroidLinkMode>None</AndroidLinkMode> <AndroidLinkMode>None</AndroidLinkMode>
<AndroidLinkSkip /> <EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
<EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
<BundleAssemblies>False</BundleAssemblies> <BundleAssemblies>False</BundleAssemblies>
<AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi> <AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
<AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis> <AndroidSupportedAbis>armeabi;armeabi-v7a;x86</AndroidSupportedAbis>
<AndroidStoreUncompressedFileExtensions />
<MandroidI18n />
<Debugger>Xamarin</Debugger> <Debugger>Xamarin</Debugger>
<AndroidEnableMultiDex>False</AndroidEnableMultiDex> <AndroidEnableMultiDex>False</AndroidEnableMultiDex>
<DevInstrumentationEnabled>True</DevInstrumentationEnabled> <DevInstrumentationEnabled>True</DevInstrumentationEnabled>
<AotAssemblies>False</AotAssemblies>
<EnableLLVM>False</EnableLLVM>
<EnableProguard>False</EnableProguard>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>

32
src/Android/Avalonia.AndroidTestApplication/MainActivity.cs

@ -2,7 +2,7 @@ using System;
using Android.App; using Android.App;
using Android.Content.PM; using Android.Content.PM;
using Android.OS; using Android.OS;
using Avalonia.Android.Platform.Specific; using Avalonia.Android;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
@ -17,36 +17,24 @@ namespace Avalonia.AndroidTestApplication
Icon = "@drawable/icon", Icon = "@drawable/icon",
LaunchMode = LaunchMode.SingleInstance/*, LaunchMode = LaunchMode.SingleInstance/*,
ScreenOrientation = ScreenOrientation.Landscape*/)] ScreenOrientation = ScreenOrientation.Landscape*/)]
public class MainBaseActivity : AvaloniaActivity public class MainBaseActivity : Activity
{ {
public MainBaseActivity() : base(typeof (App))
{
}
protected override void OnCreate(Bundle savedInstanceState) protected override void OnCreate(Bundle savedInstanceState)
{ {
base.OnCreate(savedInstanceState); base.OnCreate(savedInstanceState);
if (Avalonia.Application.Current == null)
App app;
if (Avalonia.Application.Current != null)
app = (App)Avalonia.Application.Current;
else
{ {
app = new App(); AppBuilder.Configure<App>()
AppBuilder.Configure(app)
.UseAndroid() .UseAndroid()
.UseSkia()
.SetupWithoutStarting(); .SetupWithoutStarting();
} }
SetContentView(new AvaloniaView(this) { Content = App.CreateSimpleWindow() });
app.Run();
} }
} }
public class App : Application public class App : Application
{ {
public void Run() public override void Initialize()
{ {
Styles.Add(new DefaultTheme()); Styles.Add(new DefaultTheme());
@ -55,18 +43,14 @@ namespace Avalonia.AndroidTestApplication
new Uri("resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default")); new Uri("resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"));
Styles.Add(baseLight); Styles.Add(baseLight);
var wnd = App.CreateSimpleWindow();
wnd.AttachDevTools();
Run(wnd);
} }
// This provides a simple UI tree for testing input handling, drawing, etc // This provides a simple UI tree for testing input handling, drawing, etc
public static Window CreateSimpleWindow() public static ContentControl CreateSimpleWindow()
{ {
Window window = new Window ContentControl window = new ContentControl()
{ {
Title = "Avalonia Test Application",
Background = Brushes.Red, Background = Brushes.Red,
Content = new StackPanel Content = new StackPanel
{ {

7
src/Skia/Avalonia.Skia.Android.TestApp/App.cs

@ -1,7 +0,0 @@

namespace Avalonia.Skia.Android.TestApp
{
public class App : Application
{
}
}

138
src/Skia/Avalonia.Skia.Android.TestApp/Avalonia.Skia.Android.TestApp.csproj

@ -1,138 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}</ProjectGuid>
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Avalonia.Skia.Android.TestApp</RootNamespace>
<AssemblyName>Avalonia.Skia.Android.TestApp</AssemblyName>
<FileAlignment>512</FileAlignment>
<AndroidApplication>true</AndroidApplication>
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<AndroidUseLatestPlatformSdk>False</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v4.4</TargetFrameworkVersion>
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>True</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
<AndroidLinkMode>None</AndroidLinkMode>
<EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
<BundleAssemblies>False</BundleAssemblies>
<AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
<AndroidSupportedAbis>armeabi;armeabi-v7a;x86</AndroidSupportedAbis>
<Debugger>Xamarin</Debugger>
<AndroidEnableMultiDex>False</AndroidEnableMultiDex>
<DevInstrumentationEnabled>True</DevInstrumentationEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
<AndroidLinkMode>Full</AndroidLinkMode>
<EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
<BundleAssemblies>False</BundleAssemblies>
<AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
<Debugger>Xamarin</Debugger>
<AotAssemblies>False</AotAssemblies>
<EnableLLVM>False</EnableLLVM>
<AndroidEnableMultiDex>False</AndroidEnableMultiDex>
<EnableProguard>False</EnableProguard>
<DebugSymbols>False</DebugSymbols>
<AndroidSupportedAbis>armeabi;armeabi-v7a;x86</AndroidSupportedAbis>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Android" />
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Collections" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="App.cs" />
<Compile Include="MainActivity.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Resources\Resource.Designer.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Properties\AndroidManifest.xml" />
<AndroidResource Include="Resources\layout\Main.axml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Android\Avalonia.Android\Avalonia.Android.csproj">
<Project>{7b92af71-6287-4693-9dcb-bd5b6e927e23}</Project>
<Name>Avalonia.Android</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Animation\Avalonia.Animation.csproj">
<Project>{d211e587-d8bc-45b9-95a4-f297c8fa5200}</Project>
<Name>Avalonia.Animation</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Base\Avalonia.Base.csproj">
<Project>{b09b78d8-9b26-48b0-9149-d64a2f120f3f}</Project>
<Name>Avalonia.Base</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Controls\Avalonia.Controls.csproj">
<Project>{d2221c82-4a25-4583-9b43-d791e3f6820c}</Project>
<Name>Avalonia.Controls</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj">
<Project>{4a1abb09-9047-4bd5-a4ad-a055e52c5ee0}</Project>
<Name>Avalonia.DotNetFrameworkRuntime</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Input\Avalonia.Input.csproj">
<Project>{62024b2d-53eb-4638-b26b-85eeaa54866e}</Project>
<Name>Avalonia.Input</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Interactivity\Avalonia.Interactivity.csproj">
<Project>{6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}</Project>
<Name>Avalonia.Interactivity</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Layout\Avalonia.Layout.csproj">
<Project>{42472427-4774-4c81-8aff-9f27b8e31721}</Project>
<Name>Avalonia.Layout</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Visuals\Avalonia.Visuals.csproj">
<Project>{eb582467-6abb-43a1-b052-e981ba910e3a}</Project>
<Name>Avalonia.Visuals</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Styling\Avalonia.Styling.csproj">
<Project>{f1baa01a-f176-4c6a-b39d-5b40bb1b148f}</Project>
<Name>Avalonia.Styling</Name>
</ProjectReference>
<ProjectReference Include="..\Avalonia.Skia.Android\Avalonia.Skia.Android.csproj">
<Project>{bd43f7c0-396b-4aa1-bad9-dfde54d51298}</Project>
<Name>Avalonia.Skia.Android</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\Icon.png" />
<AndroidResource Include="Resources\values\Strings.xml" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

26
src/Skia/Avalonia.Skia.Android.TestApp/Avalonia.Skia.Android.TestApp.v2.ncrunchproject

@ -1,26 +0,0 @@
<ProjectConfiguration>
<AutoDetectNugetBuildDependencies>true</AutoDetectNugetBuildDependencies>
<BuildPriority>1000</BuildPriority>
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
<AllowCodeAnalysis>false</AllowCodeAnalysis>
<IgnoreThisComponentCompletely>true</IgnoreThisComponentCompletely>
<RunPreBuildEvents>false</RunPreBuildEvents>
<RunPostBuildEvents>false</RunPostBuildEvents>
<PreviouslyBuiltSuccessfully>false</PreviouslyBuiltSuccessfully>
<InstrumentAssembly>true</InstrumentAssembly>
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
<DetectStackOverflow>true</DetectStackOverflow>
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
<DefaultTestTimeout>60000</DefaultTestTimeout>
<UseBuildConfiguration />
<UseBuildPlatform />
<ProxyProcessPath />
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
<MSTestThreadApartmentState>STA</MSTestThreadApartmentState>
<BuildProcessArchitecture>x86</BuildProcessArchitecture>
</ProjectConfiguration>

78
src/Skia/Avalonia.Skia.Android.TestApp/MainActivity.cs

@ -1,78 +0,0 @@
using Android.App;
using Android.OS;
using Android.Views;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
namespace Avalonia.Skia.Android.TestApp
{
[Activity(Label = "Avalonia.Skia.Android.TestApp", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
App app;
if (Avalonia.Application.Current != null)
app = (App)Avalonia.Application.Current;
else
{
app = new App();
AppBuilder.Configure(app)
.UseAndroid()
.UseSkia()
.SetupWithoutStarting();
}
SetContentView(new MainView(this));
}
class MainView : SkiaRenderView
{
float _radians = 0;
public MainView(Activity context) : base(context)
{
}
protected override void OnRender(DrawingContext ctx)
{
ctx.FillRectangle(Brushes.Green, new Rect(0, 0, Width, Height));
var rc = new Rect(0, 0, Width/3, Height/3);
using (ctx.PushPostTransform(
Avalonia.Matrix.CreateTranslation(-Width/6, -Width/6)*
Avalonia.Matrix.CreateRotation(_radians)*
Avalonia.Matrix.CreateTranslation(Width/2, Height/2)))
{
ctx.FillRectangle(new LinearGradientBrush()
{
GradientStops =
{
new GradientStop() {Color = Colors.Blue},
new GradientStop(Colors.Red, 1)
}
}, rc, 5);
}
}
public override bool OnTouchEvent(MotionEvent e)
{
if (e.Action == MotionEventActions.Down)
return true;
if (e.Action == MotionEventActions.Move)
{
_radians = (e.RawY + e.RawY)/100;
Invalidate();
return true;
}
return base.OnTouchEvent(e);
}
}
}
}

5
src/Skia/Avalonia.Skia.Android.TestApp/Properties/AndroidManifest.xml

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="Avalonia.Skia.Android.TestApp" android:versionCode="1" android:versionName="1.0">
<uses-sdk />
<application android:label="Avalonia.Skia.Android.TestApp" android:icon="@drawable/Icon"></application>
</manifest>

30
src/Skia/Avalonia.Skia.Android.TestApp/Properties/AssemblyInfo.cs

@ -1,30 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Android.App;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Avalonia.Skia.Android.TestApp")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Avalonia.Skia.Android.TestApp")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

114
src/Skia/Avalonia.Skia.Android.TestApp/Resources/Resource.Designer.cs

@ -1,114 +0,0 @@
#pragma warning disable 1591
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
[assembly: global::Android.Runtime.ResourceDesignerAttribute("Avalonia.Skia.Android.TestApp.Resource", IsApplication=true)]
namespace Avalonia.Skia.Android.TestApp
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
public partial class Resource
{
static Resource()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
public static void UpdateIdValues()
{
global::Avalonia.Android.Resource.String.ApplicationName = global::Avalonia.Skia.Android.TestApp.Resource.String.ApplicationName;
global::Avalonia.Android.Resource.String.Hello = global::Avalonia.Skia.Android.TestApp.Resource.String.Hello;
}
public partial class Attribute
{
static Attribute()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private Attribute()
{
}
}
public partial class Drawable
{
// aapt resource value: 0x7f020000
public const int Icon = 2130837504;
static Drawable()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private Drawable()
{
}
}
public partial class Id
{
// aapt resource value: 0x7f050000
public const int MyButton = 2131034112;
static Id()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private Id()
{
}
}
public partial class Layout
{
// aapt resource value: 0x7f030000
public const int Main = 2130903040;
static Layout()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private Layout()
{
}
}
public partial class String
{
// aapt resource value: 0x7f040001
public const int ApplicationName = 2130968577;
// aapt resource value: 0x7f040000
public const int Hello = 2130968576;
static String()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private String()
{
}
}
}
}
#pragma warning restore 1591

BIN
src/Skia/Avalonia.Skia.Android.TestApp/Resources/drawable/Icon.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

13
src/Skia/Avalonia.Skia.Android.TestApp/Resources/layout/Main.axml

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:id="@+id/MyButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/Hello"
/>
</LinearLayout>

5
src/Skia/Avalonia.Skia.Android.TestApp/Resources/values/Strings.xml

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="Hello">Hello World, Click Me!</string>
<string name="ApplicationName">Avalonia.Skia.Android.TestApp</string>
</resources>

9
src/Skia/Avalonia.Skia.Android/AndroidPlatformRenderInterface.cs

@ -9,6 +9,7 @@ using Android.OS;
using Android.Runtime; using Android.Runtime;
using Android.Views; using Android.Views;
using Android.Widget; using Android.Widget;
using Avalonia.Controls.Platform.Surfaces;
using Avalonia.Platform; using Avalonia.Platform;
namespace Avalonia.Skia namespace Avalonia.Skia
@ -17,10 +18,10 @@ namespace Avalonia.Skia
{ {
public IRenderTarget CreateRenderTarget(IEnumerable<object> surfaces) public IRenderTarget CreateRenderTarget(IEnumerable<object> surfaces)
{ {
var surfaceView = surfaces?.OfType<SurfaceView>().FirstOrDefault(); var fb = surfaces?.OfType<IFramebufferPlatformSurface>().FirstOrDefault();
if (surfaceView == null) if (fb == null)
throw new ArgumentException("Avalonia.Skia.Android is only capable of drawing on SurfaceView"); throw new ArgumentException("Avalonia.Skia.Android is only capable of drawing on framebuffer");
return new WindowRenderTarget(surfaceView); return new FramebufferRenderTarget(fb);
} }
} }
} }

24
src/Skia/Avalonia.Skia.Android/AndroidRenderTarget.cs

@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Avalonia.Media;
using Avalonia.Platform;
namespace Avalonia.Skia
{
/// <summary>
/// We will likely need platform specific pieces to support HW acceleration
/// so leaving this class here for now as placeholder.
/// </summary>
internal partial class RenderTarget : IRenderTarget
{
}
}

4
src/Skia/Avalonia.Skia.Android/Avalonia.Skia.Android.csproj

@ -88,10 +88,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="AndroidPlatformRenderInterface.cs" /> <Compile Include="AndroidPlatformRenderInterface.cs" />
<Compile Include="AndroidRenderTarget.cs" />
<Compile Include="RenderTarget.cs" />
<Compile Include="SkiaRenderView.cs" />
<Compile Include="SkiaView.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />

106
src/Skia/Avalonia.Skia.Android/RenderTarget.cs

@ -1,106 +0,0 @@
using System;
using Avalonia.Media;
using Avalonia.Platform;
using SkiaSharp;
using Android.Graphics;
using Android.Views;
namespace Avalonia.Skia
{
internal partial class RenderTarget : IRenderTarget
{
public SKSurface Surface { get; protected set; }
public virtual DrawingContext CreateDrawingContext()
{
return
new DrawingContext(
new DrawingContextImpl(Surface.Canvas));
}
public void Dispose()
{
// Nothing to do here.
}
}
internal class WindowRenderTarget : RenderTarget
{
private readonly SurfaceView _surfaceView;
Bitmap _bitmap;
int Width { get; set; }
int Height { get; set; }
public WindowRenderTarget(SurfaceView surfaceView)
{
_surfaceView = surfaceView;
FixSize();
}
private void FixSize()
{
int width, height;
GetPlatformWindowSize(out width, out height);
if (Width == width && Height == height)
return;
Width = width;
Height = height;
if (Surface != null)
{
Surface.Dispose();
}
if (_bitmap != null)
{
_bitmap.Dispose();
}
_bitmap = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888);
Surface = SKSurface.Create(width, height, SKImageInfo.PlatformColorType, SKAlphaType.Premul, _bitmap.LockPixels(), width * 4);
}
private void GetPlatformWindowSize(out int w, out int h)
{
w = _surfaceView.Width;
h = _surfaceView.Height;
}
public override DrawingContext CreateDrawingContext()
{
FixSize();
var canvas = Surface.Canvas;
canvas.RestoreToCount(0);
canvas.Save();
canvas.Clear(SKColors.Red);
canvas.ResetMatrix();
return
new DrawingContext(
new WindowDrawingContextImpl(this));
}
public void Present()
{
Canvas canvas = null;
try
{
canvas = _surfaceView.Holder.LockCanvas(null);
_bitmap.UnlockPixels();
canvas.DrawBitmap(_bitmap, 0, 0, null);
}
catch (Exception)
{
}
finally
{
if (canvas != null)
_surfaceView.Holder.UnlockCanvasAndPost(canvas);
}
_bitmap.UnlockPixels();
}
}
}

39
src/Skia/Avalonia.Skia.Android/SkiaRenderView.cs

@ -1,39 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Avalonia.Media;
using Avalonia.Platform;
namespace Avalonia.Skia.Android
{
public abstract class SkiaRenderView : SkiaView
{
private IRenderTarget _renderTarget;
public SkiaRenderView(Activity context) : base(context)
{
_renderTarget =
AvaloniaLocator.Current.GetService<IPlatformRenderInterface>()
.CreateRenderTarget(new object[]{this});
}
protected override void Draw()
{
if (_renderTarget == null)
return;
using (var ctx = _renderTarget.CreateDrawingContext())
OnRender(ctx);
}
protected abstract void OnRender(DrawingContext ctx);
}
}

1
src/Skia/Avalonia.Skia.iOS/Avalonia.Skia.iOS.csproj

@ -41,6 +41,7 @@
<Compile Include="RenderTarget.cs" /> <Compile Include="RenderTarget.cs" />
<Compile Include="SkiaView.cs" /> <Compile Include="SkiaView.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="WindowDrawingContextImpl.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="SkiaSharp, Version=1.54.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL"> <Reference Include="SkiaSharp, Version=1.54.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">

0
src/Skia/Avalonia.Skia/WindowDrawingContextImpl.cs → src/Skia/Avalonia.Skia.iOS/WindowDrawingContextImpl.cs

1
src/Skia/Avalonia.Skia/Avalonia.Skia.projitems

@ -18,7 +18,6 @@
<Compile Include="$(MSBuildThisFileDirectory)SkiaSharpExtensions.cs" /> <Compile Include="$(MSBuildThisFileDirectory)SkiaSharpExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)StreamGeometryImpl.cs" /> <Compile Include="$(MSBuildThisFileDirectory)StreamGeometryImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)TypefaceCache.cs" /> <Compile Include="$(MSBuildThisFileDirectory)TypefaceCache.cs" />
<Compile Include="$(MSBuildThisFileDirectory)WindowDrawingContextImpl.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="$(MSBuildThisFileDirectory)readme.md" /> <None Include="$(MSBuildThisFileDirectory)readme.md" />

Loading…
Cancel
Save