blob: 84937b2ab87fd75e8c28917a3f72cdc5017080c1 [file] [log] [blame]
// Copyright 2018-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 "MDCSelfSizingStereoCell.h"
#import <Foundation/Foundation.h>
#import <MDFInternationalization/MDFInternationalization.h>
#import "MaterialInk.h"
#import "MaterialMath.h"
#import "MaterialTypography.h"
#import "private/MDCSelfSizingStereoCellLayout.h"
static const CGFloat kTitleColorOpacity = (CGFloat)0.87;
static const CGFloat kDetailColorOpacity = (CGFloat)0.6;
@interface MDCSelfSizingStereoCell ()
@property(nonatomic, strong) UIView *textContainer;
@property(nonatomic, strong) UILabel *titleLabel;
@property(nonatomic, strong) UILabel *detailLabel;
@property(nonatomic, strong) UIImageView *leadingImageView;
@property(nonatomic, strong) UIImageView *trailingImageView;
@property(nonatomic, strong)
NSMutableDictionary<NSNumber *, MDCSelfSizingStereoCellLayout *> *cachedLayouts;
@end
@implementation MDCSelfSizingStereoCell
@synthesize mdc_adjustsFontForContentSizeCategory = _mdc_adjustsFontForContentSizeCategory;
- (instancetype)init {
self = [super init];
if (self) {
[self commonMDCSelfSizingStereoCellInit];
return self;
}
return nil;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self commonMDCSelfSizingStereoCellInit];
return self;
}
return nil;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self commonMDCSelfSizingStereoCellInit];
return self;
}
return nil;
}
- (void)commonMDCSelfSizingStereoCellInit {
self.cachedLayouts = [[NSMutableDictionary alloc] init];
[self createSubviews];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark Setup
- (void)createSubviews {
self.textContainer = [[UIView alloc] init];
[self.contentView addSubview:self.textContainer];
self.titleLabel = [[UILabel alloc] init];
[self.textContainer addSubview:self.titleLabel];
self.detailLabel = [[UILabel alloc] init];
[self.textContainer addSubview:self.detailLabel];
self.leadingImageView = [[UIImageView alloc] init];
[self.contentView addSubview:self.leadingImageView];
self.trailingImageView = [[UIImageView alloc] init];
[self.contentView addSubview:self.trailingImageView];
[self resetMDCSelfSizingStereoCellLabelProperties];
}
- (void)resetMDCSelfSizingStereoCellLabelProperties {
self.titleLabel.font = self.defaultTitleLabelFont;
self.titleLabel.textColor = self.defaultTitleLabelTextColor;
self.titleLabel.numberOfLines = 0;
self.detailLabel.font = self.defaultDetailLabelFont;
self.detailLabel.textColor = self.defaultDetailLabelTextColor;
self.detailLabel.numberOfLines = 0;
}
#pragma mark UIView Overrides
- (void)layoutSubviews {
[super layoutSubviews];
MDCSelfSizingStereoCellLayout *layout = [self layoutForCellWidth:self.frame.size.width];
self.textContainer.frame = layout.textContainerFrame;
self.titleLabel.frame = layout.titleLabelFrame;
self.detailLabel.frame = layout.detailLabelFrame;
self.leadingImageView.frame = layout.leadingImageViewFrame;
self.trailingImageView.frame = layout.trailingImageViewFrame;
if (self.mdf_effectiveUserInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft) {
self.leadingImageView.frame =
MDFRectFlippedHorizontally(self.leadingImageView.frame, layout.cellWidth);
self.trailingImageView.frame =
MDFRectFlippedHorizontally(self.trailingImageView.frame, layout.cellWidth);
self.textContainer.frame =
MDFRectFlippedHorizontally(self.textContainer.frame, layout.cellWidth);
self.titleLabel.frame =
MDFRectFlippedHorizontally(self.titleLabel.frame, self.textContainer.frame.size.width);
self.detailLabel.frame =
MDFRectFlippedHorizontally(self.detailLabel.frame, self.textContainer.frame.size.width);
}
}
- (void)setNeedsLayout {
[self invalidateCachedLayouts];
[super setNeedsLayout];
}
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize {
MDCSelfSizingStereoCellLayout *layout = [self layoutForCellWidth:targetSize.width];
return CGSizeMake(targetSize.width, layout.calculatedHeight);
}
#pragma mark UICollectionViewCell Overrides
- (void)prepareForReuse {
[super prepareForReuse];
self.titleLabel.text = nil;
self.detailLabel.text = nil;
self.leadingImageView.image = nil;
self.trailingImageView.image = nil;
[self setNeedsLayout];
[self mdc_setAdjustsFontForContentSizeCategory:NO];
[self resetMDCSelfSizingStereoCellLabelProperties];
}
#pragma mark Layout
- (MDCSelfSizingStereoCellLayout *)layoutForCellWidth:(CGFloat)cellWidth {
CGFloat flooredCellWidth = MDCFloor(cellWidth);
MDCSelfSizingStereoCellLayout *layout = self.cachedLayouts[@(flooredCellWidth)];
if (!layout) {
layout = [[MDCSelfSizingStereoCellLayout alloc] initWithLeadingImageView:self.leadingImageView
trailingImageView:self.trailingImageView
textContainer:self.textContainer
titleLabel:self.titleLabel
detailLabel:self.detailLabel
cellWidth:flooredCellWidth];
self.cachedLayouts[@(flooredCellWidth)] = layout;
}
return layout;
}
- (void)invalidateCachedLayouts {
[self.cachedLayouts removeAllObjects];
}
#pragma mark Dynamic Type
- (BOOL)mdc_adjustsFontForContentSizeCategory {
return _mdc_adjustsFontForContentSizeCategory;
}
- (void)mdc_setAdjustsFontForContentSizeCategory:(BOOL)adjusts {
if (adjusts == _mdc_adjustsFontForContentSizeCategory) {
return;
}
_mdc_adjustsFontForContentSizeCategory = adjusts;
if (_mdc_adjustsFontForContentSizeCategory) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contentSizeCategoryDidChange:)
name:UIContentSizeCategoryDidChangeNotification
object:nil];
} else {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIContentSizeCategoryDidChangeNotification
object:nil];
}
[self adjustFontsForContentSizeCategory];
}
// Handles UIContentSizeCategoryDidChangeNotifications
- (void)contentSizeCategoryDidChange:(__unused NSNotification *)notification {
[self adjustFontsForContentSizeCategory];
}
- (void)adjustFontsForContentSizeCategory {
UIFont *titleFont = self.titleLabel.font ?: self.defaultTitleLabelFont;
UIFont *detailFont = self.detailLabel.font ?: self.defaultDetailLabelFont;
if (_mdc_adjustsFontForContentSizeCategory) {
titleFont =
[titleFont mdc_fontSizedForMaterialTextStyle:MDCFontTextStyleTitle
scaledForDynamicType:_mdc_adjustsFontForContentSizeCategory];
detailFont =
[detailFont mdc_fontSizedForMaterialTextStyle:MDCFontTextStyleCaption
scaledForDynamicType:_mdc_adjustsFontForContentSizeCategory];
}
self.titleLabel.font = titleFont;
self.detailLabel.font = detailFont;
[self setNeedsLayout];
}
#pragma mark Font Defaults
- (UIFont *)defaultTitleLabelFont {
return [UIFont mdc_standardFontForMaterialTextStyle:MDCFontTextStyleTitle];
}
- (UIFont *)defaultDetailLabelFont {
return [UIFont mdc_standardFontForMaterialTextStyle:MDCFontTextStyleCaption];
}
- (UIColor *)defaultTitleLabelTextColor {
return [UIColor colorWithWhite:0 alpha:kTitleColorOpacity];
}
- (UIColor *)defaultDetailLabelTextColor {
return [UIColor colorWithWhite:0 alpha:kDetailColorOpacity];
}
@end