Mono

Using C# to Develop for iPhone, iPod Touch and iPad

Brian Long Consultancy & Training Services Ltd.
March 2011

Accompanying source files available through this download link

Page selection: Previous  Next

Device Information

The last page in this application is intended to display various pieces of information about the device. This requires another collection of labels to be laid out in Interface Builder, as well as a Switch (UISwitch). The six smaller labels and the Switch are needed in the code so outlets need connecting to them as shown here:

Info page in Interface Builder

Some of the information required to populate the labels can be attained as soon as the view is loaded, such as what device it is and what the screen resolution is. Some information will be updated as and when necessary, such as Application Frame Size (that will change when the status bar is toggled on and off), Proximity Sensor Status and Battery Status. Interaction is another one that will get updated by the user interacting with the phone – it will update to show when the phone is rotated or shaken, and when the user taps. Let’s tackle these one at a time.

The specific device is identified using a helper class DeviceHardware that offers a class method, Version, which returns a value from an enumerated type:

public enum HardwareVersion
{
    iPhone,
    iPhone3G,
    iPhone3GS,
    iPhone4,
    iPod1G,
    iPod2G,
    iPod3G,
    iPod4G,
    iPad,
    iPhoneSimulator,
    iPhone4Simulator,
    iPadSimulator,
    Unknown
}

The code in the class (which employs native interop) is not important here but is included with the sample projects. It is adapted from some existing C# code on the Mono wiki. The class also has a VersionString class method that returns a descriptive string for the current device. To display the device details ViewDidAppear() contains:

deviceLabel.Text = String.Format("{0}, iOS v{1}", DeviceHardware.VersionString, UIDevice.CurrentDevice.SystemVersion);

This is followed by a call to a helper routine that emits the screen resolution and application frame size.

private void UpdateUIMetrics()
{
    var scrn = UIScreen.MainScreen;
    //iPhone 4 doubles pixel count, but point count remains same
    resolutionLabel.Text = string.Format("{0}x{1} points, {2}x{3} pixels",
        scrn.Bounds.Width, scrn.Bounds.Height,
        scrn.Bounds.Width * scrn.Scale, scrn.Bounds.Height * scrn.Scale);    
    frameSizeLabel.Text = string.Format("{0}x{1} points", 
        scrn.ApplicationFrame.Width, scrn.ApplicationFrame.Height);
}

The status bar switch needs to be set to the correct value to start with and then requires an event handler:

    statusBarSwitch.On = !UIApplication.SharedApplication.StatusBarHidden;
    statusBarSwitch.ValueChanged += HandleStatusBarSwitchValueChanged;
...
void HandleStatusBarSwitchValueChanged (object sender, EventArgs e)
{
    UIApplication.SharedApplication.StatusBarHidden = !statusBarSwitch.On;
    if ((View != null) && (View.Window != null))
        View.Window.Frame = UIScreen.MainScreen.ApplicationFrame;
    
    //Without this, the nav bar is lazy about moving to the right place
    //Required a public property to be added to the AppDelegate
    var AppDel = (AppDelegate)UIApplication.SharedApplication.Delegate;
    var NavController = AppDel.NavController;
    NavController.SetNavigationBarHidden(true, false);
    NavController.SetNavigationBarHidden(false, false);  
    UpdateUIMetrics();
}

There are a few noteworthy things in here.

It’s useful to know that the Navigation Bar is exposed through properties and methods of the navigation controller but how do we access the Navigation Controller from a secondary view?

There is a property added to the AppDelegate class in the code behind file for the main window, MainWindow.xib.designer.cs, that exposes the navigation controller. In the auto-generated partial class the property navigationController is defined, but annoyingly it is private and so inaccessible from where we are writing code. The most direct way to overcome this is to define a new public property in the AppDelegate class in the main code file Main.cs, e.g.

public UINavigationController NavController
{
    get { return navigationController; }
    set { navigationController = value; }            
}

Of course we then have the issue of how to talk to the AppDelegate object from the Info Page, but this is readily solved. You may recall we saw earlier how to access the Application object using UIApplication.SharedApplication. The Application object’s delegate object (i.e. the AppDelegate) is available through the Application object’s Delegate property. Once we gain access to the navigation controller its SetNavigationBarHidden() method can be used to toggle the visibility of the Navigation Bar.

After all this the application frame size will have changed so the UpdateUIMetrics() helper is invoked again.

When this page was initially displayed the status bar was present, but it may be the case that the switch has toggled it off. Before the view exits back to the menu screen we should restore the natural order. We do this in ViewDidDisappear():

statusBarSwitch.On = true;
HandleStatusBarSwitchValueChanged(statusBarSwitch, new EventArgs());

Go back to the top of this page

Go back to start of this article

Previous page

Next page