AutocompleteBaseViewController.m 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /*
  2. * Copyright 2016 Google LLC. All rights reserved.
  3. *
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
  6. * file except in compliance with the License. You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software distributed under
  11. * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
  12. * ANY KIND, either express or implied. See the License for the specific language governing
  13. * permissions and limitations under the License.
  14. */
  15. #import "GooglePlacesDemos/Samples/Autocomplete/AutocompleteBaseViewController.h"
  16. #import "GooglePlacesDemos/Samples/PagingPhotoView.h"
  17. @implementation AutocompleteBaseViewController {
  18. PagingPhotoView *_photoView;
  19. UIButton *_photoButton;
  20. UITextView *_textView;
  21. }
  22. - (void)viewDidLoad {
  23. [super viewDidLoad];
  24. // Configure a background color.
  25. #if defined(__IPHONE_13_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0)
  26. if (@available(iOS 13.0, *)) {
  27. self.view.backgroundColor = [UIColor systemBackgroundColor];
  28. } else {
  29. self.view.backgroundColor = [UIColor whiteColor];
  30. }
  31. #else
  32. self.view.backgroundColor = [UIColor whiteColor];
  33. #endif // defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
  34. // Configure the UI. Tell our superclass we want a button and a result view below that.
  35. _photoButton =
  36. [self createButton:@selector(showPhotosButtonTapped)
  37. title:NSLocalizedString(@"Demo.Title.Photos", @"Button title for 'Photos'")];
  38. // Create a text view.
  39. _textView = [[UITextView alloc] init];
  40. _textView.editable = NO;
  41. _textView.translatesAutoresizingMaskIntoConstraints = NO;
  42. [self addResultTextView];
  43. // Configure the photo view where we are going to display the loaded photos.
  44. _photoView = [[PagingPhotoView alloc] initWithFrame:self.view.bounds];
  45. _photoView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  46. [self.view addSubview:_photoView];
  47. // Reset the various views to their initial states.
  48. [self resetViews];
  49. }
  50. - (UIButton *)createShowAutocompleteButton:(SEL)selector {
  51. return [self createButton:selector
  52. title:NSLocalizedString(@"Demo.Content.Autocomplete.ShowWidgetButton",
  53. @"Button title for 'show autocomplete widget'")];
  54. }
  55. - (NSString *)openStatusTextFromPlace:(GMSPlace *)place {
  56. GMSPlaceOpenStatus openStatus = [place isOpen];
  57. switch (openStatus) {
  58. case GMSPlaceOpenStatusOpen:
  59. return @"Open";
  60. case GMSPlaceOpenStatusClosed:
  61. return @"Closed";
  62. case GMSPlaceOpenStatusUnknown:
  63. return @"Unknown";
  64. }
  65. }
  66. - (void)autocompleteDidSelectPlace:(GMSPlace *)place {
  67. NSMutableAttributedString *text =
  68. [[NSMutableAttributedString alloc] initWithString:[place description]];
  69. [text appendAttributedString:[[NSAttributedString alloc] initWithString:@"\nPlace status: "]];
  70. NSString *openStatusText = [self openStatusTextFromPlace:place];
  71. [text appendAttributedString:[[NSAttributedString alloc] initWithString:openStatusText]];
  72. NSAttributedString *attributions = place.attributions;
  73. if (attributions) {
  74. NSAttributedString *doubleReturn = [[NSAttributedString alloc] initWithString:@"\n\n"];
  75. [text appendAttributedString:doubleReturn];
  76. [text appendAttributedString:attributions];
  77. }
  78. #if defined(__IPHONE_13_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0)
  79. if (@available(iOS 13.0, *)) {
  80. [text addAttribute:NSForegroundColorAttributeName
  81. value:[UIColor labelColor]
  82. range:NSMakeRange(0, text.length)];
  83. }
  84. #endif
  85. _textView.attributedText = text;
  86. [_textView setIsAccessibilityElement:YES];
  87. [_textView setHidden:NO];
  88. // Show the photo button be start disabled until the photos have loaded.
  89. [_photoButton setIsAccessibilityElement:YES];
  90. [_photoButton setHidden:NO];
  91. [_photoButton setEnabled:NO];
  92. if (place.photos.count > 0) {
  93. [self preloadPhotoList:place.photos];
  94. }
  95. }
  96. - (void)autocompleteDidFail:(NSError *)error {
  97. NSString *formatString =
  98. NSLocalizedString(@"Demo.Content.Autocomplete.FailedErrorMessage",
  99. @"Format string for 'autocomplete failed with error' message");
  100. _textView.text = [NSString stringWithFormat:formatString, error];
  101. }
  102. - (void)autocompleteDidCancel {
  103. _textView.text = NSLocalizedString(@"Demo.Content.Autocomplete.WasCanceledMessage",
  104. @"String for 'autocomplete canceled message'");
  105. }
  106. - (void)showCustomMessageInResultPane:(NSString *)message {
  107. _textView.text = message;
  108. }
  109. - (void)resetViews {
  110. _photoView.photoList = @[];
  111. [_textView setText:@""];
  112. [_textView setIsAccessibilityElement:NO];
  113. [_textView setHidden:NO];
  114. [_photoButton setIsAccessibilityElement:NO];
  115. [_photoButton setHidden:YES];
  116. [_photoView setHidden:YES];
  117. }
  118. #pragma mark - Private
  119. - (void)addResultTextView {
  120. NSAssert(_textView.superview == nil, @"%s should not be called twice", sel_getName(_cmd));
  121. [self.view addSubview:_textView];
  122. // Check to see if we can use readableContentGuide from iOS 9+
  123. if ([self.view respondsToSelector:@selector(readableContentGuide)]) {
  124. // Position it horizontally so it fills the readableContentGuide. Use the new anchor-based
  125. // system because we know this code will only run on iOS 9+.
  126. [self.view.readableContentGuide.leadingAnchor constraintEqualToAnchor:_textView.leadingAnchor]
  127. .active = YES;
  128. [self.view.readableContentGuide.trailingAnchor constraintEqualToAnchor:_textView.trailingAnchor]
  129. .active = YES;
  130. // Set the textContainerInset to 0 because the readableContentGuide is already handling the
  131. // inset.
  132. _textView.textContainerInset = UIEdgeInsetsZero;
  133. } else {
  134. // Position it horizontally so it fills the parent.
  135. [self.view
  136. addConstraints:[NSLayoutConstraint
  137. constraintsWithVisualFormat:@"H:|-(0)-[_textView]-(0)-|"
  138. options:0
  139. metrics:nil
  140. views:NSDictionaryOfVariableBindings(_textView)]];
  141. }
  142. // If we have a view place it below that.
  143. [self.view addConstraints:[NSLayoutConstraint
  144. constraintsWithVisualFormat:@"V:[_photoButton]-[_textView]-(0)-|"
  145. options:0
  146. metrics:nil
  147. views:NSDictionaryOfVariableBindings(
  148. _photoButton, _textView)]];
  149. }
  150. - (UIButton *)createButton:(SEL)selector title:(NSString *)title {
  151. // Create a button to show the autocomplete widget.
  152. UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
  153. [button setTitle:title forState:UIControlStateNormal];
  154. // Set the text color to adapt to light and dark mode on iOS 13+ devices
  155. // Otherwise, set the text color to black
  156. #if defined(__IPHONE_13_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0)
  157. if (@available(iOS 13.0, *)) {
  158. [button setTitleColor:[UIColor labelColor] forState:UIControlStateNormal];
  159. } else {
  160. [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  161. }
  162. #else
  163. self.view.backgroundColor = [UIColor whiteColor];
  164. #endif // defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
  165. [button addTarget:self action:selector forControlEvents:UIControlEventTouchUpInside];
  166. button.translatesAutoresizingMaskIntoConstraints = NO;
  167. [self.view addSubview:button];
  168. // Position the button from the top of the view.
  169. [button.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor].active = YES;
  170. [button.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:kButtonTopMargin].active =
  171. YES;
  172. [button.heightAnchor constraintEqualToConstant:kButtonHeight].active = YES;
  173. [button.widthAnchor constraintEqualToConstant:kButtonWidth].active = YES;
  174. return button;
  175. }
  176. - (void)showPhotosButtonTapped {
  177. [_textView setIsAccessibilityElement:NO];
  178. [_textView setHidden:YES];
  179. [_photoButton setIsAccessibilityElement:NO];
  180. [_photoButton setHidden:YES];
  181. [_photoView setHidden:NO];
  182. }
  183. // Preload the photos to be displayed.
  184. - (void)preloadPhotoList:(NSArray<GMSPlacePhotoMetadata *> *)photos {
  185. __block NSMutableArray *attributedPhotos = [NSMutableArray array];
  186. __block NSInteger photoRequestsInFlight = photos.count;
  187. for (GMSPlacePhotoMetadata *photo in photos) {
  188. [[GMSPlacesClient sharedClient] loadPlacePhoto:photo
  189. callback:^(UIImage *photoImage, NSError *error) {
  190. photoRequestsInFlight--;
  191. if (photoImage == nil) {
  192. NSLog(@"Photo request failed with error: %@", error);
  193. } else {
  194. AttributedPhoto *attributedPhoto =
  195. [[AttributedPhoto alloc] init];
  196. attributedPhoto.image = photoImage;
  197. attributedPhoto.attributions = photo.attributions;
  198. [attributedPhotos addObject:attributedPhoto];
  199. }
  200. if (photoRequestsInFlight == 0) {
  201. _photoView.photoList = attributedPhotos;
  202. [_photoButton setEnabled:YES];
  203. }
  204. }];
  205. }
  206. }
  207. @end