AutocompleteWithTextFieldController.m 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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/AutocompleteWithTextFieldController.h"
  16. #import <GooglePlaces/GooglePlaces.h>
  17. @interface AutocompleteWithTextFieldController () <UITextFieldDelegate,
  18. GMSAutocompleteTableDataSourceDelegate>
  19. @end
  20. @implementation AutocompleteWithTextFieldController {
  21. UITextField *_searchField;
  22. UITableViewController *_resultsController;
  23. GMSAutocompleteTableDataSource *_tableDataSource;
  24. }
  25. + (NSString *)demoTitle {
  26. return NSLocalizedString(
  27. @"Demo.Title.Autocomplete.UITextField",
  28. @"Title of the UITextField autocomplete demo for display in a list or nav header");
  29. }
  30. #pragma mark - View Lifecycle
  31. - (void)viewDidLoad {
  32. [super viewDidLoad];
  33. #if defined(__IPHONE_13_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0)
  34. if (@available(iOS 13.0, *)) {
  35. self.view.backgroundColor = [UIColor systemBackgroundColor];
  36. } else {
  37. }
  38. #else
  39. self.view.backgroundColor = [UIColor whiteColor];
  40. #endif // defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
  41. // Configure the text field to our linking.
  42. _searchField = [[UITextField alloc] initWithFrame:CGRectZero];
  43. _searchField.translatesAutoresizingMaskIntoConstraints = NO;
  44. _searchField.borderStyle = UITextBorderStyleNone;
  45. #if defined(__IPHONE_13_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0)
  46. if (@available(iOS 13.0, *)) {
  47. _searchField.backgroundColor = [UIColor systemBackgroundColor];
  48. } else {
  49. _searchField.backgroundColor = [UIColor whiteColor];
  50. }
  51. #else
  52. _searchField.backgroundColor = [UIColor whiteColor];
  53. #endif // defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
  54. _searchField.placeholder = NSLocalizedString(@"Demo.Content.Autocomplete.EnterTextPrompt",
  55. @"Prompt to enter text for autocomplete demo");
  56. _searchField.autocorrectionType = UITextAutocorrectionTypeNo;
  57. _searchField.keyboardType = UIKeyboardTypeDefault;
  58. _searchField.returnKeyType = UIReturnKeyDone;
  59. _searchField.clearButtonMode = UITextFieldViewModeWhileEditing;
  60. _searchField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
  61. [_searchField addTarget:self
  62. action:@selector(textFieldDidChange:)
  63. forControlEvents:UIControlEventEditingChanged];
  64. _searchField.delegate = self;
  65. // Setup the results view controller.
  66. _tableDataSource = [[GMSAutocompleteTableDataSource alloc] init];
  67. _tableDataSource.delegate = self;
  68. _tableDataSource.autocompleteFilter = self.autocompleteFilter;
  69. _tableDataSource.placeFields = self.placeFields;
  70. #if defined(__IPHONE_13_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0)
  71. if (@available(iOS 13.0, *)) {
  72. _tableDataSource.tableCellBackgroundColor = [UIColor systemBackgroundColor];
  73. } else {
  74. _tableDataSource.tableCellBackgroundColor = [UIColor whiteColor];
  75. }
  76. #else
  77. _tableDataSource.tableCellBackgroundColor = [UIColor whiteColor];
  78. #endif // defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
  79. _resultsController = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
  80. _resultsController.tableView.delegate = _tableDataSource;
  81. _resultsController.tableView.dataSource = _tableDataSource;
  82. [self.view addSubview:_searchField];
  83. // Use auto layout to place the text field, as we need to take the top layout guide into
  84. // consideration.
  85. [self.view
  86. addConstraints:[NSLayoutConstraint
  87. constraintsWithVisualFormat:@"H:|-[_searchField]-|"
  88. options:0
  89. metrics:nil
  90. views:NSDictionaryOfVariableBindings(_searchField)]];
  91. [NSLayoutConstraint constraintWithItem:_searchField
  92. attribute:NSLayoutAttributeTop
  93. relatedBy:NSLayoutRelationEqual
  94. toItem:self.topLayoutGuide
  95. attribute:NSLayoutAttributeBottom
  96. multiplier:1
  97. constant:8]
  98. .active = YES;
  99. }
  100. #pragma mark - GMSAutocompleteTableDataSourceDelegate
  101. - (void)tableDataSource:(GMSAutocompleteTableDataSource *)tableDataSource
  102. didAutocompleteWithPlace:(GMSPlace *)place {
  103. [self dismissResultsController];
  104. [_searchField resignFirstResponder];
  105. [_searchField setHidden:YES];
  106. [self autocompleteDidSelectPlace:place];
  107. }
  108. - (void)tableDataSource:(GMSAutocompleteTableDataSource *)tableDataSource
  109. didFailAutocompleteWithError:(NSError *)error {
  110. [self dismissResultsController];
  111. [_searchField resignFirstResponder];
  112. [self autocompleteDidFail:error];
  113. _searchField.text = @"";
  114. }
  115. - (void)didRequestAutocompletePredictionsForTableDataSource:
  116. (GMSAutocompleteTableDataSource *)tableDataSource {
  117. [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
  118. [_resultsController.tableView reloadData];
  119. }
  120. - (void)didUpdateAutocompletePredictionsForTableDataSource:
  121. (GMSAutocompleteTableDataSource *)tableDataSource {
  122. [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
  123. [_resultsController.tableView reloadData];
  124. }
  125. #pragma mark - UITextFieldDelegate
  126. - (void)textFieldDidBeginEditing:(UITextField *)textField {
  127. [self addChildViewController:_resultsController];
  128. // Add the results controller.
  129. _resultsController.view.translatesAutoresizingMaskIntoConstraints = NO;
  130. _resultsController.view.alpha = 0.0f;
  131. [self.view addSubview:_resultsController.view];
  132. // Layout it out below the text field using auto layout.
  133. [self.view addConstraints:[NSLayoutConstraint
  134. constraintsWithVisualFormat:@"V:[_searchField]-[resultView]-(0)-|"
  135. options:0
  136. metrics:nil
  137. views:@{
  138. @"_searchField" : _searchField,
  139. @"resultView" : _resultsController.view
  140. }]];
  141. [self.view
  142. addConstraints:[NSLayoutConstraint
  143. constraintsWithVisualFormat:@"H:|-(0)-[resultView]-(0)-|"
  144. options:0
  145. metrics:nil
  146. views:@{@"resultView" : _resultsController.view}]];
  147. // Force a layout pass otherwise the table will animate in weirdly.
  148. [self.view layoutIfNeeded];
  149. // Reload the data.
  150. [_resultsController.tableView reloadData];
  151. // Animate in the results.
  152. [UIView animateWithDuration:0.5
  153. animations:^{
  154. _resultsController.view.alpha = 1.0f;
  155. }
  156. completion:^(BOOL finished) {
  157. [_resultsController didMoveToParentViewController:self];
  158. }];
  159. }
  160. - (BOOL)textFieldShouldReturn:(UITextField *)textField {
  161. [textField resignFirstResponder];
  162. return NO;
  163. }
  164. - (BOOL)textFieldShouldClear:(UITextField *)textField {
  165. [self dismissResultsController];
  166. [textField resignFirstResponder];
  167. textField.text = @"";
  168. [_tableDataSource clearResults];
  169. return NO;
  170. }
  171. #pragma mark - Private Methods
  172. - (void)textFieldDidChange:(UITextField *)textField {
  173. [_tableDataSource sourceTextHasChanged:textField.text];
  174. }
  175. - (void)dismissResultsController {
  176. // Dismiss the results.
  177. [_resultsController willMoveToParentViewController:nil];
  178. [UIView animateWithDuration:0.5
  179. animations:^{
  180. _resultsController.view.alpha = 0.0f;
  181. }
  182. completion:^(BOOL finished) {
  183. [_resultsController.view removeFromSuperview];
  184. [_resultsController removeFromParentViewController];
  185. }];
  186. }
  187. @end