Xamarin.Forms icon indicating copy to clipboard operation
Xamarin.Forms copied to clipboard

Shell TitleView Not Working in iOS 16 [Bug]

Open mmholtman opened this issue 3 years ago • 29 comments

Description

Shell content is not visible within a TitleView when testing against iOS 16.

https://github.com/mmholtman/xamarinios16bug.git

Steps to Reproduce

  1. Download xCode 14 beta & get iOS 16 simulators
  2. Create a test Flyout App in Xamarin Forms
  3. Add a label within a <Shell.TitleView> on a XAML View.

Expected Behavior

The title is visible on the view

Actual Behavior

The title is not visible on the view

Basic Information

  • Version with issue: iOS 16 beta
  • Last known good version: any iOS version other than 16
  • Platform Target Frameworks:
    • iOS: 16
  • Affected Devices: iOS 16 devices

Environment

mmholtman avatar Aug 17 '22 18:08 mmholtman

Just wanted to second this issue. I see the same thing, and it breaks functionality in an app I have in the App Store.

Using these versions: Xcode 14 beta 5 Visual Studio for Mac 17.4 build 715 Xamarin.Forms 5.0.0.2515 Xamarin.iOS 15.99.0.335

adam-russell avatar Aug 25 '22 14:08 adam-russell

I also have this issue, is there a workaround? I feel this should be a high priority as iOS 16 should roll out in September.

bobbydharrell avatar Aug 26 '22 18:08 bobbydharrell

I believe this may be a related issue mentioned here from a native Xcode perspective: https://developer.apple.com/forums/thread/712461

Anyway, below is a custom renderer that gets the TitleView showing for me again (and it may just happen to work because of something else I'm doing, not sure). YMMV, this is not well tested at all, and is definitely more of a hack than a long term solution. And there's probably a much cleaner/easier way to do this. I based it off some code from ShellPageRendererTracker.cs, but cut out some of the old iOS support (I tested the super quickly with my specific TitleView and it seems to work on iOS 14+ for me) and some other stuff. There are probably at least some use cases where this doesn't work, because there's extra code that was in TitleViewContainer that I'm just not using below.

I also agree this should be a high priority issue to fix.

Here's the hacky custom renderer:

[assembly: ExportRenderer(typeof(Shell), typeof(CustomShellRenderer))]

namespace Your.Namespace.Here
{
    public class CustomShellRenderer : ShellRenderer
    {
        protected override IShellPageRendererTracker CreatePageRendererTracker()
        {
            return new CustomShellPageRendererTracker(this);
        }
    }

    public class CustomShellPageRendererTracker : ShellPageRendererTracker
    {
        public CustomShellPageRendererTracker(IShellContext context)
            : base(context)
        {

        }

        protected override void UpdateTitleView()
        {
            if (ViewController == null || ViewController.NavigationItem == null)
                return;

            var titleView = Shell.GetTitleView(Page);

            if (titleView == null)
            {
                var view = ViewController.NavigationItem.TitleView;
                ViewController.NavigationItem.TitleView = null;
                view?.Dispose();
            }
            else
            {
                var view = new CustomTitleViewContainer(titleView);
                ViewController.NavigationItem.TitleView = view;
            }
        }
    }

    public class CustomTitleViewContainer : UIContainerView
    {
        public CustomTitleViewContainer(View view) : base(view)
        {
            TranslatesAutoresizingMaskIntoConstraints = false;
        }

        public override CGSize IntrinsicContentSize => UILayoutFittingExpandedSize;
    }
}

Edit: updated with the version I've been using.

adam-russell avatar Aug 26 '22 20:08 adam-russell

Just wanted to add, this isn't caused by new tooling. This issue with the TitleView also occurs on a build with older tools on iOS 16.

Just tested on the below versions, and a custom TitleView also does not work on iOS 16 when built with the below:

Xcode 13.4.1 Xamarin.iOS 15.8 Xamarin.Forms 5.0.0.2515

adam-russell avatar Aug 30 '22 20:08 adam-russell

@adam-russell Thank you for the workaround!! It worked great!

the only issue I have with the workaround is my TitleView is not bottom aligned rather than centered vertically. Any tidbits on getting that to center using your Renderer? Thanks!

bobbydharrell avatar Sep 02 '22 13:09 bobbydharrell

@bobbydharrell So this code (adapted from the example in this issue, but with a red background on a Grid to see the space occupied by the TitleView):

<Shell.TitleView>
    <Grid VerticalOptions="Center" HeightRequest="44" BackgroundColor="Red">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Label TextColor="Orange"
            FontSize="Large"
            FontAttributes="Bold"
            HorizontalTextAlignment="Center"
            VerticalTextAlignment="Center"
            Text="test 2 - 2 test 2 curious">
    </Grid>
</Shell.TitleView>

Shows a TitleView like this: titleview2

Not sure if that's similar to the bottom alignment you're mentioning? Because the shell menu icon doesn't appear to itself be centered. It does seem the text in the TitleView can be centered OK in this way, but maybe not inside the frame you'd expect. I'm also not sure why I had to set the HeightRequest on the Grid above to get it to work correctly. The one I'm dealing with in a real application doesn't have the HeightRequest set, but works OK. The sizing in Xamarin Forms is often confusing to me. (As an aside, the horizontal alignment is also an issue with the Grid example I used above.. if using a Grid that way in a TitleView, I would personally hack it by adding another column at the end.. which probably isn't the right way to do it.)

adam-russell avatar Sep 02 '22 14:09 adam-russell

@adam-russell Thanks!

I was just thinking it is probably centering but the height is more than what is actually there for some reason.

<Grid.HeightRequest> <OnPlatform x:TypeArguments="x:Double"> <On Platform="iOS" Value="44"/> </OnPlatform> </Grid.HeightRequest>

And yes, the Horizontal Alignment is trash on a Custom TitleView. The menu button seems to be part of the space and pushed the Title over. I wrote custom adjusters using columns with nothing in them to get it centered per platform per idiom. It's gross but effective. Be nice if they fixed that also LOL

Code for Horizontal Alignment:

This allows me to center the title as the Title control is pushed by the Menu Button <Grid.Margin> <OnPlatform x:TypeArguments="Thickness"> <On Platform="Android" Value="-72,0,0,0"/> <On Platform="iOS" Value="-57,0,0,0"/> </OnPlatform> </Grid.Margin> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" x:Name="SpacingColumn"/> <ColumnDefinition Width="*" x:Name="TitleColumn"/> <ColumnDefinition Width="56" x:Name="ButtonColumn"/> </Grid.ColumnDefinitions>

This is to provide a buffer for the menu button for alignment <BoxView Grid.Column="0"> <BoxView.WidthRequest> <OnPlatform x:TypeArguments="x:Double"> <On Platform="iOS">57</On> <On Platform="Android">72</On> </OnPlatform> </BoxView.WidthRequest> </BoxView>

bobbydharrell avatar Sep 02 '22 15:09 bobbydharrell

Can we get an update on this issue? All Xamarin apps that use Shell TitleView are now functionally broken in iOS 16 - the content won’t show. If you have important navigation features your Shell TitleView it’s a big problem.

mphill avatar Sep 13 '22 17:09 mphill

@mphill we have a working workaround using a iOS Renderer above so that you can get your apps back up and running.

bobbydharrell avatar Sep 13 '22 17:09 bobbydharrell

To anyone using the fix from @adam-russell (thank you so much). If the TitleView is still blank, make sure you specify a RowDefintion or RequestHeight if using a Grid.

You can also try VerticalOptions="Start"

Otherwise the content will sort of slide down behind and not show.

Hopefully this gets fixed soon!

mphill avatar Sep 13 '22 19:09 mphill

occurring on builds using Xcode 13.4.1

Visual Studio Community 2022 for Mac
Version 17.3.3 (build 10)
Installation UUID: 1b89bb56-5bbb-453a-a7b1-efe28fc4be3d

Runtime
.NET 6.0.5 (64-bit)
Architecture: Arm64

Roslyn (Language Service)
4.3.0-3.22312.2+52adfb8b2dc71ed4278debcf13960f2116868608

NuGet
Version: 6.2.1.2

.NET SDK (Arm64)
SDK: /usr/local/share/dotnet/sdk/6.0.400/Sdks
SDK Versions:
	6.0.400
	6.0.400-preview.22330.6
	6.0.302
	6.0.301
	6.0.300
	6.0.203
	6.0.202
	6.0.201
	6.0.200
	6.0.101
MSBuild SDKs: /Applications/Visual Studio.app/Contents/MonoBundle/MSBuild/Current/bin/Sdks

.NET SDK (x64)
SDK Versions:
	6.0.400
	6.0.400-preview.22330.6
	6.0.302
	6.0.301
	6.0.300
	6.0.203
	6.0.202
	6.0.103
	5.0.408
	5.0.407
	5.0.406
	3.1.422
	3.1.421
	3.1.420
	3.1.419
	3.1.418
	3.1.417

.NET Runtime (Arm64)
Runtime: /usr/local/share/dotnet/dotnet
Runtime Versions:
	6.0.8
	6.0.7
	6.0.6
	6.0.5
	6.0.4
	6.0.3
	6.0.2
	6.0.1

.NET Runtime (x64)
Runtime: /usr/local/share/dotnet/x64/dotnet
Runtime Versions:
	6.0.8
	6.0.7
	6.0.6
	6.0.5
	6.0.4
	6.0.3
	5.0.17
	5.0.16
	5.0.15
	3.1.28
	3.1.27
	3.1.26
	3.1.25
	3.1.24
	3.1.23

Xamarin.Profiler
Version: 1.8.0.19
Location: /Applications/Xamarin Profiler.app/Contents/MacOS/Xamarin Profiler

Updater
Version: 11

Apple Developer Tools
Xcode 13.4.1 (20504)
Build 13F100

Xamarin.Mac
Version: 8.12.0.2 (Visual Studio Community)
Hash: 87f98a75e
Branch: d17-3
Build date: 2022-07-25 20:18:54-0400

Xamarin.iOS
Version: 15.12.0.2 (Visual Studio Community)
Hash: 87f98a75e
Branch: d17-3
Build date: 2022-07-25 20:18:55-0400

Xamarin Designer
Version: 17.3.0.208
Hash: 0de472ea0
Branch: remotes/origin/d17-3
Build date: 2022-08-25 17:15:19 UTC

Xamarin.Android
Version: 13.0.99.36 (Visual Studio Community)
Commit: xamarin-android/main/b4998c8
Android SDK: /Users/iainrough/Library/Developer/Xamarin/android-sdk-macosx
	Supported Android versions:
		12.0 (API level 31)
		11.0 (API level 30)
		10.0 (API level 29)

SDK Command-line Tools Version: 7.0
SDK Platform Tools Version: 33.0.2
SDK Build Tools Version: 33.0.0

Build Information: 
Mono: dffa5ab
Java.Interop: xamarin/java.interop/main@032f1e71
SQLite: xamarin/sqlite/3.39.2@40e8743
Xamarin.Android Tools: xamarin/xamarin-android-tools/main@9c641b3

Microsoft Build of OpenJDK
Java SDK: /Library/Java/JavaVirtualMachines/microsoft-11.jdk
11.0.12
Android Designer EPL code available here:
https://github.com/xamarin/AndroidDesigner.EPL

Eclipse Temurin JDK
Java SDK: /Library/Java/JavaVirtualMachines/temurin-8.jdk
1.8.0.302
Android Designer EPL code available here:
https://github.com/xamarin/AndroidDesigner.EPL

Android SDK Manager
Version: 17.3.0.23
Hash: 965bf40
Branch: remotes/origin/d17-3
Build date: 2022-08-25 17:15:24 UTC

Android Device Manager
Version: 0.0.0.1169
Hash: fafb1d5
Branch: fafb1d5
Build date: 2022-08-25 17:15:24 UTC

Build Information
Release ID: 1703030010
Git revision: d50fe2cc8bfbdfddb716bda6a920f1eb6c0c2c63
Build date: 2022-08-25 17:12:45+00
Build branch: release-17.3
Build lane: release-17.3

Operating System
Mac OS X 12.6.0
Darwin 21.6.0 Darwin Kernel Version 21.6.0
    Mon Aug 22 20:20:05 PDT 2022
    root:xnu-8020.140.49~2/RELEASE_ARM64_T8101 arm64

Enabled user installed extensions
NuGet Package Explorer 0.10
NuGet Package Management Extensions 0.32
VisualStudio View Inspector 0.9.1

roughiain avatar Sep 14 '22 13:09 roughiain

same issue here

Saccomani avatar Sep 15 '22 01:09 Saccomani

should i wait for a fix? or Maui is our everything...

decv86 avatar Sep 15 '22 08:09 decv86

Hi. We have implemented the workaround proposed by @adam-russell and now our app is fixed in Prod. I think you should all give it a try. Nothing complicated and that's a chance to have the ability to override/enhance/fix things in XF/MAUI...

rudyspano avatar Sep 15 '22 09:09 rudyspano

public override CGSize IntrinsicContentSize => UILayoutFittingExpandedSize;

Will be a fix in Xamarin.Forms and of course also changed on .NET MAUI.

jsuarezruiz avatar Sep 15 '22 14:09 jsuarezruiz

@jsuarezruiz I might be wrong, but doesn't TitleViewContainer already have public override CGSize IntrinsicContentSize => UILayoutFittingExpandedSize; in Xamarin Forms? Do you mean strip out some of the other code that's in that class like Frame and WillMoveToSuperview? (Feel free to correct me if I'm missing something/misinterpreting anything.)

adam-russell avatar Sep 15 '22 14:09 adam-russell

This fix causes my titleview to be visible again, but its shifted up compared to the old appearance. and when implemented with a SegmentedControl I'm using off nuget, appears to be missing until I switch segments.

In this video you can see the My Activity Title should be visible on page load and its not. And in the existing Forms implementation, showing/hiding the visibility of an imagebutton in the titleview's horizontal stacklayout shifts the title label.

https://user-images.githubusercontent.com/3627193/190451867-28896730-3558-45ff-8d19-fa359bac6ed7.mp4

Basically, while this fix somewhat resolves the issue of a completely missing titlebar, its not restoring the same layout and sizing that was present previously. we have a Searchbar control in another page's titleview and that's also not sizing as before.

image

edgiardina avatar Sep 15 '22 16:09 edgiardina

@edgiardina Yeah, the workaround definitely isn't quite right. I think there may be some differences in the underlying iOS TitleView, too, since I can't get it to be as wide as it was in previous iOS versions. In my particular implementation, I have different hacks in it that are dependent on iOS version to shift it around.

The current Xamarin.Forms implementation has extra code for sizing, but I think it's what's breaking the TitleView in iOS 16. That's stripped out of the custom renderer, but the Height in particular is often a problem, and I certainly don't understand why it works sometimes without having to force a HeightRequest/etc.

You could maybe try to set a static HeightRequest on your TitleView that's missing until the SegmentedControl is switched or maybe set the orientation as others have mentioned above? Just a guess, and I agree it probably shouldn't be needed.

On the image button, personally I would use a Grid rather than a StackLayout and set the width of the column containing the image button to a static value. I would sort of expect the StackLayout to shift when setting visibility of one of its children. I use Grids because the TitleView has changed sizing multiple times in the time I've been using Xamarin Forms, and I've unfortunately changed sizing hacks in it multiple times as new versions of Xamarin Forms are released. Sorry that's probably not super helpful, but just some thoughts.

adam-russell avatar Sep 15 '22 16:09 adam-russell

@adam-russell that's actually really helpful. Luckily we are only using titleviews in 5 of our 40+ views so I will try hacking some heights or converting them to grids to see how it renders. These are good suggestions.

edgiardina avatar Sep 15 '22 16:09 edgiardina

I can confirm on our large app with tens of thousands of users that the CustomShellRenderer from @adam-russell works in iOS 16

ianvink avatar Sep 17 '22 19:09 ianvink

So far the workaround didn't work for me. Is there any ETA for a fix for this?

NPadrutt avatar Sep 19 '22 18:09 NPadrutt

CustomShellRenderer Doesn't seem to be working for me either unfortunately

MelissaW990 avatar Sep 20 '22 14:09 MelissaW990

I just updated the comment with a very slightly different version I've been using for the last week. My code wasn't formatted very well in the previous version because the attribute didn't look like the rest of the code. Maybe for those that it's not working for, the ExportRenderer attribute (that needs to be there) was missed in a copy/paste? The other thing to try quickly is to set the HeightRequest on whatever your TitleView is to something like 44 and go from there if that works.

Anyway, presumably the fix coming in Xamarin.Forms will be better.

adam-russell avatar Sep 20 '22 15:09 adam-russell

Thanks @adam-russell for the updated comment. I had the export attribute set but for the default Shell since I assume AppShell is your custom type that inherits from Shell:

[assembly: ExportRenderer(typeof(Shell), typeof(CustomShellRenderer))]

But in the CustomShellRenderer doesn't so far no breakpoint hits, so I presume that there is still something wrong with my code and that is the reason why it doesn't work.

NPadrutt avatar Sep 20 '22 19:09 NPadrutt

@NPadrutt Oops, you're right, I didn't even notice that.. might be another reason it doesn't work for others if they don't have their Shell class named the same (which is the default name of the custom class when you create it with the wizard, I think). I just updated the comment for typeof(Shell) like you mentioned in your comment. Do you also have the custom renderer class in your iOS project already (and not your Forms project that might be referenced by your Android project/etc. if you have one)?

adam-russell avatar Sep 20 '22 19:09 adam-russell

@adam-russell now that you mention it, I do have the default class aswell.. so AppShell would have to work aswell. Yeah I do have the custom renderer in the iOS project. This is the PR I am testing on https://github.com/MoneyFox/MoneyFox/pull/2443

NPadrutt avatar Sep 20 '22 19:09 NPadrutt

@NPadrutt Cool app. :) You have multiple custom renderers for shell. I emailed you a merged version of a renderer (to avoid pasting it here), or you could merge them differently. You'll have to adjust the height of the view or button in the TitleView, but it'll make it show up to do this.

adam-russell avatar Sep 20 '22 20:09 adam-russell

@adam-russell oh thanks :) oh dear, you are absolutly right. I totally overlooked the renderer I already had.. Now it does work. thanks a lot for your help! :)

NPadrutt avatar Sep 20 '22 21:09 NPadrutt

Updated comment works perfectly :) thank you!

MelissaW990 avatar Sep 21 '22 07:09 MelissaW990

This fix causes my titleview to be visible again, but its shifted up compared to the old appearance. and when implemented with a SegmentedControl I'm using off nuget, appears to be missing until I switch segments.

In this video you can see the My Activity Title should be visible on page load and its not. And in the existing Forms implementation, showing/hiding the visibility of an imagebutton in the titleview's horizontal stacklayout shifts the title label. Basically, while this fix somewhat resolves the issue of a completely missing titlebar, its not restoring the same layout and sizing that was present previously. we have a Searchbar control in another page's titleview and that's also not sizing as before.

@edgiardina In my case i fixed the "visibility" issue by setting the height in the custom renderer like this

protected override void UpdateTitleView()
{
    if (ViewController == null || ViewController.NavigationItem == null)
        return;

    var titleView = Shell.GetTitleView(Page);

    if (titleView == null)
    {
        var view = ViewController.NavigationItem.TitleView;
        ViewController.NavigationItem.TitleView = null;
        view?.Dispose();
    }
    else
    {
        titleView.HeightRequest = 44;
        var view = new CustomTitleViewContainer(titleView);
        ViewController.NavigationItem.TitleView = view;
    }
}

In addition, this seems to fix the appearance issue for me, maybe it will work for others. I also added the following just to make sure everything is the same for older os versions

protected override IShellPageRendererTracker CreatePageRendererTracker()
{
    if (UIDevice.CurrentDevice.CheckSystemVersion(16, 0))
        return new CustomShellPageRendererTracker(this);
    else
        return base.CreatePageRendererTracker();

}

I tested it on simulator with iOS 16.0 and iPhone XS with iOS 15.5

andreiionita avatar Sep 26 '22 11:09 andreiionita