CustomIndoorViewController.m 5.56 KB
Newer Older
Julio Hermosa committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
/*
 * Copyright 2016 Google LLC. All rights reserved.
 *
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
 * file except in compliance with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under
 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
 * ANY KIND, either express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

#import "GoogleMapsDemos/Samples/CustomIndoorViewController.h"

#import <GoogleMaps/GoogleMaps.h>

@interface CustomIndoorViewController () <
  GMSIndoorDisplayDelegate,
  UIPickerViewDelegate,
  UIPickerViewDataSource>

@end

@implementation CustomIndoorViewController {
  GMSMapView *_mapView;
  UIPickerView *_levelPickerView;
  NSArray *_levels;
}

- (void)viewDidLoad {
  [super viewDidLoad];
  GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:37.78318
                                                          longitude:-122.403874
                                                               zoom:18];

  // set backgroundColor, otherwise UIPickerView fades into the background
  self.view.backgroundColor = [UIColor grayColor];

  _mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
  _mapView.settings.myLocationButton = NO;
  _mapView.settings.indoorPicker = NO; // We are implementing a custom level picker.

  _mapView.indoorEnabled = YES; // Defaults to YES. Set to NO to hide indoor maps.
  _mapView.indoorDisplay.delegate = self;
  _mapView.translatesAutoresizingMaskIntoConstraints = NO;
  [self.view addSubview:_mapView];

  // This UIPickerView will be populated with the levels of the active building.
  _levelPickerView = [[UIPickerView alloc] init];
  _levelPickerView.delegate = self;
  _levelPickerView.dataSource = self;
  _levelPickerView.showsSelectionIndicator = YES;
  _levelPickerView.translatesAutoresizingMaskIntoConstraints = NO;
  [self.view addSubview:_levelPickerView];

  // The height of the UIPickerView, used below in the vertical constraint
  NSDictionary *metrics = @{@"height": @180.0};
  NSDictionary *views = NSDictionaryOfVariableBindings(_mapView, _levelPickerView);

  // Constraining the map to the full width of the display.
  // The |_levelPickerView| is constrained below with the NSLayoutFormatAlignAll*
  // See http://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/Articles/formatLanguage.html
  [self.view addConstraints:[NSLayoutConstraint
                             constraintsWithVisualFormat:@"|[_mapView]|"
                             options:0
                             metrics:metrics
                             views:views]];

  // Constraining the _mapView and the _levelPickerView as siblings taking
  // the full height of the display, with _levelPickerView at 200 points high
  [self.view addConstraints:[NSLayoutConstraint
                             constraintsWithVisualFormat:@"V:|[_mapView][_levelPickerView(height)]|"
                             options:NSLayoutFormatAlignAllLeft|NSLayoutFormatAlignAllRight
                             metrics:metrics
                             views:views]];
}

#pragma mark - GMSIndoorDisplayDelegate

- (void)didChangeActiveBuilding:(GMSIndoorBuilding *)building {
  // Everytime we change active building force the picker to re-display the labels.

  NSMutableArray *levels = [NSMutableArray array];
  if (building.underground) {
    // If this building is completely underground, add a fake 'top' floor. This must be the 'boxed'
    // nil, [NSNull null], as NSArray/NSMutableArray cannot contain nils.
    [levels addObject:[NSNull null]];
  }
  [levels addObjectsFromArray:building.levels];
  _levels = [levels copy];

  [_levelPickerView reloadAllComponents];
  [_levelPickerView selectRow:-1 inComponent:0 animated:NO];

  // UIPickerView insists on having some data; disable interaction if there's no levels.
  _levelPickerView.userInteractionEnabled = (_levels.count > 0);
}

- (void)didChangeActiveLevel:(GMSIndoorLevel *)level {
  // On level change, sync our level picker's selection to the IndoorDisplay.
  if (level == nil) {
    level = (id)[NSNull null];  // box nil to NSNull for use in NSArray
  }
  NSUInteger index = [_levels indexOfObject:level];
  if (index != NSNotFound) {
    NSInteger currentlySelectedLevel = [_levelPickerView selectedRowInComponent:0];
    if ((NSInteger)index != currentlySelectedLevel) {
      [_levelPickerView selectRow:index inComponent:0 animated:NO];
    }
  }
}

#pragma mark - UIPickerViewDelegate

- (void)pickerView:(UIPickerView *)pickerView
      didSelectRow:(NSInteger)row
       inComponent:(NSInteger)component {
  // On user selection of a level in the picker, set the right level in IndoorDisplay
  id level = _levels[row];
  if (level == [NSNull null]) {
    level = nil;  // unbox NSNull
  }
  [_mapView.indoorDisplay setActiveLevel:level];
}

- (NSString *)pickerView:(UIPickerView *)pickerView
             titleForRow:(NSInteger)row
            forComponent:(NSInteger)component {
  id object = _levels[row];
  if (object == [NSNull null]) {
    return @"\u2014";  // use an em dash for 'above ground'
  }
  GMSIndoorLevel *level = object;
  return level.name;
}

#pragma mark - UIPickerViewDataSource

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
  return 1;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
  return _levels.count;
}

@end