Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.mm

Issue 2865183003: Use the same design for all suggestions (Closed)
Patch Set: Reviewable Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_art icle_item.h" 5 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_ite m.h"
6 6
7 #include "base/time/time.h" 7 #include "base/time/time.h"
8 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" 8 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
9 #import "ios/chrome/browser/ui/favicon/favicon_attributes.h" 9 #import "ios/chrome/browser/ui/favicon/favicon_attributes.h"
10 #import "ios/chrome/browser/ui/favicon/favicon_view.h" 10 #import "ios/chrome/browser/ui/favicon/favicon_view.h"
11 #import "ios/chrome/browser/ui/uikit_ui_util.h" 11 #import "ios/chrome/browser/ui/uikit_ui_util.h"
12 #import "ios/chrome/browser/ui/util/i18n_string.h" 12 #import "ios/chrome/browser/ui/util/i18n_string.h"
13 #import "ios/third_party/material_components_ios/src/components/Palettes/src/Mat erialPalettes.h" 13 #import "ios/third_party/material_components_ios/src/components/Palettes/src/Mat erialPalettes.h"
14 #import "ios/third_party/material_components_ios/src/components/Typography/src/M aterialTypography.h" 14 #import "ios/third_party/material_components_ios/src/components/Typography/src/M aterialTypography.h"
15 #include "url/gurl.h" 15 #include "url/gurl.h"
16 16
17 #if !defined(__has_feature) || !__has_feature(objc_arc) 17 #if !defined(__has_feature) || !__has_feature(objc_arc)
18 #error "This file requires ARC support." 18 #error "This file requires ARC support."
19 #endif 19 #endif
20 20
21 namespace { 21 namespace {
22 const CGFloat kImageSize = 72; 22 const CGFloat kImageSize = 72;
23 const CGFloat kStandardSpacing = 16; 23 const CGFloat kStandardSpacing = 16;
24 const CGFloat kSmallSpacing = 8; 24 const CGFloat kSmallSpacing = 8;
25 25
26 // Name of the icon displayed when a suggestion is available offline.
27 NSString* const kOfflineIconName = @"content_suggestions_offline";
28 // Size of the icon displayed when a suggestion is available offline.
29 const CGFloat kOfflineIconSize = 24;
30
26 // Size of the favicon view. 31 // Size of the favicon view.
27 const CGFloat kFaviconSize = 16; 32 const CGFloat kFaviconSize = 16;
28 // Size of the icon displayed when there is not image. 33 // Size of the icon displayed when there is not image but one should be
34 // displayed.
29 const CGFloat kIconSize = 24; 35 const CGFloat kIconSize = 24;
30 // Name of the icon displayed when there is not image. 36 // Name of the icon displayed when there is not image but one should be
37 // displayed.
31 NSString* const kNoImageIconName = @"content_suggestions_no_image"; 38 NSString* const kNoImageIconName = @"content_suggestions_no_image";
32 // No image icon percentage of white. 39 // No image icon percentage of white.
33 const CGFloat kNoImageIconWhite = 0.38; 40 const CGFloat kNoImageIconWhite = 0.38;
34 // No image background percentage of white. 41 // No image background percentage of white.
35 const CGFloat kNoImageBackgroundWhite = 0.95; 42 const CGFloat kNoImageBackgroundWhite = 0.95;
36 // Duration of the animation to display the image for the article. 43 // Duration of the animation to display the image.
37 const CGFloat kAnimationDuration = 0.3; 44 const CGFloat kAnimationDuration = 0.3;
38 } 45 }
39 46
40 @interface ContentSuggestionsArticleItem () 47 @interface ContentSuggestionsItem ()
41 48
42 @property(nonatomic, copy) NSString* subtitle; 49 @property(nonatomic, copy) NSString* subtitle;
43 // Used to check if the image has already been fetched. There is no way to 50 // Used to check if the image has already been fetched. There is no way to
44 // discriminate between failed image download and nonexitent image. The article 51 // discriminate between failed image download and nonexitent image. The
45 // tries to download the image only once. 52 // suggestion tries to download the image only once.
46 @property(nonatomic, assign) BOOL imageFetched; 53 @property(nonatomic, assign) BOOL imageFetched;
47 54
48 @end 55 @end
49 56
50 #pragma mark - ContentSuggestionsArticleItem 57 #pragma mark - ContentSuggestionsItem
51 58
52 @implementation ContentSuggestionsArticleItem 59 @implementation ContentSuggestionsItem
53 60
54 @synthesize title = _title; 61 @synthesize title = _title;
55 @synthesize subtitle = _subtitle; 62 @synthesize subtitle = _subtitle;
56 @synthesize image = _image; 63 @synthesize image = _image;
57 @synthesize articleURL = _articleURL; 64 @synthesize URL = _URL;
58 @synthesize publisher = _publisher; 65 @synthesize publisher = _publisher;
59 @synthesize publishDate = _publishDate; 66 @synthesize publishDate = _publishDate;
60 @synthesize suggestionIdentifier = _suggestionIdentifier; 67 @synthesize suggestionIdentifier = _suggestionIdentifier;
61 @synthesize delegate = _delegate; 68 @synthesize delegate = _delegate;
62 @synthesize imageFetched = _imageFetched; 69 @synthesize imageFetched = _imageFetched;
63 @synthesize attributes = _attributes; 70 @synthesize attributes = _attributes;
71 @synthesize hasImage = _hasImage;
72 @synthesize availableOffline = _availableOffline;
64 73
65 - (instancetype)initWithType:(NSInteger)type 74 - (instancetype)initWithType:(NSInteger)type
66 title:(NSString*)title 75 title:(NSString*)title
67 subtitle:(NSString*)subtitle 76 subtitle:(NSString*)subtitle
68 delegate:(id<ContentSuggestionsArticleItemDelegate>)delegate 77 delegate:(id<ContentSuggestionsItemDelegate>)delegate
69 url:(const GURL&)url { 78 url:(const GURL&)url {
70 self = [super initWithType:type]; 79 self = [super initWithType:type];
71 if (self) { 80 if (self) {
72 self.cellClass = [ContentSuggestionsArticleCell class]; 81 self.cellClass = [ContentSuggestionsCell class];
73 _title = [title copy]; 82 _title = [title copy];
74 _subtitle = [subtitle copy]; 83 _subtitle = [subtitle copy];
75 _articleURL = url; 84 _URL = url;
76 _delegate = delegate; 85 _delegate = delegate;
77 } 86 }
78 return self; 87 return self;
79 } 88 }
80 89
81 - (void)configureCell:(ContentSuggestionsArticleCell*)cell { 90 - (void)configureCell:(ContentSuggestionsCell*)cell {
82 [super configureCell:cell]; 91 [super configureCell:cell];
83 if (!self.imageFetched) { 92 if (self.hasImage && !self.imageFetched) {
84 self.imageFetched = YES; 93 self.imageFetched = YES;
85 // Fetch the image. During the fetch the cell's image should still be set. 94 // Fetch the image. During the fetch the cell's image should still be set.
86 [self.delegate loadImageForArticleItem:self]; 95 [self.delegate loadImageForSuggestionItem:self];
87 } 96 }
88 if (self.attributes) 97 [cell.faviconView configureWithAttributes:self.attributes];
89 [cell.faviconView configureWithAttributes:self.attributes];
90 cell.titleLabel.text = self.title; 98 cell.titleLabel.text = self.title;
91 cell.subtitleLabel.text = self.subtitle; 99 [cell setSubtitleText:self.subtitle];
100 cell.displayImage = self.hasImage;
92 [cell setContentImage:self.image]; 101 [cell setContentImage:self.image];
93 [cell setPublisherName:self.publisher date:self.publishDate]; 102 [cell setAdditionalInformationWithPublisherName:self.publisher
103 date:self.publishDate
104 offlineAvailability:self.availableOffline];
94 } 105 }
95 106
96 @end 107 @end
97 108
98 #pragma mark - ContentSuggestionsArticleCell 109 #pragma mark - ContentSuggestionsCell
99 110
100 @interface ContentSuggestionsArticleCell () 111 @interface ContentSuggestionsCell ()
101 112
102 @property(nonatomic, strong) UILabel* publisherLabel; 113 @property(nonatomic, strong) UILabel* additionalInformationLabel;
103 // Contains the no-image icon or the image. 114 // Contains the no-image icon or the image.
104 @property(nonatomic, strong) UIView* imageContainer; 115 @property(nonatomic, strong) UIView* imageContainer;
105 // The no-image icon displayed when there is no image. 116 // The no-image icon displayed when there is no image.
106 @property(nonatomic, strong) UIImageView* noImageIcon; 117 @property(nonatomic, strong) UIImageView* noImageIcon;
107 // Displays the image associated with this article. It is added to the 118 // Displays the image associated with this suggestion. It is added to the
108 // imageContainer only if there is an image to display, hiding the no-image 119 // imageContainer only if there is an image to display, hiding the no-image
109 // icon. 120 // icon.
110 @property(nonatomic, strong) UIImageView* contentImageView; 121 @property(nonatomic, strong) UIImageView* contentImageView;
122 // Constraint for the size of the image.
123 @property(nonatomic, strong) NSLayoutConstraint* imageSize;
124 // Constraint for the distance between the texts and the image.
125 @property(nonatomic, strong) NSLayoutConstraint* imageTitleSpacing;
126 // Constraint for the vertical distance between the title and the subtitle.
127 @property(nonatomic, strong) NSLayoutConstraint* titleSubtitleSpacing;
128 // Label for the subtitle.
129 @property(nonatomic, readonly, strong) UILabel* subtitleLabel;
111 130
112 // Applies the constraints on the elements. Called in the init. 131 // Applies the constraints on the elements. Called in the init.
113 - (void)applyConstraints; 132 - (void)applyConstraints;
114 133
115 @end 134 @end
116 135
117 @implementation ContentSuggestionsArticleCell 136 @implementation ContentSuggestionsCell
118 137
119 @synthesize titleLabel = _titleLabel; 138 @synthesize titleLabel = _titleLabel;
120 @synthesize subtitleLabel = _subtitleLabel; 139 @synthesize subtitleLabel = _subtitleLabel;
121 @synthesize imageContainer = _imageContainer; 140 @synthesize imageContainer = _imageContainer;
122 @synthesize noImageIcon = _noImageIcon; 141 @synthesize noImageIcon = _noImageIcon;
123 @synthesize publisherLabel = _publisherLabel; 142 @synthesize additionalInformationLabel = _additionalInformationLabel;
124 @synthesize contentImageView = _contentImageView; 143 @synthesize contentImageView = _contentImageView;
125 @synthesize faviconView = _faviconView; 144 @synthesize faviconView = _faviconView;
145 @synthesize imageSize = _imageSize;
146 @synthesize imageTitleSpacing = _imageTitleSpacing;
147 @synthesize displayImage = _displayImage;
148 @synthesize titleSubtitleSpacing = _titleSubtitleSpacing;
126 149
127 - (instancetype)initWithFrame:(CGRect)frame { 150 - (instancetype)initWithFrame:(CGRect)frame {
128 self = [super initWithFrame:frame]; 151 self = [super initWithFrame:frame];
129 if (self) { 152 if (self) {
130 _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 153 _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
131 _subtitleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 154 _subtitleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
132 _imageContainer = [[UIView alloc] initWithFrame:CGRectZero]; 155 _imageContainer = [[UIView alloc] initWithFrame:CGRectZero];
133 _noImageIcon = [[UIImageView alloc] initWithFrame:CGRectZero]; 156 _noImageIcon = [[UIImageView alloc] initWithFrame:CGRectZero];
134 _publisherLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 157 _additionalInformationLabel = [[UILabel alloc] initWithFrame:CGRectZero];
135 _contentImageView = [[UIImageView alloc] initWithFrame:CGRectZero]; 158 _contentImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
136 _faviconView = [[FaviconViewNew alloc] init]; 159 _faviconView = [[FaviconViewNew alloc] init];
137 160
138 _titleLabel.numberOfLines = 2; 161 _titleLabel.numberOfLines = 2;
139 _subtitleLabel.numberOfLines = 2; 162 _subtitleLabel.numberOfLines = 2;
140 [_subtitleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh 163 [_subtitleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh
141 forAxis:UILayoutConstraintAxisVertical]; 164 forAxis:UILayoutConstraintAxisVertical];
142 [_titleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh 165 [_titleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh
143 forAxis:UILayoutConstraintAxisVertical]; 166 forAxis:UILayoutConstraintAxisVertical];
144 167
145 _contentImageView.contentMode = UIViewContentModeScaleAspectFill; 168 _contentImageView.contentMode = UIViewContentModeScaleAspectFill;
146 _contentImageView.clipsToBounds = YES; 169 _contentImageView.clipsToBounds = YES;
147 _contentImageView.hidden = YES; 170 _contentImageView.hidden = YES;
148 171
149 _imageContainer.translatesAutoresizingMaskIntoConstraints = NO; 172 _imageContainer.translatesAutoresizingMaskIntoConstraints = NO;
150 _noImageIcon.translatesAutoresizingMaskIntoConstraints = NO; 173 _noImageIcon.translatesAutoresizingMaskIntoConstraints = NO;
151 _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; 174 _titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
152 _subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO; 175 _subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
153 _publisherLabel.translatesAutoresizingMaskIntoConstraints = NO; 176 _additionalInformationLabel.translatesAutoresizingMaskIntoConstraints = NO;
154 _contentImageView.translatesAutoresizingMaskIntoConstraints = NO; 177 _contentImageView.translatesAutoresizingMaskIntoConstraints = NO;
155 _faviconView.translatesAutoresizingMaskIntoConstraints = NO; 178 _faviconView.translatesAutoresizingMaskIntoConstraints = NO;
156 179
157 [self.contentView addSubview:_imageContainer]; 180 [self.contentView addSubview:_imageContainer];
158 [self.contentView addSubview:_titleLabel]; 181 [self.contentView addSubview:_titleLabel];
159 [self.contentView addSubview:_subtitleLabel]; 182 [self.contentView addSubview:_subtitleLabel];
160 [self.contentView addSubview:_publisherLabel]; 183 [self.contentView addSubview:_additionalInformationLabel];
161 [self.contentView addSubview:_faviconView]; 184 [self.contentView addSubview:_faviconView];
162 185
163 [_imageContainer addSubview:_noImageIcon]; 186 [_imageContainer addSubview:_noImageIcon];
164 [_imageContainer addSubview:_contentImageView]; 187 [_imageContainer addSubview:_contentImageView];
165 188
166 _imageContainer.backgroundColor = 189 _imageContainer.backgroundColor =
167 [UIColor colorWithWhite:kNoImageBackgroundWhite alpha:1]; 190 [UIColor colorWithWhite:kNoImageBackgroundWhite alpha:1];
168 _noImageIcon.image = [[UIImage imageNamed:kNoImageIconName] 191 _noImageIcon.image = [[UIImage imageNamed:kNoImageIconName]
169 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; 192 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
170 [_noImageIcon 193 [_noImageIcon
171 setTintColor:[UIColor colorWithWhite:kNoImageIconWhite alpha:1]]; 194 setTintColor:[UIColor colorWithWhite:kNoImageIconWhite alpha:1]];
172 195
173 _titleLabel.font = [MDCTypography subheadFont]; 196 _titleLabel.font = [MDCTypography subheadFont];
174 _subtitleLabel.font = [MDCTypography body1Font]; 197 _subtitleLabel.font = [MDCTypography body1Font];
175 _publisherLabel.font = [MDCTypography captionFont]; 198 _additionalInformationLabel.font = [MDCTypography captionFont];
176 _faviconView.font = [[MDCTypography fontLoader] mediumFontOfSize:10]; 199 _faviconView.font = [[MDCTypography fontLoader] mediumFontOfSize:10];
177 200
178 _subtitleLabel.textColor = [[MDCPalette greyPalette] tint700]; 201 _subtitleLabel.textColor = [[MDCPalette greyPalette] tint700];
179 _publisherLabel.textColor = [[MDCPalette greyPalette] tint700]; 202 _additionalInformationLabel.textColor = [[MDCPalette greyPalette] tint700];
180 203
181 [self applyConstraints]; 204 [self applyConstraints];
182 } 205 }
183 return self; 206 return self;
184 } 207 }
185 208
186 - (void)setContentImage:(UIImage*)image { 209 - (void)setContentImage:(UIImage*)image {
187 if (!image) { 210 if (!image) {
188 self.contentImageView.hidden = YES; 211 self.contentImageView.hidden = YES;
189 return; 212 return;
190 } 213 }
191 214
192 self.contentImageView.image = image; 215 self.contentImageView.image = image;
193 216
194 self.contentImageView.alpha = 0; 217 self.contentImageView.alpha = 0;
195 self.contentImageView.hidden = NO; 218 self.contentImageView.hidden = NO;
196 219
197 [UIView animateWithDuration:kAnimationDuration 220 [UIView animateWithDuration:kAnimationDuration
198 animations:^{ 221 animations:^{
199 self.contentImageView.alpha = 1; 222 self.contentImageView.alpha = 1;
200 }]; 223 }];
201 } 224 }
202 225
203 - (void)setPublisherName:(NSString*)publisherName date:(base::Time)publishDate { 226 - (void)setAdditionalInformationWithPublisherName:(NSString*)publisherName
227 date:(base::Time)publishDate
228 offlineAvailability:(BOOL)availableOffline {
204 NSDate* date = [NSDate dateWithTimeIntervalSince1970:publishDate.ToDoubleT()]; 229 NSDate* date = [NSDate dateWithTimeIntervalSince1970:publishDate.ToDoubleT()];
205 NSString* dateString = 230 NSString* dateString =
206 [NSDateFormatter localizedStringFromDate:date 231 [NSDateFormatter localizedStringFromDate:date
207 dateStyle:NSDateFormatterMediumStyle 232 dateStyle:NSDateFormatterMediumStyle
208 timeStyle:NSDateFormatterNoStyle]; 233 timeStyle:NSDateFormatterNoStyle];
209 234
210 self.publisherLabel.text = AdjustStringForLocaleDirection( 235 NSString* publisherString = AdjustStringForLocaleDirection(
211 [NSString stringWithFormat:@"%@ - %@.", publisherName, dateString]); 236 [NSString stringWithFormat:@"%@ - %@ ", publisherName, dateString]);
237
238 NSMutableAttributedString* additionInformation =
239 [[NSMutableAttributedString alloc] initWithString:publisherString
240 attributes:nil];
241
242 if (availableOffline) {
243 NSTextAttachment* offlineIcon = [[NSTextAttachment alloc] init];
244 offlineIcon.image = [[UIImage imageNamed:kOfflineIconName]
245 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
246 offlineIcon.bounds = CGRectMake(
247 0, (_additionalInformationLabel.font.xHeight - kOfflineIconSize) / 2,
248 kOfflineIconSize, kOfflineIconSize);
249
250 [additionInformation
251 appendAttributedString:[NSAttributedString
252 attributedStringWithAttachment:offlineIcon]];
253 }
254
255 self.additionalInformationLabel.attributedText = additionInformation;
212 } 256 }
213 257
258 - (void)setSubtitleText:(NSString*)subtitle {
259 self.subtitleLabel.text = subtitle;
260 if (subtitle.length > 0) {
261 self.titleSubtitleSpacing.constant = kSmallSpacing;
262 } else {
263 self.titleSubtitleSpacing.constant = 0;
264 }
265 }
266
267 - (void)setDisplayImage:(BOOL)displayImage {
268 if (displayImage) {
269 self.imageTitleSpacing.constant = kStandardSpacing;
270 self.imageSize.constant = kImageSize;
271 self.imageContainer.hidden = NO;
272 } else {
273 self.imageSize.constant = 0;
jif 2017/05/10 09:06:19 initialize the variables in the same order please
gambard 2017/05/10 09:23:27 Done.
274 self.imageTitleSpacing.constant = 0;
275 self.imageContainer.hidden = YES;
276 }
277 _displayImage = displayImage;
278 }
279
280 #pragma mark - UICollectionViewCell
281
214 - (void)prepareForReuse { 282 - (void)prepareForReuse {
215 self.contentImageView.hidden = YES; 283 self.contentImageView.hidden = YES;
216 } 284 }
217 285
218 #pragma mark - UIView 286 #pragma mark - UIView
219 287
220 // Implements -layoutSubviews as per instructions in documentation for 288 // Implements -layoutSubviews as per instructions in documentation for
221 // +[MDCCollectionViewCell cr_preferredHeightForWidth:forItem:]. 289 // +[MDCCollectionViewCell cr_preferredHeightForWidth:forItem:].
222 - (void)layoutSubviews { 290 - (void)layoutSubviews {
223 [super layoutSubviews]; 291 [super layoutSubviews];
224 292
225 // Adjust the text label preferredMaxLayoutWidth when the parent's width 293 // Adjust the text label preferredMaxLayoutWidth when the parent's width
226 // changes, for instance on screen rotation. 294 // changes, for instance on screen rotation.
227 CGFloat parentWidth = CGRectGetWidth(self.contentView.bounds); 295 CGFloat parentWidth = CGRectGetWidth(self.contentView.bounds);
228 296
297 CGFloat offset = 0;
298 if (self.displayImage) {
299 offset = kImageSize + kStandardSpacing;
300 }
301
229 self.titleLabel.preferredMaxLayoutWidth = 302 self.titleLabel.preferredMaxLayoutWidth =
230 parentWidth - kImageSize - 3 * kStandardSpacing; 303 parentWidth - 2 * kStandardSpacing - offset;
231 self.subtitleLabel.preferredMaxLayoutWidth = 304 self.subtitleLabel.preferredMaxLayoutWidth =
232 parentWidth - kImageSize - 3 * kStandardSpacing; 305 parentWidth - 2 * kStandardSpacing - offset;
233 self.publisherLabel.preferredMaxLayoutWidth = 306 self.additionalInformationLabel.preferredMaxLayoutWidth =
234 parentWidth - kFaviconSize - kSmallSpacing - 2 * kStandardSpacing; 307 parentWidth - kFaviconSize - kSmallSpacing - 2 * kStandardSpacing;
235 308
236 // Re-layout with the new preferred width to allow the label to adjust its 309 // Re-layout with the new preferred width to allow the label to adjust its
237 // height. 310 // height.
238 [super layoutSubviews]; 311 [super layoutSubviews];
239 } 312 }
240 313
241 #pragma mark - Private 314 #pragma mark - Private
242 315
243 - (void)applyConstraints { 316 - (void)applyConstraints {
317 _imageSize =
318 [_imageContainer.heightAnchor constraintEqualToConstant:kImageSize];
319 _imageTitleSpacing = [_imageContainer.leadingAnchor
320 constraintEqualToAnchor:_titleLabel.trailingAnchor
321 constant:kStandardSpacing];
322 _titleSubtitleSpacing =
323 [_subtitleLabel.topAnchor constraintEqualToAnchor:_titleLabel.bottomAnchor
324 constant:kSmallSpacing];
325
244 [NSLayoutConstraint activateConstraints:@[ 326 [NSLayoutConstraint activateConstraints:@[
245 [_imageContainer.widthAnchor constraintEqualToConstant:kImageSize], 327 // Image.
246 [_imageContainer.heightAnchor 328 _imageSize,
247 constraintEqualToAnchor:_imageContainer.widthAnchor], 329 [_imageContainer.widthAnchor
330 constraintEqualToAnchor:_imageContainer.heightAnchor],
248 [_imageContainer.topAnchor constraintEqualToAnchor:_titleLabel.topAnchor], 331 [_imageContainer.topAnchor constraintEqualToAnchor:_titleLabel.topAnchor],
249 332
250 // Publisher. 333 // Text.
251 [_publisherLabel.topAnchor 334 _imageTitleSpacing, _titleSubtitleSpacing,
335 [_titleLabel.trailingAnchor
336 constraintEqualToAnchor:_subtitleLabel.trailingAnchor],
337
338 // Additional Information.
339 [_additionalInformationLabel.topAnchor
252 constraintGreaterThanOrEqualToAnchor:_imageContainer.bottomAnchor 340 constraintGreaterThanOrEqualToAnchor:_imageContainer.bottomAnchor
253 constant:kStandardSpacing], 341 constant:kStandardSpacing],
254 [_publisherLabel.topAnchor 342 [_additionalInformationLabel.topAnchor
255 constraintGreaterThanOrEqualToAnchor:_subtitleLabel.bottomAnchor 343 constraintGreaterThanOrEqualToAnchor:_subtitleLabel.bottomAnchor
256 constant:kStandardSpacing], 344 constant:kStandardSpacing],
257 [_publisherLabel.bottomAnchor 345 [_additionalInformationLabel.bottomAnchor
258 constraintLessThanOrEqualToAnchor:self.contentView.bottomAnchor 346 constraintLessThanOrEqualToAnchor:self.contentView.bottomAnchor
259 constant:-kStandardSpacing], 347 constant:-kStandardSpacing],
260 348
261 // Favicon. 349 // Favicon.
262 [_faviconView.topAnchor 350 [_faviconView.topAnchor
263 constraintGreaterThanOrEqualToAnchor:_imageContainer.bottomAnchor 351 constraintGreaterThanOrEqualToAnchor:_imageContainer.bottomAnchor
264 constant:kStandardSpacing], 352 constant:kStandardSpacing],
265 [_faviconView.topAnchor 353 [_faviconView.topAnchor
266 constraintGreaterThanOrEqualToAnchor:_subtitleLabel.bottomAnchor 354 constraintGreaterThanOrEqualToAnchor:_subtitleLabel.bottomAnchor
267 constant:kStandardSpacing], 355 constant:kStandardSpacing],
268 [_faviconView.centerYAnchor 356 [_faviconView.centerYAnchor
269 constraintEqualToAnchor:_publisherLabel.centerYAnchor], 357 constraintEqualToAnchor:_additionalInformationLabel.centerYAnchor],
270 [_faviconView.bottomAnchor 358 [_faviconView.bottomAnchor
271 constraintLessThanOrEqualToAnchor:self.contentView.bottomAnchor 359 constraintLessThanOrEqualToAnchor:self.contentView.bottomAnchor
272 constant:-kStandardSpacing], 360 constant:-kStandardSpacing],
273 [_faviconView.heightAnchor constraintEqualToConstant:kFaviconSize], 361 [_faviconView.heightAnchor constraintEqualToConstant:kFaviconSize],
274 [_faviconView.widthAnchor 362 [_faviconView.widthAnchor
275 constraintEqualToAnchor:_faviconView.heightAnchor], 363 constraintEqualToAnchor:_faviconView.heightAnchor],
276 364
277 // No image icon. 365 // No image icon.
278 [_noImageIcon.centerXAnchor 366 [_noImageIcon.centerXAnchor
279 constraintEqualToAnchor:_imageContainer.centerXAnchor], 367 constraintEqualToAnchor:_imageContainer.centerXAnchor],
280 [_noImageIcon.centerYAnchor 368 [_noImageIcon.centerYAnchor
281 constraintEqualToAnchor:_imageContainer.centerYAnchor], 369 constraintEqualToAnchor:_imageContainer.centerYAnchor],
282 [_noImageIcon.widthAnchor constraintEqualToConstant:kIconSize], 370 [_noImageIcon.widthAnchor constraintEqualToConstant:kIconSize],
283 [_noImageIcon.heightAnchor constraintEqualToAnchor:_noImageIcon.widthAnchor] 371 [_noImageIcon.heightAnchor constraintEqualToAnchor:_noImageIcon.widthAnchor]
284 ]]; 372 ]];
285 373
286 AddSameConstraints(_contentImageView, _imageContainer); 374 AddSameConstraints(_contentImageView, _imageContainer);
287 375
288 ApplyVisualConstraintsWithMetrics( 376 ApplyVisualConstraintsWithMetrics(
289 @[ 377 @[
290 @"H:|-(space)-[title]-(space)-[image]-(space)-|", 378 @"H:|-(space)-[title]",
291 @"H:|-(space)-[text]-(space)-[image]", 379 @"H:[image]-(space)-|",
292 @"V:|-(space)-[title]-[text]", 380 @"H:|-(space)-[text]",
293 @"H:|-(space)-[favicon]-(small)-[publish]-(space)-|", 381 @"V:|-(space)-[title]",
382 @"H:|-(space)-[favicon]-(small)-[additional]-(space)-|",
294 ], 383 ],
295 @{ 384 @{
296 @"image" : _imageContainer, 385 @"image" : _imageContainer,
297 @"title" : _titleLabel, 386 @"title" : _titleLabel,
298 @"text" : _subtitleLabel, 387 @"text" : _subtitleLabel,
299 @"publish" : _publisherLabel, 388 @"additional" : _additionalInformationLabel,
300 @"favicon" : _faviconView, 389 @"favicon" : _faviconView,
301 }, 390 },
302 @{ @"space" : @(kStandardSpacing), 391 @{ @"space" : @(kStandardSpacing),
303 @"small" : @(kSmallSpacing) }); 392 @"small" : @(kSmallSpacing) });
304 } 393 }
305 394
306 @end 395 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698