July 16, 2014

New Collection View Features in iOS 8

By

Collection Views are a powerful user interface technology for laying out collections of data. With fantastic support for high performance grid layouts, flexible line based layouts, and fully custom layouts, along with integrated animation capabilities, they make creating beautiful data-driven UIs a wonderful experience both for the developer and the end user.

collection views

iOS 8 adds some nice enhancements to Collection Views, including the ability to self-size cells without the need for using a delegate. Likewise, the layout attributes of individual cells can now be adjusted directly from within the cell class without having to use a delegate. This makes it easier to make small layout changes that are related to a particular cell.

Self-sizing Cells

First, let’s look at how to self-size cells. Before iOS 8, creating cells that sized to their content required working within a layout class directly or via a layout’s delegate, such as the UICollectionViewDelegateFlowLayout.

For example, the following code adjusts the cell size to fit cells comprised of simple UILabels, presented using a UICollectionViewFlowLayout:

class FlowLayoutDelegate : UICollectionViewDelegateFlowLayout
{
  string[] items;
  UIStringAttributes attr;
  public FlowLayoutDelegate (string[] items)
  {
    this.items = items;
    attr = new UIStringAttributes {
      Font = new UILabel ().Font
    };
  }
  public override SizeF GetSizeForItem (UICollectionView collectionView, UICollectionViewLayout layout, NSIndexPath indexPath)
  {
    string text = items [indexPath.Row];
    return new NSString (text).GetSizeUsingAttributes (attr);
  }
}

This code results in a Collection View where each cell fits the text it contains:

self sizing cells

Creating cells that are self-sized is much easier in iOS 8. Simply set the EstimatedItemSize on the UICollectionViewFlowLayout and implement SizeThatFits or use AutoLayout in the cell class.

For example, to self-size the cells in the example above, set EstimatedItemSize as shown below:

flowLayout = new UICollectionViewFlowLayout (){
  EstimatedItemSize = new SizeF (44, 144)
};

Then, simply adding the following implementation of SizeThatFits in the cell class produces the same result, without the need for the UICollectionViewDelegateFlowLayout implementation:

public override SizeF SizeThatFits (SizeF size)
{
  label.Frame = new RectangleF (new PointF (0, 0), label.AttributedText.Size);
  return label.AttributedText.Size;
}

Adjusting Layout Attributes in Cells

iOS 8 also makes it easier to manipulate the layout attributes returned from within the cell class without resorting to a UICollectionViewDelegateFlowLayout. Just override PreferredLayoutAttributesFittingAttributes in the cell class.

The following code changes the font of every other label and adjusts the layout for each cell appropriately:

public override UICollectionViewLayoutAttributes PreferredLayoutAttributesFittingAttributes (UICollectionViewLayoutAttributes layoutAttributes)
{
  var newLayoutAttributes = (UICollectionViewLayoutAttributes)layoutAttributes.Copy ();
  if (layoutAttributes.IndexPath.Row % 2 == 0) {
    //
    label.TextColor = UIColor.Red;
    ContentView.BackgroundColor = UIColor.LightGray;
    var attr = new NSAttributedString (Text, UIFont.SystemFontOfSize (28.0f));
    label.Font = UIFont.SystemFontOfSize (28.0f);
    //
    newLayoutAttributes.Frame = new RectangleF (new PointF (0, 0), attr.Size);
    label.Frame = new RectangleF (new PointF (0, 0), attr.Size);
  } else {
    //
    newLayoutAttributes.Frame = new RectangleF (new PointF (0, 0), label.AttributedText.Size);
    label.Frame = new RectangleF (new PointF (0, 0), label.AttributedText.Size);
  }
  return newLayoutAttributes;
}

This allows fine-grained control at the cell level, as shown below:

layout attributes

As you can see, iOS 8 adds flexibility to Collection Views, allowing granular control of cells directly from the cell class and making it easier to control cell layout and sizing when needed.

The code from this post is available here.

Discuss this blog post in the Xamarin Forums

TwitterFacebookGoogle+LinkedInEmail
July 15, 2014

Mobile .NET Meetups and Xamarin 3 Celebrations in July

By

We’ve had some amazing Xamarin 3 celebrations over the last few months, but we aren’t done just yet. This month, Mobile .NET developer groups around the world are joining in to celebrate the latest Xamarin release with pizza, cake, and in-depth sessions on all of the new features in Xamarin 3. We have also launched a brand new Twitter account, @XamarinEvents, which will regularly tweet about upcoming Xamarin and community events.

Xamarin Cake

Here are some upcoming Xamarin developer group meetups:

Nashville Xamarin User Group us

  • Nashville, TN: Tuesday, July 15th 6:30PM

  • Xamarin.Forms Demo & Lab

Austin Mobile .NET Developers Group us

  • Austin, TX: Wednesday, July 16th 6:30PM
  • Cross Platform Development with Portable Class Libraries

Portland Area .NET Users Group in

  • Portland, OR: Thursday, July 17th 6:00PM
  • Creating UIs for Cross-Platform Apps with Xamarin, with Xamarin’s James Montemagno

Los Angeles Mobile .NET Developers Group in

  • Los Angeles, CA: Monday, July 21st 7:00PM
  • Xamarin Basics

Israel .NET Developer Group il

  • Tel Aviv, Israel: Tuesday, July 22nd 5:30PM
  • Building Cross Platform Apps with Xamarin

Minnesota Enterprise Mobile in

  • Wayzata, MN: Tuesday, July 22nd 5:30PM
  • Building iOS User Interfaces with Xamarin

Northwest Valley .NET User Group in

  • Glendale, AZ: Wednesday, July 23rd 6:00PM
  • Building iOS, Android, and Windows Apps in C# with Xamarin, with Xamarin’s James Montemagno

Boston Mobile C# Developers Group us

  • Cambridge, MA: Thursday, July 24th 6:00PM
  • Introduction to Xamarin.Forms, with Xamarin’s Pierce Boggan

Arizona – Xamarin us

  • Scottsdale, AZ: Thursday, July 24th 6:00PM
  • Xamarin 3! iOS and Android Development in C# with Xamarin

Chicago .NET Mobile Developers us

  • Chicago, IL: Thursday, July 31st 5:45PM

  • Introduction to the MVVMCross Cross Platform Framework

Xamarin events are always happening around the world, so if you don’t see your city listed above, be sure to also check out the Xamarin Events forum where new meetups are being added all the time. Additionally, don’t forget to follow our brand new @XamarinEvents Twitter account to make sure you never miss an upcoming Xamarin event.

Don’t see a developer group in your area and want to get one started? We’re here to help! We have a tips and tricks guide on starting a developer group, our introduction to Xamarin slide deck, and of course our community sponsorship program to get you on your way. We also want to hear from you, so please feel free to send us an email or tweet @XamarinHQ so we can help spread the word and continue to grow the Xamarin community.

TwitterFacebookGoogle+LinkedInEmail
July 11, 2014

Xamarin on Film: @dotnetConf & FlashCast

By

Earlier this year, Xamarin invaded Channel 9′s Visual Studio Toolbox and Dev Radio shows. Response to all 6 shows has been amazing, with over 325,000 views so far! Now, we’re back again with even more great videos for your weekend enjoyment.

dotnetconflogo

Microsoft hosted their second dotnetConf, a free online conference, in June, and Xamarin was there in full force. I’ve included my talk Developing Native iOS, Android, and Windows Apps with Xamarin below, which you can find, with all of the great .NET related videos from this year’s conference, on Channel 9.

FlashCast is a brand new web series offering unique, 15-minute webinars on awesome topics. Evangelist Mike Bluestein kicked off the very first FlashCast with Build your first iOS App with Visual Studio and Xamarin, included below:

Our next entry in the FlashCast series was on how to Build your first Android app with Visual Studio and Xamarin:

Stay tuned over the next few weeks for even more new FlashCast episodes featuring Xamarin!

TwitterFacebookGoogle+LinkedInEmail
July 9, 2014

Adding View Effects in iOS 8

By

In iOS 8, Apple has added UIKit level support for effects such as blur and vibrancy. These effects are seen in system-level UIs such as the blur effect shown when opening a folder or swiping to the lock screen, and can now be added to your own applications with just a few lines of code.

view effects

Blur Effect

The first effect you can use is the blur effect, represented by the UIBlurEffect class. Adding a blur effect is easy. Create a UIBlurEffect and a UIVisualEffectView from the effect. Then just add the effect view to the view hierarchy.

For example, the following code adds a blur effect:

var blur = UIBlurEffect.FromStyle (UIBlurEffectStyle.Light);
var blurView = new UIVisualEffectView (blur) {
  Frame = new RectangleF (0, 0, imageView.Frame.Width, 400)
};
View.Add (blurView);

This code dynamically blurs the content beneath it. For instance, when added to a view hierarchy containing a scrollable image, the effect of the blur changes at runtime as the image is moved:

blur

The blur effect comes in three styles:

  • UIBlurEffectStyle.Light
  • UIBlurEffectStyle.ExtraLight
  • UIBlurEffectStyle.Dark

These change the appearance of the blur as shown below:

blur style

Vibrancy Effect

In addition to blur, iOS includes a vibrancy effect (UIVibrancyEffect), which allows content displayed over a blur to remain legible. Vibrancy effects are created from blur effects, and are also displayed using a UIVisualEffectView. Any view the effect should be applied to is added as a subview of the UIVisualEffectView‘s ContentView.

For example, the following code adds a label to be displayed over the blurred view created above:

// vibrancy view
var frame = new Rectangle (10, 10, 100, 50);
var vibrancy = UIVibrancyEffect.FromBlurEffect (blur);
var vibrancyView = new UIVisualEffectView (vibrancy) {
  Frame = frame
};
label = new UILabel {
  Text = "Hello iOS 8!",
  Frame = vibrancyView.Bounds
};
vibrancyView.ContentView.Add (label);
blurView.ContentView.Add (vibrancyView);

When the user scrolls the image, the blur changes and the label’s text is modified dynamically such that it remains readable:

vibrancy

These effects are useful when you want them applied dynamically. Of course, rendering them has some cost, so if you can get the results you are looking for with a static effect, that should be used. However, for creating a level of polish, with a sense of depth on par with iOS itself, it’s nice to now have these features available.

The code from this post is available here.

Discuss this blog post in the Xamarin Forums

 

TwitterFacebookGoogle+LinkedInEmail
July 7, 2014

Build Great Photo Experiences in iOS 8 with PhotoKit

By

PhotoKit is a new framework in iOS 8 that allows you to query the system image library and create custom user interfaces to view and modify its contents. To use PhotoKit from Xamarin.iOS, you can download the preview release in our alpha channel.

PhotoKit1

PhotoKit includes a number of classes that represent image and video assets, as well as collections of assists such as albums and folders. Collectively, PhotoKit represents these in what it calls model objects.

The model objects that represents the photos and videos themselves are of type PHAsset. A PHAsset contains metadata such as the asset’s media type and its creation date.

Similarly, the PHAssetCollection and PHCollectionList classes contain metadata about asset collections and collection lists respectively. Asset collections are groups of assets, such as all the photos and videos for a given year. Likewise, collection lists are groups of asset collections, such as photos and videos grouped by year.

PhotoKit makes it easy to query model data through a variety of fetch methods. For example, to retrieve all images, you would call PFAsset.Fetch, passing the PHAssetMediaType.Image media type.

PHFetchResult fetchResults = PHAsset.FetchAssets (PHAssetMediaType.Image, null);

The PHFetchResult instance would then contain all the PFAsset instances representing images. To get the images themselves, you use the PHImageManager (or the caching version, PHCachingImageManager) to make a request for the image by calling RequestImageForAsset. For example, the following code retrieves an image for each asset in a PHFetchResult to display in a collection view cell:

public override UICollectionViewCell GetCell (UICollectionView collectionView, NSIndexPath indexPath)
{
  var imageCell = (ImageCell)collectionView.DequeueReusableCell (cellId, indexPath);
  imageMgr.RequestImageForAsset ((PHAsset)fetchResults [(uint)indexPath.Item], thumbnailSize,
    PHImageContentMode.AspectFill, new PHImageRequestOptions (), (img, info) => {
      imageCell.ImageView.Image = img;
    });
    return imageCell;
}

This results in a grid of images as shown below:

PhotoKit1

That’s how to handle querying and reading data. You can also write changes back to the library. Since multiple interested applications are able to interact with the system photo library, you can register an observer to be notified of changes using a PhotoLibraryObserver. Then, when changes come in, your application can update accordingly. For example, here’s a simple implementation to reload the collection view above:

class PhotoLibraryObserver : PHPhotoLibraryChangeObserver
{
  readonly PhotosViewController controller;
  public PhotoLibraryObserver (PhotosViewController controller)
  {
    this.controller = controller;
  }
  public override void PhotoLibraryDidChange (PHChange changeInstance)
  {
    DispatchQueue.MainQueue.DispatchAsync (() => {
      var changes = changeInstance.GetFetchResultChangeDetails (controller.fetchResults);
      controller.fetchResults = changes.FetchResultAfterChanges;
      controller.CollectionView.ReloadData ();
    });
  }
}

To actually write changes back from your application, you create a change request. Each of the model classes has an associated change request class. For example, to change a PHAsset, you create a PHAssetChangeRequest. The steps to perform changes that are written back to the photo library and sent to observers like the one above are:

  1. Perform the editing operation.
  2. Save the filtered image data to a PHContentEditingOutput instance.
  3. Make a change request to publish the changes form the editing output.

Here’s an example that writes back a change to an image that applies a core image noir filter:

void ApplyNoirFilter (object sender, EventArgs e)
{
  Asset.RequestContentEditingInput (new PHContentEditingInputRequestOptions (), (input, options) => {
    //
    // perform the editing operation, which applies a noir filter in this case
    var image = CIImage.FromUrl (input.FullSizeImageUrl);
    image = image.CreateWithOrientation ((CIImageOrientation)input.FullSizeImageOrientation);
    var noir = new CIPhotoEffectNoir {
      Image = image
    };
    var ciContext = CIContext.FromOptions (null);
    var output = noir.OutputImage;
    var uiImage = UIImage.FromImage (ciContext.CreateCGImage (output, output.Extent));
    imageView.Image = uiImage;
    //
    // save the filtered image data to a PHContentEditingOutput instance
    var editingOutput = new PHContentEditingOutput(input);
    var adjustmentData = new PHAdjustmentData();
    var data = uiImage.AsJPEG();
    NSError error;
    data.Save(editingOutput.RenderedContentUrl, false, out error);
    editingOutput.AdjustmentData = adjustmentData;
    //
    // make a change request to publish the changes form the editing output
    PHPhotoLibrary.GetSharedPhotoLibrary.PerformChanges (
      () => {
        PHAssetChangeRequest request = PHAssetChangeRequest.ChangeRequest(Asset);
        request.ContentEditingOutput = editingOutput;
      },
      (ok, err) => Console.WriteLine ("photo updated successfully: {0}", ok));
  });
}

When the users selects the button, the filter is applied:

PhotoKit2

And thanks to the PHPhotoLibraryChangeObserver, the change is reflected in the collection view when the user navigates back:

PhotoKit3

PhotoKit is a welcome addition to iOS that allows greater flexibility for incorporating photo library data into applications. It opens the doors for third party developers to build more integrated photo and video experiences than ever before.

The code from this post is available in my GitHub repo.

Discuss this blog post in the Xamarin Forums

TwitterFacebookGoogle+LinkedInEmail
July 3, 2014

Contest: Build Your First F# Mobile App

By

Experience the power of building native mobile apps in F# with Xamarin.

What’s better than F# week? F# weekend! We’re announcing another contest to commemorate this programming language in a new contest. Earlier this week, we started F# week off by announcing our “Run an F# app, get an F# shirt” campaign. Tuesday and Wednesday, Microsoft F# MVP Rachel Reese taught us the basics of F#, and even built a simple task-management app.

Today, we are inviting you to dive into building native mobile apps in F# with our newest contest. Creating a mobile app with F# is as easy as File -> New -> F# -> iOS or Android within Xamarin Studio.

How to Enter

  1. Install Xamarin 3
  2. File -> New -> F# -> iOS or Android in Xamarin Studio
  3. Build an succinct, expressive native mobile app using F#
  4. Tweet your entry with a picture of your F# app running and this text:
    I just built my first F# mobile app using @XamarinHQ:  http://xamar.in/r/fsharp

2014-07-01_1728

How to Win

Want to stack the cards in your favor? Do any or all of the following to increase your odds of winning:

  • Build something cool
  • Utilize F# language features
  • Blog about your experience
  • Open-source your app

Prizes

Not sure where to begin? Xamarin evangelist James Montemagno has put together a list of some guides, samples, and apps to help get you started. If you are new to mobile development or Xamarin and want to get started today, visit xamarin.com/download.

All submissions must be made by Monday, July 21st at 8AM EDT. We will evaluate each app and choose a winner. A valid entry consists of a tweet with screenshot(s) of your F# app running. Other factors considered will include novelty, code quality, and reliability. Winners will be announced on Twitter. Contestants should follow @xamarinhq to enable us to DM you for private follow-up. There is no purchase necessary to enter the Build Your First F# Mobile App contest.

TwitterFacebookGoogle+LinkedInEmail

Awesome Samples to Jumpstart F# Mobile Development

By

Throughout the week we have seen a wide assortment of F# samples and applications that you can use to jump start your F# mobile development. Here are a few new resources available to developers, including full sample applications comprised of beautiful F# source code.

F# Tutorial

Starter Guides

With the release of Xamarin 3, we brought first class F# support to developers inside of Xamarin Studio. To go along with that, we also have great getting started documentation, along with a few other fantastic resources to get you going:

Mobile App Samples

F# Shallow App
In addition to documentation here are a few open source F# mobile apps that you can run right away.

Shallow

Based on popular dating apps, Shallow is a great example of using beautiful animations built into iOS, that you can take advantage of with a few lines of code in F#.

For a full break down of Shallow’s features and introduction to its F# goodness be sure to see the full blog post by Xamarin’s David Siegel, and its GitHub repo.

Tasky F#

Recently announced Xamarin Evolve speaker and F# enthusiast Rachel Reese wrote an amazing introduction to mobile development in F# post. Not only did she break down all of the benefits of F#, but also built out a full Task taking app, Tasky F#, that is completely open source on GitHub.

Xamarin Store

anuj f sharp shirtWhen we kicked off F# week, we released a brand new version of the Xamarin Store app for iOS and Android. This is where you can get your very own F# t-shirt shipped for FREE directly to your doorstep for trying Xamarin and running your first F# app. This is a beautiful application with elegant animations such as Ken Burn’s effects on images. Download the source code today and get your very own F# t-shirt.

Show us your F# Hacks!

These are a few great examples to help kick start your F# mobile development with Xamarin. We are sure might have your own F# tips and tricks to share with developers, so head over to our Community Forums and share your own F# hacks!

TwitterFacebookGoogle+LinkedInEmail
July 2, 2014

Headed to the Capitol for Microsoft WPC 2014

By

Xamarin is headed to the capitol to meet with our rapidly growing network of partners, and to strike new relationships at Microsoft’s premier partner event this July.  We will be in Washington, D.C for Microsoft’s Worldwide Partner Conference at booth #828 to meet our community, learn about your apps, and connect with our partners.  

washington-dc

Join Xamarin for food and drinks during WPC week on Tuesday, July 15th from 7:30 pm to 10:30 pm. We’ll have a selection of delicious drinks and appetizers, and of course, plenty of mobile development talk. We look forward to seeing you there!

When: Tuesday, July 15th, 7:30pm – 10:30pm

Where: Redline Gastrolounge, 707 G Street Northwest, Washington, D.C. 20001

RSVP

Not at the Worldwide Partner Conference but in the DC area?  Stop by anyway! You and your friends are welcome. Make the most of your time at WPC and schedule dedicated time with the Xamarin partner team while you’re in town for the conference.

TwitterFacebookGoogle+LinkedInEmail
July 1, 2014

Introduction to F# with Xamarin, Part II

By

rachel-reeseRachel Reese is a long-time software engineer and math geek who recently relocated to Nashville, TN to work at Firefly Logic. Rachel is an ASPInsider and an F# MVP. You can catch her at Xamarin Evolve 2014, the largest conference for cross-platform mobile development.

This blog post is part of our continuing celebration of F# Week at Xamarin! Celebrate by getting your own F# t-shirt! Yesterday, Rachel gave us an “Introduction to F# with Xamarin”. Today, she takes us through building a task management app with F# and Xamarin.

Getting Started with iOS Development
Yesterday, we took a look at the benefits of F# by building much of the data layer for the F# version of the task-management app Tasky. Today, let’s complete that, add a couple of views, and we’ll be up and running with an F# version of Xamarin’s favorite task app!

In Xamarin Studio, create a new F# iOS Single View Application named “Tasky”. Xamarin Studio will create a solution for us, with two important files:

    1. AppDelegate.fs – This is the heart of the application. The Main module defines an application’s entry point, while the AppDelegate type inherits from UIApplicationDelegate, which provides such application lifecycle events as ApplicationDidFinishLaunching and ApplicationWillTerminate. From AppDelegate, we’ll define which view controller should load first. In this case, because the application is named Tasky, the first view controller that’s called is TaskyViewController.fs.
    2. TaskyViewController.fs – This is the project’s first view controller. This is inherited from UIViewController, and the main overridable methods here handle the view lifecycle. For example: ViewDidLoad, DidReceiveMemoryWarning, DidRotate, ViewWillDisappear, etc.

If we run the project at this point, before making any changes, it will load a blank, black screen. Let’s make it do a bit more. We will start by setting up navigation. Open AppDelegate.fs and update the RootViewController to the following:

window.RootViewController <- new UINavigationController (new TaskyViewController ())

Wrapping the TaskyViewController in a UINavigationController will allow a user to navigate back from the update task screen (once we create it). In other words, that screen will display a back button allowing return to the task list. That finishes off the changes we’ll need to make for Tasky in AppDelegate.fs.

Next, let’s work on the main view controller. Open TaskyViewController.fs, and we’ll add an event handler in ViewDidLoad, for adding a new task from a “+” button on the navigation bar.

let addNewTask =
    new EventHandler (fun sender eventargs ->
        this.NavigationController.PushViewController (new AddTaskViewController (), true)
    )
this.NavigationItem.SetRightBarButtonItem (new UIBarButtonItem (UIBarButtonSystemIcon.Add, addNewTask), false)

At this point, we’ll also need to create a nearly empty AddTaskViewController.fs, inherited from UIViewController, like so:

type AddTaskViewController () =
    inherit UIViewController ()
    override this.ViewDidLoad () =
        base.ViewDidLoad ()

Our final project structure will look like this:

2014-07-01_1723

Creating and Populating with Data

Now that the navigation is set up, let’s build the task list itself. First, create the UITableView:

let table <- new UITableView ()

Next, within the ViewDidLoad method, set the view’s frame to be the full screen, and add the table to the view.

table.Frame <- this.View.Bounds
this.View.Add table

Displaying the table was the easy part. Next, we’ll need to fill the table with data. To help do this, we need to create a UITableViewSource. In our case, we take in the list of tasks that are returned from the SQLite Type Provider, as well as our navigation controller. We will need to include the navigation controller as a parameter, so that we can navigate when the user clicks a row in the table. We also copy the task list locally, and set the cell identifier to a unique name for this cell type. It’s possible to load a mix of different cell types (with completely varied layouts) into an iOS table, and this identifies which one is being loaded.

type TaskDataSource(tasksource: task list, navigation: UINavigationController) =
    inherit UITableViewSource ()
    let tasks = new List<task> (taskSource)
    member x.cellIDentifier = "TaskCell"

Once we’ve defined those, there are two methods we absolutely must override in TaskDataSource: RowsInSection, and GetCell. RowsInSection returns the total number of rows that the table contains; GetCell dequeues or creates a new UITableViewCell, then populates that cell with the correct data for that row. [For more information on dequeuing, see the “Note on Cell Reuse” in the Xamarin docs, above.]

override x.RowsInSection (view, section) = tasks.Count
override x.GetCell (view, indexPath) =
    let t = tasks.[indexPath.Item]
    let cell =
        let newCell = view.DequeueReusableCell x.cellIdentifier
        match newCell with
            | null -> new UITableViewCell (UITableViewCellStyle.Default, x.cellIdentifier)
            | _ -> newCell
    cell.TextLabel.Text <- t.Description
    cell

With these added, let’s jump back to the TaskyViewController type. We need to override ViewWillAppear, to set the newly created TaskDataSource to be the UITableView source. We also must reload the data each time the view appears. Using the GetIncompleteTasks method we created in the type providers section, we should now be able to run Tasky and load the tasks.

override this.ViewWillAppear animated =
    base.ViewWillAppear animated
    table.Source <- new TaskDataSource (Data.GetIncompleteTasks (), this.NavigationController)
    table.ReloadData ()

This will give us the basic set up to load a table of tasks, but we aren’t yet able to navigate to a detail page upon selecting a row, nor are we able to delete with a swipe in from the right.

Swipe to Delete
Adding the ability to swipe delete is only a matter of adding two more overrides into the TaskDataSource type.

  • CanEditRow is, logically, whether or not that row can be edited.
  • CommitEditingStyle handles the deletion. First, delete the task from the data source; second, remove the task from the tasks list; finally, delete that row from the view.
override x.CanEditRow (view, indexPath) = true
override x.CommitEditingStyle (view, editingStyle, indexPath) =
    match editingStyle with
        | UITableViewCellEditingStyle.Delete ->
          Data.DeleteTask tasks.[indexPath.Item].Description
          tasks.RemoveAt (indexPath.Item)
          view.DeleteRows ( [|indexPath|], UITableViewRowAnimation.Fade)
        | _ -> Console.WriteLine "CommitEditingStyle:None called"

Selection and Navigating
The final step in the TaskyViewController functionality is to handle navigation. To select a row and navigate to a detail page for that row, we only need to override the RowSelected method. In this case, we first want to deselect the row (so that when we return to the view, the row doesn’t remain selected), and then push the new view controller. We’re using the AddTaskViewController, which handles both adding and updating tasks.

override x>RowSelected (tableView, indexPath) =
    tableView.DeselectRow (indexPath, false)
    navigation.PushViewController (new AddTaskViewController (tasks.[indexPath.Item], false), true)

The above code modifies the constructor of the AddTaskViewController (created previously) to accept a current task, as well as a Boolean determining whether or not that task is a new task. We’ll update this in the next section.

Creating a Non-Table View
We’re almost done now; we just need to add a quick form to handle adding and updating a task. Let’s start by updating the constructor to accept a task and a Boolean, as just mentioned. To do this, we need to modify the AddTaskViewController type to take in the new parameters. We’ll also add a second, parameterless constructor, which creates an instance of the controller with some defaults – specifically: Description should be empty, Complete should be false, and the isNew Boolean should be true, exactly as one would expect with a brand new task.

type AddTaskViewController (task:task, isNew:bool) =
    inherit UIViewController ()
    new () = new AddTaskViewController ({Description=""; Complete=false}, true)
    override this.ViewDidLoad () =
        base.ViewDidLoad ()

Now, let’s move into the ViewDidLoad method. Create a new subview to which we will add our fields, and set the background color to white.

let addView = new UIView (this.View.Bounds)
addView.BackgroundColor <- UIColor.White

From here, we simply add and position our form elements. We’ll start with a UITextField for the Description, and a UISwitch with corresponding UILabel for our Complete field. We also add an event handler to handle setting Complete on our task when the switch is toggled.

let description = new UITextField (new RectangleF (20.f, 64.f, 280.f, 50.f))
description.Text <- task.Description
description.Placeholder <- "task description"
addView.Add description
let completeLabel = new UILabel (new RectangleF (20.f, 114.f, 100.f, 30.f))
completeLabel.Text <- Complete
addView.Add completeLabel
let completeCheck = new UISwitch (new RectnagleF (120.f, 114.f, 200.f, 30.f))
completeCheck.SetState (task.Complete, false)
let changeCompleteStatus =
    new EventHandler (fun sender eventargs ->
        task.Complete <- completeCheck.On
    )
completeCheck.TouchDragInside.AddHandler changeCompleteStatus
addView.Add completeCheck

Now that the input part is complete, we need to be able to save new tasks, along with a corresponding label to indicate the operation has completed. Depending on whether or not the task is new, we call the appropriate Add or Update function in our Data file, and then print “Added” or “Updated”.

let addedLabel = new UILabel (new RectangleF (20.f, 214.f, 280.f, 50.f))
addView.Add addedLabel
let addUpdateButton = UIButton.FromType (UIButtonType.RoundedRect)
addUpdateButton.Frame <- new RectangleF (20.f, 164.f, 280.f, 50.f)
let addUpdateHandler =
    new EventHandler (fun sender eventargs ->
        match isNew with
            | true ->
                Data.AddTask description.Text
                addedLabel.Text <- "Added!"
            | false ->
                Data.UpdateTask description.Text completeCheck.On
                addedLabel.Text <- "Updated!"
        description.Text <- ""
    )
addUpdateButton.TouchUpInside.AddHandler addUpdateHandler
addUpdateButton.SetTItle ("Save", UIControlState.Normal)
addView.Add addUpdateButton

Since the label was added to indicate that saving is complete, we need to clear the text when we want to add a new task, to minimize confusion, and make it obvious that the new task has also been added. To that end, we add a clear label function that is called when the user clicks back into the Description field.

let clearLabel =
    new EventHandler (fun sender eventargs ->
        addedLabel.Text <- ""
    )
description.TouchDown.AddHandler clearLabel

Finally, we simply need to add the subview that we’ve been populating to the main view, and we’re done!

this.View.Add addView

We have just built an F# version of Tasky, Xamarin’s favorite task-management app! You can get the bits on GitHub and follow me on Twitter @RachelReese.

TwitterFacebookGoogle+LinkedInEmail

Introduction to F# with Xamarin

By

rachel-reeseRachel Reese (@RachelReese) is a long-time software engineer and math geek who recently relocated to Nashville, TN to work at Firefly Logic. Rachel is an ASPInsider and an F# MVP. You can catch her at Xamarin Evolve 2014, where you can learn from industry leaders and Xamarin expertsto advance your projects and career.

This blog post is part of our continuing celebration of F# Week at Xamarin! Celebrate by getting your own F# t-shirt!

Why F#?
Let’s first dig into a few of my favorite reasons to consider F# for your next Xamarin project: type inference, units of measure, type providers, as well as the ever-crucial clarity and conciseness of code.

Type Inference
People often underestimate the benefits of type inference, but the ability to clear out the type definitions from code and concentrate on the code itself, instead of all the clutter around the declaration, is tremendous. Consider this example (from here, via here):

C#:

    public static Tree<KeyValuePair<A, bool>> DiffTree<A>(Tree<A> tree, Tree<A> tree2)
    {
        return XFoldTree((A x, Func<Tree<A>, Tree<KeyValuePair<A, bool>>> l, Func<Tree<A>, Tree<KeyValuePair<A, bool>>> r, Tree<A> t) => (Tree<A> t2) =>
            Node(new KeyValuePair<A, bool>(t2.Data, object.ReferenceEquals(t, t2)),
                 l(t2.Left), r(t2.Right)),
            x => y => null, tree)(tree2);
    }

The equivalent F# is much easier on the eyes. The code itself might still be incomprehensible, but it is at least not drowning in required type definitions. It’s no longer necessary to filter through all the extra information before trying to understand what’s happening.

let DiffTree(tree,tree2) =
    XFoldTree (fun x l r t t2 ->
        let (Node(x2,l2,r2)) = t2
        Node((x2,t===t2), l l2, r r2)) (fun _ _ -> Leaf) tree tree2

For more information on type inference, see the F# for Fun and Profit website. There are some fabulous examples of how it works, and how to troubleshoot the errors that sometimes show up.

Units of Measure
Units of measure are types that allow one to add unit information to a numeric type in F#. Once a value is tagged with a unit type, it can only be combined with other values that have that same unit. For example, if we want to track distances and times, it’s possible to create:

[<Measure>] type s
[<Measure>] type m

Then, when we define a new value, we can easily associate our new unit with it:

let time = 30<s>
let distance = 10<m>

The compiler will error if we try to add the two values, but it is possible to divide them:

let velocity = distance/time

If we hover over this declaration, the tooltip for this value will show:

val velocity : int<m/s>

All scientific computing will benefit from enforcing units (game physics!) but it doesn’t have to be exclusively the domain of science. Think about using pixel, USD, or Fahrenheit, among others!

It’s also possible to use generic units of measure in a function. For example, we’d like to calculate a perimeter, given some distances. We can declare the function like so:

let perimeter = (x:int,<'distance>) (y:int<'distance>) = 2*x + 2*y

In this manner, we’re able to utilize one function for many different units of measure. As long as the units for a single given call are the same, the code will compile. However, the compiler will still throw an error if we try to call perimeter with two different units. To wit:

// Compiler error: The unit of measure 'ft' does not match the unit of measure 'm'
let p_1 = perimeter 10<m> 4<m>
let p_2 = perimeter 2<ft> 3<m>

Type Providers
Type providers are a mechanism that allows F# code to access typed information from external data sources with no code generation, all in just a few lines of code. They are a revolution in data access! F# was the first enterprise-grade language to have type providers, and is still the only .NET language to have them. So, if we want to use a type provider in our Xamarin project, we’ll need to use F#!

There are many, many type providers available, but I’ll concentrate on two that are especially useful with Xamarin projects today – the SQLProvider and the Freebase Provider.

SQLProvider

The SQLProvider provides access to MS SQL Server, SQLite, PostgreSQL, Oracle, MySQL, ODBC, and MS Access databases. Since SQLite is a tremendously common database to hook up with both iOS and Android applications, let’s take a look at what’s required to use the SQLProvider type provider to connect to a SQLite database in an F# Xamarin project!

First, we declare a type. We’ll need to change this to include the connection string, as well as the path to the mono.sqlite.dll.

type sql = SqlDataProvider

At this point, we’re ready to go. To show off the SQLite provider, let’s build a quick port of the Xamarin Tasky app (see original here). We’ll need to create just a couple of functions for our data layer: GetIncompleteTasks, AddTask, UpdateTask, and DeleteTask. However, first we need to get the data context:

let ctx = sql.GetDataContext ()

Every time we type `ctx`, we’ll get code completion on the remaining pieces:

2014-07-01_1414

As well as tooltips, which show that the information coming back from SQLite is fully typed:

2014-07-01_1415

Once we have set up the data context, creating the methods we need is as easy as pie. Let’s declare a type for the return data, to use in our queries:

type task = { Description : string; mutable Complete : bool; }

Then, to return the incomplete tasks, we use the familiar query syntax:

let GetIncompleteTasks () =
    query { for data in ctx.``[main].[tasks]`` do
                where (data.complete = 0L)
                select {Description=data.task; Complete = false}}
            |> Sql.toList

This returns an F# list of tasks, where complete is false. That’s it. No messy ORMs to contend with, no long data access libraries to futz with; we only need a database connection and a query. Adding a task is just as easy, we need to create a new task, update the two fields (“<-” is the F# assignment operator), and finally, submit our updates.

let AddTask description =
    let newTask = ctx.``[main].[tasks]``.Create()
    newTask.task <- description
    newTask.complete <- 0L
    ctx.SubmitUpdates()

Freebase

The Freebase.com web site describes itself as a community-curated database. They currently have a list of nearly 44 million topics, and over 2.5 billion facts. Connecting our app in to all their data is simple, with the Freebase type provider! We merely need to get the context, and start querying.

The Freebase database is especially exciting because the data is returned with additional units of measure. In the example above, when the results are returned, and in the tooltips, we can see that the particle charge is shown in coulombs!

2014-07-01_1422

As with all type providers, the Freebase provider also has code completion into the structure of our data source. It frees us up to explore the data!

2014-07-01_1423

Keep an eye out on the Xamarin Blog for Part 2 of Getting Started with Xamarin and F#, where I’ll discuss using F# to build amazing cross-platform, native apps.

TwitterFacebookGoogle+LinkedInEmail