Windows Bridge for iOS: Customizing the Surface Dial Experience

Windows

Windows
In
Please, Log in or Register to view URLs content!
of the
Please, Log in or Register to view URLs content!
series, we created a simple to-do list app in Xcode and used the iOS bridge to bring it over to Windows 10. In
Please, Log in or Register to view URLs content!
of the series, we went on a tour of Visual Studio for iOS developers. In
Please, Log in or Register to view URLs content!
, we used the Windows Bridge for iOS to convert an iOS calculator app created using Storyboards and Auto Layout to a Universal Windows Platform app that adjusts to various form factors on Windows 10. In
Please, Log in or Register to view URLs content!
, we discussed how to mix and match UIKit with XAML controls in a bridged UWP app.

Today, we explain how to customize the Surface Dial Experience for bridged UWP apps using Objective-C projections.

Getting Started


For today’s tutorial, you will need:


If you don’t have a Windows 10 PC, you can download one of our pre-built evaluation virtual machines
Please, Log in or Register to view URLs content!
. Download the package for your preferred virtualization environment and you’ll be up and running in no time.

Understanding the Project Structure


With the radial control sample initial code downloaded and unzipped on your Mac development environment, open the Xcode project and briefly explore the application. The application consists of:

  • AppDelegate – contains the UIApplicationInitialStartupMode Category that ensures the app scales properly on Windows 10 for a variety of form factors.
  • ViewController – provides the view management infrastructure for the app’s user interface, which consists of a slider, a label that is updated with the value of the slider and a switch.

Build and run the application in the simulator and move the slider to make sure everything is properly set up.

Please, Log in or Register to view URLs content!


Using vsimporter


You are now ready to run the app through the vsimporter tool. To do so, you’ll need to copy your Xcode project files to your Windows Machine (or VM). With the files copied, follow the steps under the Using vsimporter section of
Please, Log in or Register to view URLs content!
of the blog series. Once you’re done, return to your radial control project directory, which should now contain a brand new Visual Studio solution file.

Open the Visual Studio solution by double-clicking on the RadialControlSample-WinStore10.sln file and build and run the application on your local machine by clicking on the Run button on the top menu. You’ll notice the same UI we saw running in the Xcode Simulator — you now have a native iOS app running on Windows. Try moving the slider and you’ll see its value label change.

Please, Log in or Register to view URLs content!


Please, Log in or Register to view URLs content!


Adding a New Menu Item to the Radial Controller Tool


You will now update this app to add a custom menu item to the radial controller tool that will respond to rotate and click actions by changing the slider value and toggling the switch.

To implement radial controller features in your app, you will need the public headers for the relevant UWP frameworks. In the bridge SDK you downloaded, go to the
Please, Log in or Register to view URLs content!
directory and take a look at what you find. Each header file represents a different namespace within the
Please, Log in or Register to view URLs content!
. For our purposes, you will need APIs from
Please, Log in or Register to view URLs content!
since the radial controller is an input device and all of its classes are contained in that namespace.

To include this framework – and make sure it’s only included when the code is being run on Windows – start by adding an #ifdef and the #import macros to the top of the view controller implementation file:



#import "ViewController.h"

#ifdef WINOBJC
#import <UWP/WindowsUIInput.h>
#endif



To interact with the radial controller, you will need to add a property to the view controller of your app that will allow you to access it. In C++, wheel input devices are represented by the
Please, Log in or Register to view URLs content!
class. However, as you build using Objective-C projections, you will notice that the standard naming scheme for these objects has been modified to match Objective-C conventions, where classes are prefixed with the letters that constitute their containing namespace:

  • Windows.UI.Input.RadialController becomes WUIRadialController

As a result, add a WUIRadialController property to the @interface section of the view controller implementation file:



@interface ViewController()

@property UILabel *demoTitle;
@property UILabel *demoInfo;
@property UISlider *slider;
@property UILabel *sliderLabel;
@property UISwitch *switchControl;

#ifdef WINOBJC
@property WUIRadialController* radialController;
#endif

@end



Next, you need to get a reference to the WUIRadialController object with the
Please, Log in or Register to view URLs content!
method as explained in the
Please, Log in or Register to view URLs content!
class documentation. Looking at the
Please, Log in or Register to view URLs content!
header you’ll find the equivalent Objective-C projection under the WUIRadialController class interface:



@interface WUIRadialController : RTObject
[...]
+ (WUIRadialController*)createForCurrentView;



Call this method at the end of the viewDidLoad method of the view controller file to instantiate the WUIRadialController property:



- (void)viewDidLoad {
[...]

#ifdef WINOBJC
// Create a reference to the radial controller
self.radialController = [WUIRadialController createForCurrentView];
#endif
}



Now you need to get a reference to the radial controller menu and its items. This is done via the
Please, Log in or Register to view URLs content!
property of the
Please, Log in or Register to view URLs content!
class that returns a
Please, Log in or Register to view URLs content!
object. Looking back at the
Please, Log in or Register to view URLs content!
header, you’ll find the equivalent Objective-C property under the WUIRadialController class interface that returns a WUIRadialControllerMenu object:



@interface WUIRadialController : RTObject
[...]
@property (readonly) WUIRadialControllerMenu* menu;



Call this property to get a reference to the radial controller menu:



- (void)viewDidLoad {
[...]

#ifdef WINOBJC
// Create a reference to the radial controller
self.radialController = [WUIRadialController createForCurrentView];

// Get the radial controller menu
WUIRadialControllerMenu* menu = self.radialController.menu;
#endif
}



The menu items are accessible via the
Please, Log in or Register to view URLs content!
property of the
Please, Log in or Register to view URLs content!
class. As before, the interface of the WUIRadialControllerMenu class in the
Please, Log in or Register to view URLs content!
header gives you the equivalent Objective-C property:



@interface WUIRadialControllerMenu : RTObject
[...]
@property (readonly) NSMutableArray* /* WUIRadialControllerMenuItem* */ items;



Call this property to get a reference to the menu items:



- (void)viewDidLoad {
[...]

// Get the radial controller menu
WUIRadialControllerMenu* menu = self.radialController.menu;

// Get the menu items
NSMutableArray* menuItems = menu.items;
#endif
}



Next, you need to create a new
Please, Log in or Register to view URLs content!
object to add to the menu with the projection of the
Please, Log in or Register to view URLs content!
class method:



@interface WUIRadialControllerMenuItem : RTObject
+ (WUIRadialControllerMenuItem*)createFromIcon:(NSString *)displayText icon:(WSSRandomAccessStreamReference*)icon;



Call this method to create the new menu item:



- (void)viewDidLoad {
[...]

// Get the menu items
NSMutableArray* menuItems = menu.items;

// Create a new menu item
// To use your own custom icon for the menu item, use the createFromIcon method instead
WUIRadialControllerMenuItem* newMenuItem = [WUIRadialControllerMenuItem createFromKnownIcon:mad:"Custom Tool" value:WUIRadialControllerMenuKnownIconRuler];
#endif
}



Note that we reused an existing icon for our tool from the
Please, Log in or Register to view URLs content!
enumeration, but you can create your own and use the
Please, Log in or Register to view URLs content!
method instead.

Finally, add your new menu item to the menu items array:



- (void)viewDidLoad {
[...]

// Create a new menu item
// To use your own custom icon for the menu item, use the createFromIcon method instead
WUIRadialControllerMenuItem* newMenuItem = [WUIRadialControllerMenuItem createFromKnownIcon:mad:"Custom Tool" value:WUIRadialControllerMenuKnownIconRuler];
#endif

// Add a new menu item
[menuItems addObject:newMenuItem];
}



That’s it! Now build and run your application and press and hold the Surface Dial to see the new menu item appear.

Please, Log in or Register to view URLs content!


Adding a Handler for Click Input


In this section, you will add a handler for click input that will toggle the application switch control if the radial controller is clicked when the new tool you added to the menu is selected. Taking a look at the
Please, Log in or Register to view URLs content!
header, you’ll see you need the addButtonClickedEvent: method:



@interface WUIRadialController : RTObject
[...]
- (EventRegistrationToken)addButtonClickedEvent:(void(^)(WUIRadialController*, WUIRadialControllerButtonClickedEventArgs



Since the callback relies on Objective-C blocks, you need to mark the self reference with the __block keyword before using it to access the switch to avoid creating a retain cycle. Add the following code at the end of the viewDidLoad method to do this:



- (void)viewDidLoad {
[...]

// Add a new menu item
[menuItems addObject:newMenuItem];

__weak ViewController* weakSelf = self; // Ensures self will not be retained
}



Now you can safely toggle the switch in the radial controller click callback:



- (void)viewDidLoad {
[...]

__weak ViewController* weakSelf = self; // Ensures self will not be retained

// Add a handler for click input from the radial controller
[self.radialController addButtonClickedEvent:^(WUIRadialController* controller, WUIRadialControllerButtonClickedEventArgs* args)
{
[weakSelf.switchControl setOn:!(weakSelf.switchControl.on) animated:YES];
}];
}



You can now build and run your application, select the new menu item, and click on the radial controller to see the switch toggle.

Adding a Handler for Rotation Input


In this section, you will add a handler for rotation input that will move the application slider control if the radial controller is rotated when the new tool you added to the menu is selected. Taking a look at the
Please, Log in or Register to view URLs content!
header, you’ll see that you need the addRotationChangedEvent: method:



@interface WUIRadialController : RTObject
[...]
- (EventRegistrationToken)addRotationChangedEvent:(void(^)(WUIRadialController*, WUIRadialControllerRotationChangedEventArgs



As for the click event handler, simply call the method and update the slider value in the callback block:



- (void)viewDidLoad {
[...]

__weak ViewController* weakSelf = self; // Ensures self will not be retained

[...]

// Add a handler for rotation input from the radial controller
[self.radialController addRotationChangedEvent:^(WUIRadialController* controller, WUIRadialControllerRotationChangedEventArgs* args)
{
[weakSelf.slider setValue:(weakSelf.slider.value + ([args rotationDeltaInDegrees]/360.0f)) animated:YES];
}];
}



That’s it! Now build and run your application, select the new menu item and rotate the radial controller to see the slider value change.

Wrapping Up


Thanks for following along! You can download the complete
Please, Log in or Register to view URLs content!
for the final project. Take a look at the following resources for more information:

  • For the latest release of the Windows Bridge for iOS, see the
    Please, Log in or Register to view URLs content!
  • For documentation and tutorials, visit the Windows Bridge for iOS
    Please, Log in or Register to view URLs content!
  • To evaluate the compatibility of your app with the bridge and evaluation virtual machines, go to the
    Please, Log in or Register to view URLs content!
  • For sample apps and code using the bridge, check the
    Please, Log in or Register to view URLs content!
  • For an overview of Windows wheel devices and UX and developer guidance, see
    Please, Log in or Register to view URLs content!
    on MSDN.
  • For developer documentation on the Windows input system and classes, go to the
    Please, Log in or Register to view URLs content!
    namespace documentation on MSDN.
  • To find the iOS bridge API, check the
    Please, Log in or Register to view URLs content!
    .

Also, be sure to check out the other posts in our series:


Please, Log in or Register to view URLs content!
 

Users who are viewing this thread

Top