I'm trying to migrate a Xamarin.Forms app to .NET MAUI. So far I've managed to port almost everything, but I'm having a hard time trying to understand how to rewrite a custom renderer for a ScrollView using the new MAUI paradigm (handlers). The Xamarin renderer is very simple. I just need to override OnIntereptTouchEvent and OnTouchEvent:
class MyScrollViewRenderer : ScrollViewRenderer
{
public MyScrollViewRenderer(Context context) : base(context)
{
/* nothing here */
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
}
public override bool OnInterceptTouchEvent(MotionEvent ev)
{
if (((MyScrollView)Element).ScrollingEnabled)
{
return base.OnInterceptTouchEvent(ev);
}
else
{
return false;
}
}
public override bool OnTouchEvent(MotionEvent ev)
{
if (((MyScrollView)Element).ScrollingEnabled)
{
return base.OnTouchEvent(ev);
}
else
{
return false;
}
}
}
The meaning of this renderer is to disable the ScrollView scrolling while the user interacts with a custom component to trace some lines on the screen. On iOS this is pretty simple. It's just a matter of setting handler.PlatformView.ScrollEnabled = false;
. On Android this property do not exist, so, the need to override OnInterceptTouchEvent
and OnTouchEvent
.
I've read through the MAUI docs, but just found ways to map property changes with handlers. Couldn't find any guidance on how to implement and register a method override using the same approach (I really don't want to use the compatibility namespace, if possible). Any clue on this regard will be much appreciated!
The custom handler doesn't support to override the platform view's method. If you want to override it, you need to create a custom platform view. Here is my code:
namespace MauiApp10.Platforms.Android
{
// declare the custom platform view
public class MyScrollView : MauiScrollView
{
public bool scroallable = true;
public MyScrollView(Context context) : base(context){}
public MyScrollView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr) { }
public override bool OnTouchEvent(MotionEvent e)
{
switch (e.Action)
{
case MotionEventActions.Down: return scroallable&& base.OnTouchEvent(e);
default: return base.OnTouchEvent(e);
}
}
public override bool OnInterceptTouchEvent(MotionEvent ev)
{
return scroallable && base.OnInterceptTouchEvent(ev);
}
}
// declare the custom handler
public class MyHandler : ScrollViewHandler
{
protected override MauiScrollView CreatePlatformView()
{
var scrollView = new MyScrollView(
new ContextThemeWrapper(MauiContext!.Context, Resource.Style.scrollViewTheme), null!,
Resource.Attribute.scrollViewStyle)
{
ClipToOutline = true,
FillViewport = true
};
return scrollView;
}
}
}
And use the custom handler in the program.cs:
.ConfigureMauiHandlers(handlers =>
{
#if ANDROID
handlers.AddHandler(typeof(ScrollView), typeof(MyHandler));
#endif
});
And disable the scrollview in the button click event:
private void Button_Clicked(object sender, EventArgs e)
{
#if ANDROID
var myscrollview = scrollview.Handler.PlatformView as MyScrollView;
// the scrollview is the x:Name in the xaml
myscrollview.scroallable = false;
#endif
}
And I see you used custom control and custom renderer in the xamarin.forms, you can create the property mapper to map the custom control's scrollable property to the andorid platform view.