maui
maui copied to clipboard
[regression/8.0.3] [iOS] [SDK 17] Touch events are not working on WebView when a PDF is displayed.
Description
With iOS Sdk 17 / XCode 15, the WebView on iOS doesn't respond to any touch events (no zoom or scroll is possible) with PDF file. Works fine with any other html content.
Steps to Reproduce
- Create a new Maui App
- Add a web view control under a Grid Element to the Xaml
<Grid>
<WebView Grid.Row="0" x:Name="WebView"
Source="https://www.africau.edu/images/default/sample.pdf">
</WebView>
</Grid>
- Launch the App on iOS (16 or 17)
Actual: PDF file is rendered but no touch events are working on WebView (No scroll, no Zoom).
Expected: Should be able to zoom or scroll.
Notes:
- Rendering a webpage works fine without any issue (e.g. www.bing.com)
- This worked fine before updating to Microsoft.iOS SDK / XCode 15 for SDK 17
- Tested on .Net Maui Workload (8.0.0-rc.2.9511, 8.0.0-rc.2.9530) and both are impacted.
Link to public reproduction project repository
No response
Version with bug
8.0.0-rc.2.9511
Is this a regression from previous behavior?
Yes, this used to work in .NET MAUI
Last version that worked well
8.0.0-rc.2.9373
Affected platforms
iOS
Affected platform versions
iOS (All versions)
Did you find any workaround?
No :(
Relevant log output
No response
Trying this on Catalyst, it happens there as well. It also happens when wrapping the webview inside of other controls (Grid, StackLayout, etc), but seems fine inside ContentView
. If the WebView is the root of the page, it should also work. It's specifically when incase in other views.
PDF embedding generates a special UIKit view, one of the other elements could be capturing the touch contents and not passing them forward.
Thanks @drasticactions for the confirmation. This is a regression from RC2 to GA. Can you help get this triaged?
@rolfbjarne Does this look like an iOS change?
@rolfbjarne Does this look like an iOS change?
No, not if it happens on both iOS 16 and 17:
Launch the App on iOS (16 or 17)
I don't think it's a bug on our side either, I can't remember any relevant changes this late in the .NET 8 time frame.
@drasticactions does this happen in a plain iOS (non-MAUI) project?
@rolfbjarne I couldn't reproduce it in one. If I have the RootViewController to contain a WKWebView, and load the PDF, touch events pass through and it works. Within MAUI it also works if the WebView is the top most level view. It's when you nest it within other controls (Like Grid) where it breaks, which leads me to think this is an MAUI issue with how it handles touch events.
@PureWeen is this maybe related to your mac gestures fixes?
We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process.
i have the exactly same problem on my side. Inside a grid or any other layout it is not working to interact with the webview presenting a PDF. As i move it out to the root, its working.
This was working with SDK 8.0.100-rc.2. After update to SDK 8.0.100 this bug appears.
@DevDachi did you found any workaround here? I open a popup (Maui Community Toolkit) to show the PDF. So i need a Close button as well. In this case i cannot place the webview in the root ... My release is fully blocked now with this bug ...
For everybody struggle with the same issue, i created now a ViewHandler for the iOS WebView and placed a close UIButton there. In this case i can keep the outer structure flat and place only the WebView inside of the popup. If you need detailed infos just write me a pm.
@stoff99 could you please share how you solved the problem?
thanks
Hello @last-Programmer ,
i created a ViewHandler for iOS: Here is the Code:
`using CoreGraphics; using Foundation; using Microsoft.Maui.Handlers; using PlentycoMaui.Logger; using UIKit; using WebKit;
namespace PlentycoMaui.iOS;
public class PdfViewHandler : ViewHandler<IPdfView, WKWebView> { private static readonly PropertyMapper<IPdfView, PdfViewHandler> PfgViewMapper = new(ViewMapper); private WKWebView _wkWebView; private UIButton _closeButton; private const int ButtonSize = 50; public PdfViewHandler() : base(PfgViewMapper) { }
protected override WKWebView CreatePlatformView()
{
try
{
if (_wkWebView == null)
{
var wkWebViewConfiguration = new WKWebViewConfiguration();
_wkWebView = new WKWebView(CGRect.Empty, wkWebViewConfiguration)
{
AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
};
_wkWebView.Configuration.Preferences.SetValueForKey(Foundation.NSObject.FromObject(true), (Foundation.NSString)"allowFileAccessFromFileURLs");
}
// We implemented this solution on the 10.01.2024 because if we put the close button and the pdf view inside any grid or layout, the touch events are gone in the pdf view.
// We can revert this solution when the ticket is fixed https://github.com/dotnet/maui/issues/18716
CreateCloseButton();
var url = new NSUrl(VirtualView.PdfUri, false);
_wkWebView.LoadFileUrl(url, url);
}
catch (Exception e)
{
Log.Error(e.Message, e.StackTrace, e);
}
return _wkWebView;
}
private void CreateCloseButton()
{
if (_closeButton != null)
{
return;
}
_closeButton = new UIButton(UIButtonType.Custom);
_closeButton.Frame = new CGRect(UIScreen.MainScreen.Bounds.Width - ButtonSize - 4, 4, ButtonSize, ButtonSize);
_closeButton.BackgroundColor = FromHex("#D71065");
_closeButton.Layer.CornerRadius = ButtonSize / 2;
var label = new UILabel(new CGRect(0, 0, _closeButton.Frame.Width, _closeButton.Frame.Height));
label.Text = "X";
label.TextColor = UIColor.White;
label.Font = UIFont.SystemFontOfSize(24);
label.TextAlignment = UITextAlignment.Center;
label.Center = new CGPoint(_closeButton.Frame.Width / 2, _closeButton.Frame.Height / 2);
_closeButton.AddSubview(label);
_wkWebView.Add(_closeButton);
_closeButton.TouchDown += CloseButtonTouchDown;
_closeButton.TouchUpOutside += CloseButtonTouchUpOutside;
_closeButton.TouchUpInside += CloseButtonTouchUpInside;
}
private void CloseButtonTouchDown(object sender, EventArgs ev)
{
if (_closeButton == null)
{
return;
}
try
{
_closeButton.Alpha = 0.7f;
}
catch (Exception e)
{
Log.Error(e.Message, e.StackTrace, e);
}
}
private void CloseButtonTouchUpOutside(object sender, EventArgs e)
{
if (_closeButton == null)
{
return;
}
try
{
_closeButton.Alpha = 1.0f;
}
catch (Exception ex)
{
Log.Error(ex.Message, ex.StackTrace, ex);
}
}
private void CloseButtonTouchUpInside(object sender, EventArgs ev)
{
try
{
if (VirtualView.Close != null)
{
VirtualView.Close();
}
if (_closeButton == null)
{
return;
}
_closeButton.Alpha = 1.0f;
}
catch (Exception e)
{
Log.Error(e.Message, e.StackTrace, e);
}
}
public override Size GetDesiredSize(double widthConstraint, double heightConstraint)
{
try
{
if (_closeButton != null)
{
_closeButton.Frame = new CGRect(widthConstraint / 2 - ButtonSize / 2, heightConstraint - ButtonSize - 4, ButtonSize, ButtonSize);
}
}
catch (Exception e)
{
Log.Error(e.Message, e.StackTrace, e);
}
return base.GetDesiredSize(widthConstraint, heightConstraint);
}
protected override void DisconnectHandler(WKWebView platformView)
{
base.DisconnectHandler(platformView);
try
{
if (_closeButton != null)
{
_closeButton.TouchDown -= CloseButtonTouchDown;
_closeButton.TouchUpInside -= CloseButtonTouchUpInside;
_closeButton.TouchUpOutside -= CloseButtonTouchUpOutside;
}
_wkWebView?.Dispose();
}
catch (Exception e)
{
Log.Error(e.Message, e.StackTrace, e);
}
}
private UIColor FromHex(string hex)
{
hex = hex.TrimStart('#');
if (hex.Length == 6)
{
int r = int.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
int g = int.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
int b = int.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);
return UIColor.FromRGB(r, g, b);
}
return UIColor.Red;
}
}`
i don't know why the code is not correctly formatted here ...
Just keep in mind that i load local pdf's, not hosted once. So in this case you have to change the call of _wkWebView.LoadFileUrl(url, url);
You can use pdfjshttps://github.com/mozilla/pdf.js.
Workground for me
寄件者: last-Programmer @.> 寄件日期: 2024年1月12日 下午 07:55 收件者: dotnet/maui @.> 副本: ea543 @.>; Manual @.> 主旨: Re: [dotnet/maui] [regression/8.0.3] [iOS] [SDK 17] Touch events are not working on WebView when a PDF is displayed. (Issue #18716)
@stoff99https://github.com/stoff99 could you please share how you solved the problem?
thanks
— Reply to this email directly, view it on GitHubhttps://github.com/dotnet/maui/issues/18716#issuecomment-1888977929, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AHMICZJ73CY5TTH4TEAUIULYOEQDBAVCNFSM6AAAAAA7JRMB2CVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQOBYHE3TOOJSHE. You are receiving this because you are subscribed to this thread.
A slightly more involved solution, but I ended up resolving this by creating a custom control that implements PDFView from PDFKit instead of using WkWebView for iOS.
This solution provides an equal user experience and allows you to leverage the other features of PDFKit if needed.
This repo by @vitalii-vov has a great example on how you can implement this: https://github.com/vitalii-vov/Maui.PDFView/blob/master/Maui.PDFView/Platforms/iOS/PdfViewHandler.cs
For the Android implementation of this control, I used a WebView with pdf.js by Mozilla.
This blog outlines how you can implement pdf.js in Xamarin.Forms: https://medium.com/medialesson/show-pdf-files-in-your-xamarin-android-app-3718148de1c0
These steps can be adapted to use .NET MAUI handlers fairly simply.
I didn't need to implement this control for Mac or Windows but imagine PDFKit would work the same for Mac and a similar WebView solution would work for Windows.
For more info on creating custom controls from scratch see Create a custom control using handlers.
I am migrating from Xamarin to .NET MAUI 8.0.2. I use the WebView for viewing local pdf files in iOS and it used to work fine. The WebView is the only control inside a ContentPage. Scrolling didn't work now in MAUI. Wrapping the WebView inside a Grid didn't work either. But luckily I read the comment of @drasticactions that it seems to work when wrapping it inside a ContentView. And I can confirm it indeed works. So that saved me from creating a new control like @eth-ellis did (although nice to learn the preferred way create such control)
I can confirm that it is fixed in 8.060 nightly build.