Search code examples
xamarin.formsuwpbackgroundeffectsacrylic-material

Applying a background for the control in an Effect in XamarinForms


I'm trying to apply a background for what ever the control the effect is attached to.

First i made the effect to apply a background for the controls that have either a Fill or Background properties in UWP. But the problem is a lot of controls renderes to FrameworkElement in UWP. And FrameworkElement doesn't have a Background property . In the VisualElementRenderer Xamarin forms adresses this issue be applying a background layer behind the content but this is an effect. Is there is any way to apply a background for whatever the effect is attached to? I'm appplying an AcrylicBrush So it must be assigned to the Control directly.

The code i written before:

try
{
   Control.GetType().GetProperty("Background").SetValue(Control, brush);
}
catch
{
   Control.GetType().GetProperty("Fill").SetValue(Control, brush);
}

Solution

  • I'm appplying an AcrylicBrush So it must be assigned to the Control directly.

    You could use compositor to apply Acrylic to SpriteVisual. We use Win2D to make GaussianBlurEffect for UIElement before we have Acrylic API. Get Compositor of UIElement, and use this Compositor to CreateSpriteVisual. then set GaussianBlurEffect to hostSprite.Brush like the following.

    Compositor _compositor;
    SpriteVisual _hostSprite;
    
    private void applyAcrylicAccent(Panel panel)
    {
        _compositor = ElementCompositionPreview.GetElementVisual(panel).Compositor;
        _hostSprite = _compositor.CreateSpriteVisual();
        _hostSprite.Size = new Vector2((float)panel.ActualWidth, (float)panel.ActualHeight);
    
        var backdrop = _compositor.CreateHostBackdropBrush();
    
        // Use a Win2D blur affect applied to a CompositionBackdropBrush.
        var graphicsEffect = new GaussianBlurEffect
        {
            Name = "Blur",
            BlurAmount = 100f,
            Source = new CompositionEffectSourceParameter("backdrop")
        };
    
        var effectFactory = Window.Current.Compositor.CreateEffectFactory(graphicsEffect, new[] { "Blur.BlurAmount" });
        var effectBrush = effectFactory.CreateBrush();
    
        effectBrush.SetSourceParameter("backdrop", backdrop);
        _hostSprite.Brush = effectBrush;
    
        ElementCompositionPreview.SetElementChildVisual(panel, _hostSprite);
    }
    

    And calling it with applyAcrylicAccent(RootLayout). You also will need to handle the SizeChanged event :

    private void LayoutRoot_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        if (_hostSprite != null)
            _hostSprite.Size = e.NewSize.ToVector2();
    }
    

    enter image description here