Forum Xamarin.Forms

Blurred ContentView

JonasRembrattJonasRembratt SEUniversity ✭✭✭
edited April 2017 in Xamarin.Forms

I need a content view that blurs whatever is below it so I thought I'd try writing a custom control and an iOS renderer for it. This is the class definition ...

public class XBlurredContentView : ContentView
{
}

... here's the custom renderer ...

public class XBlurFrameRenderer : ViewRenderer<XBlurredContentView,UIView>
{
    private UIVisualEffectView _effectView;

    protected override void OnElementChanged(ElementChangedEventArgs<XBlurredContentView> e)
    {
        base.OnElementChanged(e);
        var blurFrame = e.NewElement;
        if (blurFrame != null)
        {
            var effect = UIBlurEffect.FromStyle(UIBlurEffectStyle.Light);
            _effectView = new UIVisualEffectView(effect);
            SetNativeControl(_effectView);
        }
    }

    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == VisualElement.XProperty.PropertyName
            || e.PropertyName == VisualElement.YProperty.PropertyName
            || e.PropertyName == VisualElement.HeightProperty.PropertyName
            || e.PropertyName == VisualElement.WidthProperty.PropertyName)
        {
            var x = Element.X; var y = Element.Y; var w = Element.Width; var h = Element.Height;
            _effectView.Frame = new CGRect(x, y, w, h);
        }
        base.OnElementPropertyChanged(sender, e);
    }
}

... and here's the XAML to test it ...

    <customUi:XBlurredContentView HeightRequest="50">
        <Grid>
            <Button Text="Hello World" TextColor="White" />
        </Grid>
    </customUi:XBlurredContentView>

The expected are does get blurred as expected but the content (the "Hello World" button isn't visible. I double checked with the Live Inspector and it does look like the button (and it's UILabel) is added correctly but nothing is visible on screen. This is my first go at deriving the ContentView into a custom control so I guess I need to learn more but what have I missed?

Answers

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭
    protected override void OnElementChanged(ElementChangedEventArgs<XBlurredContentView> e)
        {
            base.OnElementChanged(e);
            var blurFrame = e.NewElement;
            if (blurFrame != null)
            {
                var effect = UIBlurEffect.FromStyle(UIBlurEffectStyle.Light);
                _effectView = new UIVisualEffectView(effect);
                SetNativeControl(_effectView);
            }
        }
    

    So the new control (the XBlurredContentView) comes in as e.NewElement.
    That becomes blurFrame. Then .... ?
    Where does the effect make use of that? Doesn't the effect have to be applied to the new control in some way?
    Then the _effectView is assigned the value of the new UIVisualEffectView... but what is that really? Where did it get any controls from e?

  • JonasRembrattJonasRembratt SEUniversity ✭✭✭
    edited April 2017

    I'm not trying to apply the blur effect to the ContentView itself. The idea is to have a ContentView that is blurring its underlying content (but not its own content). The UIVisualEffectView is a view and just needs to be added as a subview to the view controller's view, which is done using the SetNativeControl(). Or have I misunderstood that? Did you try the code? Didn't you see any effect at all?

    What seems to be happening to me is that the ContentView's content also appears to get blurred. Is this supposed to be happening? Another, perhaps more plausible, explnation is that I have to add code to add the ContentView's content as sub views to the UIVisualEffectView (I assumed calling base.OnElementChanged() did that.

  • JonasRembrattJonasRembratt SEUniversity ✭✭✭

    Thinking about exploring that second option (the custom renderer adding the ContentView's sub views to the UIVisualEffectView); is there a way to retrieve those (iOS/Android) sub views from the ContentView?

  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭

    The forms community toolkit has a blur effect that can be applied to any view.

  • JonasRembrattJonasRembratt SEUniversity ✭✭✭
    edited April 2017

    Sounds interesting but I need a "blurring layer", like the toolbar you can swipe up from the home screen, that's blurring its underlying content. The ability to blur an individual image sounds useful too but it's not what I'm looking for here. I'll give the toolkit a look though.

  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭

    I mean it applies to anything that inherits from view. I assume you could apply it to a layout, content view, etc, to blur the whole thing.

  • JonasRembrattJonasRembratt SEUniversity ✭✭✭
    edited April 2017
    Maybe I misunderstand. Will it blur any controls as they are scrolled underneath it?
  • VarunBabuSVarunBabuS INMember ✭✭✭

    Hi @JonasRembratt If i am correct with the understanding of your requirement is this what you are expecting
    "There would be a content page OnTop of the same we would Overlay it so that the contents are blurred" if this is your expectation , Please follow below steps

    Step1: say suppose your content would be present inside a Stack Layout

    First create a Relative Layout

    RelativeLayout mainLayout = new RelativeLayout() { };

    mainLayout.Children.Add(YourStackLayout
    , Constraint.Constant(0), Constraint.Constant(0),
    widthConstraint: Constraint.RelativeToParent((parent) => { return parent.Width; }),
    heightConstraint: Constraint.RelativeToParent((parent) => { return (parent.Height*0.9); }));

    Step 2: Create a Blur kind of content like the below code

    StackLayout backgroundPane = new StackLayout() { BackgroundColor = Color.Black.MultiplyAlpha(.5) };

    Step 3: Finally add the blur content on Top of your initial content that is Stack Layout

    mainLayout.Children.Add(backgroundPane, Constraint.Constant(0), Constraint.Constant(0),
    widthConstraint: Constraint.RelativeToParent((parent) => { return parent.Width; }),
    heightConstraint: Constraint.RelativeToParent((parent) => { return (parent.Height); }));

    Assign this relative layout to Content

    this.Content = mainLayout;

  • JonasRembrattJonasRembratt SEUniversity ✭✭✭
    edited May 2017

    Thanks VarunBabuS. I tried that and what happens is that I add a semi-transparent layer on top of other controls (a StackLayout) but the underlying controls are not getting blurred. Or did I misunderstand your code? Is it really supposed to blur the underlying content (and not just darken it)?

  • VarunBabuSVarunBabuS INMember ✭✭✭

    Sorry then @JonasRembratt I misunderstood your question,yes it add a layer on top of other controls and would not blur the underlying content

  • MikeRampanelliMikeRampanelli USMember, University

    @JonasRembratt Did you ever figure out a solution for this? This is something I need to do as well.

  • AlfonsiAlfonsi USMember ✭✭✭

    I just released the Sharpnado.MaterialFrame which supports blurred background:

    https://github.com/roubachof/Sharpnado.MaterialFrame

Sign In or Register to comment.