1

I implemented a blur behavior for images in a .NET MAUI app using multi-targetting so that it is available in both Android and iOS.

The shared class looks like this:

public partial class BlurBehavior
{
    public static readonly BindableProperty RadiusProperty = BindableProperty.Create(nameof(Radius), typeof(float), typeof(BlurBehavior), 10f, propertyChanged: OnRadiusChanged);

    public float Radius
    {
        get => (float)GetValue(RadiusProperty);
        set => SetValue(RadiusProperty, value);
    }

    static void OnRadiusChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var behavior = (BlurBehavior)bindable;
        if (behavior.imageView is null)
        {
            return;
        }

        behavior.SetRendererEffect(behavior.imageView, Convert.ToSingle(newValue));
    }
}

The Android class like this:

public partial class BlurBehavior : PlatformBehavior<Image, ImageView>
{
    ImageView? imageView;
    protected override void OnAttachedTo(Image bindable, ImageView platformView)
    {
        imageView = platformView;
        SetRendererEffect(platformView, Radius);
    }

    protected override void OnDetachedFrom(Image bindable, ImageView platformView)
    {
        SetRendererEffect(platformView, 0);
    }

    void SetRendererEffect(ImageView imageView, float radius)
    {
        if (OperatingSystem.IsAndroidVersionAtLeast(31))
        {
            var renderEffect = radius > 0 ? GetEffect(radius) : null;
            imageView.SetRenderEffect(renderEffect);
        }
        else
        {

        }
    }
    static RenderEffect? GetEffect(float radius)
    {
        return OperatingSystem.IsAndroidVersionAtLeast(31) ?
            RenderEffect.CreateBlurEffect(radius, radius, Shader.TileMode.Clamp!) :
            null;
    }
}

Both files are located in a subfolder (/Behaviors/BlurBehavior) and have specific suffixes (BlurBehavior.[Android|iOS|Shared].cs).

So that multi-targetting works, I added filter to the project file like this:

<!-- Android -->
    <ItemGroup Condition="'$(TargetFramework)'!='net7.0-android'">
        <Compile Remove="**\**\*.Android.cs" />
        <None Include="**\**\*.Android.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
        <Compile Remove="**\Android\**\*.cs" />
        <None Include="**\Android\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
    </ItemGroup>

    <!-- iOS -->
    <ItemGroup Condition="'$(TargetFramework)'!='net7.0-ios'">
        <Compile Remove="**\**\*.iOS.cs" />
        <None Include="**\**\*.iOS.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
        <Compile Remove="**\iOS\**\*.cs" />
        <None Include="**\iOS\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
    </ItemGroup>

In Visual Studio, when I open the BlurBehavior.Android.cs file for instance and set the target platform dropdown to net7.0-android, the file looks good - no error messages. Also then I open the BlurBehavior.Shared.cs file, and set the target platform dropdown to either net7.0-android or net7.0-ios, everything looks fine.

However, when I try to compile the source, the compiler then gives me a lot of error messages about

  • BlurBehavior not containing a definition for imageView
  • BlurBehavior not containing a definition of SetRenderEffect
  • The compiler not being able to convert the BindableObject type to my BlurBehavior type
  • GetValue and SetValue not existing in the current context

It is as if the compiler is not able to understand that the partial classes belong together, so it is missing the point that the mentioned fields and methods are defined in the respective platform implementation...

I really feel like a blockhead... and I hope that anyone here has a good hint for me. :)

EDIT: When I select the target in the respective Drop Down (my Android device for example) and hit the "Play" button directly, building and deployment works. When I use the menu to build the solution instead, the errors above are reported...

Mephisztoe
  • 3,276
  • 7
  • 34
  • 48

1 Answers1

0

"building and deployment works."

So its just an Intellisense problem?

Just above any source code pane, at upper-left, there is a dropdown. Make sure YourProjectName (net7.0-android) is selected.

ToolmakerSteve
  • 18,547
  • 14
  • 94
  • 196
  • It seems so... with one exception: As I said, building and deploying at the same time using the "Play" button (with the target platform selected) works. In this case this seems to be only an Intellisense Problem. However, even when the target platform is selected: When I don't hit the "Play" button but use the menu entry for building the solution instead, it's not only an intellisense problem, but the build fails. – Mephisztoe Dec 01 '22 at 11:26
  • Ok, that builds all targets, so build must be failing for some platform *other* than Android. If you edit .csproj to remove other platforms (Windows; MacCatalyst), then does build succeed? – ToolmakerSteve Dec 01 '22 at 20:34