Skip to content

Commit

Permalink
Fixes #18204 border lagging behind content on iOS and improves initia…
Browse files Browse the repository at this point in the history
…l render performance
  • Loading branch information
albyrock87 committed Jun 20, 2024
1 parent 4fabb3e commit 07617f5
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 7 deletions.
17 changes: 17 additions & 0 deletions src/Controls/tests/TestCases/Issues/Issue18204.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Maui.Controls.Sample.Issues.Issue18204"
Title="Issue18204">

<VerticalStackLayout Padding="24">
<Border
HorizontalOptions="Center"
x:Name="TheBorder"
BackgroundColor="LightBlue"
Shadow="{Shadow Brush=Black, Offset='0,2', Radius=2, Opacity=0.20}"
StrokeShape="{RoundRectangle CornerRadius=20}">
<Button x:Name="TheButton" Clicked="ButtonClicked" BackgroundColor="LightGreen" WidthRequest="200" HeightRequest="500" />
</Border>
</VerticalStackLayout>
</ContentPage>
25 changes: 25 additions & 0 deletions src/Controls/tests/TestCases/Issues/Issue18204.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using Microsoft.Maui;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Xaml;

namespace Maui.Controls.Sample.Issues;

[XamlCompilation(XamlCompilationOptions.Compile)]
[Issue(IssueTracker.Github, 18204, "[iOS] Drawing of Borders lags behind other elements creating bizarre overlaps and glitches", PlatformAffected.iOS)]

public partial class Issue18204 : ContentPage
{
public Issue18204()
{
InitializeComponent();
}

private void ButtonClicked(object sender, EventArgs e)
{
var button = (Button)sender;
button.CancelAnimations();
var targetHeight = button.HeightRequest == 200.0 ? 500.0 : 200.0;
button.Animate("Height", new Animation(v => button.HeightRequest = v, button.Height, targetHeight, Easing.Linear));
}
}
6 changes: 0 additions & 6 deletions src/Core/src/Handlers/Border/BorderHandler.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,7 @@ static partial void UpdateContent(IBorderHandler handler)

public override void PlatformArrange(Rect rect)
{
// Disable the animation during arrange for the Border; otherwise, all resizing actions
// will animate, and it makes the Border lag behind its content.

CATransaction.Begin();
CATransaction.AnimationDuration = 0;
base.PlatformArrange(rect);
CATransaction.Commit();
}
}
}
7 changes: 7 additions & 0 deletions src/Core/src/Platform/iOS/ContentView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,14 @@ public override void LayoutSubviews()
base.LayoutSubviews();

UpdateClip();

// iOS by default adds animations to certain actions such as layer resizing (setting the Frame property).
// This can result in the background layer not keeping up with animations controlled by MAUI.
// To prevent this undesired effect, native animations will be turned off for the duration of the operation.
CATransaction.Begin();
CATransaction.AnimationDuration = 0;
this.UpdateMauiCALayer();
CATransaction.Commit();
}

internal IBorderStroke? Clip
Expand Down
31 changes: 30 additions & 1 deletion src/Core/src/Platform/iOS/StrokeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,15 @@ internal static void UpdateMauiCALayer(this UIView platformView, IBorderStroke?
{
CALayer? backgroundLayer = platformView.Layer as MauiCALayer;

var initialRender = false;
if (backgroundLayer == null)
{
backgroundLayer = platformView.Layer?.Sublayers?
.FirstOrDefault(x => x is MauiCALayer);

if (backgroundLayer == null)
{
initialRender = true;
backgroundLayer = new MauiCALayer
{
Name = ViewExtensions.BackgroundLayerName
Expand All @@ -122,6 +124,13 @@ internal static void UpdateMauiCALayer(this UIView platformView, IBorderStroke?
}
}

// While we're in the process of connecting the handler properties will not change
// So it's useless to update the layer many times with the same value
if (platformView is ContentView { View: null } && !initialRender)
{
return;
}

if (backgroundLayer is MauiCALayer mauiCALayer)
{
backgroundLayer.Frame = platformView.Bounds;
Expand Down Expand Up @@ -155,9 +164,29 @@ internal static void UpdateMauiCALayer(this UIView view)
return;

var layer = view.Layer;

UpdateBackgroundLayer(layer, view.Bounds);
}

static int GetShapeHashCode(this IBorderStroke? shape)
{
if (shape == null)
return 0;

unchecked
{
// compute a hash code based on the shape properties
int hash = 17;
hash = hash * 23 + shape.Shape?.GetHashCode() ?? 0;
hash = hash * 23 + shape.Stroke?.GetHashCode() ?? 0;
hash = hash * 23 + shape.StrokeThickness.GetHashCode();
hash = hash * 23 + shape.StrokeDashOffset.GetHashCode();
hash = hash * 23 + shape.StrokeDashPattern?.GetHashCode() ?? 0;
hash = hash * 23 + shape.StrokeLineCap.GetHashCode();
hash = hash * 23 + shape.StrokeLineJoin.GetHashCode();
hash = hash * 23 + shape.StrokeMiterLimit.GetHashCode();
return hash;
}
}

static void UpdateBackgroundLayer(this CALayer layer, CGRect bounds)
{
Expand Down

0 comments on commit 07617f5

Please sign in to comment.