Browse Source

Removed IWindowImpl which was a lie, removed initialization hack, fixed rendering

pull/868/head
Nikita Tsukanov 9 years ago
parent
commit
c446aaf5a6
  1. 7
      samples/ControlCatalog.Android/ControlCatalog.Android.csproj
  2. 24
      samples/ControlCatalog.Android/MainActivity.cs
  3. 25
      src/Android/Avalonia.Android/AndroidPlatform.cs
  4. 12
      src/Android/Avalonia.Android/AndroidThreadingInterface.cs
  5. 7
      src/Android/Avalonia.Android/Avalonia.Android.csproj
  6. 50
      src/Android/Avalonia.Android/AvaloniaActivity.cs
  7. 59
      src/Android/Avalonia.Android/AvaloniaView.cs
  8. 44
      src/Android/Avalonia.Android/Platform/SkiaPlatform/MainWindowImpl.cs
  9. 24
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  10. 60
      src/Android/Avalonia.Android/Platform/Specific/AvaloniaActivity.cs
  11. 2
      src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs
  12. 2
      src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs
  13. 12
      src/Android/Avalonia.Android/Platform/Specific/IAndroidActivity.cs
  14. 12
      src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
  15. 32
      src/Android/Avalonia.AndroidTestApplication/MainActivity.cs
  16. 1
      src/Skia/Avalonia.Skia.Android/Avalonia.Skia.Android.csproj
  17. 71
      src/Skia/Avalonia.Skia.Android/NativeMethods.cs
  18. 77
      src/Skia/Avalonia.Skia.Android/RenderTarget.cs
  19. 4
      src/Skia/Avalonia.Skia.Android/SkiaView.cs

7
samples/ControlCatalog.Android/ControlCatalog.Android.csproj

@ -29,12 +29,15 @@
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
<AndroidLinkMode>None</AndroidLinkMode>
<EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
<EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
<BundleAssemblies>False</BundleAssemblies>
<AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
<AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis>
<AndroidSupportedAbis>armeabi;armeabi-v7a;x86</AndroidSupportedAbis>
<Debugger>Xamarin</Debugger>
<AndroidEnableMultiDex>False</AndroidEnableMultiDex>
<AotAssemblies>False</AotAssemblies>
<EnableLLVM>False</EnableLLVM>
<EnableProguard>False</EnableProguard>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>

24
samples/ControlCatalog.Android/MainActivity.cs

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

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

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

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

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

7
src/Android/Avalonia.Android/Avalonia.Android.csproj

@ -63,16 +63,15 @@
<ItemGroup>
<Compile Include="AndroidPlatform.cs" />
<Compile Include="AndroidThreadingInterface.cs" />
<Compile Include="AvaloniaActivity.cs" />
<Compile Include="AvaloniaView.cs" />
<Compile Include="PlatformIconLoader.cs" />
<Compile Include="Platform\ClipboardImpl.cs" />
<Compile Include="CursorFactory.cs" />
<Compile Include="Platform\Input\AndroidKeyboardDevice.cs" />
<Compile Include="Platform\Input\AndroidMouseDevice.cs" />
<Compile Include="Platform\SkiaPlatform\MainWindowImpl.cs" />
<Compile Include="Platform\SkiaPlatform\WindowImpl.cs" />
<Compile Include="Platform\SkiaPlatform\TopLevelImpl.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\AndroidKeyboardEventsHelper.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();
}
}
}
}

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);
}
}
}

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

@ -14,25 +14,21 @@ using Avalonia.Controls;
namespace Avalonia.Android.Platform.SkiaPlatform
{
public class WindowImpl : SkiaView, IAndroidView, IWindowImpl, ISurfaceHolderCallback
class TopLevelImpl : SkiaView, IAndroidView, ITopLevelImpl, ISurfaceHolderCallback
{
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);
_touchHelper = new AndroidTouchEventsHelper<WindowImpl>(this, () => InputRoot, p => GetAvaloniaPointFromEvent(p));
_keyboardHelper = new AndroidKeyboardEventsHelper<TopLevelImpl>(this);
_touchHelper = new AndroidTouchEventsHelper<TopLevelImpl>(this, () => InputRoot, p => GetAvaloniaPointFromEvent(p));
MaxClientSize = new Size(Resources.DisplayMetrics.WidthPixels, Resources.DisplayMetrics.HeightPixels);
ClientSize = MaxClientSize;
Init();
}
public WindowImpl() : this(AvaloniaLocator.Current.GetService<IAndroidActivity>().Activity)
{
}
void ISurfaceHolderCallback.SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height)
{
@ -46,11 +42,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
base.SurfaceChanged(holder, format, width, height);
}
protected virtual void Init()
{
}
private bool _handleEvents;
public bool HandleEvents

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
{
public class AndroidKeyboardEventsHelper<TView> : IDisposable where TView : View, IWindowImpl, IAndroidView
public class AndroidKeyboardEventsHelper<TView> : IDisposable where TView : View, ITopLevelImpl, IAndroidView
{
private TView _view;
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
{
public class AndroidTouchEventsHelper<TView> : IDisposable where TView : View, IWindowImpl, IAndroidView
public class AndroidTouchEventsHelper<TView> : IDisposable where TView : View, ITopLevelImpl, IAndroidView
{
private TView _view;
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>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugSymbols>True</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
@ -29,16 +29,16 @@
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
<AndroidLinkMode>None</AndroidLinkMode>
<AndroidLinkSkip />
<EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
<EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
<BundleAssemblies>False</BundleAssemblies>
<AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
<AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis>
<AndroidStoreUncompressedFileExtensions />
<MandroidI18n />
<AndroidSupportedAbis>armeabi;armeabi-v7a;x86</AndroidSupportedAbis>
<Debugger>Xamarin</Debugger>
<AndroidEnableMultiDex>False</AndroidEnableMultiDex>
<DevInstrumentationEnabled>True</DevInstrumentationEnabled>
<AotAssemblies>False</AotAssemblies>
<EnableLLVM>False</EnableLLVM>
<EnableProguard>False</EnableProguard>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>

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

@ -2,7 +2,7 @@ using System;
using Android.App;
using Android.Content.PM;
using Android.OS;
using Avalonia.Android.Platform.Specific;
using Avalonia.Android;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Avalonia.Markup.Xaml;
@ -17,36 +17,24 @@ namespace Avalonia.AndroidTestApplication
Icon = "@drawable/icon",
LaunchMode = LaunchMode.SingleInstance/*,
ScreenOrientation = ScreenOrientation.Landscape*/)]
public class MainBaseActivity : AvaloniaActivity
public class MainBaseActivity : Activity
{
public MainBaseActivity() : base(typeof (App))
{
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
App app;
if (Avalonia.Application.Current != null)
app = (App)Avalonia.Application.Current;
else
if (Avalonia.Application.Current == null)
{
app = new App();
AppBuilder.Configure(app)
AppBuilder.Configure<App>()
.UseAndroid()
.UseSkia()
.SetupWithoutStarting();
}
app.Run();
SetContentView(new AvaloniaView(this) { Content = App.CreateSimpleWindow() });
}
}
public class App : Application
{
public void Run()
public override void Initialize()
{
Styles.Add(new DefaultTheme());
@ -55,18 +43,14 @@ namespace Avalonia.AndroidTestApplication
new Uri("resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"));
Styles.Add(baseLight);
var wnd = App.CreateSimpleWindow();
wnd.AttachDevTools();
Run(wnd);
}
// 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,
Content = new StackPanel
{

1
src/Skia/Avalonia.Skia.Android/Avalonia.Skia.Android.csproj

@ -89,6 +89,7 @@
<ItemGroup>
<Compile Include="AndroidPlatformRenderInterface.cs" />
<Compile Include="AndroidRenderTarget.cs" />
<Compile Include="NativeMethods.cs" />
<Compile Include="RenderTarget.cs" />
<Compile Include="SkiaRenderView.cs" />
<Compile Include="SkiaView.cs" />

71
src/Skia/Avalonia.Skia.Android/NativeMethods.cs

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace Avalonia.Skia.Android
{
static class NativeMethods
{
[DllImport("android")]
internal static extern IntPtr ANativeWindow_fromSurface(IntPtr jniEnv, IntPtr handle);
[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;
}
}
}

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

@ -3,7 +3,9 @@ using Avalonia.Media;
using Avalonia.Platform;
using SkiaSharp;
using Android.Graphics;
using Android.Runtime;
using Android.Views;
using Avalonia.Skia.Android;
namespace Avalonia.Skia
{
@ -27,49 +29,38 @@ namespace Avalonia.Skia
internal class WindowRenderTarget : RenderTarget
{
private readonly SurfaceView _surfaceView;
Bitmap _bitmap;
int Width { get; set; }
int Height { get; set; }
private IntPtr _window;
public WindowRenderTarget(SurfaceView surfaceView)
{
_surfaceView = surfaceView;
FixSize();
}
private void FixSize()
private void PrepareForDraw()
{
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;
int width = _surfaceView.Width;
var height = _surfaceView.Height;
_window = NativeMethods.ANativeWindow_fromSurface(JNIEnv.Handle, _surfaceView.Holder.Surface.Handle);
var buffer = new NativeMethods.ANativeWindow_Buffer();
var rc = new NativeMethods.ARect() {right = width, bottom = height};
NativeMethods.ANativeWindow_lock(_window, out buffer, ref rc);
var colorType = buffer.format == NativeMethods.AndroidPixelFormat.WINDOW_FORMAT_RGB_565
? SKColorType.Rgb565 : SKImageInfo.PlatformColorType;
var stride = buffer.stride * (colorType == SKColorType.Rgb565 ? 2 : 4);
Surface = SKSurface.Create(buffer.width, buffer.height, colorType,
SKAlphaType.Premul, buffer.bits, stride);
if (Surface == null)
throw new Exception("Unable to create Skia surface");
}
public override DrawingContext CreateDrawingContext()
{
FixSize();
PrepareForDraw();
var canvas = Surface.Canvas;
canvas.RestoreToCount(0);
@ -84,23 +75,11 @@ namespace Avalonia.Skia
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();
Surface?.Dispose();
Surface = null;
NativeMethods.ANativeWindow_unlockAndPost(_window);
NativeMethods.ANativeWindow_release(_window);
_window = IntPtr.Zero;
}
}
}

4
src/Skia/Avalonia.Skia.Android/SkiaView.cs

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

Loading…
Cancel
Save