Mike's Dev Blog

Draw a PDF in Landscape with Core Graphics

Posted in iOS, Xamarin by mikebluestein on March 15, 2014

I just got a question from a Core Graphics presentation I gave a while back (from the first Xamarin Seminar) about how to use Core Graphics to render a PDF with 2 pages side-by-side in landscape. Since this question has come up a couple times in the past I figured I’d write a blog post about it.

The solution I use for this is to create a rectangle to display each page and then apply a transform to render the page within the rectangle. CGPDFPage has a handy GetDrawingTransform function that returns the transform. To get back a transform that crops the page to the rectangle while preserving the aspect ratio simply call:

CGAffineTransform transform = 
    pdfPage.GetDrawingTransform (CGPDFBox.Crop, pageRectangle, 0, true);

To do this for 2 pages, use the SaveState and RestoreState functions of the CGContext to get the transformation matrix back to its intial state, so that the transformation of the first page isn’t applied to the second page.

The following code shows how to implement this in a UIView subclass:

public override void Draw (RectangleF rect)
{
    base.Draw (rect);

    var rect1 = new RectangleF (0, 0, Bounds.Width / 2, Bounds.Height);
    var rect2 = new RectangleF (Bounds.Width / 2, 0, Bounds.Width / 2, Bounds.Height);
    
    using (CGContext gctx = UIGraphics.GetCurrentContext ()) {
        gctx.TranslateCTM (0, Bounds.Height);
        gctx.ScaleCTM (1, -1);

        gctx.SaveState ();

        using (CGPDFPage page = pdf.GetPage (page1)) {
            CGAffineTransform transform = 
                page.GetDrawingTransform (CGPDFBox.Crop, rect1, 0, true);
            gctx.ConcatCTM (transform);
            gctx.DrawPDFPage (page);
        }

        gctx.RestoreState ();

        using (CGPDFPage page = pdf.GetPage (page2)) {
            CGAffineTransform transform = 
                page.GetDrawingTransform (CGPDFBox.Crop, rect2, 0, true);
            gctx.ConcatCTM (transform);
            gctx.DrawPDFPage (pdfPg);
        }
    }
}

This renders the PDF to the screen as shown below:

landscapepdf

Use Nokia X HERE Maps with Xamarin.Android

Posted in Xamarin by mikebluestein on February 27, 2014

Earlier this week Nokia announced their new line of Nokia X Android phones. C# developers using Xamarin can target this platform via the Nokia components in the Xamarin Component Store.

Let’s take a look at using the Nokia HERE Maps API in a Xamarin.Android applcation.

Nokia HERE Maps have a wealth of features ranging from 3D landmarks, to street-level imagery and venue maps.

here_map

See the HERE Maps section of the Nokia developer site for more information on the entire feature set.

The first thing you need to do is set up the Nokia X Platform, which can be done via the Android SDK Manager. The following doc on the Nokia developer site explains how to do this:

http://developer.nokia.com/resources/library/nokia-x/getting-started/environment-setup.html

Note, when you create a Nokia X emulator, be sure to set the target to Nokia X services (Nokia) – API Level 16 as shown below:

nokiax_emulator_setup

Once you have your environment set up, create a new Android project that targets API level 16. To use Nokia HERE Maps from Xamarin, simply add the Xamarin component:

http://components.xamarin.com/view/NokiaHERE

The component brings everything you need directly into the project in either Visual Studio or Xamarin Studio. The sample projects included with the component show you how to get started.

Adding a Map

Basically, to include a map:

  1. Add your AppID and AppToken
  2. Set the required permissions
  3. Add a MapFragment
  4. Initialize the MapFragment
  5. Setup the map after the fragment has been initialized

AppID and AppToken

The AppID and AppToken can be set using attributes:

[assembly: MetaData("com.here.android.maps.appid", Value = "YourAppID")]
[assembly: MetaData("com.here.android.maps.apptoken", Value = "YourAppToken")]

Also, enable hardware-accelerated rendering:

[assembly: Application(HardwareAccelerated = true)]

Required Permissions

Next, the following required permissions need to be set in the Android manifest:

  • AccessFineLocation
  • AccessNetworkState
  • AccessWifiState
  • ChangeNetworkState
  • Internet
  • WriteExternalStorage

MapFragment

The Sample.HERE application included with the component adds the MapFragment in code via the FragmentManager:

fragment = new MapFragment ();
FragmentManager.BeginTransaction ()
  .Replace (Resource.Id.fragmentcontainer, fragment).Commit();

Additionally, you can add the MapFragment in the axml file, which is what I’ve done in this example:

Then in the Activity’s OnCreate method, retrieve the MapFragment and initialize it as follows:

mapFragment = FragmentManager.FindFragmentById (Resource.Id.mapfragment);
mapFragment.Init (this, this);

Accessing the Map Object

To get a reference to the map itself after the fragment initialization has completed, implement the IFragmentInitListener from the Nokia.Here.Mapping namespace, where you can access the map via the MapFragment’s Map property. Then you can call methods on the map such as SetCenter and SetZoomLevel:

public void OnFragmentInitializationCompleted (InitError error)
{
  if (error == InitError.None) {
    map = mapFragment.Map;

    double lat = 30.2652233534254;
    double lon = -97.73815460962083;

    map.SetCenter (MapFactory.CreateGeoCoordinate (lat, lon, 0.0), MapAnimation.None);
    map.SetZoomLevel (18.0, MapAnimation.None);
  }
}

This displays a map in the application as shown below:

nokiax_map

There are variety of map schemes that can be easily set via the MapScheme property. For example, setting map.MapScheme = MapScheme.SatelliteDay will show a map with daytime satellite imagery:

nokiax_satellite

See Nokia Map Schemes documentation for the other schemes that are available.

As you can see, it’s pretty easy to get started. There are wealth of additional feature as well. For example, you can add a polygon to a map using the MapFactory class to create an IMapPolygon:

var geoPolygon = MapFactory.CreateGeoPolygon (new JavaList {
  MapFactory.CreateGeoCoordinate (30.2648461170005, -97.7381627734755),
  MapFactory.CreateGeoCoordinate (30.2648355402574, -97.7381750192576),
  MapFactory.CreateGeoCoordinate (30.2647791309417, -97.7379872505988),
  MapFactory.CreateGeoCoordinate (30.2654525150319, -97.7377341711021),
  MapFactory.CreateGeoCoordinate (30.2654807195004, -97.7377994819399),
  MapFactory.CreateGeoCoordinate (30.2655089239607, -97.7377994819399),
  MapFactory.CreateGeoCoordinate (30.2656428950368, -97.738346460207),
  MapFactory.CreateGeoCoordinate (30.2650364981811, -97.7385709662122),
  MapFactory.CreateGeoCoordinate (30.2650470749025, -97.7386199493406)
});

MapPolygon’s are one of many MapObjects. These are added to the map by calling AddMapObject:

map.AddMapObject (mapPolyline);

With this, we get an overlay of the specified coordinates:

nokiax_mappolygon

You can download the sample code shown here from my github repo.

Tagged with: , ,

Creating Collection View Cells from a Xib

Posted in Uncategorized by mikebluestein on February 6, 2014

I’ve had the question of how to create a collection view cell using a xib file come up a few times, so I figured I would put together a quick example to show how to do it. In this case, I just created a collection view with 100 cells each containing a label:

cv_xib_cells

Basically, you need to register the cell using the CollectionView.RegisterNibForCell method like this:

CollectionView.RegisterNibForCell (UINib.FromName ("CVCell", NSBundle.MainBundle),
  cellId);

There is a template file in Xamarin Studio you can use to create a collection view cell. This will create a xib to design the cell in, along with a class that is wired up to the xib. The template adds a bit of additional code but all you really need is the constructor that takes an IntPtr, as the class will be created by iOS via the call to DequeueReusableCell.

For example, here’s the code for the cell I’m using in this simple example:

public partial class CVCell : UICollectionViewCell
{
    public string Text {
        set{
            Label.Text = value;
        }
    }

    public CVCell (IntPtr handle) : base (handle)
    {
    }
}

The Text property simply sets the text on a UILabel that is added in Interface Builder.

The code to create the cell in the UIViewController is just like when you create the cell entirely in code:

public override UICollectionViewCell GetCell (UICollectionView collectionView, NSIndexPath indexPath)
{
    var cell = (CVCell)collectionView.DequeueReusableCell (cellId, indexPath);

    cell.Text = indexPath.Row.ToString ();

    return cell;
}

The project is available in my github repo here.

Core Animation Resources for Xamarin.iOS Developers

Posted in iOS, Xamarin by mikebluestein on February 2, 2014

If you are an iOS developer, you owe it to yourself to try and learn the Core Animation framework because it isn’t just about animation. Core Animation makes much of what you see in iOS applications possible.

Here are some resources to get  you started:

Going through these resources will give an understanding of how the Core Animation framework is at the heart of iOS, which will help you to create experiences that differentiate your application.

Advanced Collection Views

Posted in iOS, Xamarin by mikebluestein on January 25, 2014
Tagged with: , ,

MonkeySpace 2013

Posted in Xamarin by mikebluestein on July 31, 2013

Last week I was lucky enough to attend the MonkeySpace conference, where I got to present 3 different talks. This is one of my favorite conferences as the attendees tend to work on some very interesing projects and have an affinity for sharing information.

The first talk I gave was about collection views. This is a very interesting technology that allows you to easily create grid-like layouts of items in iOS. Additionally, they are easy enough to extend to create any sort of layout you can imagine.

Here’s one of the examples I demonstrated during my talk. It creates a layout over a baseball field where you can toggle between the home and away teams:

BaseballLayout

The code is available here:

https://github.com/mikebluestein/CVLayoutsDemo

Up next, I presented the latest version of the excellent Xamarin.Mobile API, showing the new changes to the MediaPicker among other things. What’s particularly exciting about this is the API was open-sourced just before my talk, so I was able to demonstrate from the latest source.

Finally, for my third talk, I showed how to make a small game using the new Cocos2D-XNA API, a C# port of the widely used Cocos2D iOS API. What’s interesting about Cocos2D-XNA is that it builds on MonoGame, so it allows you to reach many platforms with the same code base.

More information, along with sample code can be found in the article I wrote on the Xamarin site:

http://docs.xamarin.com/guides/cross-platform/cocos2d_xna/cocos2dxna_tutorial

Beyond my talks, I really enjoyed meeting so many new people and hearing about all the exciting work everyone is doing. I’m looking forward to MonkeySpace again next year!

Tagged with: ,

UISplitViewController and UICollectionView

Posted in iOS, iPad, monotouch by mikebluestein on October 21, 2012

Continuing from the previous post that used a UICollectionView to display a grid of images from Bing, the following example adds a UICollectionView to a UISplitViewController.

When the row is selected, a new search is issued and the resulting images are updated in the UICollectionView. To connect the selection in the UISplitViewController’s master controller, which is an MT.D DialogViewController in this case, to the UICollectionViewController contained in the UISplitViewController’s detail controller, an event is raised when a row is selected:

public AnimalsController () : base (null)
{
    Root = new RootElement ("Animals") {
        new Section () {
            from animal in animals
            select (Element) new StringElement(animal, () => {
            if(AnimalSelected != null)
                AnimalSelected(this, new AnimalSelectedEventArgs{Animal = animal});
            })
         }};
 }

Then the UISplitViewController’s implementation handles this event to communicate to the UICollectionViewController:

animalImageController = new BingImageGridViewController (layout);

animalsController.AnimalSelected += (sender, e) => {
    animalImageController.LoadImages (e.Animal);
};

In the LoadImages method, the UICollectionViewController calls Bing for the selected item and uploads the UICollectionView when the data is returned by calling ReloadData:


public void LoadImages (string search)
{
    UIApplication.SharedApplication.NetworkActivityIndicatorVisible = true;

    bing = new Bing ((results) => {
        InvokeOnMainThread (delegate {
            imageUrls = results;
            CollectionView.ReloadData ();
            UIApplication.SharedApplication.NetworkActivityIndicatorVisible = false;
        });
    });

    bing.ImageSearch (search);
}

The sample is available at https://github.com/mikebluestein/BingImageGrid/tree/master/BingImageGridSplit

Note: you’ll need a Bing API key, which you can get at http://datamarket.azure.com

Using Azure Marketplace’s Bing Image Search on iOS with UICollectionView in C#

Posted in iOS, monotouch, Xamarin by mikebluestein on October 7, 2012

The Windows Azure Marketplace now includes the Bing web service. Using the image search feature, combined with a UICollectionView, can be used to display images in a grid on iOS like this:

Consuming the Bing service with Xamarin on iOS can be accomplished just like anywhere else C# is available.  The UI here consists of a UICollectionView, using a UICollectionViewFlowLayout to achieve the grid display. Programming against a UICollectionView is very similar to using a UITableView, the big difference being that UICollectionView works with a layout class to achieve any layout you desire. iOS provides a very flexible UICollectionViewFlowLayout class that can be used  when a line-based layout is needed. Also, you can subclass UICollectionViewLayout directly as well to implement layouts that aren’t line-based.

You can get the code for this example here: https://github.com/mikebluestein/BingImageGrid

To run the exmaple, you need to sign up for an API key from the Windows Azure Marketplace.

For more information on using Collection Views, see this article in Xamarin’s Developer Center:

http://docs.xamarin.com/ios/tutorials/Introduction_to_CollectionViews

NY State User Group Tour

Posted in Uncategorized by mikebluestein on June 26, 2012

I’ll be in NY state this week speaking on Xamarin’s MonoTouch and Mono for Android.

6/26 – Buffalo http://www.meetup.com/MSDevWNY/events/67359302/

6/27 – Rochester http://vduny.org/FutureMeetings.aspx

6/28 – Syracuse http://www.cnydevelopers.net/

Tagged with:

Xamarin.Mobile API Code Camp Session

Posted in Mono for Android, monotouch, WindowsPhone7, Xamarin by mikebluestein on March 17, 2012

I’ll be giving a presentation on using the Xamarin.Mobile API for cross platform, native mobile development with MonoTouch, Mono for Android and Windows Phone at New England Code Camp 17 on March 31.

Follow

Get every new post delivered to your Inbox.