Monday, September 23, 2013

Create blurred backgrounds with iOS 7 and Xamarin.iOS

UPDATE: This is outdated and broken. Visit my new blog here for an update on how to do this with a binding project I made.
I found this a pretty cool part of the UI in iOS 7, and here is how to do it with Xamarin.iOS.

1. The Code

Setup our UI with a controller for our initial screen, background image, and a button. We haven't added the ApplyBackgroundToButton() method yet, so don't worry.
// class-level declarations
UIWindow window;
UIViewController controller;
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
// create a new window instance based on the screen size
window = new UIWindow (UIScreen.MainScreen.Bounds);
// Initialize the main screen
controller = new UIViewController ();
// Load our background image
UIImageView backgroundImage = new UIImageView (UIImage.FromFile ("background.png"));
// Setup the button control. We will blur the background of this.
UIButton button = UIButton.FromType (UIButtonType.System);
button.Frame = new RectangleF (115, 175, 100, 44);
button.SetTitle ("Hello Blur", UIControlState.Normal);
controller.View.AddSubviews (backgroundImage, button);
// If you have defined a root view controller, set it here:
window.RootViewController = controller;
// make the window visible
window.MakeKeyAndVisible ();
// Applies the blurred image as the background image of the button
ApplyBackgroundToButton (button, controller.View);
return true;
}
view raw gistfile1.cs hosted with ❤ by GitHub
Here is what we have so far:


You can barely see the button in the center, but next we will improve that with a blur. Lets add the ApplyBackgroundToButton() to take care of that. Add this below the FinishedLaunching method.
void ApplyBackgroundToButton(UIButton button, UIView backgroundView)
{
// This makes sure we have the coordinates relative to the backgroundView. Without this, the image drawn
// for the button would be at the incorrect place of the background.
RectangleF buttonRectInBGViewCoords = button.ConvertRectToView (button.Bounds, backgroundView);
UIGraphics.BeginImageContextWithOptions (button.Frame.Size, false, window.Screen.Scale);
// Make a new image of the backgroundView (basically a screenshot of the view)
backgroundView.DrawViewHierarchy (new RectangleF (-buttonRectInBGViewCoords.X, -buttonRectInBGViewCoords.Y,
backgroundView.Frame.Width, backgroundView.Frame.Height), true);
UIImage newBGImage = UIGraphics.GetImageFromCurrentImageContext ();
UIGraphics.EndImageContext ();
// Apply the blur effect
newBGImage = newBGImage.ApplyLightEffect ();
// Set the blurred image as the background for the button
button.SetBackgroundImage (newBGImage, UIControlState.Normal);
button.Layer.CornerRadius = 4.0f;
button.Layer.MasksToBounds = true;
}
view raw gistfile1.cs hosted with ❤ by GitHub
Now the real magic happens in the ApplyLightEffect method, which was originally provided by Apple as an obj-c Category. I have converted that for use within Xamarin.iOS. Warning: Scary Code You can find the original code from Apple here: http://pastebin.com/6cs6hsyQ In order for this method to work, you'll need to add a few extra bits that are not part of Xamarin.iOS. Add these somewhere in your project Because the code requires some pointers and general "unsafe" code, you'll need to add the -unsafe compiler flag to your iOS project for it to build. I bet there is a nicer way to do this, but using the method Apple provided makes for a really close copy of the what they are doing. Here is the final result:


A button with a nicely blurred background of what is underneath. You can download the project here:

4 comments:

  1. Hey! It's great! BUT does not work! when i am using methods with parameter, such as applyBlurWithRadius or applyTintEffectWithColor.

    I get error:
    Objectiv-C exception thrown.
    Name: NSInvalidArgumentException
    Reason: -[UIImage applyTintEffectWithColor]: unrecognized selector sent to instance 0x7bd48ec0

    I get this when run your ImageEffects.Example project. with changes:

    // Apply the blur effect
    //newBGImage = newBGImage.ApplyLightEffect ();
    UIColor tintColor = UIColor.FromWhiteAlpha(0.5f, 0.3f);
    newBGImage = newBGImage.ApplyTintEffectWithColor(tintColor);

    ReplyDelete
  2. Hey!

    Sorry you found this to be not working! I don't manage this blog anymore. I have moved to jmillerdev.net

    I have a post on my new blog there with a binding project that will do this for you and it works. Take a look:

    http://jmillerdev.net/blog/2013/10/21/ios-7-blur-with-xamarin-dot-ios/

    Thanks!

    ReplyDelete
  3. Reuse existing code: The developer can Use its favorite .NET libraries in Xamarin.Android applications. Easily bind third-party native frameworks and libraries. The Xamarin development Component Store offers tons of third-party libraries packaged

    ReplyDelete