1// Copyright 2018 The Flutter Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#import "NativeViewController.h" 6 7@interface NativeViewController () 8 9@end 10 11@implementation NativeViewController { 12 int _counter; 13 UILabel* _incrementLabel; 14} 15 16- (instancetype)initWithDelegate:(id<NativeViewControllerDelegate>)delegate { 17 self = [super initWithNibName:nil bundle:nil]; 18 if (self) { 19 self.delegate = delegate; 20 } 21 return self; 22} 23 24- (instancetype)initWithCoder:(NSCoder *)aDecoder { 25 return [self initWithDelegate:nil]; 26} 27 28-(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 29 return [self initWithDelegate:nil]; 30} 31 32- (void)viewDidLoad { 33 [super viewDidLoad]; 34 35 self.title = @"Native iOS View"; 36 self.view.backgroundColor = UIColor.lightGrayColor; 37 self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] 38 initWithTitle:@"Back" 39 style:UIBarButtonItemStylePlain 40 target:nil 41 action:nil]; 42 43 _incrementLabel = [self addIncrementLabel]; 44 UIStackView* footer = [self addFooter]; 45 46 _incrementLabel.translatesAutoresizingMaskIntoConstraints = false; 47 footer.translatesAutoresizingMaskIntoConstraints = false; 48 UILayoutGuide* marginsGuide = self.view.layoutMarginsGuide; 49 NSMutableArray* array = [[NSMutableArray alloc] init]; 50 [array addObject:[_incrementLabel.centerXAnchor 51 constraintEqualToAnchor:self.view.centerXAnchor]]; 52 [array addObject:[_incrementLabel.centerYAnchor 53 constraintEqualToAnchor:self.view.centerYAnchor]]; 54 [array addObject:[footer.centerXAnchor 55 constraintEqualToAnchor:self.view.centerXAnchor]]; 56 [array addObject:[footer.widthAnchor 57 constraintEqualToAnchor:marginsGuide.widthAnchor]]; 58 [array addObject:[footer.bottomAnchor 59 constraintEqualToAnchor:marginsGuide.bottomAnchor]]; 60 61 [NSLayoutConstraint activateConstraints:array]; 62 [self updateIncrementLabel]; 63} 64 65/// Adds a label to the view that will contain the counter text. 66/// 67/// - Returns: The new label. 68-(UILabel*) addIncrementLabel { 69 UILabel* incrementLabel = [[UILabel alloc] init]; 70 incrementLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; 71 incrementLabel.textColor = UIColor.blackColor; 72 incrementLabel.accessibilityIdentifier = @"counter_on_iOS"; 73 [self.view addSubview:incrementLabel]; 74 return incrementLabel; 75} 76 77/// Adds a horizontal stack to the view, anchored to the bottom. 78/// 79/// - Returns: The new stack. 80-(UIStackView*) addFooter { 81 UILabel* mainLabel = [self createMainLabel]; 82 UIButton* incrementButton = [self createIncrementButton]; 83 UIStackView* stackView = [[UIStackView alloc] initWithFrame:self.view.frame]; 84 [stackView addArrangedSubview:mainLabel]; 85 [stackView addArrangedSubview:incrementButton]; 86 stackView.axis = UILayoutConstraintAxisHorizontal; 87 stackView.alignment = UIStackViewAlignmentBottom; 88 [self.view addSubview:stackView]; 89 return stackView; 90} 91 92/// Creates a label identifying this view. Does not add it to the view. 93/// 94/// - Returns: The new label. 95-(UILabel*) createMainLabel { 96 UILabel* mainLabel = [[UILabel alloc] init]; 97 mainLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleTitle1]; 98 mainLabel.textColor = UIColor.blackColor; 99 mainLabel.text = @"Native"; 100 return mainLabel; 101} 102 103/// Creates a button that will increment a counter. Does not add it to the view. 104/// 105/// - Returns: The new button. 106-(UIButton*) createIncrementButton { 107 UIButton *incrementButton = [UIButton buttonWithType:UIButtonTypeSystem]; 108 incrementButton.titleLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleTitle2]; 109 [incrementButton setTitle:@"Add" forState:UIControlStateNormal]; 110 incrementButton.accessibilityLabel = @"Increment via iOS"; 111 incrementButton.layer.cornerRadius = 15.0; 112 [incrementButton addTarget:self 113 action:@selector(handleIncrement:) 114 forControlEvents:UIControlEventTouchUpInside]; 115 return incrementButton; 116} 117 118// MARK: - Actions 119 120/// Action triggered from tapping on the increment button. Triggers a corresponding event in the 121/// delegate if one is available, otherwise increments our internal counter. 122-(void) handleIncrement:(UIButton*)sender { 123 if (self.delegate) { 124 [self.delegate didTapIncrementButton]; 125 } else { 126 [self didReceiveIncrement]; 127 } 128} 129 130/// Updates the increment label text to match the increment counter. 131-(void) updateIncrementLabel { 132 _incrementLabel.text = [NSString 133 stringWithFormat:@"%@ tapped %d %@.", 134 self.delegate == nil ? @"Button" : @"Flutter button", 135 _counter, _counter == 1 ? @"time" : @"times"]; 136} 137 138/// Increments our internal counter and updates the view. 139-(void) didReceiveIncrement { 140 _counter += 1; 141 [self updateIncrementLabel]; 142} 143 144@end 145