CustomIndoorViewController.m 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #if !defined(__has_feature) || !__has_feature(objc_arc)
  2. #error "This file requires ARC support."
  3. #endif
  4. #import "SDKDemos/Samples/CustomIndoorViewController.h"
  5. #import <GoogleMaps/GoogleMaps.h>
  6. @interface CustomIndoorViewController () <
  7. GMSIndoorDisplayDelegate,
  8. UIPickerViewDelegate,
  9. UIPickerViewDataSource>
  10. @end
  11. @implementation CustomIndoorViewController {
  12. GMSMapView *_mapView;
  13. UIPickerView *_levelPickerView;
  14. NSArray *_levels;
  15. }
  16. - (void)viewDidLoad {
  17. [super viewDidLoad];
  18. GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:37.78318
  19. longitude:-122.403874
  20. zoom:18];
  21. // set backgroundColor, otherwise UIPickerView fades into the background
  22. self.view.backgroundColor = [UIColor grayColor];
  23. _mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
  24. _mapView.settings.myLocationButton = NO;
  25. _mapView.settings.indoorPicker = NO; // We are implementing a custom level picker.
  26. _mapView.indoorEnabled = YES; // Defaults to YES. Set to NO to hide indoor maps.
  27. _mapView.indoorDisplay.delegate = self;
  28. _mapView.translatesAutoresizingMaskIntoConstraints = NO;
  29. [self.view addSubview:_mapView];
  30. // This UIPickerView will be populated with the levels of the active building.
  31. _levelPickerView = [[UIPickerView alloc] init];
  32. _levelPickerView.delegate = self;
  33. _levelPickerView.dataSource = self;
  34. _levelPickerView.showsSelectionIndicator = YES;
  35. _levelPickerView.translatesAutoresizingMaskIntoConstraints = NO;
  36. [self.view addSubview:_levelPickerView];
  37. // The height of the UIPickerView, used below in the vertical constraint
  38. NSDictionary *metrics = @{@"height": @180.0};
  39. NSDictionary *views = NSDictionaryOfVariableBindings(_mapView, _levelPickerView);
  40. // Constraining the map to the full width of the display.
  41. // The |_levelPickerView| is constrained below with the NSLayoutFormatAlignAll*
  42. // See http://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/Articles/formatLanguage.html
  43. [self.view addConstraints:[NSLayoutConstraint
  44. constraintsWithVisualFormat:@"|[_mapView]|"
  45. options:0
  46. metrics:metrics
  47. views:views]];
  48. // Constraining the _mapView and the _levelPickerView as siblings taking
  49. // the full height of the display, with _levelPickerView at 200 points high
  50. [self.view addConstraints:[NSLayoutConstraint
  51. constraintsWithVisualFormat:@"V:|[_mapView][_levelPickerView(height)]|"
  52. options:NSLayoutFormatAlignAllLeft|NSLayoutFormatAlignAllRight
  53. metrics:metrics
  54. views:views]];
  55. }
  56. #pragma mark - GMSIndoorDisplayDelegate
  57. - (void)didChangeActiveBuilding:(GMSIndoorBuilding *)building {
  58. // Everytime we change active building force the picker to re-display the labels.
  59. NSMutableArray *levels = [NSMutableArray array];
  60. if (building.underground) {
  61. // If this building is completely underground, add a fake 'top' floor. This must be the 'boxed'
  62. // nil, [NSNull null], as NSArray/NSMutableArray cannot contain nils.
  63. [levels addObject:[NSNull null]];
  64. }
  65. [levels addObjectsFromArray:building.levels];
  66. _levels = [levels copy];
  67. [_levelPickerView reloadAllComponents];
  68. [_levelPickerView selectRow:-1 inComponent:0 animated:NO];
  69. // UIPickerView insists on having some data; disable interaction if there's no levels.
  70. _levelPickerView.userInteractionEnabled = ([_levels count] > 0);
  71. }
  72. - (void)didChangeActiveLevel:(GMSIndoorLevel *)level {
  73. // On level change, sync our level picker's selection to the IndoorDisplay.
  74. if (level == nil) {
  75. level = (id)[NSNull null]; // box nil to NSNull for use in NSArray
  76. }
  77. NSUInteger index = [_levels indexOfObject:level];
  78. if (index != NSNotFound) {
  79. NSInteger currentlySelectedLevel = [_levelPickerView selectedRowInComponent:0];
  80. if ((NSInteger)index != currentlySelectedLevel) {
  81. [_levelPickerView selectRow:index inComponent:0 animated:NO];
  82. }
  83. }
  84. }
  85. #pragma mark - UIPickerViewDelegate
  86. - (void)pickerView:(UIPickerView *)pickerView
  87. didSelectRow:(NSInteger)row
  88. inComponent:(NSInteger)component {
  89. // On user selection of a level in the picker, set the right level in IndoorDisplay
  90. id level = _levels[row];
  91. if (level == [NSNull null]) {
  92. level = nil; // unbox NSNull
  93. }
  94. [_mapView.indoorDisplay setActiveLevel:level];
  95. }
  96. - (NSString *)pickerView:(UIPickerView *)pickerView
  97. titleForRow:(NSInteger)row
  98. forComponent:(NSInteger)component {
  99. id object = _levels[row];
  100. if (object == [NSNull null]) {
  101. return @"\u2014"; // use an em dash for 'above ground'
  102. }
  103. GMSIndoorLevel *level = object;
  104. return level.name;
  105. }
  106. #pragma mark - UIPickerViewDataSource
  107. - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
  108. return 1;
  109. }
  110. - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
  111. return [_levels count];
  112. }
  113. @end