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

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

Issue 2770113006: Add no-image image in ContentSuggestions (Closed)
Patch Set: Add prepare for reuse Created 3 years, 9 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_art icle_item.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/uikit_ui_util.h" 9 #import "ios/chrome/browser/ui/uikit_ui_util.h"
10 #import "ios/chrome/browser/ui/util/i18n_string.h" 10 #import "ios/chrome/browser/ui/util/i18n_string.h"
11 #import "ios/third_party/material_components_ios/src/components/Palettes/src/Mat erialPalettes.h"
11 #import "ios/third_party/material_components_ios/src/components/Typography/src/M aterialTypography.h" 12 #import "ios/third_party/material_components_ios/src/components/Typography/src/M aterialTypography.h"
12 #include "url/gurl.h" 13 #include "url/gurl.h"
13 14
14 #if !defined(__has_feature) || !__has_feature(objc_arc) 15 #if !defined(__has_feature) || !__has_feature(objc_arc)
15 #error "This file requires ARC support." 16 #error "This file requires ARC support."
16 #endif 17 #endif
17 18
18 namespace { 19 namespace {
19 const CGFloat kImageSize = 72; 20 const CGFloat kImageSize = 72;
20 // When updating this, make sure to update |layoutSubviews|. 21 // When updating this, make sure to update |layoutSubviews|.
21 const CGFloat kStandardSpacing = 16; 22 const CGFloat kStandardSpacing = 16;
23 // Size of the icon displayed when there is not image.
24 const CGFloat kIconSize = 24;
25 // Name of the image.
26 NSString* const kImageName = @"content_suggestions_no_image";
jif 2017/03/28 09:04:58 kImageName can be made more precise. Possible repl
gambard 2017/03/28 09:40:29 The backend service use "fetchSuggestionImage". I
27 // No image icon percentage of white.
28 const CGFloat kImageWhite = 0.38;
29 // No image background percentage of white.
30 const CGFloat kBackgroundWhite = 0.95;
31 const CGFloat kAnimationDuration = 0.3;
22 } 32 }
23 33
24 @interface ContentSuggestionsArticleItem () 34 @interface ContentSuggestionsArticleItem ()
25 35
26 @property(nonatomic, copy) NSString* subtitle; 36 @property(nonatomic, copy) NSString* subtitle;
27 // Used to check if the image has already been fetched. There is no way to 37 // Used to check if the image has already been fetched. There is no way to
28 // discriminate between failed image download and nonexitent image. The article 38 // discriminate between failed image download and nonexitent image. The article
29 // tries to download the image only once. 39 // tries to download the image only once.
30 @property(nonatomic, assign) BOOL imageFetched; 40 @property(nonatomic, assign) BOOL imageFetched;
31 41
(...skipping 18 matching lines...) Expand all
50 subtitle:(NSString*)subtitle 60 subtitle:(NSString*)subtitle
51 delegate:(id<ContentSuggestionsArticleItemDelegate>)delegate 61 delegate:(id<ContentSuggestionsArticleItemDelegate>)delegate
52 url:(const GURL&)url { 62 url:(const GURL&)url {
53 self = [super initWithType:type]; 63 self = [super initWithType:type];
54 if (self) { 64 if (self) {
55 self.cellClass = [ContentSuggestionsArticleCell class]; 65 self.cellClass = [ContentSuggestionsArticleCell class];
56 _title = [title copy]; 66 _title = [title copy];
57 _subtitle = [subtitle copy]; 67 _subtitle = [subtitle copy];
58 _articleURL = url; 68 _articleURL = url;
59 _delegate = delegate; 69 _delegate = delegate;
60 _image = [self emptyImageBackground];
61 } 70 }
62 return self; 71 return self;
63 } 72 }
64 73
65 - (void)configureCell:(ContentSuggestionsArticleCell*)cell { 74 - (void)configureCell:(ContentSuggestionsArticleCell*)cell {
66 [super configureCell:cell]; 75 [super configureCell:cell];
67 if (!self.imageFetched) { 76 if (!self.imageFetched) {
68 self.imageFetched = YES; 77 self.imageFetched = YES;
69 // Fetch the image. During the fetch the cell's image should still be set. 78 // Fetch the image. During the fetch the cell's image should still be set.
70 [self.delegate loadImageForArticleItem:self]; 79 [self.delegate loadImageForArticleItem:self];
71 } 80 }
72 cell.titleLabel.text = self.title; 81 cell.titleLabel.text = self.title;
73 cell.subtitleLabel.text = self.subtitle; 82 cell.subtitleLabel.text = self.subtitle;
74 cell.imageView.image = self.image; 83 if (self.image)
jif 2017/03/28 09:04:58 we are already checking in |setContentImage| if it
gambard 2017/03/28 09:40:29 Done.
84 [cell setContentImage:self.image];
75 [cell setPublisherName:self.publisher date:self.publishDate]; 85 [cell setPublisherName:self.publisher date:self.publishDate];
76 } 86 }
77 87
78 #pragma mark - Private
79
80 - (UIImage*)emptyImageBackground {
81 // TODO(crbug.com/698171): Remove this function once we have real background
82 // image.
83 UIColor* color = [UIColor lightGrayColor];
84 CGRect rect = CGRectMake(0, 0, 1, 1);
85 UIGraphicsBeginImageContext(rect.size);
86 [color setFill];
87 UIRectFill(rect);
88 UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
89 UIGraphicsEndImageContext();
90 return image;
91 }
92
93 @end 88 @end
94 89
95 #pragma mark - ContentSuggestionsArticleCell 90 #pragma mark - ContentSuggestionsArticleCell
96 91
97 @interface ContentSuggestionsArticleCell () 92 @interface ContentSuggestionsArticleCell ()
98 93
99 @property(nonatomic, strong) UILabel* publisherLabel; 94 @property(nonatomic, strong) UILabel* publisherLabel;
95 @property(nonatomic, strong) UIView* imageContainer;
96 @property(nonatomic, strong) UIImageView* noImageIcon;
97 @property(nonatomic, strong) UIImageView* contentImageView;
100 98
101 // Applies the constraints on the elements. Called in the init. 99 // Applies the constraints on the elements. Called in the init.
102 - (void)applyConstraints; 100 - (void)applyConstraints;
103 101
104 @end 102 @end
105 103
106 @implementation ContentSuggestionsArticleCell 104 @implementation ContentSuggestionsArticleCell
107 105
108 @synthesize titleLabel = _titleLabel; 106 @synthesize titleLabel = _titleLabel;
109 @synthesize subtitleLabel = _subtitleLabel; 107 @synthesize subtitleLabel = _subtitleLabel;
110 @synthesize imageView = _imageView; 108 @synthesize imageContainer = _imageContainer;
109 @synthesize noImageIcon = _noImageIcon;
111 @synthesize publisherLabel = _publisherLabel; 110 @synthesize publisherLabel = _publisherLabel;
111 @synthesize contentImageView = _contentImageView;
112 112
113 - (instancetype)initWithFrame:(CGRect)frame { 113 - (instancetype)initWithFrame:(CGRect)frame {
114 self = [super initWithFrame:frame]; 114 self = [super initWithFrame:frame];
115 if (self) { 115 if (self) {
116 _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 116 _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
117 _subtitleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 117 _subtitleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
118 _imageView = [[UIImageView alloc] initWithFrame:CGRectZero]; 118 _imageContainer = [[UIView alloc] initWithFrame:CGRectZero];
119 _noImageIcon = [[UIImageView alloc] initWithFrame:CGRectZero];
119 _publisherLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 120 _publisherLabel = [[UILabel alloc] initWithFrame:CGRectZero];
120 121
121 _titleLabel.numberOfLines = 2; 122 _titleLabel.numberOfLines = 2;
122 _subtitleLabel.numberOfLines = 2; 123 _subtitleLabel.numberOfLines = 2;
123 [_subtitleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh 124 [_subtitleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh
124 forAxis:UILayoutConstraintAxisVertical]; 125 forAxis:UILayoutConstraintAxisVertical];
125 [_titleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh 126 [_titleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh
126 forAxis:UILayoutConstraintAxisVertical]; 127 forAxis:UILayoutConstraintAxisVertical];
127 _imageView.contentMode = UIViewContentModeScaleAspectFill;
128 _imageView.clipsToBounds = YES;
129 128
130 _imageView.translatesAutoresizingMaskIntoConstraints = NO; 129 _imageContainer.translatesAutoresizingMaskIntoConstraints = NO;
130 _noImageIcon.translatesAutoresizingMaskIntoConstraints = NO;
131 _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; 131 _titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
132 _subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO; 132 _subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
133 _publisherLabel.translatesAutoresizingMaskIntoConstraints = NO; 133 _publisherLabel.translatesAutoresizingMaskIntoConstraints = NO;
134 134
135 [self.contentView addSubview:_imageView]; 135 [self.contentView addSubview:_imageContainer];
136 [self.contentView addSubview:_titleLabel]; 136 [self.contentView addSubview:_titleLabel];
137 [self.contentView addSubview:_subtitleLabel]; 137 [self.contentView addSubview:_subtitleLabel];
138 [self.contentView addSubview:_publisherLabel]; 138 [self.contentView addSubview:_publisherLabel];
139 139
140 [_imageContainer addSubview:_noImageIcon];
141
142 _imageContainer.backgroundColor =
143 [UIColor colorWithWhite:kBackgroundWhite alpha:1];
144 _noImageIcon.image = [[UIImage imageNamed:kImageName]
145 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
146 [_noImageIcon setTintColor:[UIColor colorWithWhite:kImageWhite alpha:1]];
147
140 _titleLabel.font = [MDCTypography subheadFont]; 148 _titleLabel.font = [MDCTypography subheadFont];
141 _subtitleLabel.font = [MDCTypography body1Font]; 149 _subtitleLabel.font = [MDCTypography body1Font];
142 _publisherLabel.font = [MDCTypography captionFont]; 150 _publisherLabel.font = [MDCTypography captionFont];
143 151
144 _subtitleLabel.textColor = [[MDCPalette greyPalette] tint700]; 152 _subtitleLabel.textColor = [[MDCPalette greyPalette] tint700];
145 _publisherLabel.textColor = [[MDCPalette greyPalette] tint700]; 153 _publisherLabel.textColor = [[MDCPalette greyPalette] tint700];
146 154
147 [self applyConstraints]; 155 [self applyConstraints];
148 } 156 }
149 return self; 157 return self;
150 } 158 }
151 159
160 - (void)setContentImage:(UIImage*)image {
161 if (!image)
162 return;
163 self.contentImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
164 self.contentImageView.translatesAutoresizingMaskIntoConstraints = NO;
165 self.contentImageView.contentMode = UIViewContentModeScaleAspectFill;
166 self.contentImageView.clipsToBounds = YES;
167 self.contentImageView.image = image;
168
169 self.contentImageView.alpha = 0;
170 [self.imageContainer addSubview:self.contentImageView];
171 AddSameSizeConstraint(self.contentImageView, self.imageContainer);
172
173 [UIView animateWithDuration:kAnimationDuration
174 animations:^{
175 self.contentImageView.alpha = 1;
176 }];
177 }
178
152 - (void)setPublisherName:(NSString*)publisherName date:(base::Time)publishDate { 179 - (void)setPublisherName:(NSString*)publisherName date:(base::Time)publishDate {
153 NSDate* date = [NSDate dateWithTimeIntervalSince1970:publishDate.ToDoubleT()]; 180 NSDate* date = [NSDate dateWithTimeIntervalSince1970:publishDate.ToDoubleT()];
154 NSString* dateString = 181 NSString* dateString =
155 [NSDateFormatter localizedStringFromDate:date 182 [NSDateFormatter localizedStringFromDate:date
156 dateStyle:NSDateFormatterMediumStyle 183 dateStyle:NSDateFormatterMediumStyle
157 timeStyle:NSDateFormatterNoStyle]; 184 timeStyle:NSDateFormatterNoStyle];
158 185
159 self.publisherLabel.text = AdjustStringForLocaleDirection( 186 self.publisherLabel.text = AdjustStringForLocaleDirection(
160 [NSString stringWithFormat:@"%@ - %@.", publisherName, dateString]); 187 [NSString stringWithFormat:@"%@ - %@.", publisherName, dateString]);
161 } 188 }
162 189
190 - (void)prepareForReuse {
191 [self.contentImageView removeFromSuperview];
192 }
193
163 #pragma mark - UIView 194 #pragma mark - UIView
164 195
165 // Implements -layoutSubviews as per instructions in documentation for 196 // Implements -layoutSubviews as per instructions in documentation for
166 // +[MDCCollectionViewCell cr_preferredHeightForWidth:forItem:]. 197 // +[MDCCollectionViewCell cr_preferredHeightForWidth:forItem:].
167 - (void)layoutSubviews { 198 - (void)layoutSubviews {
168 [super layoutSubviews]; 199 [super layoutSubviews];
169 200
170 // Adjust the text label preferredMaxLayoutWidth when the parent's width 201 // Adjust the text label preferredMaxLayoutWidth when the parent's width
171 // changes, for instance on screen rotation. 202 // changes, for instance on screen rotation.
172 CGFloat parentWidth = CGRectGetWidth(self.contentView.bounds); 203 CGFloat parentWidth = CGRectGetWidth(self.contentView.bounds);
173 204
174 self.titleLabel.preferredMaxLayoutWidth = 205 self.titleLabel.preferredMaxLayoutWidth =
175 parentWidth - kImageSize - 3 * kStandardSpacing; 206 parentWidth - kImageSize - 3 * kStandardSpacing;
176 self.subtitleLabel.preferredMaxLayoutWidth = 207 self.subtitleLabel.preferredMaxLayoutWidth =
177 parentWidth - kImageSize - 3 * kStandardSpacing; 208 parentWidth - kImageSize - 3 * kStandardSpacing;
178 209
179 // Re-layout with the new preferred width to allow the label to adjust its 210 // Re-layout with the new preferred width to allow the label to adjust its
180 // height. 211 // height.
181 [super layoutSubviews]; 212 [super layoutSubviews];
182 } 213 }
183 214
184 #pragma mark - Private 215 #pragma mark - Private
185 216
186 - (void)applyConstraints { 217 - (void)applyConstraints {
187 [NSLayoutConstraint activateConstraints:@[ 218 [NSLayoutConstraint activateConstraints:@[
188 [_imageView.widthAnchor constraintEqualToConstant:kImageSize], 219 [_imageContainer.widthAnchor constraintEqualToConstant:kImageSize],
189 [_imageView.heightAnchor constraintEqualToAnchor:_imageView.widthAnchor], 220 [_imageContainer.heightAnchor
190 [_imageView.topAnchor constraintEqualToAnchor:_titleLabel.topAnchor], 221 constraintEqualToAnchor:_imageContainer.widthAnchor],
222 [_imageContainer.topAnchor constraintEqualToAnchor:_titleLabel.topAnchor],
191 [_publisherLabel.topAnchor 223 [_publisherLabel.topAnchor
192 constraintGreaterThanOrEqualToAnchor:_imageView.bottomAnchor 224 constraintGreaterThanOrEqualToAnchor:_imageContainer.bottomAnchor
193 constant:kStandardSpacing], 225 constant:kStandardSpacing],
194 [_publisherLabel.topAnchor 226 [_publisherLabel.topAnchor
195 constraintGreaterThanOrEqualToAnchor:_subtitleLabel.bottomAnchor 227 constraintGreaterThanOrEqualToAnchor:_subtitleLabel.bottomAnchor
196 constant:kStandardSpacing], 228 constant:kStandardSpacing],
229
230 // No image icon.
231 [_noImageIcon.centerXAnchor
232 constraintEqualToAnchor:_imageContainer.centerXAnchor],
233 [_noImageIcon.centerYAnchor
234 constraintEqualToAnchor:_imageContainer.centerYAnchor],
235 [_noImageIcon.widthAnchor constraintEqualToConstant:kIconSize],
236 [_noImageIcon.heightAnchor constraintEqualToAnchor:_noImageIcon.widthAnchor]
197 ]]; 237 ]];
198 238
199 ApplyVisualConstraintsWithMetrics( 239 ApplyVisualConstraintsWithMetrics(
200 @[ 240 @[
201 @"H:|-(space)-[title]-(space)-[image]-(space)-|", 241 @"H:|-(space)-[title]-(space)-[image]-(space)-|",
202 @"H:|-(space)-[text]-(space)-[image]", 242 @"H:|-(space)-[text]-(space)-[image]",
203 @"V:|-(space)-[title]-[text]", 243 @"V:|-(space)-[title]-[text]",
204 @"H:|-(space)-[publish]-(space)-|", 244 @"H:|-(space)-[publish]-(space)-|",
205 @"V:[publish]-|", 245 @"V:[publish]-|",
206 ], 246 ],
207 @{ 247 @{
208 @"image" : _imageView, 248 @"image" : _imageContainer,
209 @"title" : _titleLabel, 249 @"title" : _titleLabel,
210 @"text" : _subtitleLabel, 250 @"text" : _subtitleLabel,
211 @"publish" : _publisherLabel, 251 @"publish" : _publisherLabel,
212 }, 252 },
213 @{ @"space" : @(kStandardSpacing) }); 253 @{ @"space" : @(kStandardSpacing) });
214 } 254 }
215 255
216 @end 256 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698