maui
maui copied to clipboard
[regression/8.0.3] Disabling RefreshView disables the keyboard
Description
This might be related to a change in the Android SDK or maybe in the MAUI keyboard/View implementation, but disabling a RefreshView with refreshView.IsEnabled = false
disables keyboard entry into textareas (and probably inputs too) in MAUI Blazor. Haven't had the chance to try if native inputs were affected yet.
Steps to Reproduce
- Create a new MAUI Blazor Hybrid project
- Wrap the BlazorWebView in a RefreshView
- Set IsEnabled on the RefreshView to false
- Add a textarea to the Razor view
- Run the application, tap into the textarea and start typing
- Caret doesn't appear, input is ignored
Link to public reproduction project repository
No response
Version with bug
8.0.3
Is this a regression from previous behavior?
Yes, this used to work in .NET MAUI
Last version that worked well
7.0.101
Affected platforms
Android
Affected platform versions
Android 11 and Android 14 confirmed
Did you find any workaround?
Yes, we're currently using the following workaround:
// Platforms/Android/CustomDisableSwipeRefreshLayout.cs
public class CustomDisableSwipeRefreshLayout : MauiSwipeRefreshLayout
{
public bool DisableRefresh { get; set; }
public CustomDisableSwipeRefreshLayout(Context context) : base(context)
{
}
public override bool CanChildScrollUp()
{
if (DisableRefresh)
return true;
return base.CanChildScrollUp();
}
}
with a custom ViewHandler, we are abusing CanChildScrollUp
to disable refresh without disabling the Control itself, and then setting it directly:
// Platforms/Android/ViewHandlers/RefreshViewHandler.cs
public class RefreshViewHandler : Microsoft.Maui.Handlers.RefreshViewHandler
{
protected override MauiSwipeRefreshLayout CreatePlatformView()
{
return new CustomDisableSwipeRefreshLayout(Context);
}
}
// MauiProgram.cs
handlers.AddHandler<RefreshView, RefreshViewHandler>();
// Usage
#if ANDROID
if (RefreshViewInstance.Handler?.PlatformView is CustomDisableSwipeRefreshLayout platformView)
{
platformView.DisableRefresh = !isReloadable;
}
else
{
RefreshViewInstance.IsEnabled = isReloadable;
}
#else
RefreshViewInstance.IsEnabled = isReloadable;
#endif
Obviously, it would be nicer to inherit from RefreshView and fully implement this in the MAUI view itself, but this works as a quick and dirty patch.
Relevant log output
No response
I think disabling a control/layout also disables all the children. So this feels expected. If it worked in net7 that sounds like a bug. @PureWeen thoughts?
Also, pull to refresh a blazor webview will refresh and reload the whole app? @Eilon ?
Maybe you are needing a refresh view in the blazor view, not wrapping it.
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.
@mattleibow pull to refresh doesn't really work properly inside the browser to be honest. JavaScript implementations are extremely buggy. Using the RefreshView as a wrapper works much better - it doesn't reload the browser, but we have tied our own logic inside the Blazor views to the event.
Disabling the RefreshView doesn't actually disable the browser either, just text input inside it. This wasn't the case previously either, so I'm not sure what changed to cause this. Couldn't find any relevant code changes.
@mattleibow indeed, I'm also surprised this ever worked. But probably not many people tried. I would normally expect that if a container is disabled, then everything inside it should all be disabled unconditionally. And if it isn't, that would be a bug.
@kanadaj indeed, I think pull-to-refresh is more of a 'web browser' thing and not a 'webview' thing, so it wouldn't work in a BlazorWebView by default (please correct me if I am wrong).
@kanadaj indeed, I think pull-to-refresh is more of a 'web browser' thing and not a 'webview' thing, so it wouldn't work in a BlazorWebView by default (please correct me if I am wrong).
Browsers typically implement it just like we did - by wrapping a native RefreshView around the WebView. The issue is that we only need the mechanism selectively. Until now, IsEnabled has actually worked for this and there are actually a number of posts and articles online suggesting to do this to disable refresh.
See: https://stackoverflow.com/a/30328196 https://stackoverflow.com/a/34092085
And from the Android docs: https://developer.android.com/reference/androidx/swiperefreshlayout/widget/SwipeRefreshLayout
To disable the gesture and progress animation, call setEnabled(false) on the view.
So I'm reasonably sure that disabling the RefreshView isn't meant to disable its children. Which would mean that the IsEnabled flag being propagated to its children is the bug here.
Hmm interesting. I'm not sure if I was trying the exact same thing with the WindowsAppSDK (WinUI3) RefreshContainer (which is what .NET MAUI uses on Windows), but setting RefreshContainer.IsEnabled = false
seems to disable elements currently in the refresh container, but if more items are added to the container, they don't seem to inherit being disabled.
I'm not quite sure what to make of that, but it seems already inconsistent between platforms (at least Android and Windows).
I've updated the labels on this issue to indicate it's likely a problem with the .NET MAUI RefreshView and not with the BlazorWebView. The BlazorWebView doesn't enable/disable itself or even listen to such events - it's presumably up to either the developer to set such a thing, or that it 'inherits' it from a parent container, such as a RefreshView.
This is causing major issues for our app at the moment, it's also worth noting that it prevents SwipeViews from functioning as well as the Entries. The CollectionView functionality bugs really could do with some attention.
We're in the process of figuring out whether it's worth writing a workaround that just picks up and hides the refresh functionality, but I also feel as though this shouldn't be an issue that we have to bodge to fix.
It also seems to have an effect on the system back button on android. We have both the problems. The one with the keyboard not working and navigationlock which no longer work on .net 8, and just closes the app.
It does no longer react when disabling refreshview.
Hello @kanadaj ,
I hope this message finds you well. I recently came across the issue you reported.
Could you possibly share more details on how you implemented this workaround? I'm particularly interested in your "Usage" example.
To manage which pages utilize the RefreshView in my application, I control it through a bound boolean, managed by the following code snippet:
public class RefreshViewState : INotifyPropertyChanged
{
public bool IsRefreshing { get; private set; }
public bool IsEnabled { get; private set; }
public event PropertyChangedEventHandler PropertyChanged;
public void SetIsRefreshing(bool isRefreshing)
{
IsRefreshing = isRefreshing;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsRefreshing)));
}
public void SetIsEnabled(bool isEnabled)
{
IsEnabled = isEnabled;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsEnabled)));
}
}
This RefreshViewState class is injected as a service into my pages to dynamically control the RefreshView's state. Could you elaborate on how I might integrate your "Usage" example in your workaround please ?
@Rebrandsoft To be honest your usage is likely better. We reference the RefreshView directly in a singleton service and set the property on it. But your method should also work and it's honestly a bit better if we're being honest. The goal is to get the variable to a custom implementation which overrides CanChildScrollUp
either way.
Has there been any progress on resolving this issue with the actual component. It does seem to be fundamentally broken that when you set is IsEnabled to false it disables all child components.
I am working on a mobile app using Blazor Hybrid and have implemented the pull to refresh. In Android it works without any issues when I set it to "IsEnabled = false", but running as a desktop application it does not. My workaround is to set a "IsWindows" field and if it's windows don't do anything with the refresh and keep it enabled.
It also seems to have an effect on the system back button on android. We have both the problems. The one with the keyboard not working and navigationlock which no longer work on .net 8, and just closes the app.
It does no longer react when disabling refreshview.
Just noticed this as part of an issue in my application when trying to implement the RefreshView it stopped my NavigationLock from working.
I have the same issue :(
I can repro this issue at Windows platform on the latest 17.12.0 Preview 1.0(8.0.80 & 8.0.3), but it worked on vs 17.11.0 for.NET 7. MauiApp43.zip
I have encountered the same issue using MAUI hybrid blazor with MudBlazor library. Whenever I disable RefreshView this also disables MudBlazor's inputs.
Any chance this will be fixed soon?