Use case for ContainerView #xamarin #iosdev

Think of a scenario where you have multiple subviews within a view in your application. The screen below shows Cinema Details view in my Cineworld app for iOS

iOS Simulator Screen Shot 23 Apr 2015 15.23.01 iOS Simulator Screen Shot 23 Apr 2015 15.23.06 iOS Simulator Screen Shot 23 Apr 2015 15.23.11 iOS Simulator Screen Shot 23 Apr 2015 15.23.18

 

The screen originally consisted of

  • Segment Control
  • Label (Date display)
  • Calendar Button
  • TableView (List by Date)
  • TableView (Current and Upcoming)
  • RatingView
  • Rate count Label
  • Address and Telephone labels
  • Walking / Driving Direction buttons
  • RateView Button
  • Cinema reviews TableView
  • Ad View

The first iteration of this view used Autosizing and as you can imagine there was some cropping for iPhone 4s. To get around it, I started using Autolayout. Can you imagine managing and creating constraints for this many controls ? I tried.. not once but a few times however it never seemed to fully work.

A few times I moaned how in Windows Phone I have above controls in Panorama and how crappy iOS is. I tried both Xamarin Studio and Xcode to set the constraints.. Nada.. It was explained to me that I am using too many controls and I should simplify my view.. was told have a look at ContainerView. So I did

A container view is a view that can host other views. So i got rid of most controls to have

  • Segment control
  • container view
  • Ad control

Screen Shot 2015-04-23 at 15.42.55   Screen Shot 2015-04-23 at 15.41.28

At this point adding constraints to this view was very very simple. Now simplify by adding new View Controllers for each subviews

Screen Shot 2015-04-23 at 15.49.21

 

Screen Shot 2015-04-23 at 15.51.59

They layouts of each subviews is lot simpler now and auto layout was much easier. Now lets look at how we show / hide desired subviews.

private void ShowContainerView(UIViewController vc)
{
	this.AddChildViewController(vc);

	this.CinemaDetailsContainer.AddSubview(vc.View);

	vc.DidMoveToParentViewController(this);
}

private void HideContainerView(UIViewController vc)
{
	vc.WillMoveToParentViewController (null);

	vc.View.RemoveFromSuperview ();

	vc.RemoveFromParentViewController ();
}

The above methods can be used to add / remove view / view controllers from current view.

FilmsByDateViewController GetFilmsByDateViewController()
{
	if (this.filmsByDateVC == null) 
	{
		var vc = this.Storyboard.InstantiateViewController ("FilmsByDateViewController") as FilmsByDateViewController;

		vc.FilmPerformaceDictionary = this.dateFilms;
		vc.Cinema = this.Cinema;

		vc.View.Frame = new CoreGraphics.CGRect(0, 0, CinemaDetailsContainer.Frame.Width, CinemaDetailsContainer.Frame.Height);

		this.filmsByDateVC = vc;
	}

	return this.filmsByDateVC;
}

FilmListViewController GetCurrentFilmsViewController ()
{
	if (this.currentFilmsVC == null) 
	{
		var vc = this.Storyboard.InstantiateViewController ("FilmListViewController") as FilmListViewController;
		var currentFilms = new AllFilmsTableSource (AllFilmsTableSource.FilmListingType.Current, this.Films);
		vc.FilmSource = currentFilms;
		vc.Cinema = this.Cinema;

		vc.View.Frame = new CoreGraphics.CGRect(0, 0, CinemaDetailsContainer.Frame.Width, CinemaDetailsContainer.Frame.Height);

		this.currentFilmsVC = vc;
	}

	return this.currentFilmsVC;
}

FilmListViewController GetUpcomingFilmsViewController ()
{
	if (this.upcomingFilmsVC == null) 
	{
		var vc = this.Storyboard.InstantiateViewController ("FilmListViewController") as FilmListViewController;
		var upcomingFilms = new AllFilmsTableSource (AllFilmsTableSource.FilmListingType.Upcoming, this.Films);
		vc.FilmSource = upcomingFilms;
		vc.Cinema = this.Cinema;

		vc.View.Frame = new CoreGraphics.CGRect(0, 0, CinemaDetailsContainer.Frame.Width, CinemaDetailsContainer.Frame.Height);

		this.upcomingFilmsVC = vc;
	}

	return this.upcomingFilmsVC;
}

CinemaInfoViewController GetCinemaInfoViewController()
{
	if (this.cinemaInfoVC == null) 
	{
		var vc = this.Storyboard.InstantiateViewController("CinemaInfoViewController") as CinemaInfoViewController;
		vc.Cinema = this.Cinema;
		vc.View.Frame = new CoreGraphics.CGRect(0, 0, CinemaDetailsContainer.Frame.Width, CinemaDetailsContainer.Frame.Height);

		this.cinemaInfoVC = vc;
	}

	return this.cinemaInfoVC;
}

The above methods are helpers to instantiate contained view controllers and the code below is the ViewDidLoad showing how Segment control’s ValueChanged shows the correct contained view

public override async void ViewDidLoad ()
{
	base.ViewDidLoad ();

	this.CinemaSegments.Enabled = false;

	// page init code...

	var filmsDateVC = this.GetFilmsByDateViewController();

	this.CinemaSegments.ValueChanged += (sender, e) => 
	{
		var currentVC = this.GetCurrentFilmsViewController();
		var upcomingVC = this.GetUpcomingFilmsViewController();
		var cinemaVC = this.GetCinemaInfoViewController();

		this.HideContainerView(filmsDateVC);
		this.HideContainerView(currentVC);
		this.HideContainerView(upcomingVC);
		this.HideContainerView(cinemaVC);

		switch(this.CinemaSegments.SelectedSegment)
		{
		case 0:
			this.ShowContainerView(filmsDateVC);
			break;

		case 1:
			this.ShowContainerView(currentVC);
			break;

		case 2:
			this.ShowContainerView(upcomingVC);
			break;

		case 3:
			this.ShowContainerView(cinemaVC);
			break;
		}
	};

	this.CinemaSegments.Enabled = true;

	this.ShowContainerView (filmsDateVC);

}

I similarly simplified a few other views and job done.

Getting started with iOS dev using #Xamarin Part 2

In early days, iPhones sported a resolution of 320 x 480.. everything was rosy.. Eventually it grew taller by 88px when iPhone 5 came out.. since then for dev purposes the resolution sported by newer devices 5, 5s, 6, 6Plus sport 320×568 res with varying pixel densities.

iPhone 4s is still supported with iOS 8.x this means that developers need to continue supporting 320×480 res while filling the space (88px) for newer devices.

iOS supports 2 layout mechanism

  • Autosizing
  • Autolayout

With Autosizing think of the view as a canvas. You can draw other (sub)views by setting X, Y and Width & Height. If you only have a single subview, resizing subviews isn’t a problem and happens easily (table view, collection view, map view) as long as they expand to fill all available space. But what happens if you have a complex view ? Say a Label, Button, TableView and another Button at the very bottom !

If we used a designer to design the view in storyboard, the view would be rendered as shown below

Screen Shot 2015-04-22 at 11.07.01 iOS Simulator Screen Shot 22 Apr 2015 11.03.22  iOS Simulator Screen Shot 22 Apr 2015 11.03.51

The screenshots show the view in iOS Designer, app running on iPhone 4s and iPhone 5. Its clear that iPhone4s cropped the view as designer had layout set to iPhone5. Now many developers prefer designing the view in code and yes you could look at this.View.Bounds and then create all controls in code but i personally prefer to use designer.

To overcome this issue with Autosizing, Apple introduced Autolayout. Auto layout isn’t something that makes full sense until you battle it out. What one needs to do is define constraints that span across the width and height of the view. You can’t leave one bit otherwise the whole thing falls over.If you tap on a control twice on iOS designer, the design switches auto layout mode (pin-spacing) for the control. Lets have a look. As you can see, the Label control now shows 4 T shaped handles and 2 I shaped handles. You can drag the T shaped handles left, top, right and bottom and associate them with the view border and controls at the top and bottom.

Screen Shot 2015-04-22 at 11.15.15

The screenshots below show the constraints i have set. I modified the size of table to 333 (88 px) less than before and then i added a greater than or equal to constraint with a value 333. This ensure that it will fill the available space.

Screen Shot 2015-04-22 at 11.28.58 iOS Simulator Screen Shot 22 Apr 2015 11.26.01 iOS Simulator Screen Shot 22 Apr 2015 11.54.03

You can also add constraints programmatically and modify them programmatically but i haven’t had the need to go there yet.

For more info on how to use Autolayout and a better primer, have a look at http://developer.xamarin.com/guides/ios/user_interface/designer/designer_auto_layout/ 

Getting started with iOS dev using #Xamarin Part 1

.NET developers wishing to develop for iOS should look at Xamarin Studio. It offers an experience similar to that offered by Visual Studio from the comfort of OS X. If you are a Visual Studio fanatic, Xamarin offers a package with deep integration with Visual Studio that allows you to develop using Visual Studio on Windows (you still need a mac somewhere to be able to compile). Over the last month, I have primarily used Xamarin Studio on MacBook Pro. This is what it looks like on launch

Screen Shot 2015-04-01 at 10.19.21

Just like Visual Studio, Xamarin Studio offers many stock templates. Here is what iOS Unified API templates look like.

Screen Shot 2015-04-01 at 10.21.43

We will start with Single View Application targeting iPhone. Once we add a name, the template creates the project with required files.. main, AppDelegate, Storyboard and the ViewController. The arrow as shown in storyboard indicates the ViewController that is launched.

Screen Shot 2015-04-01 at 10.26.13

There is little you can do with a single View and for that reason let us add NavigationController and set the XiOSDemoViewController as the root view controller (the process is very visual and click oriented and Xamarin Studio makes it less so than Xcode)

Screen Shot 2015-04-01 at 10.37.00

Click and Drag (while holding Ctrl key) from Navigation Controller to the ViewController and set relationship as Root.As you can see we have set the App to delegate control to Navigation Controller which now has the XiOSViewController as the Root controller. Lets drop a few controls.. Navigation Item for Page Title, a label and a couple of buttons. A few things to remember is that if you want set anything during view lifecycle, the view controller provides a few handy methods that can be overridden. Screen Shot 2015-04-01 at 11.03.45 Let’s wire up button’s TouchUpInside Event. This is equivalent Click / Tap event in Windows world. We will wire it up in the view’s load event as shown below

int clickCount = 0;

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();

    // Perform any additional setup after loading the view, typically from a nib.
    this.btnClickMe.TouchUpInside += (sender, e) => 
    {
        clickCount++;
        this.lblClickMessage.Text = String.Format("You clicked {0} times", clickCount);
    };
}

Running the project in simulator and clicking the button increments the count and displays the message. Note that you did not have to associate the controls with ViewControllers.. that was done for you as you would have expected with Visual Studio. Xcode developers have to do lot of click drag from storyboard on to ViewControllers to make them available. This might seem trivial but it is very useful and a no-brainer from IDE perspective.

Screen Shot 2015-04-01 at 11.30.00

Finally lets add a button to the view and a view controller to storyboard. Another nice feature unlike Xcode is that when you set the class name for ViewController in storyboard, Xamarin Studio creates the class for you. You don’t need to create one.. similarly any controls you add are automatically available as i mentioned before. Screen Shot 2015-04-01 at 11.36.51 Screen Shot 2015-04-01 at 11.38.21 To navigate from one view to another, you can add a segue from button to view controller or you can do so in code. I have added a visual segue and chose action as push. Thats it.. now when you run the app navigation is in place.

Coding4Fun toolkit 2.1.0 released #WinRT #wpdev #windev

c4f

This is the 3rd iteration of toolkit updates I am pushing out. Like the other 2, this one builds on Windows Runtime WinRT app support for Windows Platform development.

This release also brings WinRT support close to what Silverlight version supported and finally drops support for Silverlight apps. The SL version is still available on nuget but it is unlikely to receive any updates.

SuperSlider (ColorSlider + ColorPicker) has a gotcha and its gonna need some clever work. Internally it uses code that monitors movement for updates and movements to prevent scrolling when the control is contained within Pivot, Hub or FlipView containers however lack of Touch class has forced me to use PointerPressed / PointerMoved and PointerReleased for these and in my tests, Pivot does not bubble those events and control doesn’t work correctly. Keep this in mind

Sample apps available in stores will be updated to reflect the changes

258x67_WP_Store_cyan WindowsStore

Control Windows Phone 8.1 Windows 8.1
RoundButton
ToggleButton
OpacityButton
Tile
ImageTile
ChatBubble
ChatBubbleTextBox
ColorHexPicker
ColorPicker
ColorSlider
AboutPrompt ×
InputPrompt ×
MessagePrompt ×
ToastPrompt ×
PasswordInputPrompt ×
MetroFlow
Overlay
SuperSlider
SuperImage

Happy coding

Coding4Fun v2.0.9 released #wpdev #windev #winrt

Coding4Fun toolkit v2.0.9 for Windows Platform dev has been released and packages are available for download from Nuget.

This update builds additional support for Windows Runtime on Windows Phone 8.1 and Windows 8.1. Controls added to this release include

  • MetroFlow control (Windows 8.1 and WP 8.1)
  • Prompts (Toast, User, Message, Input, PasswordInput) for WP 8.1
  • BrushToBrushConverter now allows use of parameter to set output Opacity.

AppBarPrompt requires additional work the port wasn’t successful first time around. For issues there’s codeplex.

Happy coding

Lumia 735 – the affordable windows phone

A month back I really needed a device with Windows Phone Navigation Bar.. talking to @Connects team, they asked if I’d like to do a comparison of say 735 vs 830. I used the device for over 2 weeks and it was great. Aside from the occasional yearning for the 830.

1Shot_20141113_090348 1Shot_20141113_090307 1Shot_20141113_090214 1Shot_20141113_090553

The device closely resembles the first Nokia Windows Phone 7 device – the Lumia 800. Its very light and the one I received was green. This device comes with wireless charging back cover as you can see and despite that its very light. When wireless charging, the circuit does not make noise unlike the 830 which was rather annoying

Like all 2nd gen devices, it takes nano sim and setup took the usual time and I was up and running. The 735 ships with Denim firmware

Lumia 73x specs

  • Snapdragon s400 same as 830
  • 1GB RAM
  • SD Expansion slot
  • Nano SIM
  • 4.7 inch 720p display with navigation bar
  • 6.7 MP rear and 5 MP front camera
  • Collapsible Navigation Bar instead of Back / Home / Search button
  • No Camera button

Spec wise 735 is nearly identical to 830 – the major difference is the camera.. The rear camera is 6.7 MP as opposed to 10MP for 830 however.. front camera is 5MP unlike 1.2 MP for 830

So this rightly comes with the best selfie camera in the entire Lumia range. The device like 830 stays nice and cool.. battery last the entire day.. no complains there.. I took many pictures with this device and occasionally I could see 6.7MP rear camera as a weak point oh. Lack of camera button meant that one hand photography was out of question. Here are some pictures taken using my 1Shot camera app. It does a decent job covering some foggy nights and walks around Cheshunt

1Shot_20141129_222134 1Shot_20141129_155355 1Shot_20141129_150726 1Shot_20141129_150713 1Shot_20141129_144520 1Shot_20141129_144028 1Shot_20141119_152802 1Shot_20141119_135147

I missed the hardware camera button. The capacitive buttons not being around was actually kinda nice.. seriously though put in a 10MP rear camera module and a physical camera button and its a winner.

Oh did I mention that its about £100 cheaper when you compare it to 830 ?

WinRT and application view wide Pointer event monitoring #wpdev #windev

It seems like every year I go through same technical difficulties. Last year I blogged about WinRT and pointer manipulation #win8dev #winrtdev

One of the underlying classes detects manipulation by user by means of Touch class. This class never made it to WinRT XAML and I have been messing around for a few days now… until something finally sunk in..

CoreWindow exposes following events

PointerEntered Occurs when a pointer moves into the bounding box of the Windows Store app.
PointerExited Occurs when the pointer moves outside the bounding box of the Windows Store app.
PointerMoved Occurs when a pointer moves within the bounding box of the Windows Store app.
PointerPressed Occurs when a mouse button is clicked, or a touch or pen contact is detected, within the bounding rectangle of the Windows Store app.
PointerReleased Occurs when a mouse button is released, or a touch or pen contact is lifted, within the bounding rectangle of the Windows Store app.

These events work exactly like Touch.TouchFrameReported and get bubbled up no matter which UIElement is tapped.

Time to continue porting