blob: 9d5f2a451099fd14a699b56c3e98f2b43f05544c [file] [log] [blame]
// Copyright 2019-present the Material Components for iOS authors. 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 "MDCTextControlAssistiveLabelViewLayout.h"
@interface MDCTextControlAssistiveLabelViewLayout ()
@property(nonatomic, assign) CGRect leadingAssistiveLabelFrame;
@property(nonatomic, assign) CGRect trailingAssistiveLabelFrame;
@property(nonatomic, assign) CGFloat calculatedHeight;
@end
@implementation MDCTextControlAssistiveLabelViewLayout
#pragma mark Object Lifecycle
- (instancetype)initWithWidth:(CGFloat)superviewWidth
leadingAssistiveLabel:(UILabel *)leadingAssistiveLabel
trailingAssistiveLabel:(UILabel *)trailingAssistiveLabel
assistiveLabelDrawPriority:
(MDCTextControlAssistiveLabelDrawPriority)assistiveLabelDrawPriority
customAssistiveLabelDrawPriority:(CGFloat)customAssistiveLabelDrawPriority
horizontalPadding:(CGFloat)horizontalPadding
paddingAboveAssistiveLabels:(CGFloat)paddingAboveAssistiveLabels
paddingBelowAssistiveLabels:(CGFloat)paddingBelowAssistiveLabels
isRTL:(BOOL)isRTL {
self = [super init];
if (self) {
[self calculateLayoutWithSuperviewWidth:superviewWidth
leadingAssistiveLabel:leadingAssistiveLabel
trailingAssistiveLabel:trailingAssistiveLabel
assistiveLabelDrawPriority:assistiveLabelDrawPriority
customAssistiveLabelDrawPriority:customAssistiveLabelDrawPriority
horizontalPadding:horizontalPadding
paddingAboveAssistiveLabels:(CGFloat)paddingAboveAssistiveLabels
paddingBelowAssistiveLabels:(CGFloat)paddingBelowAssistiveLabels
isRTL:isRTL];
return self;
}
return nil;
}
#pragma mark Layout Calculation
- (void)calculateLayoutWithSuperviewWidth:(CGFloat)superviewWidth
leadingAssistiveLabel:(UILabel *)leadingAssistiveLabel
trailingAssistiveLabel:(UILabel *)trailingAssistiveLabel
assistiveLabelDrawPriority:
(MDCTextControlAssistiveLabelDrawPriority)assistiveLabelDrawPriority
customAssistiveLabelDrawPriority:(CGFloat)customAssistiveLabelDrawPriority
horizontalPadding:(CGFloat)horizontalPadding
paddingAboveAssistiveLabels:(CGFloat)paddingAboveAssistiveLabels
paddingBelowAssistiveLabels:(CGFloat)paddingBelowAssistiveLabels
isRTL:(BOOL)isRTL {
CGFloat assistiveLabelsCombinedMinX = horizontalPadding;
CGFloat assistiveLabelsCombinedMaxX = superviewWidth - horizontalPadding;
CGFloat assistiveLabelsCombinedMaxWidth =
assistiveLabelsCombinedMaxX - assistiveLabelsCombinedMinX;
CGFloat assistiveLabelsCombinedMinY = paddingAboveAssistiveLabels;
CGFloat leadingAssistiveLabelWidth = 0;
CGFloat trailingAssistiveLabelWidth = 0;
CGSize leadingAssistiveLabelSize = CGSizeZero;
CGSize trailingAssistiveLabelSize = CGSizeZero;
switch (assistiveLabelDrawPriority) {
case MDCTextControlAssistiveLabelDrawPriorityCustom:
leadingAssistiveLabelWidth = [self
leadingAssistiveLabelWidthWithCombinedAssistiveLabelsWidth:assistiveLabelsCombinedMaxWidth
customDrawPriority:
customAssistiveLabelDrawPriority];
trailingAssistiveLabelWidth = assistiveLabelsCombinedMaxWidth - leadingAssistiveLabelWidth;
leadingAssistiveLabelSize = [self assistiveLabelSizeWithLabel:leadingAssistiveLabel
constrainedToWidth:leadingAssistiveLabelWidth];
trailingAssistiveLabelSize = [self assistiveLabelSizeWithLabel:trailingAssistiveLabel
constrainedToWidth:trailingAssistiveLabelWidth];
break;
case MDCTextControlAssistiveLabelDrawPriorityLeading:
leadingAssistiveLabelSize =
[self assistiveLabelSizeWithLabel:leadingAssistiveLabel
constrainedToWidth:assistiveLabelsCombinedMaxWidth];
if ([self isLabelMultilineWithLabel:leadingAssistiveLabel size:leadingAssistiveLabelSize]) {
trailingAssistiveLabelSize = CGSizeZero;
} else {
trailingAssistiveLabelSize =
[self assistiveLabelSizeWithLabel:trailingAssistiveLabel
constrainedToWidth:assistiveLabelsCombinedMaxWidth -
leadingAssistiveLabelSize.width];
}
break;
case MDCTextControlAssistiveLabelDrawPriorityTrailing:
// Pass through (.trailing is the default priority)
default:
trailingAssistiveLabelSize =
[self assistiveLabelSizeWithLabel:trailingAssistiveLabel
constrainedToWidth:assistiveLabelsCombinedMaxWidth];
if ([self isLabelMultilineWithLabel:trailingAssistiveLabel size:trailingAssistiveLabelSize]) {
leadingAssistiveLabelSize = CGSizeZero;
} else {
leadingAssistiveLabelSize =
[self assistiveLabelSizeWithLabel:leadingAssistiveLabel
constrainedToWidth:assistiveLabelsCombinedMaxWidth -
trailingAssistiveLabelSize.width];
}
break;
}
BOOL leadingAssistiveLabelIsVisible = !CGSizeEqualToSize(leadingAssistiveLabelSize, CGSizeZero);
BOOL trailingAssistiveLabelIsVisible = !CGSizeEqualToSize(trailingAssistiveLabelSize, CGSizeZero);
if (!leadingAssistiveLabelIsVisible && !trailingAssistiveLabelIsVisible) {
self.leadingAssistiveLabelFrame = CGRectZero;
self.trailingAssistiveLabelFrame = CGRectZero;
self.calculatedHeight = 0;
return;
}
CGSize leftAssistiveLabelSize = isRTL ? trailingAssistiveLabelSize : leadingAssistiveLabelSize;
CGSize rightAssistiveLabelSize = isRTL ? leadingAssistiveLabelSize : trailingAssistiveLabelSize;
CGRect leftAssistiveLabelFrame = CGRectZero;
CGRect rightAssistiveLabelFrame = CGRectZero;
if (!CGSizeEqualToSize(leftAssistiveLabelSize, CGSizeZero)) {
leftAssistiveLabelFrame =
CGRectMake(assistiveLabelsCombinedMinX, assistiveLabelsCombinedMinY,
leftAssistiveLabelSize.width, leftAssistiveLabelSize.height);
}
if (!CGSizeEqualToSize(rightAssistiveLabelSize, CGSizeZero)) {
rightAssistiveLabelFrame = CGRectMake(
assistiveLabelsCombinedMaxX - rightAssistiveLabelSize.width, assistiveLabelsCombinedMinY,
rightAssistiveLabelSize.width, rightAssistiveLabelSize.height);
}
CGFloat maxAssistiveLabelHeight =
MAX(CGRectGetMaxY(leftAssistiveLabelFrame), CGRectGetMaxY(rightAssistiveLabelFrame));
self.leadingAssistiveLabelFrame = isRTL ? rightAssistiveLabelFrame : leftAssistiveLabelFrame;
self.trailingAssistiveLabelFrame = isRTL ? leftAssistiveLabelFrame : rightAssistiveLabelFrame;
self.calculatedHeight = maxAssistiveLabelHeight + paddingBelowAssistiveLabels;
}
- (CGSize)assistiveLabelSizeWithLabel:(UILabel *)label constrainedToWidth:(CGFloat)maxWidth {
if (maxWidth <= 0 || label.text.length <= 0 || label.hidden) {
return CGSizeZero;
}
CGSize fittingSize = CGSizeMake(maxWidth, CGFLOAT_MAX);
CGSize size = [label sizeThatFits:fittingSize];
if (size.width > maxWidth) {
size.width = maxWidth;
}
return size;
}
- (CGFloat)leadingAssistiveLabelWidthWithCombinedAssistiveLabelsWidth:
(CGFloat)totalAssistiveLabelsWidth
customDrawPriority:(CGFloat)customDrawPriority {
return customDrawPriority * totalAssistiveLabelsWidth;
}
- (BOOL)isLabelMultilineWithLabel:(UILabel *)label size:(CGSize)size {
CGFloat lineHeight = label.font.lineHeight;
return round((double)(size.height / lineHeight)) > 1;
}
@end