1236 lines
52 KiB
Objective-C
1236 lines
52 KiB
Objective-C
/*
|
|
Copyright (c) 2019, Apple Inc. All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without modification,
|
|
are permitted provided that the following conditions are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright notice, this
|
|
list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
this list of conditions and the following disclaimer in the documentation and/or
|
|
other materials provided with the distribution.
|
|
|
|
3. Neither the name of the copyright holder(s) nor the names of any contributors
|
|
may be used to endorse or promote products derived from this software without
|
|
specific prior written permission. No license is granted to the trademarks of
|
|
the copyright holders even if such marks are included in this software.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
|
|
#import "ORKStepContentView_Private.h"
|
|
#import "ORKTitleLabel.h"
|
|
#import "ORKBodyLabel.h"
|
|
#import "ORKBodyItem.h"
|
|
#import "ORKCompletionCheckmarkView.h"
|
|
#import "ORKBodyContainerView.h"
|
|
#import "ORKSkin.h"
|
|
#import "UIImageView+ResearchKit.h"
|
|
|
|
/*
|
|
+_________________________+
|
|
| |<-------------_stepContentView
|
|
| +-------+ |
|
|
| | _icon | |
|
|
| | | |
|
|
| +-------+ |
|
|
| |
|
|
| +---------------------+ |
|
|
| | _titleLabel | |
|
|
| |_____________________| |
|
|
| |
|
|
| +---------------------+ |
|
|
| | _textLabel | |
|
|
| |_____________________| |
|
|
| |
|
|
| +---------------------+ |
|
|
| | _detailTextLabel | |
|
|
| |_____________________| |
|
|
| |
|
|
| +---------------------+ |
|
|
| | |<-------------_bodyContainerView: UIstackView
|
|
| | +-----------------+ | |
|
|
| | | | | |
|
|
| | |--Title | | |
|
|
| | |--Text |<-------------- BodyItemStyleText
|
|
| | |--LearnMore | | |
|
|
| | |_________________| | |
|
|
| | | |
|
|
| | +---+-------------+ | |
|
|
| | | |--Title | | |
|
|
| | | o |--Text |<-------------- BodyItemStyleBullet
|
|
| | | |--LearnMore | | |
|
|
| | |___|_____________| | |
|
|
| |_____________________| |
|
|
| |
|
|
| +---------------------+ |
|
|
| | _centeredVertically-| |
|
|
| | ImageView | |
|
|
| |_____________________| |
|
|
|_________________________|
|
|
*/
|
|
|
|
static const CGFloat ORKStepContentIconImageViewToTitleLabelPadding = 15.0;
|
|
static const CGFloat ORKStepContentIconToBodyTopPaddingStandard = 20.0;
|
|
static const CGFloat ORKStepContentIconToBulletTopPaddingStandard = 20.0;
|
|
static const CGFloat ORKStepContentTagPaddingTop = 15.0;
|
|
static const CGFloat ORKStepContentBottomPadding = 35.0;
|
|
|
|
NSString * const ORKStepBodyContainerViewAccessibilityIdentifier = @"ORKStepBodyContainerView";
|
|
|
|
typedef NS_CLOSED_ENUM(NSInteger, ORKUpdateConstraintSequence) {
|
|
ORKUpdateConstraintSequenceTopContentImageView = 0,
|
|
ORKUpdateConstraintSequenceIconImageView,
|
|
ORKUpdateConstraintSequenceTitleLabel,
|
|
ORKUpdateConstraintSequenceTextLabel,
|
|
ORKUpdateConstraintSequenceDetailTextLabel,
|
|
ORKUpdateConstraintSequenceBodyContainerView,
|
|
ORKUpdateConstraintSequenceCenteredVerticallyImageView
|
|
} ORK_ENUM_AVAILABLE;
|
|
|
|
|
|
@interface ORKStepContentView()<ORKBodyContainerViewDelegate>
|
|
|
|
@end
|
|
|
|
|
|
@implementation ORKStepContentView {
|
|
CGFloat _additionalTopPaddingForTopLabel;
|
|
CGFloat _leftRightPadding;
|
|
NSMutableArray<NSLayoutConstraint *> *_updatedConstraints;
|
|
|
|
NSArray<NSLayoutConstraint *> *_topContentImageViewConstraints;
|
|
NSArray<NSLayoutConstraint *> *_iconImageViewConstraints;
|
|
NSArray<NSLayoutConstraint *> *_textLabelConstraints;
|
|
NSArray<NSLayoutConstraint *> *_detailTextLabelConstraints;
|
|
NSArray<NSLayoutConstraint *> *_centeredVerticallyImageViewContraints;
|
|
NSMutableArray<NSLayoutConstraint *> *_leftRightPaddingConstraints;
|
|
|
|
NSLayoutConstraint *_iconImageViewTopConstraint;
|
|
NSLayoutConstraint *_titleLabelTopConstraint;
|
|
NSLayoutConstraint *_textLabelTopConstraint;
|
|
NSLayoutConstraint *_detailTextLabelTopConstraint;
|
|
NSLayoutConstraint *_bodyContainerViewTopConstraint;
|
|
NSLayoutConstraint *_centeredVerticallyImageViewTopConstraint;
|
|
NSArray<NSLayoutConstraint *> *_bodyContainerLeftRightConstraints;
|
|
NSLayoutConstraint *_stepContentBottomConstraint;
|
|
ORKCompletionCheckmarkView *_completionCheckmarkView;
|
|
BOOL useStandardTextAndFormPadding;
|
|
}
|
|
|
|
- (instancetype)init {
|
|
self = [super init];
|
|
if (self) {
|
|
[self setupContentView];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (instancetype)initWithStandardPadding {
|
|
self = [super init];
|
|
if (self) {
|
|
useStandardTextAndFormPadding = true;
|
|
[self setupContentView];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)setupContentView {
|
|
[self setupUpdatedConstraints];
|
|
[self setStepContentViewBottomConstraint];
|
|
_leftRightPadding = ORKStepContainerLeftRightPaddingForWindow(self.window);
|
|
}
|
|
|
|
// top content image
|
|
|
|
- (void)setStepTopContentImage:(UIImage *)stepTopContentImage {
|
|
_stepTopContentImage = stepTopContentImage;
|
|
|
|
// 1.) nil Image; updateConstraints
|
|
if (!stepTopContentImage && _topContentImageView) {
|
|
[_topContentImageView removeFromSuperview];
|
|
_topContentImageView = nil;
|
|
[self deactivateTopContentImageViewConstraints];
|
|
[self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceTopContentImageView];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
|
|
// 2.) First Image; updateConstraints
|
|
if (stepTopContentImage && !_topContentImageView) {
|
|
[self setupTopContentImageView];
|
|
_topContentImageView.image = [self topContentAndAuxiliaryImage];
|
|
[self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceTopContentImageView];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
|
|
// 3.) >= second Image;
|
|
if (stepTopContentImage && _topContentImageView) {
|
|
_topContentImageView.image = [self topContentAndAuxiliaryImage];
|
|
}
|
|
|
|
[self updateViewColors];
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:ORKStepTopContentImageChangedKey object:nil];
|
|
}
|
|
|
|
- (void)setShouldAutomaticallyAdjustImageTintColor:(BOOL)shouldAutomaticallyAdjustImageTintColor {
|
|
_shouldAutomaticallyAdjustImageTintColor = shouldAutomaticallyAdjustImageTintColor;
|
|
[self updateViewColors];
|
|
}
|
|
|
|
- (void)updateViewColors {
|
|
if (!_shouldAutomaticallyAdjustImageTintColor) {
|
|
return;
|
|
}
|
|
|
|
// this requires the image to be set to the UIImageRenderingModeAlwaysTemplate rendering mode
|
|
// in the UIImageRenderingModeAlwaysOriginal rendering mode, tintColor does not apply
|
|
[_topContentImageView updateRenderingModeForUserInterfaceStyle:self.traitCollection.userInterfaceStyle];
|
|
[_iconImageView updateRenderingModeForUserInterfaceStyle:self.traitCollection.userInterfaceStyle];
|
|
|
|
UIColor *imageViewTintColor = self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ? [UIColor whiteColor] : nil;
|
|
_topContentImageView.tintColor = imageViewTintColor;
|
|
_iconImageView.tintColor = imageViewTintColor;
|
|
|
|
}
|
|
|
|
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
|
|
[super traitCollectionDidChange:previousTraitCollection];
|
|
[self updateViewColors];
|
|
}
|
|
|
|
- (void)setAuxiliaryImage:(UIImage *)auxiliaryImage {
|
|
_auxiliaryImage = auxiliaryImage;
|
|
if (_stepTopContentImage) {
|
|
_topContentImageView.image = [self topContentAndAuxiliaryImage];
|
|
}
|
|
}
|
|
|
|
- (UIImage *)topContentAndAuxiliaryImage {
|
|
if (!_auxiliaryImage) {
|
|
return _stepTopContentImage;
|
|
}
|
|
CGSize size = _auxiliaryImage.size;
|
|
UIGraphicsBeginImageContext(size);
|
|
|
|
CGRect rect = CGRectMake(0.0, 0.0, size.width, size.height);
|
|
|
|
[_auxiliaryImage drawInRect:rect];
|
|
[_stepTopContentImage drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0];
|
|
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
|
UIGraphicsEndImageContext();
|
|
|
|
return image;
|
|
}
|
|
|
|
- (void)setupTopContentImageView {
|
|
if (!_topContentImageView) {
|
|
_topContentImageView = [UIImageView new];
|
|
}
|
|
_topContentImageView.contentMode = UIViewContentModeScaleAspectFit;
|
|
[_topContentImageView setBackgroundColor:ORKColor(ORKTopContentImageViewBackgroundColorKey)];
|
|
[_topContentImageView setClipsToBounds:YES];
|
|
[self addSubview:_topContentImageView];
|
|
[self setTopContentImageViewConstraints];
|
|
}
|
|
|
|
- (void)setTopContentImageViewConstraints {
|
|
_topContentImageView.translatesAutoresizingMaskIntoConstraints = NO;
|
|
_topContentImageViewConstraints = @[
|
|
[NSLayoutConstraint constraintWithItem:_topContentImageView
|
|
attribute:NSLayoutAttributeTop
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:self
|
|
attribute:NSLayoutAttributeTop
|
|
multiplier:1.0
|
|
constant:0.0],
|
|
[NSLayoutConstraint constraintWithItem:_topContentImageView
|
|
attribute:NSLayoutAttributeLeft
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:self
|
|
attribute:NSLayoutAttributeLeft
|
|
multiplier:1.0
|
|
constant:0.0],
|
|
[NSLayoutConstraint constraintWithItem:_topContentImageView
|
|
attribute:NSLayoutAttributeRight
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:self
|
|
attribute:NSLayoutAttributeRight
|
|
multiplier:1.0
|
|
constant:0.0],
|
|
[NSLayoutConstraint constraintWithItem:_topContentImageView
|
|
attribute:NSLayoutAttributeHeight
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:nil
|
|
attribute:NSLayoutAttributeNotAnAttribute
|
|
multiplier:1.0
|
|
constant:ORKStepContainerTopContentHeightForWindow(self.window)]
|
|
];
|
|
[_updatedConstraints addObjectsFromArray:_topContentImageViewConstraints];
|
|
}
|
|
|
|
- (void)deactivateTopContentImageViewConstraints {
|
|
[self deactivateConstraints:_topContentImageViewConstraints];
|
|
_topContentImageViewConstraints = nil;
|
|
}
|
|
|
|
|
|
// icon image
|
|
|
|
- (void)setTitleIconImage:(UIImage *)titleIconImage {
|
|
_titleIconImage = titleIconImage;
|
|
|
|
if (!titleIconImage && _iconImageView) {
|
|
[_iconImageView removeFromSuperview];
|
|
_iconImageView = nil;
|
|
[self deactivateIconImageViewConstraints];
|
|
[self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceIconImageView];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
if (titleIconImage && !_iconImageView) {
|
|
[self setupIconImageView];
|
|
_iconImageView.image = titleIconImage;
|
|
[self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceIconImageView];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
if (titleIconImage && _iconImageView) {
|
|
_iconImageView.image = titleIconImage;
|
|
}
|
|
}
|
|
|
|
- (void)updateTitleLabelTopConstraint {
|
|
if (_titleLabelTopConstraint && _titleLabelTopConstraint.isActive) {
|
|
[NSLayoutConstraint deactivateConstraints:@[_titleLabelTopConstraint]];
|
|
}
|
|
if ([_updatedConstraints containsObject:_titleLabelTopConstraint]) {
|
|
[_updatedConstraints removeObject:_titleLabelTopConstraint];
|
|
}
|
|
[self setTitleLabelTopConstraint];
|
|
if (_titleLabelTopConstraint) {
|
|
[_updatedConstraints addObject:_titleLabelTopConstraint];
|
|
}
|
|
}
|
|
|
|
- (void)setupIconImageView {
|
|
if (!_iconImageView) {
|
|
_iconImageView = [UIImageView new];
|
|
}
|
|
_iconImageView.contentMode = UIViewContentModeScaleAspectFit;
|
|
|
|
[self addSubview:_iconImageView];
|
|
[self updateViewColors];
|
|
[self setIconImageViewConstraints];
|
|
}
|
|
|
|
- (void)setIconImageViewTopConstraint {
|
|
if (_iconImageView) {
|
|
_iconImageViewTopConstraint = [NSLayoutConstraint constraintWithItem:_iconImageView
|
|
attribute:NSLayoutAttributeTop
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_topContentImageView ? : self
|
|
attribute:_topContentImageView ? NSLayoutAttributeBottom : NSLayoutAttributeTop
|
|
multiplier:1.0
|
|
constant:ORKStepContentIconImageViewToTitleLabelPadding]; // This needs to match what the text padding is
|
|
}
|
|
}
|
|
|
|
- (void)updateIconImageViewTopConstraint {
|
|
if (_iconImageViewTopConstraint) {
|
|
[self deactivateConstraints:@[_iconImageViewTopConstraint]];
|
|
}
|
|
[self setIconImageViewTopConstraint];
|
|
if (_iconImageViewTopConstraint) {
|
|
[_updatedConstraints addObject:_iconImageViewTopConstraint];
|
|
}
|
|
}
|
|
|
|
- (void)setIconImageViewConstraints {
|
|
_iconImageView.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self setIconImageViewTopConstraint];
|
|
|
|
_iconImageViewConstraints = @[
|
|
_iconImageViewTopConstraint,
|
|
[NSLayoutConstraint constraintWithItem:_iconImageView
|
|
attribute:NSLayoutAttributeWidth
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:nil
|
|
attribute:NSLayoutAttributeNotAnAttribute
|
|
multiplier:1.0
|
|
constant:ORKStepContentIconImageViewDimension],
|
|
[NSLayoutConstraint constraintWithItem:_iconImageView
|
|
attribute:NSLayoutAttributeHeight
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:nil
|
|
attribute:NSLayoutAttributeNotAnAttribute
|
|
multiplier:1.0
|
|
constant:ORKStepContentIconImageViewDimension]];
|
|
[_updatedConstraints addObjectsFromArray:_iconImageViewConstraints];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
|
|
- (void)deactivateIconImageViewConstraints {
|
|
[self deactivateConstraints:_iconImageViewConstraints];
|
|
_iconImageViewConstraints = nil;
|
|
}
|
|
|
|
// step title
|
|
|
|
- (void)setStepTitle:(NSString *)stepTitle {
|
|
_stepTitle = stepTitle;
|
|
if (!_titleLabel) {
|
|
[self setupTitleLabel];
|
|
[self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceTitleLabel];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
|
|
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
|
|
[paragraphStyle setHyphenationFactor:0.5];
|
|
[paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping];
|
|
|
|
if (@available(iOS 14.0, *)) {
|
|
[paragraphStyle setLineBreakStrategy:NSLineBreakStrategyPushOut];
|
|
}
|
|
|
|
NSDictionary *hyphenAttribute = @{NSParagraphStyleAttributeName : paragraphStyle};
|
|
|
|
NSAttributedString *attributedStepTitle = [[NSAttributedString alloc] initWithString:stepTitle ?: @"" attributes:hyphenAttribute];
|
|
[_titleLabel setAttributedText:attributedStepTitle];
|
|
}
|
|
|
|
- (void)setupTitleLabel {
|
|
if (!_titleLabel) {
|
|
_titleLabel = [ORKTitleLabel new];
|
|
}
|
|
_titleLabel.numberOfLines = 0;
|
|
_titleLabel.textAlignment = _stepHeaderTextAlignment;
|
|
_titleLabel.accessibilityIdentifier = @"ORKStepContentView_titleLabel";
|
|
[self addSubview:_titleLabel];
|
|
[self setupTitleLabelConstraints];
|
|
[self setContainerLeftRightConstraints];
|
|
}
|
|
|
|
- (void)setupTitleLabelConstraints {
|
|
_titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self setTitleLabelTopConstraint];
|
|
[_updatedConstraints addObjectsFromArray:@[
|
|
_titleLabelTopConstraint
|
|
]];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
|
|
- (void)setTitleLabelTopConstraint {
|
|
if (_titleLabel) {
|
|
id topItem;
|
|
NSLayoutAttribute attribute;
|
|
CGFloat constant;
|
|
|
|
if (_iconImageView) {
|
|
topItem = _iconImageView;
|
|
attribute = NSLayoutAttributeBottom;
|
|
constant = ORKStepContentIconImageViewToTitleLabelPadding;
|
|
} else if (_topContentImageView) {
|
|
topItem = _topContentImageView;
|
|
attribute = NSLayoutAttributeBottom;
|
|
constant = ORKStepContentIconImageViewToTitleLabelPadding;
|
|
} else {
|
|
topItem = self;
|
|
attribute = NSLayoutAttributeTop;
|
|
constant = _customTopPadding ? [_customTopPadding floatValue] : ORKStepContentIconImageViewToTitleLabelPadding;
|
|
}
|
|
|
|
_titleLabelTopConstraint = [NSLayoutConstraint constraintWithItem:_titleLabel
|
|
attribute:NSLayoutAttributeTop
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:topItem
|
|
attribute:attribute
|
|
multiplier:1.0
|
|
constant:constant];
|
|
}
|
|
}
|
|
|
|
- (void)setCustomTopPadding:(NSNumber *)customTopPadding {
|
|
_customTopPadding = customTopPadding;
|
|
[self updateTitleLabelTopConstraint];
|
|
}
|
|
|
|
// step text
|
|
|
|
- (void)setStepText:(NSString *)stepText {
|
|
_stepText = stepText;
|
|
if (stepText && !_textLabel) {
|
|
[self setupTextLabel];
|
|
[self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceTextLabel];
|
|
[self setNeedsUpdateConstraints];
|
|
[_textLabel setText:stepText];
|
|
}
|
|
else if (stepText && _textLabel) {
|
|
[_textLabel setText:_stepText];
|
|
}
|
|
else if (!stepText) {
|
|
[_textLabel removeFromSuperview];
|
|
_textLabel = nil;
|
|
[self deactivateTextLabelConstraints];
|
|
[self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceTextLabel];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
}
|
|
|
|
- (void)setupTextLabel {
|
|
if (!_textLabel) {
|
|
_textLabel = [ORKBodyLabel new];
|
|
}
|
|
_textLabel.textAlignment = _stepHeaderTextAlignment;
|
|
_textLabel.numberOfLines = 0;
|
|
_textLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
|
_textLabel.accessibilityIdentifier = @"ORKStepContentView_textLabel";
|
|
[self addSubview:_textLabel];
|
|
[self setupTextLabelConstraints];
|
|
[self setContainerLeftRightConstraints];
|
|
}
|
|
|
|
- (void)setupTextLabelConstraints {
|
|
_textLabel.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self setTextLabelTopConstraint];
|
|
_textLabelConstraints = @[_textLabelTopConstraint];
|
|
|
|
[_updatedConstraints addObjectsFromArray:_textLabelConstraints];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
|
|
- (void)setTextLabelTopConstraint {
|
|
if (_textLabel) {
|
|
id topItem;
|
|
NSLayoutAttribute attribute;
|
|
CGFloat constant;
|
|
|
|
if (_titleLabel) {
|
|
topItem = _titleLabel;
|
|
attribute = NSLayoutAttributeBottom;
|
|
constant = ORKStepContainerTitleToBodyTopPaddingForWindow(self.window);
|
|
}
|
|
else if (_iconImageView) {
|
|
topItem = _iconImageView;
|
|
attribute = NSLayoutAttributeBottom;
|
|
constant = ORKStepContentIconToBodyTopPaddingStandard;
|
|
}
|
|
else if (_topContentImageView) {
|
|
topItem = _topContentImageView;
|
|
attribute = NSLayoutAttributeBottom;
|
|
constant = ORKStepContainerFirstItemTopPaddingForWindow(self.window);
|
|
}
|
|
else {
|
|
topItem = self;
|
|
attribute = NSLayoutAttributeTop;
|
|
constant = ORKStepContainerFirstItemTopPaddingForWindow(self.window) + _additionalTopPaddingForTopLabel;
|
|
}
|
|
|
|
_textLabelTopConstraint = [NSLayoutConstraint constraintWithItem:_textLabel
|
|
attribute:NSLayoutAttributeTop
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:topItem
|
|
attribute:attribute
|
|
multiplier:1.0
|
|
constant:constant];
|
|
}
|
|
}
|
|
|
|
- (void)updateTextLabelTopConstraint {
|
|
if (_textLabelTopConstraint) {
|
|
[self deactivateConstraints:@[_textLabelTopConstraint]];
|
|
}
|
|
[self setTextLabelTopConstraint];
|
|
if (_textLabelTopConstraint) {
|
|
[_updatedConstraints addObject:_textLabelTopConstraint];
|
|
}
|
|
}
|
|
|
|
- (void)deactivateTextLabelConstraints {
|
|
[self deactivateConstraints:_textLabelConstraints];
|
|
_textLabelConstraints = nil;
|
|
}
|
|
|
|
|
|
// step detail text
|
|
|
|
- (void)setStepDetailText:(NSString *)stepDetailText {
|
|
_stepDetailText = stepDetailText;
|
|
if (stepDetailText && !_detailTextLabel) {
|
|
[self setupDetailTextLabel];
|
|
[self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceDetailTextLabel];
|
|
[self setNeedsUpdateConstraints];
|
|
[_detailTextLabel setText:stepDetailText];
|
|
}
|
|
else if (stepDetailText && _detailTextLabel) {
|
|
[_detailTextLabel setText:_stepDetailText];
|
|
}
|
|
else if (!stepDetailText) {
|
|
[_detailTextLabel removeFromSuperview];
|
|
_detailTextLabel = nil;
|
|
[self deactivateDetailTextLabelConstraints];
|
|
[self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceDetailTextLabel];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
}
|
|
|
|
- (void)setupDetailTextLabel {
|
|
if (!_detailTextLabel) {
|
|
_detailTextLabel = [ORKBodyLabel new];
|
|
}
|
|
_detailTextLabel.textAlignment = _stepHeaderTextAlignment;
|
|
_detailTextLabel.numberOfLines = 0;
|
|
_detailTextLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
|
_detailTextLabel.accessibilityIdentifier = @"ORKStepContentView_detailTextLabel";
|
|
[self addSubview:_detailTextLabel];
|
|
[self setupDetailTextLabelConstraints];
|
|
[self setContainerLeftRightConstraints];
|
|
}
|
|
|
|
- (void)setStepHeaderTextAlignment:(NSTextAlignment)stepHeaderTextAlignment {
|
|
_stepHeaderTextAlignment = stepHeaderTextAlignment;
|
|
_titleLabel.textAlignment = _stepHeaderTextAlignment;
|
|
_detailTextLabel.textAlignment = _stepHeaderTextAlignment;
|
|
_textLabel.textAlignment = _stepHeaderTextAlignment;
|
|
}
|
|
|
|
- (void)setBodyTextAlignment:(NSTextAlignment)bodyTextAlignment {
|
|
_bodyTextAlignment = bodyTextAlignment;
|
|
}
|
|
|
|
- (void)setUseExtendedPadding:(BOOL)useExtendedPadding {
|
|
_useExtendedPadding = useExtendedPadding;
|
|
_leftRightPadding = useExtendedPadding ? ORKStepContainerExtendedLeftRightPaddingForWindow(self.window) : ORKStepContainerLeftRightPaddingForWindow(self.window);
|
|
[NSLayoutConstraint deactivateConstraints:_leftRightPaddingConstraints];
|
|
[_updatedConstraints removeObjectsInArray:_leftRightPaddingConstraints];
|
|
[self setContainerLeftRightConstraints];
|
|
}
|
|
|
|
- (void)setupDetailTextLabelConstraints {
|
|
_detailTextLabel.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self setDetailTextLabelTopConstraint];
|
|
_detailTextLabelConstraints = @[_detailTextLabelTopConstraint];
|
|
|
|
[_updatedConstraints addObjectsFromArray:_detailTextLabelConstraints];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
|
|
- (void)setDetailTextLabelTopConstraint {
|
|
if (_detailTextLabel) {
|
|
id topItem;
|
|
NSLayoutAttribute attribute;
|
|
CGFloat constant;
|
|
if (_textLabel) {
|
|
topItem = _textLabel;
|
|
attribute = NSLayoutAttributeBottom;
|
|
constant = ORKBodyToBodyPaddingStandard;
|
|
}
|
|
|
|
else if (_titleLabel) {
|
|
topItem = _titleLabel;
|
|
attribute = NSLayoutAttributeBottom;
|
|
constant = ORKStepContainerTitleToBodyTopPaddingForWindow(self.window);
|
|
}
|
|
else if (_iconImageView) {
|
|
topItem = _iconImageView;
|
|
attribute = NSLayoutAttributeBottom;
|
|
constant = ORKStepContentIconToBodyTopPaddingStandard;
|
|
}
|
|
else if (_topContentImageView) {
|
|
topItem = _topContentImageView;
|
|
attribute = NSLayoutAttributeBottom;
|
|
constant = ORKStepContainerFirstItemTopPaddingForWindow(self.window);
|
|
}
|
|
else {
|
|
topItem = self;
|
|
attribute = NSLayoutAttributeTop;
|
|
constant = ORKStepContainerFirstItemTopPaddingForWindow(self.window) + _additionalTopPaddingForTopLabel;
|
|
}
|
|
|
|
_detailTextLabelTopConstraint = [NSLayoutConstraint constraintWithItem:_detailTextLabel
|
|
attribute:NSLayoutAttributeTop
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:topItem
|
|
attribute:attribute
|
|
multiplier:1.0
|
|
constant:constant];
|
|
}
|
|
}
|
|
|
|
- (void)updateDetailTextLabelTopConstraint {
|
|
if (_detailTextLabelTopConstraint) {
|
|
[self deactivateConstraints:@[_detailTextLabelTopConstraint]];
|
|
}
|
|
[self setDetailTextLabelTopConstraint];
|
|
if (_detailTextLabelTopConstraint) {
|
|
[_updatedConstraints addObject:_detailTextLabelTopConstraint];
|
|
}
|
|
}
|
|
|
|
- (void)deactivateDetailTextLabelConstraints {
|
|
[self deactivateConstraints:_detailTextLabelConstraints];
|
|
_detailTextLabelConstraints = nil;
|
|
}
|
|
|
|
|
|
// body container
|
|
|
|
- (void)setBodyItems:(NSArray<ORKBodyItem *> *)bodyItems {
|
|
_bodyItems = bodyItems;
|
|
if (_bodyItems) {
|
|
if (!_bodyContainerView) {
|
|
[self setupBodyContainerView];
|
|
[self updateStepContentViewBottomConstraint];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
else {
|
|
_bodyContainerView.bodyItems = _bodyItems;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)setBuildsInBodyItems:(BOOL)buildsInBodyItems {
|
|
_buildsInBodyItems = buildsInBodyItems;
|
|
_bodyContainerView.buildsInBodyItems = _buildsInBodyItems;
|
|
_bodyContainerView.accessibilityIdentifier = ORKStepBodyContainerViewAccessibilityIdentifier;
|
|
}
|
|
|
|
- (void)setupBodyContainerView {
|
|
__weak id<ORKBodyContainerViewDelegate> weakSelf = self;
|
|
if (!_bodyContainerView) {
|
|
_bodyContainerView = [[ORKBodyContainerView alloc] initWithBodyItems:_bodyItems
|
|
textAlignment:_bodyTextAlignment
|
|
delegate:weakSelf];
|
|
}
|
|
[self addSubview:_bodyContainerView];
|
|
[self setupBodyContainerViewConstraints];
|
|
}
|
|
|
|
- (void)updateBodyContainerViewTopConstraint {
|
|
if (_bodyContainerView) {
|
|
if (_bodyContainerViewTopConstraint) {
|
|
[self deactivateConstraints:@[_bodyContainerViewTopConstraint]];
|
|
}
|
|
[self setBodyContainerViewTopConstraint];
|
|
if (_bodyContainerViewTopConstraint) {
|
|
[_updatedConstraints addObject:_bodyContainerViewTopConstraint];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)setupBodyContainerViewConstraints {
|
|
_bodyContainerView.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self setBodyContainerViewTopConstraint];
|
|
[_updatedConstraints addObjectsFromArray:@[
|
|
_bodyContainerViewTopConstraint,
|
|
]];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
|
|
#pragma mark - Vertical ImageView
|
|
|
|
- (void)setCenteredVerticallyImage:(UIImage *)centeredVerticallyImage {
|
|
|
|
_centeredVerticallyImage = centeredVerticallyImage;
|
|
|
|
if (centeredVerticallyImage && !_centeredVerticallyImageView) {
|
|
[self setupCenteredVerticallyImageView];
|
|
[self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceCenteredVerticallyImageView];
|
|
[self setNeedsUpdateConstraints];
|
|
[_centeredVerticallyImageView setImage:centeredVerticallyImage];
|
|
[_centeredVerticallyImageView setContentMode:UIViewContentModeScaleAspectFit];
|
|
}
|
|
else if (centeredVerticallyImage && _centeredVerticallyImageView) {
|
|
[_centeredVerticallyImageView setImage:_centeredVerticallyImage];
|
|
[_centeredVerticallyImageView setContentMode:UIViewContentModeScaleAspectFit];
|
|
}
|
|
else if (!_centeredVerticallyImage) {
|
|
[_centeredVerticallyImageView removeFromSuperview];
|
|
_centeredVerticallyImageView = nil;
|
|
[self deactivateCenteredVerticallyImageViewConstraints];
|
|
[self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceCenteredVerticallyImageView];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
}
|
|
|
|
- (void)deactivateCenteredVerticallyImageViewConstraints {
|
|
[self deactivateConstraints:_centeredVerticallyImageViewContraints];
|
|
_centeredVerticallyImageViewContraints = nil;
|
|
}
|
|
|
|
- (void)setupCenteredVerticallyImageView {
|
|
|
|
if (!_centeredVerticallyImageView) {
|
|
_centeredVerticallyImageView = [[UIImageView alloc] init];
|
|
}
|
|
|
|
[self addSubview:_centeredVerticallyImageView];
|
|
[self setupCenteredVerticallyImageViewContraints];
|
|
[self setContainerLeftRightConstraints];
|
|
}
|
|
|
|
- (void)updateCenteredVerticallyImageViewTopContraint {
|
|
|
|
if (_centeredVerticallyImageView) {
|
|
|
|
if (_centeredVerticallyImageViewTopConstraint) {
|
|
[self deactivateConstraints:@[_centeredVerticallyImageViewTopConstraint]];
|
|
}
|
|
[self setCenteredVerticallyImageViewTopConstraint];
|
|
if (_centeredVerticallyImageViewTopConstraint) {
|
|
[_updatedConstraints addObject:_centeredVerticallyImageViewTopConstraint];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)setupCenteredVerticallyImageViewContraints {
|
|
_centeredVerticallyImageView.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self setCenteredVerticallyImageViewTopConstraint];
|
|
_centeredVerticallyImageViewContraints = @[_centeredVerticallyImageViewTopConstraint];
|
|
|
|
[_updatedConstraints addObjectsFromArray:_centeredVerticallyImageViewContraints];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
|
|
- (void)setCenteredVerticallyImageViewTopConstraint {
|
|
|
|
if (_centeredVerticallyImageView) {
|
|
|
|
id topItem;
|
|
CGFloat topPadding;
|
|
NSLayoutAttribute attribute;
|
|
|
|
if (_bodyContainerView) {
|
|
topItem = _bodyContainerView;
|
|
attribute = NSLayoutAttributeBottom;
|
|
topPadding = ORKBodyToBodyPaddingStandard;
|
|
} else if (_detailTextLabel && ![_stepDetailText isEqualToString:@""]) {
|
|
topItem = _detailTextLabel;
|
|
topPadding = ORKBodyToBodyPaddingStandard;
|
|
attribute = NSLayoutAttributeBottom;
|
|
} else if (_textLabel && ![_stepText isEqualToString:@""]) {
|
|
topItem = _textLabel;
|
|
if (_bodyItems.firstObject.bodyItemStyle == ORKBodyItemStyleTag ||
|
|
_bodyItems.firstObject.bodyItemStyle == ORKBodyItemStyleHorizontalRule) {
|
|
topPadding = ORKBodyToBodyParagraphPaddingStandard;
|
|
} else {
|
|
topPadding = ORKBodyToBodyPaddingStandard;
|
|
}
|
|
attribute = NSLayoutAttributeBottom;
|
|
} else if (_titleLabel) {
|
|
topItem = _titleLabel;
|
|
|
|
if (_bodyItems.firstObject.bodyItemStyle == ORKBodyItemStyleTag) {
|
|
topPadding = ORKStepContentTagPaddingTop;
|
|
} else {
|
|
topPadding = _bodyItems.firstObject.bodyItemStyle == ORKBodyItemStyleText ? ORKStepContainerTitleToBodyTopPaddingForWindow(self.window) : ORKStepContainerTitleToBulletTopPaddingForWindow(self.window);
|
|
}
|
|
|
|
attribute = NSLayoutAttributeBottom;
|
|
} else if (_iconImageView) {
|
|
topItem = _iconImageView;
|
|
topPadding = _bodyItems.firstObject.bodyItemStyle == ORKBodyItemStyleText ? ORKStepContentIconToBodyTopPaddingStandard : ORKStepContentIconToBulletTopPaddingStandard;
|
|
attribute = NSLayoutAttributeBottom;
|
|
} else if (_topContentImageView) {
|
|
topItem = _topContentImageView;
|
|
topPadding = ORKStepContainerFirstItemTopPaddingForWindow(self.window);
|
|
attribute = NSLayoutAttributeBottom;
|
|
} else {
|
|
topItem = self;
|
|
topPadding = ORKStepContainerFirstItemTopPaddingForWindow(self.window);
|
|
attribute = NSLayoutAttributeTop;
|
|
}
|
|
|
|
_centeredVerticallyImageViewTopConstraint = [NSLayoutConstraint constraintWithItem:_centeredVerticallyImageView
|
|
attribute:NSLayoutAttributeTop
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:topItem
|
|
attribute:attribute
|
|
multiplier:1.0
|
|
constant:topPadding];
|
|
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
}
|
|
|
|
-(void)updateCenteredVerticallyImageViewTopConstraint {
|
|
if (_centeredVerticallyImageViewTopConstraint && _centeredVerticallyImageViewTopConstraint.isActive) {
|
|
[NSLayoutConstraint deactivateConstraints:@[_centeredVerticallyImageViewTopConstraint]];
|
|
}
|
|
if ([_updatedConstraints containsObject:_centeredVerticallyImageViewTopConstraint]) {
|
|
[_updatedConstraints removeObject:_centeredVerticallyImageViewTopConstraint];
|
|
}
|
|
[self setCenteredVerticallyImageViewTopConstraint];
|
|
if (_centeredVerticallyImageViewTopConstraint) {
|
|
[_updatedConstraints addObject:_centeredVerticallyImageViewTopConstraint];
|
|
}
|
|
}
|
|
|
|
- (void)setContainerLeftRightConstraints {
|
|
[NSLayoutConstraint deactivateConstraints:_leftRightPaddingConstraints];
|
|
[_updatedConstraints removeObjectsInArray:_leftRightPaddingConstraints];
|
|
|
|
_leftRightPaddingConstraints = [[NSMutableArray alloc] init];
|
|
if (_textLabel != nil) {
|
|
[_leftRightPaddingConstraints addObjectsFromArray:@[
|
|
[NSLayoutConstraint constraintWithItem:_textLabel
|
|
attribute:NSLayoutAttributeLeading
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:self
|
|
attribute:NSLayoutAttributeLeading
|
|
multiplier:1.0
|
|
constant:_leftRightPadding],
|
|
[NSLayoutConstraint constraintWithItem:_textLabel
|
|
attribute:NSLayoutAttributeTrailing
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:self
|
|
attribute:NSLayoutAttributeTrailing
|
|
multiplier:1.0
|
|
constant:-_leftRightPadding]
|
|
]];
|
|
}
|
|
|
|
if (_titleLabel != nil) {
|
|
[_leftRightPaddingConstraints addObjectsFromArray:@[
|
|
[NSLayoutConstraint constraintWithItem:_titleLabel
|
|
attribute:NSLayoutAttributeLeading
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:self
|
|
attribute:NSLayoutAttributeLeading
|
|
multiplier:1.0
|
|
constant:_leftRightPadding],
|
|
[NSLayoutConstraint constraintWithItem:_titleLabel
|
|
attribute:NSLayoutAttributeTrailing
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:self
|
|
attribute:NSLayoutAttributeTrailing
|
|
multiplier:1.0
|
|
constant:-_leftRightPadding]
|
|
]];
|
|
}
|
|
|
|
if (_detailTextLabel != nil) {
|
|
[_leftRightPaddingConstraints addObjectsFromArray:@[
|
|
[NSLayoutConstraint constraintWithItem:_detailTextLabel
|
|
attribute:NSLayoutAttributeLeading
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:self
|
|
attribute:NSLayoutAttributeLeading
|
|
multiplier:1.0
|
|
constant:_leftRightPadding],
|
|
[NSLayoutConstraint constraintWithItem:_detailTextLabel
|
|
attribute:NSLayoutAttributeTrailing
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:self
|
|
attribute:NSLayoutAttributeTrailing
|
|
multiplier:1.0
|
|
constant:-_leftRightPadding]
|
|
]];
|
|
}
|
|
|
|
if (_bodyContainerView != nil) {
|
|
[_leftRightPaddingConstraints addObjectsFromArray:@[
|
|
[NSLayoutConstraint constraintWithItem:_bodyContainerView
|
|
attribute:NSLayoutAttributeLeft
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:self
|
|
attribute:NSLayoutAttributeLeft
|
|
multiplier:1.0
|
|
constant:_leftRightPadding],
|
|
[NSLayoutConstraint constraintWithItem:_bodyContainerView
|
|
attribute:NSLayoutAttributeRight
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:self
|
|
attribute:NSLayoutAttributeRight
|
|
multiplier:1.0
|
|
constant:-_leftRightPadding]
|
|
]];
|
|
}
|
|
|
|
if (_centeredVerticallyImageView != nil) {
|
|
[_leftRightPaddingConstraints addObjectsFromArray:@[
|
|
[_centeredVerticallyImageView.centerXAnchor constraintEqualToAnchor:self.centerXAnchor constant:0.0]
|
|
]];
|
|
}
|
|
|
|
if (_iconImageView != nil) {
|
|
if (_stepHeaderTextAlignment == NSTextAlignmentLeft) {
|
|
[_leftRightPaddingConstraints addObjectsFromArray:@[
|
|
[NSLayoutConstraint constraintWithItem:_iconImageView
|
|
attribute:NSLayoutAttributeLeading
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:self
|
|
attribute:NSLayoutAttributeLeading
|
|
multiplier:1.0
|
|
constant:_leftRightPadding]
|
|
]];
|
|
} else {
|
|
[_leftRightPaddingConstraints addObjectsFromArray:@[
|
|
[NSLayoutConstraint constraintWithItem:_iconImageView
|
|
attribute:NSLayoutAttributeCenterX
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:self
|
|
attribute:NSLayoutAttributeCenterX
|
|
multiplier:1.0
|
|
constant:0.0]
|
|
]];
|
|
}
|
|
}
|
|
|
|
[_updatedConstraints addObjectsFromArray:_leftRightPaddingConstraints];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
|
|
- (void)setBodyContainerViewTopConstraint {
|
|
id topItem;
|
|
CGFloat topPadding;
|
|
NSLayoutAttribute attribute;
|
|
|
|
// Checking empty string as we have an odd case where the label gets created because the text
|
|
// is an empty string. This causes the layout to be bigger than expected as the label is given
|
|
// some amount of height and we are calculating vertical padding based off a label that is not
|
|
// visible. TODO - rework the labels so they do not get created with empty text.
|
|
if (_detailTextLabel && ![_stepDetailText isEqualToString:@""]) {
|
|
topItem = _detailTextLabel;
|
|
topPadding = ORKBodyToBodyPaddingStandard;
|
|
attribute = NSLayoutAttributeBottom;
|
|
}
|
|
|
|
else if (_textLabel && ![_stepText isEqualToString:@""]) {
|
|
topItem = _textLabel;
|
|
if (_bodyItems.firstObject.bodyItemStyle == ORKBodyItemStyleTag ||
|
|
_bodyItems.firstObject.bodyItemStyle == ORKBodyItemStyleHorizontalRule) {
|
|
topPadding = ORKBodyToBodyParagraphPaddingStandard;
|
|
} else {
|
|
topPadding = ORKBodyToBodyPaddingStandard;
|
|
}
|
|
attribute = NSLayoutAttributeBottom;
|
|
}
|
|
|
|
else if (_titleLabel) {
|
|
topItem = _titleLabel;
|
|
|
|
if (_bodyItems.firstObject.bodyItemStyle == ORKBodyItemStyleTag) {
|
|
topPadding = ORKStepContentTagPaddingTop;
|
|
} else {
|
|
topPadding = _bodyItems.firstObject.bodyItemStyle == ORKBodyItemStyleText ? ORKStepContainerTitleToBodyTopPaddingForWindow(self.window) : ORKStepContainerTitleToBulletTopPaddingForWindow(self.window);
|
|
}
|
|
|
|
attribute = NSLayoutAttributeBottom;
|
|
}
|
|
else if (_iconImageView) {
|
|
topItem = _iconImageView;
|
|
topPadding = _bodyItems.firstObject.bodyItemStyle == ORKBodyItemStyleText ? ORKStepContentIconToBodyTopPaddingStandard : ORKStepContentIconToBulletTopPaddingStandard;
|
|
attribute = NSLayoutAttributeBottom;
|
|
}
|
|
|
|
else if (_topContentImageView) {
|
|
topItem = _topContentImageView;
|
|
topPadding = ORKStepContainerFirstItemTopPaddingForWindow(self.window);
|
|
attribute = NSLayoutAttributeBottom;
|
|
}
|
|
else {
|
|
topItem = self;
|
|
topPadding = ORKStepContainerFirstItemTopPaddingForWindow(self.window);
|
|
attribute = NSLayoutAttributeTop;
|
|
}
|
|
|
|
|
|
_bodyContainerViewTopConstraint = [NSLayoutConstraint constraintWithItem:_bodyContainerView
|
|
attribute:NSLayoutAttributeTop
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:topItem
|
|
attribute:attribute
|
|
multiplier:1.0
|
|
constant:topPadding];
|
|
}
|
|
|
|
|
|
// Variable constraints methods
|
|
|
|
- (void)updateViewConstraintsForSequence:(ORKUpdateConstraintSequence)sequence {
|
|
switch (sequence) {
|
|
case ORKUpdateConstraintSequenceTopContentImageView:
|
|
[self updateIconImageViewTopConstraint];
|
|
case ORKUpdateConstraintSequenceIconImageView:
|
|
[self updateTitleLabelTopConstraint];
|
|
case ORKUpdateConstraintSequenceTitleLabel:
|
|
[self updateTextLabelTopConstraint];
|
|
case ORKUpdateConstraintSequenceTextLabel:
|
|
[self updateDetailTextLabelTopConstraint];
|
|
case ORKUpdateConstraintSequenceDetailTextLabel:
|
|
[self updateBodyContainerViewTopConstraint];
|
|
case ORKUpdateConstraintSequenceCenteredVerticallyImageView:
|
|
[self updateCenteredVerticallyImageViewTopConstraint];
|
|
default:
|
|
break;
|
|
}
|
|
[self updateStepContentViewBottomConstraint];
|
|
}
|
|
|
|
- (void)updateStepContentViewBottomConstraint {
|
|
[self deactivateConstraints:@[_stepContentBottomConstraint]];
|
|
[self setStepContentViewBottomConstraint];
|
|
[_updatedConstraints addObject:_stepContentBottomConstraint];
|
|
}
|
|
|
|
- (void)setStepContentViewBottomConstraint {
|
|
id bottomItem;
|
|
NSLayoutAttribute attribute;
|
|
CGFloat constant = 0.0;
|
|
|
|
if (@available(iOS 15, *)) {
|
|
if (!useStandardTextAndFormPadding) {
|
|
constant += ORKStepContentBottomPadding;
|
|
}
|
|
}
|
|
|
|
if (_centeredVerticallyImageView) {
|
|
bottomItem = _centeredVerticallyImageView;
|
|
attribute = NSLayoutAttributeBottom;
|
|
} else if (_bodyContainerView) {
|
|
bottomItem = _bodyContainerView;
|
|
attribute = NSLayoutAttributeBottom;
|
|
}
|
|
else if (_detailTextLabel && ![_stepDetailText isEqualToString:@""]) {
|
|
bottomItem = _detailTextLabel;
|
|
attribute = NSLayoutAttributeBottom;
|
|
}
|
|
else if (_textLabel && ![_stepText isEqualToString:@""]) {
|
|
bottomItem = _textLabel;
|
|
attribute = NSLayoutAttributeBottom;
|
|
}
|
|
else if (_titleLabel) {
|
|
bottomItem = _titleLabel;
|
|
attribute = NSLayoutAttributeBottom;
|
|
}
|
|
else if (_iconImageView) {
|
|
bottomItem = _iconImageView;
|
|
attribute = NSLayoutAttributeBottom;
|
|
}
|
|
else {
|
|
bottomItem = nil;
|
|
attribute = NSLayoutAttributeNotAnAttribute;
|
|
}
|
|
|
|
_stepContentBottomConstraint = [NSLayoutConstraint constraintWithItem:self
|
|
attribute:bottomItem ? NSLayoutAttributeBottom : NSLayoutAttributeHeight
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:bottomItem
|
|
attribute:attribute
|
|
multiplier:1.0
|
|
constant:constant];
|
|
}
|
|
|
|
- (void)setStepContentViewBottomConstraint:(CGFloat)bottomConstraint {
|
|
_stepContentBottomConstraint.constant = bottomConstraint;
|
|
}
|
|
|
|
- (void)setupUpdatedConstraints {
|
|
_updatedConstraints = [[NSMutableArray alloc] init];
|
|
}
|
|
|
|
- (void)deactivateConstraints:(nullable NSArray<NSLayoutConstraint *> *)constraints {
|
|
if (constraints) {
|
|
[NSLayoutConstraint deactivateConstraints:constraints];
|
|
}
|
|
[self updatedConstraintsWithdrawConstraints:constraints];
|
|
[self setNeedsUpdateConstraints];
|
|
}
|
|
|
|
- (void)updatedConstraintsWithdrawConstraints:(nullable NSArray<NSLayoutConstraint *> *)constraints {
|
|
if (constraints && constraints.count > 0) {
|
|
for (NSLayoutConstraint *constraint in constraints) {
|
|
if ([_updatedConstraints containsObject:constraint]) {
|
|
[_updatedConstraints removeObject:constraint];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)updateContentConstraints {
|
|
[NSLayoutConstraint activateConstraints:_updatedConstraints];
|
|
[_updatedConstraints removeAllObjects];
|
|
}
|
|
|
|
- (void)updateConstraints {
|
|
[self updateContentConstraints];
|
|
[super updateConstraints];
|
|
}
|
|
|
|
|
|
// Private methods
|
|
|
|
- (void)setAdditionalTopPaddingForTopLabel:(CGFloat)padding {
|
|
_additionalTopPaddingForTopLabel = padding;
|
|
if (!_topContentImageView && !_iconImageView) {
|
|
if (_titleLabel) {
|
|
[self updateTitleLabelTopConstraint];
|
|
}
|
|
else if (_textLabel) {
|
|
[self updateTextLabelTopConstraint];
|
|
}
|
|
else if (_detailTextLabel) {
|
|
[self updateDetailTextLabelTopConstraint];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (nullable ORKCompletionCheckmarkView *)completionCheckmarkView {
|
|
if (!_completionCheckmarkView) {
|
|
_completionCheckmarkView = [[ORKCompletionCheckmarkView alloc] initWithDefaultDimension];
|
|
[self addSubview:_completionCheckmarkView];
|
|
self.titleIconImage = [UIImage new];
|
|
[_iconImageView setHidden:YES];
|
|
_completionCheckmarkView.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[self setContainerLeftRightConstraints];
|
|
[_updatedConstraints addObjectsFromArray:@[
|
|
[NSLayoutConstraint constraintWithItem:_completionCheckmarkView
|
|
attribute:NSLayoutAttributeLeading
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_iconImageView
|
|
attribute:NSLayoutAttributeLeading
|
|
multiplier:1.0
|
|
constant:0.0],
|
|
[NSLayoutConstraint constraintWithItem:_completionCheckmarkView
|
|
attribute:NSLayoutAttributeCenterY
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_iconImageView
|
|
attribute:NSLayoutAttributeCenterY
|
|
multiplier:1.0
|
|
constant:0.0],
|
|
[NSLayoutConstraint constraintWithItem:_completionCheckmarkView
|
|
attribute:NSLayoutAttributeWidth
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_iconImageView
|
|
attribute:NSLayoutAttributeWidth
|
|
multiplier:1.0
|
|
constant:0.0],
|
|
[NSLayoutConstraint constraintWithItem:_completionCheckmarkView
|
|
attribute:NSLayoutAttributeHeight
|
|
relatedBy:NSLayoutRelationEqual
|
|
toItem:_iconImageView
|
|
attribute:NSLayoutAttributeHeight
|
|
multiplier:1.0
|
|
constant:0.0]
|
|
]];
|
|
}
|
|
return _completionCheckmarkView;
|
|
}
|
|
|
|
#pragma mark - ORKBodycontainerViewDelegate
|
|
|
|
- (void)bodyContainerLearnMoreButtonPressed:(ORKLearnMoreInstructionStep *)learnMoreStep {
|
|
[_delegate stepContentLearnMoreButtonPressed:learnMoreStep];
|
|
}
|
|
|
|
@end
|