Flip between two views

When we added a subview to a bigger view in Touch or Hit, the subview remained permanently inside the bigger view. We will now swap out the subview and replace it with a different subview while the app is running.

The big view contains an array of two little views, although only one of the little views is visible (i.e., currently added to the big view) at any given moment. The property index in class View is the index in the array of the curently visible little view. It is initialized to 0 and flips back and forth between 0 and 1.

When the big view detects a touch, it changes the currently visible subview by calling transitionFromView(_:toView:duration:options:completion:) and updates the index accordingly. The finger actually touches down inside a little view. But the little views have no touchesBegan(_:withEvent:) method, so the touchesBegan(_:withEvent:) of the big view is called instead. The view that is rotated is the superview of the first argument of transitionFromView(_:toView:duration:options:completion:). This view is completely covered by one of the little views.

Whenever we insert a LittleView (a subview) into the big View (the superview), we make sure that the LittleView has the same size as the View. We do this in the init and touchesBegan(_:withEvent) methods of class View. But there’s one complication. When init is called, the size of the superview is the dummy size 600 × 600. By the time the superview is displayed on the screen, the size of the superview has been changed to the size of the screen. When the size of the superview changes, we want the size of the subview (both the width and the height) to change with it. That’s the purpose of the autoresizingMask property of the LittleViews.

Source code in Flip.zip

Our classes LittleView0 and LittleView1 are very similar. But they don’t have to be. They could be totally different subclasses of UIView.

  1. Class AppDelegate
  2. Class ViewController
  3. Class View
  4. Class LittleView0: red.
  5. Class LittleView1: blue.

Things to try

  1. Verify that the background behind the doors stays black even if we insert the following statement immediately after the call to super.init in the init method of class View.
    		backgroundColor = UIColor.yellowColor();
    
    Then remove the above statement. To change the background to yellow, we must change the background of the superview of the big View, which is the window. Add the following statement to the application(_:didFinishLaunchingWithOptions:) method of the application delegate.
    		window!.backgroundColor = UIColor.yellowColor();
    

  2. In UIViewAnimationOptions.TransitionFlipFromLeft, the left edge of the old view moves to the right, and the right edge of the old view moves away from the user and to the left. Try one of the following in place of UIViewAnimationOptions.TransitionFlipFromLeft. Also see UIBarButtonSystemItem.PageCurl.
    1. UIViewAnimationOptions.TransitionFlipFromRight
    2. UIViewAnimationOptions.TransitionCurlUp
    3. UIViewAnimationOptions.TransitionCrossDissolve

  3. Our app doesn’t actually detect a swipe at all. It merely detects the start of a touch. When we learn how to detect a swipe here, come back to this app and distinguish between left, right, up, and down swipes. Then specify one of the options
    1. UIViewAnimationOptions.TransitionFlipFromLeft
    2. UIViewAnimationOptions.TransitionFlipFromRight
    3. UIViewAnimationOptions.TransitionCurlUp
    4. UIViewAnimationOptions.TransitionCurlDown

  4. Would it be clearer if we change
    		let newIndex: Int = 1 - index;	//toggle the index
    
    to the following?
    		//toggle the index
    		var newIndex: Int;
    		if index == 0 {
    			newIndex = 1;
    		} else {
    			newIndex = 0;
    		}
    

  5. Transition between three little views. Keep them in an array. Change
    		let newIndex: Int = 1 - index;	//toggle the index
    
    to whichever one of the following you feel is clearest. The % is the remainder operator.
    		//Advance to the next index.
    		let newIndex: Int = (index + 1) % littleViews.count;
    
    		//Advance to the next index.
    		var newIndex: Int = index + 1;
    		if newIndex == 3 {
    			newIndex = 0;
    		}
    
    		//Advance to the next index.
    		var newIndex: Int;
    		if index == 0 {
    			newIndex = 1;
    		} else if index == 1 {
    			newIndex = 2;
    		} else {
    			newIndex = 0;
    		}
    

  6. When we move from one little view to another, is the first little view removed from the big view or merely hidden somehow? Let’s print the number of elements in the big view’s array of subviews. Insert the following statement at the end of the init and touchesBegan(_:withEvent:) methods of the big View.
    		print("subviews.count = \(subviews.count)");