Brian Long Consultancy & Training Services
Ltd.
March 2011
Accompanying source files available through this
download link
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:
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.
The status bar’s visibility is simply controlled via UIApplication.SharedApplication.StatusBarHidden
.
Just hiding the status bar does little to our current view. In order to fill the
new amount of space on the screen the underlying window’s Frame
property
is set to match the screen’s ApplicationFrame
property. Remember we
are in a view controller descendant class at the moment. The underlying window is
a property of the view, for which UIViewController
defines a property,
View
(upper case V
). However the code behind file for
this class also happens to define a property view
(lower case v
),
which always returns null
. Whenever you wish to access the view associated
with your view controller it is vital to remember to use View
instead of view
.
Even after we resize the view’s window into the available space the Navigation Bar often doesn’t respond when it should (its decision on when to move up with the window seems unpredictable). The best way I found to overcome the issue is to hide and then re-show the Navigation Bar after the status bar has been toggled. However gaining access to the Navigation Bar requires some thought.
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