xamarin / Essentials

Xamarin.Essentials is no longer supported. Migrate your apps to .NET MAUI, which includes Maui.Essentials.
https://aka.ms/xamarin-upgrade
Other
1.52k stars 505 forks source link

[Bug] Share Text does not work as expected on iPadOS 13.4 #1247

Closed bobwhitten closed 4 years ago

bobwhitten commented 4 years ago

Description

Siimilar to #979, but appears to have returned.

Share Text for iPadOS 13.4 does not bring up "pop-over" window UNLESS app is displayed with certain split screen modes.

It appears to work fine on iPhone and iPadOS 12.x

Steps to Reproduce

  1. Attached is a sample program, which provides four buttons for the various ways that a Share for text can be done, including using PresentationSourceBounds.
  2. Click each button to test. Note that a click that does not work will need to "cleared" by clicking somewhere else before clicking next button.

Expected Behavior

Pop-Over (activity controller) allows shared text to be sent to various apps

Actual Behavior

No Pop-Over on iPad with 13.4, UNLESS in split screen mode and narrow (1/2 on iPad Air, 1/3 on iPad Pro 12.9"). Note that the device "thinks" there is a pop-over, and with one click in "full screen" mode, then going to split-screen, a pop-over appears. ShareTest.zip

Basic Information

Reproduction Link

ShareTest.zip

jamesmontemagno commented 4 years ago

Very odd as if I run our sample app it works just fine.....

I tested a blank non-forms app and saw this as well. Very strange.

jamesmontemagno commented 4 years ago

Ah yes, for iPadOS you need to specify the PresentationSourceBounds for this to work.... in iOS 13.4... :( So you will need to set this. We do that in our code: https://github.com/xamarin/Essentials/commit/8341f328a23c926a475b72f4e294bfd7225f11fb

bobwhitten commented 4 years ago

OK, I see the sample code... but only for ShareFile? I suppose I wish there was a document coumment or better yet a defaulting so that code that "works" for iPhone, Android phone/tablet doesn't unexpectedely fail for iPad.

By the way, my repro code still fails to do ShareText, even if a PresentationSourceBounds is included similar to sample code.

jamesmontemagno commented 4 years ago

It is for both in the 1.6.0 branch: https://github.com/xamarin/Essentials/commit/8341f328a23c926a475b72f4e294bfd7225f11fb#diff-a9e5971cde031d789696b97ebfee4f92R85 in the current develop it is not there yet, that is why it worked for me in the 1.6.0 branch.

For your sample I did:

var bounds = ((Button)sender).Bounds;
            await Share.RequestAsync(new ShareTextRequest
            {
                Subject = "test",
                Text = "Hello",
                Title = "hello",
                PresentationSourceBounds = new System.Drawing.Rectangle((int)bounds.X, (int)bounds.Y, (int)bounds.Width, (int)bounds.Height)
            });

and it worked out.

jamesmontemagno commented 4 years ago

@mattleibow you wrote the code for the 1.6.0 branch. Any insight there?

jamesmontemagno commented 4 years ago

I believe that our defaults actually did work before 13.4 btw so this is something apple changed on us :(

g4mb10r commented 4 years ago

@jamesmontemagno Perhaps this should be marked as critical? Apple is rejecting any app that has share functionality because it doesn't work on iPad.

jamesmontemagno commented 4 years ago

So, the workaround today to get things working:

Add this helper class:

 public static class ViewHelpers
    {
        public static Rectangle GetAbsoluteBounds(this Xamarin.Forms.View element)
        {
            Element looper = element;

            var absoluteX = element.X + element.Margin.Top;
            var absoluteY = element.Y + element.Margin.Left;

            // TODO: add logic to handle titles, headers, or other non-view bars

            while (looper.Parent != null)
            {
                looper = looper.Parent;
                if (looper is Xamarin.Forms.View v)
                {
                    absoluteX += v.X + v.Margin.Top;
                    absoluteY += v.Y + v.Margin.Left;
                }
            }

            return new Rectangle(absoluteX, absoluteY, element.Width, element.Height);
        }

        public static System.Drawing.Rectangle ToSystemRectangle(this Rectangle rect) =>
            new System.Drawing.Rectangle((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height);
    }

Update your Command or call to take in a Xamarin.Forms.View and call the helpers:

async Task SendFriendRequest(Xamarin.Forms.View element)
{
       var bounds = element.GetAbsoluteBounds();
            await Share.RequestAsync(new ShareTextRequest
            {
                Title = "Title",
                Text = message,
                PresentationSourceBounds = bounds.ToSystemRectangle()
            });
}

Pass in parameter:

CommandParameter="{Binding Source={RelativeSource Self}}"
jamesmontemagno commented 4 years ago

We will now set it to the default rect on iOS 13: https://github.com/xamarin/Essentials/pull/1250 the nuget will be generated there.

A quick work around would just to set it to new Rectangle (0,20,0,0). although i recommend ^ above

navylover commented 4 years ago

But I met the error: "ShareFileRequest does not contain a definition of PresentationSourceBounds", even I update the xamarin.essential to the latest version(1.5.3.2)

ish-1313 commented 4 years ago

worth to mention, that PresentationSourceBounds is not about placing share UI , but for specifying anchor point for Share UI (where Share UI "arrow " ) will point

 if (Device.RuntimePlatform == Device.iOS && DeviceInfo.Idiom == DeviceIdiom.Tablet)
     {
          var c = slShareButton.Bounds;
          file.PresentationSourceBounds = new System.Drawing.Rectangle((int)c.X,(int) c.Y, (int) c.Width, (int) c.Height);
      }

slShareButton is blue button in the lower right corner .

the code above leads for the following UI position (i put some green on the background and circle in red what i call arrow )

share