.net MAUI: Disable scrolling on Android
A quick one today!
So for a new drag and drop component I needed to temporary disable the scrolling of a parent ScrollView
.
Ok no biggies I went just scrollView.IsEnable = false
.
But, hey!! Nothing happens like WTFudge REALLY MAUI???
I then went to MAUI sources and saw that:
public partial class ScrollViewHandler : IScrollViewHandler
{
public static IPropertyMapper<IScrollView, IScrollViewHandler> Mapper = new PropertyMapper<IScrollView, IScrollViewHandler>(ViewMapper)
{
[nameof(IScrollView.Content)] = MapContent,
[nameof(IScrollView.HorizontalScrollBarVisibility)] = MapHorizontalScrollBarVisibility,
[nameof(IScrollView.VerticalScrollBarVisibility)] = MapVerticalScrollBarVisibility,
[nameof(IScrollView.Orientation)] = MapOrientation,
#if __IOS__
[nameof(IScrollView.IsEnabled)] = MapIsEnabled,
#endif
};
...
}
WHAT? Only supported for iOS???
AAAAAHHH.... Ok... Then I remembered.
There is indeed no way to support this natively in Android. Even Android programmers have to tweak the ScrollView
in order to achieve this: you have to override touch events methods and return false.
So in Xamarin.Forms we all had a nice renderer called MySuperScrollViewRenderer
which was dealing with this. Our solution is easy: just create a MAUI handler for this!
Here it is.
First create a ScrollViewEnableHandler
in your_project > Platforms > Android > Handlers
directory (maybe you will have a create the Handlers
directory). Yes the naming sucks, I'm not lazy, it's an homage.
using _Microsoft.Android.Resource.Designer;
using global::Android.Content;
using global::Android.Runtime;
using global::Android.Util;
using global::Android.Views;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform;
public class ScrollViewEnableHandler : ScrollViewHandler
{
public ScrollViewEnableHandler()
{
Mapper.AppendToMapping(
nameof(IScrollView.IsEnabled),
(handler, view) =>
((MauiScrollViewEnable)handler.PlatformView)
.UpdateIsEnabled(view.IsEnabled));
}
protected override MauiScrollView CreatePlatformView()
{
var scrollView = new MauiScrollViewEnable(
new ContextThemeWrapper(MauiContext!.Context, ResourceConstant.Style.scrollViewTheme),
null!,
ResourceConstant.Attribute.scrollViewStyle)
{
ClipToOutline = true,
FillViewport = true,
};
return scrollView;
}
}
Then create your MauiScrollViewEnable
at the same location:
public class MauiScrollViewEnable : MauiScrollView
{
private bool _disableScrolling;
public MauiScrollViewEnable(Context context)
: base(context)
{
}
public MauiScrollViewEnable(Context context, IAttributeSet attrs)
: base(context, attrs)
{
}
public MauiScrollViewEnable(Context context, IAttributeSet attrs, int defStyleAttr)
: base(context, attrs, defStyleAttr)
{
}
protected MauiScrollViewEnable(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
}
public void UpdateIsEnabled(bool isEnabled)
{
_disableScrolling = !isEnabled;
}
public override bool OnInterceptTouchEvent(MotionEvent? ev)
{
if (_disableScrolling)
{
return false;
}
return base.OnInterceptTouchEvent(ev);
}
public override bool OnTouchEvent(MotionEvent? ev)
{
if (_disableScrolling)
{
return false;
}
return base.OnTouchEvent(ev);
}
}
And finally, update your MauiProgram
file:
var builder = MauiApp.CreateBuilder();
builder
...
.ConfigureMauiHandlers(handlers =>
{
...
#if ANDROID
handlers.AddHandler<ScrollView, ScrollViewEnableHandler>();
#endif
})
And ZOUBILOU you're done! Just like that.
You could also wait for this issue to be resolved: https://github.com/dotnet/maui/issues/18418. And then you will be able to set Orientation="Neither"
.