From 6ee0e66d56f02c4b534dd83fca24cb0c1f408f06 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Sat, 1 Feb 2014 19:47:09 +0400 Subject: 0ld-zkul hax0r manual cell layout --- Juick/0.png | Bin 0 -> 1586 bytes Juick/Juick-Info.plist | 4 +- Juick/MessageCell.h | 17 +++-- Juick/MessageCell.m | 158 +++++++++++++++++++++-------------------- Juick/MessagesViewController.m | 35 +++------ Juick/UIImage+Utils.h | 19 +++++ Juick/UIImage+Utils.m | 69 ++++++++++++++++++ 7 files changed, 194 insertions(+), 108 deletions(-) create mode 100644 Juick/0.png create mode 100644 Juick/UIImage+Utils.h create mode 100644 Juick/UIImage+Utils.m (limited to 'Juick') diff --git a/Juick/0.png b/Juick/0.png new file mode 100644 index 0000000..7f2f7ac Binary files /dev/null and b/Juick/0.png differ diff --git a/Juick/Juick-Info.plist b/Juick/Juick-Info.plist index 06e7432..f89e3d3 100644 --- a/Juick/Juick-Info.plist +++ b/Juick/Juick-Info.plist @@ -17,11 +17,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0.7 + 1.0.10 CFBundleSignature ???? CFBundleVersion - 1.0.7 + 1.0.10 LSApplicationCategoryType public.app-category.social-networking LSRequiresIPhoneOS diff --git a/Juick/MessageCell.h b/Juick/MessageCell.h index 7972470..a042ff3 100644 --- a/Juick/MessageCell.h +++ b/Juick/MessageCell.h @@ -7,26 +7,35 @@ // #import +#import #import "TTTAttributedLabel.h" #import "Message.h" #import "NSString+HTML.h" +#import "UIImage+Utils.h" #define kLabelHorizontalInsets 20.0f +@interface MessageCell : UITableViewCell -@interface MessageCell : UITableViewCell - +@property (strong, nonatomic) IBOutlet Message *message; @property (strong, nonatomic) IBOutlet UILabel *titleLabel; @property (strong, nonatomic) IBOutlet UILabel *timestampLabel; @property (strong, nonatomic) IBOutlet UIImageView *avatar; -@property (strong, nonatomic) IBOutlet TTTAttributedLabel *bodyLabel; +@property (strong, nonatomic) IBOutlet UILabel *bodyLabel; @property (strong, nonatomic) IBOutlet UIImageView *attach; @property (strong, nonatomic) IBOutlet UILabel *summaryLabel; - (void) updateFonts; -- (void) bind:(Message *)msg; +- (CGRect) avatarRect; +- (CGRect) timestampRect; +- (CGRect) titleRect; +- (CGRect) bodyRect; +- (CGRect) attachRect; +- (CGRect) summaryRect; + +- (CGFloat) heightForCell; @end diff --git a/Juick/MessageCell.m b/Juick/MessageCell.m index d396181..8c2f001 100644 --- a/Juick/MessageCell.m +++ b/Juick/MessageCell.m @@ -8,14 +8,13 @@ #import "MessageCell.h" #import "ColorScheme.h" -#import #import "NSDate+TimeAgo.h" +#import "UIImage+Utils.h" -@interface MessageCell () - -@property (nonatomic, assign) BOOL didSetupConstraints; - -@end +#define kAvatarSizeX 32 +#define kAvatarSizeY 32 +#define kPaddingX 10 +#define kPaddingY 10 @implementation MessageCell @@ -24,8 +23,7 @@ self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { [self.contentView setBackgroundColor:[UIColor whiteColor]]; - self.contentView.bounds = CGRectMake(0, 0, 320, 999); - self.avatar = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 32, 32)]; + self.avatar = [[UIImageView alloc] initWithFrame:CGRectZero]; [self.avatar setBackgroundColor:[UIColor clearColor]]; self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; @@ -42,9 +40,9 @@ [self.timestampLabel setTextColor:[UIColor grayColor]]; [self.timestampLabel setBackgroundColor:[UIColor clearColor]]; - self.bodyLabel = [[TTTAttributedLabel alloc] initWithFrame:CGRectZero]; - self.bodyLabel.dataDetectorTypes = NSTextCheckingTypeLink; - self.bodyLabel.delegate = self; + self.bodyLabel = [[UILabel alloc] initWithFrame:CGRectZero]; + //self.bodyLabel.dataDetectorTypes = NSTextCheckingTypeLink; + //self.bodyLabel.delegate = self; [self.bodyLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; [self.bodyLabel setLineBreakMode:NSLineBreakByTruncatingTail]; [self.bodyLabel setNumberOfLines:0]; @@ -53,16 +51,15 @@ [self.bodyLabel setBackgroundColor:[UIColor clearColor]]; - self.summaryLabel = [[TTTAttributedLabel alloc] initWithFrame:CGRectZero]; - [self.summaryLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; + self.summaryLabel = [[UILabel alloc] initWithFrame:CGRectZero]; [self.summaryLabel setLineBreakMode:NSLineBreakByTruncatingTail]; [self.summaryLabel setNumberOfLines:1]; [self.summaryLabel setTextAlignment:NSTextAlignmentLeft]; [self.summaryLabel setTextColor:[UIColor grayColor]]; [self.summaryLabel setBackgroundColor:[UIColor clearColor]]; - self.attach = [[UIImageView alloc] initWithFrame:CGRectZero]; + self.attach = [[UIImageView alloc]initWithImage:[UIImage imageWithImage:[UIImage imageNamed:@"AttachPlaceholder.png"] convertToWidth:300.0f]]; [self.attach setBackgroundColor:[UIColor clearColor]]; - self.attach.contentMode = UIViewContentModeScaleAspectFit; + self.attach.contentMode = UIViewContentModeTopLeft; [self.contentView addSubview:self.avatar]; [self.contentView addSubview:self.titleLabel]; @@ -83,53 +80,65 @@ // Configure the view for the selected state } -- (void)updateConstraints { - [super updateConstraints]; - - if (self.didSetupConstraints) return; - - UIEdgeInsets padding = UIEdgeInsetsMake(10, 20, 10, 20); - - [self.avatar makeConstraints:^(MASConstraintMaker *make) { - make.top.equalTo(self.contentView.top).with.offset(padding.top); - make.left.equalTo(self.contentView.left).with.offset(padding.left); - make.width.equalTo(@32); - make.height.equalTo(@32); - }]; - - [self.titleLabel makeConstraints:^(MASConstraintMaker *make) { - make.left.equalTo(self.avatar.right).with.offset(padding.right); - make.top.equalTo(self.contentView.top).with.offset(padding.top); - make.right.equalTo(self.contentView.right).with.offset(-padding.right); - }]; - [self.timestampLabel makeConstraints:^(MASConstraintMaker *make) { - make.left.equalTo(self.avatar.right).with.offset(padding.left); - make.top.equalTo(self.titleLabel.bottom).with.offset(padding.top /2); - make.right.equalTo(self.contentView.right).with.offset(-padding.right); - }]; - - [self.bodyLabel makeConstraints:^(MASConstraintMaker *make) { - make.left.equalTo(self.contentView.left).with.offset(padding.left); - make.top.equalTo(self.timestampLabel.bottom).with.offset(padding.top); - make.right.equalTo(self.contentView.right).with.offset(-padding.right); - }]; - - [self.attach makeConstraints:^(MASConstraintMaker *make) { - make.left.equalTo(self.contentView.left).with.offset(padding.left); - make.right.equalTo(self.contentView.right).with.offset(-padding.right); - make.top.equalTo(self.bodyLabel.bottom).with.offset(padding.top); - }]; - - [self.summaryLabel makeConstraints:^(MASConstraintMaker *make) { - make.left.equalTo(self.contentView.left).with.offset(padding.left); - make.bottom.equalTo(self.contentView.bottom).with.offset(-padding.bottom); - make.right.equalTo(self.contentView.right).with.offset(-padding.right); - make.top.equalTo(self.attach.bottom).with.offset(padding.top); - }]; - - - - self.didSetupConstraints = YES; +- (CGRect) sizeForLabel:(UILabel *)label width:(CGFloat)width { + return [label.text boundingRectWithSize:(CGSize) {width, CGFLOAT_MAX} options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:label.font} context:nil]; +} + +- (CGRect) avatarRect { + return CGRectMake(kPaddingX, kPaddingY, kAvatarSizeX, kAvatarSizeY); +} + +- (CGRect) bodyRect { + CGRect bodySize = [self sizeForLabel:self.bodyLabel width:(self.contentView.bounds.size.width - kPaddingX * 2)]; + return CGRectMake(kPaddingX, kPaddingY + kAvatarSizeY + kPaddingY * 2, bodySize.size.width, bodySize.size.height); +} + +- (CGRect) titleRect { + CGRect titleSize = [self sizeForLabel:self.titleLabel width:self.contentView.bounds.size.width - [self avatarRect].size.width - kPaddingX * 2]; + return CGRectMake(kPaddingX + kAvatarSizeX + kPaddingX, kPaddingY, titleSize.size.width, titleSize.size.height); +} + +- (CGRect) timestampRect { + CGRect timeStampSize = [self sizeForLabel:self.timestampLabel width:self.contentView.bounds.size.width - [self avatarRect].size.width - kPaddingX * 2]; + return CGRectMake(kPaddingX + [self avatarRect].size.width + kPaddingX, kPaddingY + [self titleRect].size.height + kPaddingY, timeStampSize.size.width, timeStampSize.size.height); +} + +- (CGRect) summaryRect { + CGRect summarySize = [self sizeForLabel:self.summaryLabel width:(self.contentView.bounds.size.width - 20)]; + float summaryY = 10 + 32 + 10 + [self bodyRect].size.height + 10; + if (self.message.attach != nil) { + summaryY += [self attachRect].size.height + 10; + } + return CGRectMake(10, summaryY , summarySize.size.width, summarySize.size.height); +} + +- (CGRect) attachRect { + return CGRectMake(10, 10 + 32 + 10 + [self bodyRect].size.height + 10, self.attach.image.size.width, self.attach.image.size.height); +} + +- (CGFloat) heightForCell { + CGFloat baseSize = 10 + [self avatarRect].size.height + 20 + [self bodyRect].size.height + 10; + if (self.message.repliesCount > 0) { + baseSize += 10 + [self summaryRect].size.height; + } + if (self.attach.image != nil) { + baseSize += 10 + [self attachRect].size.height + 10; + } + return baseSize; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + self.avatar.frame = [self avatarRect]; + self.titleLabel.frame = [self titleRect]; + self.timestampLabel.frame = [self timestampRect]; + self.bodyLabel.frame = [self bodyRect]; + if (self.message.repliesCount > 0) { + self.summaryLabel.frame = [self summaryRect]; + } + if (self.message.attach != nil) { + self.attach.frame = [self attachRect]; + } } @@ -143,8 +152,9 @@ } } -- (void) bind:(Message *)msg { - [self.avatar setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://i.juick.com/as/%d.png", [msg.userID intValue]]]]; +- (void) setMessage:(Message *)msg { + _message = msg; + [self.avatar setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://i.juick.com/as/%d.png", [msg.userID intValue]]] placeholderImage:[UIImage imageNamed:@"0.png"] options:SDWebImageContinueInBackground]; __weak MessageCell *weakSelf = self; self.titleLabel.text = msg.user; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; @@ -167,22 +177,18 @@ [msg.text stringByDecodingHTMLEntities]]; } if ([msg.attach length] > 0) { - [self.attach setImageWithURL:[NSURL URLWithString:msg.attach] placeholderImage:[UIImage imageNamed:@"AttachPlaceholder.png"] options:SDWebImageContinueInBackground - progress:^(NSUInteger receivedSize, long long expectedSize) { - // <#code#> - } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) { - [weakSelf setNeedsUpdateConstraints]; - [weakSelf updateConstraintsIfNeeded]; - [weakSelf.contentView setNeedsLayout]; - [weakSelf.contentView layoutIfNeeded]; + SDWebImageManager * manager = [SDWebImageManager sharedManager]; + [manager downloadWithURL:[NSURL URLWithString:msg.attach] options:SDWebImageContinueInBackground progress:^(NSUInteger receivedSize, long long expectedSize) { + // <#code#> + } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished) { + self.attach.image = [UIImage imageWithImage:image convertToWidth:300.0f]; + [self setNeedsLayout]; + [self layoutIfNeeded]; }]; } else { self.attach.image = nil; } - [weakSelf setNeedsUpdateConstraints]; - [weakSelf updateConstraintsIfNeeded]; - [weakSelf.contentView setNeedsLayout]; - [weakSelf.contentView layoutIfNeeded]; + [self setNeedsLayout]; } - (void) attributedLabel:(TTTAttributedLabel *)label didSelectLinkWithURL:(NSURL *)url { diff --git a/Juick/MessagesViewController.m b/Juick/MessagesViewController.m index 6930de8..e8e02e1 100644 --- a/Juick/MessagesViewController.m +++ b/Juick/MessagesViewController.m @@ -27,7 +27,6 @@ static NSString *CellIdentifier = @"MessageCell"; @property(nonatomic, assign) Boolean dataLoading; @property(nonatomic, strong) NSString *path; @property(nonatomic, strong) NSMutableDictionary *params; -@property(nonatomic, strong) MessageCell *sizingCell; @end @@ -36,7 +35,7 @@ static NSString *CellIdentifier = @"MessageCell"; - (void)loadFromPath:(NSString *)messagesPath withParams:(NSDictionary *)params withTitle:(NSString *)title { [self setPath:messagesPath]; - [self setParams:params]; + [self setParams:[[NSMutableDictionary alloc] initWithDictionary:params]]; self.title = title; [self refreshData:nil]; } @@ -47,12 +46,11 @@ static NSString *CellIdentifier = @"MessageCell"; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ self.dataLoading = YES; [Message pullNextFromPath:self.path params:self.params callback:^(NSArray *next) { - dispatch_async(dispatch_get_main_queue(), ^{ [self.messages addObjectsFromArray:next]; [self.tableView reloadData]; [refresh endRefreshing]; self.dataLoading = NO; - }); + }]; }); } @@ -80,11 +78,10 @@ static NSString *CellIdentifier = @"MessageCell"; [self.params setObject:lastMessage.MID forKey:@"before_mid"]; } [Message pullNextFromPath:self.path params:self.params callback:^(NSArray *next) { - dispatch_async(dispatch_get_main_queue(), ^{ [self.messages addObjectsFromArray:next]; [self.tableView reloadData]; self.dataLoading = NO; - }); + }]; }); @@ -109,12 +106,7 @@ static NSString *CellIdentifier = @"MessageCell"; self.navigationController.navigationBar.tintColor = [ColorScheme navbarBackground]; } - [self.tableView registerClass:[MessageCell class] forCellReuseIdentifier:CellIdentifier]; - self.sizingCell = [[MessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; - self.sizingCell.hidden = YES; - [self.tableView addSubview:self.sizingCell]; - - self.sizingCell.frame = CGRectMake(0, 0, CGRectGetWidth(self.tableView.bounds), 0); + [self.tableView registerClass:[MessageCell class] forCellReuseIdentifier:CellIdentifier]; } - (void) composePressed { @@ -171,26 +163,17 @@ static NSString *CellIdentifier = @"MessageCell"; MessageCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; [cell updateFonts]; Message *msg = [_messages objectAtIndex:indexPath.row]; - [cell bind:msg]; - - [cell.contentView layoutIfNeeded]; + [cell setMessage:msg]; return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - [self.sizingCell updateFonts]; - + MessageCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + [cell updateFonts]; Message *msg = [_messages objectAtIndex:indexPath.row]; - - [self.sizingCell bind:msg]; - - [self.sizingCell setNeedsLayout]; - [self.sizingCell layoutIfNeeded]; - - CGFloat calculatedHeight = [self.sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; - - return calculatedHeight; + [cell setMessage:msg]; + return [cell heightForCell]; } - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath diff --git a/Juick/UIImage+Utils.h b/Juick/UIImage+Utils.h new file mode 100644 index 0000000..8de91bf --- /dev/null +++ b/Juick/UIImage+Utils.h @@ -0,0 +1,19 @@ +// +// UIImage+Utils.h +// Juick +// +// Created by Vitaly on 01.02.14. +// Copyright (c) 2014 com.juick. All rights reserved. +// + +#import + +@interface UIImage (Utils) + ++ (UIImage*)imageWithImage:(UIImage *)image convertToWidth:(float)width covertToHeight:(float)height; ++ (UIImage*)imageWithImage:(UIImage *)image convertToHeight:(float)height; ++ (UIImage*)imageWithImage:(UIImage *)image convertToWidth:(float)width; ++ (UIImage*)imageWithImage:(UIImage *)image fitInsideWidth:(float)width fitInsideHeight:(float)height; ++ (UIImage*)imageWithImage:(UIImage *)image fitOutsideWidth:(float)width fitOutsideHeight:(float)height; ++ (UIImage*)imageWithImage:(UIImage *)image cropToWidth:(float)width cropToHeight:(float)height; +@end diff --git a/Juick/UIImage+Utils.m b/Juick/UIImage+Utils.m new file mode 100644 index 0000000..4617c65 --- /dev/null +++ b/Juick/UIImage+Utils.m @@ -0,0 +1,69 @@ +// +// UIImage+Utils.m +// Juick +// +// Created by Vitaly on 01.02.14. +// Copyright (c) 2014 com.juick. All rights reserved. +// + +#import "UIImage+Utils.h" + +@implementation UIImage (Utils) + ++ (UIImage*)imageWithImage:(UIImage *)image convertToWidth:(float)width covertToHeight:(float)height { + CGSize size = CGSizeMake(width, height); + UIGraphicsBeginImageContext(size); + [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; + UIImage * newimage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return newimage; +} + ++ (UIImage*)imageWithImage:(UIImage *)image convertToHeight:(float)height { + float ratio = image.size.height / height; + float width = image.size.width / ratio; + CGSize size = CGSizeMake(width, height); + UIGraphicsBeginImageContext(size); + [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; + UIImage * newimage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return newimage; +} + ++ (UIImage*)imageWithImage:(UIImage *)image convertToWidth:(float)width { + float ratio = image.size.width / width; + float height = image.size.height / ratio; + CGSize size = CGSizeMake(width, height); + UIGraphicsBeginImageContext(size); + [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; + UIImage * newimage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return newimage; +} + ++ (UIImage*)imageWithImage:(UIImage *)image fitInsideWidth:(float)width fitInsideHeight:(float)height { + if (image.size.height >= image.size.width) { + return [UIImage imageWithImage:image convertToWidth:width]; + } else { + return [UIImage imageWithImage:image convertToHeight:height]; + } +} + ++ (UIImage*)imageWithImage:(UIImage *)image fitOutsideWidth:(float)width fitOutsideHeight:(float)height { + if (image.size.height >= image.size.width) { + return [UIImage imageWithImage:image convertToHeight:height]; + } else { + return [UIImage imageWithImage:image convertToWidth:width]; + } +} + ++ (UIImage*)imageWithImage:(UIImage *)image cropToWidth:(float)width cropToHeight:(float)height { + CGSize size = [image size]; + CGRect rect = CGRectMake(((size.width-width) / 2.0f), ((size.height-height) / 2.0f), width, height); + CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], rect); + UIImage * img = [UIImage imageWithCGImage:imageRef]; + CGImageRelease(imageRef); + return img; +} + +@end -- cgit v1.2.3