diff --git a/Demo/LWAsyncDisplayViewDemo.xcodeproj/project.pbxproj b/Demo/LWAsyncDisplayViewDemo.xcodeproj/project.pbxproj index a25fcda..8e245ca 100755 --- a/Demo/LWAsyncDisplayViewDemo.xcodeproj/project.pbxproj +++ b/Demo/LWAsyncDisplayViewDemo.xcodeproj/project.pbxproj @@ -72,10 +72,11 @@ 01BE57FC1E5865C400A2A266 /* CALayer+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 01BE57FB1E5865C400A2A266 /* CALayer+WebCache.m */; }; 01BE57FF1E5865DD00A2A266 /* CALayer+WebCacheOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 01BE57FE1E5865DD00A2A266 /* CALayer+WebCacheOperation.m */; }; 01D14EF41CDCFA780028714A /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 01D14EF31CDCFA780028714A /* RootViewController.m */; }; - 01D5B2F51D37D548007C5CB1 /* CornerRadiusViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 01D5B2F41D37D548007C5CB1 /* CornerRadiusViewController.m */; }; 01F51A0E1CA1B1CE00463571 /* CoreData.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 01F51A0C1CA1B1CE00463571 /* CoreData.xcdatamodeld */; }; 01F51A181CA1B7A400463571 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 01F51A171CA1B7A400463571 /* CoreData.framework */; }; 01F58BC01D85AA8C0089DB02 /* RichTextDemo1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 01F58BBF1D85AA8C0089DB02 /* RichTextDemo1ViewController.m */; }; + 01FFE22B1E5A062500D05DFE /* ImageDemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 01FFE22A1E5A062500D05DFE /* ImageDemoViewController.m */; }; + 01FFE22E1E5A070100D05DFE /* ImageDemoTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 01FFE22D1E5A070100D05DFE /* ImageDemoTableViewCell.m */; }; B0ACEC021CEDC9A50019074F /* AutoFitSizeTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = B0ACEBEF1CEDC9A50019074F /* AutoFitSizeTextView.m */; }; B0ACEC031CEDC9A50019074F /* CellLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B0ACEBF11CEDC9A50019074F /* CellLayout.m */; }; B0ACEC041CEDC9A50019074F /* CommentModel.m in Sources */ = {isa = PBXBuildFile; fileRef = B0ACEBF31CEDC9A50019074F /* CommentModel.m */; }; @@ -242,12 +243,14 @@ 01BE57FE1E5865DD00A2A266 /* CALayer+WebCacheOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "CALayer+WebCacheOperation.m"; path = "../Gallop/CALayer+WebCacheOperation.m"; sourceTree = ""; }; 01D14EF21CDCFA780028714A /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = ""; }; 01D14EF31CDCFA780028714A /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = ""; }; - 01D5B2F31D37D548007C5CB1 /* CornerRadiusViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CornerRadiusViewController.h; sourceTree = ""; }; - 01D5B2F41D37D548007C5CB1 /* CornerRadiusViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CornerRadiusViewController.m; sourceTree = ""; }; 01F51A0D1CA1B1CE00463571 /* CoreData.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = CoreData.xcdatamodel; sourceTree = ""; }; 01F51A171CA1B7A400463571 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 01F58BBE1D85AA8C0089DB02 /* RichTextDemo1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RichTextDemo1ViewController.h; sourceTree = ""; }; 01F58BBF1D85AA8C0089DB02 /* RichTextDemo1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RichTextDemo1ViewController.m; sourceTree = ""; }; + 01FFE2291E5A062500D05DFE /* ImageDemoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageDemoViewController.h; sourceTree = ""; }; + 01FFE22A1E5A062500D05DFE /* ImageDemoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImageDemoViewController.m; sourceTree = ""; }; + 01FFE22C1E5A070100D05DFE /* ImageDemoTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageDemoTableViewCell.h; sourceTree = ""; }; + 01FFE22D1E5A070100D05DFE /* ImageDemoTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImageDemoTableViewCell.m; sourceTree = ""; }; B0ACEBEE1CEDC9A50019074F /* AutoFitSizeTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutoFitSizeTextView.h; sourceTree = ""; }; B0ACEBEF1CEDC9A50019074F /* AutoFitSizeTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AutoFitSizeTextView.m; sourceTree = ""; }; B0ACEBF01CEDC9A50019074F /* CellLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CellLayout.h; sourceTree = ""; }; @@ -397,7 +400,7 @@ 015FC0E31CDFA48800B4DF82 /* Gallop.h */, 0130235C1D43B061005EAE25 /* Model */, B085B3421CB68CF500087739 /* Views */, - 01BE57F31E5846B200A2A266 /* SDWebImageHook */, + 01BE57F31E5846B200A2A266 /* Hook */, 01D5B32D1D37F630007C5CB1 /* ImageDisplay */, B08CFE2B1D02CD4100A8B70D /* Transactions */, B079C2841CD8C58F003B15D3 /* CoreText */, @@ -512,7 +515,7 @@ name = Root; sourceTree = ""; }; - 01BE57F31E5846B200A2A266 /* SDWebImageHook */ = { + 01BE57F31E5846B200A2A266 /* Hook */ = { isa = PBXGroup; children = ( 012EDDE81D931D08009AFA90 /* SDWebImageManager+Gallop.h */, @@ -528,14 +531,16 @@ 01BE57FD1E5865DD00A2A266 /* CALayer+WebCacheOperation.h */, 01BE57FE1E5865DD00A2A266 /* CALayer+WebCacheOperation.m */, ); - name = SDWebImageHook; + name = Hook; sourceTree = ""; }; 01D5B2F21D37D525007C5CB1 /* LWImageStorageDemo */ = { isa = PBXGroup; children = ( - 01D5B2F31D37D548007C5CB1 /* CornerRadiusViewController.h */, - 01D5B2F41D37D548007C5CB1 /* CornerRadiusViewController.m */, + 01FFE2291E5A062500D05DFE /* ImageDemoViewController.h */, + 01FFE22A1E5A062500D05DFE /* ImageDemoViewController.m */, + 01FFE22C1E5A070100D05DFE /* ImageDemoTableViewCell.h */, + 01FFE22D1E5A070100D05DFE /* ImageDemoTableViewCell.m */, ); name = LWImageStorageDemo; sourceTree = ""; @@ -811,6 +816,7 @@ B0F991D11D937EA000D7B529 /* LWImageBrowserModel.m in Sources */, B0F991CB1D937EA000D7B529 /* LWActionSheetView.m in Sources */, 012EDE491D931FB1009AFA90 /* LWHTMLLayout.m in Sources */, + 01FFE22B1E5A062500D05DFE /* ImageDemoViewController.m in Sources */, 012EDDE01D931CB8009AFA90 /* LWLayout.m in Sources */, 0106E7C81E57303C00C5A3C6 /* SDWebImageDownloader.m in Sources */, 012EDE4D1D931FB1009AFA90 /* LWStorageBuilder.m in Sources */, @@ -857,7 +863,7 @@ 0106E7CD1E57303C00C5A3C6 /* UIImage+GIF.m in Sources */, 012EDDEC1D931D08009AFA90 /* SDWebImageManager+Gallop.m in Sources */, 019141C01E58BA8500587074 /* LWGIFImage.m in Sources */, - 01D5B2F51D37D548007C5CB1 /* CornerRadiusViewController.m in Sources */, + 01FFE22E1E5A070100D05DFE /* ImageDemoTableViewCell.m in Sources */, B0ACEC0A1CEDC9A50019074F /* TableViewHeader.m in Sources */, B0C9A9321D2273EF00DFAA44 /* ArticleListModel.m in Sources */, 0106E7D21E57303C00C5A3C6 /* UIView+WebCache.m in Sources */, diff --git a/Demo/LWAsyncDisplayViewDemo.xcodeproj/project.xcworkspace/xcuserdata/liuwei.xcuserdatad/UserInterfaceState.xcuserstate b/Demo/LWAsyncDisplayViewDemo.xcodeproj/project.xcworkspace/xcuserdata/liuwei.xcuserdatad/UserInterfaceState.xcuserstate index e2cf26e..df5efeb 100755 Binary files a/Demo/LWAsyncDisplayViewDemo.xcodeproj/project.xcworkspace/xcuserdata/liuwei.xcuserdatad/UserInterfaceState.xcuserstate and b/Demo/LWAsyncDisplayViewDemo.xcodeproj/project.xcworkspace/xcuserdata/liuwei.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Demo/LWAsyncDisplayViewDemo/CornerRadiusViewController.m b/Demo/LWAsyncDisplayViewDemo/CornerRadiusViewController.m deleted file mode 100755 index e031d3c..0000000 --- a/Demo/LWAsyncDisplayViewDemo/CornerRadiusViewController.m +++ /dev/null @@ -1,88 +0,0 @@ -/********************* 有任何问题欢迎反馈给我 liuweiself@126.com ****************************************/ -/*************** https://github.com/waynezxcv/Gallop 持续更新 ***************************/ -/******************** 正在不断完善中,谢谢~ Enjoy ******************************************************/ - - - - - -#import "CornerRadiusViewController.h" -#import "Gallop.h" - -@interface CornerRadiusViewController () - - -@end - -@implementation CornerRadiusViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - self.title = @"LWImageStorage示例"; - self.view.backgroundColor = [UIColor whiteColor]; - - LWAsyncDisplayView* view = [[LWAsyncDisplayView alloc] - initWithFrame:CGRectMake(0.0f, 64.0f, SCREEN_WIDTH, SCREEN_HEIGHT - 64.0f)]; - [self.view addSubview:view]; - - LWTextStorage* ts = [[LWTextStorage alloc] initWithFrame:CGRectMake(20.0f, 20.0f, SCREEN_WIDTH - 40.0f, CGFLOAT_MAX)]; - ts.text = @"使用Gallop可以直接给网络图片设置圆角半径、描边处理、模糊效果,下载完成后将对处理过的图片额外缓存一份,而不需要每次都重复处理。"; - ts.font = [UIFont fontWithName:@"Heiti SC" size:16.0f]; - ts.textAlignment = NSTextAlignmentCenter; - - //1.普通的加载网络图片 - LWImageStorage* is1 = [[LWImageStorage alloc] init]; - is1.contentMode = UIViewContentModeScaleAspectFill; - is1.frame = CGRectMake(SCREEN_WIDTH/2 - 50.0f, ts.bottom + 10.0f, 100.0f, 100.0f); - is1.contents = [NSURL URLWithString:@"http://img4.bitautoimg.com/autoalbum/files/20101220/862/13374086240035_1469891_15.JPG"]; - is1.clipsToBounds = YES; - - - //2.本地图片 - LWImageStorage* lis = [[LWImageStorage alloc] init]; - lis.contents = [UIImage imageNamed:@"test"]; - lis.backgroundColor = [UIColor grayColor]; - lis.cornerRadius = 25.0f; - lis.cornerBackgroundColor = [UIColor whiteColor]; - lis.cornerBorderColor = [UIColor redColor]; - lis.cornerBorderWidth = 3.0f; - lis.contentMode = UIViewContentModeScaleAspectFill; - lis.frame = CGRectMake(SCREEN_WIDTH/2 - 50.0f, is1.bottom + 10.0f, 100.0f, 100.0f); - - - //3.网络图片设置圆角半径和模糊效果 - LWImageStorage* is2 = [[LWImageStorage alloc] init]; - is2.frame = CGRectMake(SCREEN_WIDTH/2 - 50.0f, lis.bottom + 10.0f, 100.0f, 100.0f); - is2.contents = [NSURL URLWithString:@"http://img4.bitautoimg.com/autoalbum/files/20101220/862/13374086240035_1469891_15.JPG"]; - is2.cornerRadius = 50.0f; - is2.contentMode = UIViewContentModeScaleAspectFill; - is2.isBlur = YES; - - - //4.直接对CALayer对象使用 - UIView* view2 = [[UIImageView alloc] initWithFrame:CGRectMake(SCREEN_WIDTH/2 - 50, - 64.0f + is2.bottom + 10 , - 100.0f, - 100.0f)]; - [self.view addSubview:view2]; - - [view2.layer lw_setImageWithURL:[NSURL URLWithString:@"http://img4.bitautoimg.com/autoalbum/files/20101220/862/13374086240035_1469891_15.JPG"] - placeholderImage:nil - cornerRadius:50.0f - cornerBackgroundColor:RGB(255, 255, 255, 1.0f) - borderColor:[UIColor orangeColor] - borderWidth:5.0f - size:CGSizeMake(100, 100) - contentMode:UIViewContentModeScaleAspectFill - isBlur:NO - options:0 - progress:nil - completed:nil]; - - LWLayout* layout = [[LWLayout alloc] init]; - [layout addStorages:@[ts,is1,lis,is2]]; - view.layout = layout; -} - - -@end diff --git a/Demo/LWAsyncDisplayViewDemo/ImageDemoTableViewCell.h b/Demo/LWAsyncDisplayViewDemo/ImageDemoTableViewCell.h new file mode 100644 index 0000000..b739b08 --- /dev/null +++ b/Demo/LWAsyncDisplayViewDemo/ImageDemoTableViewCell.h @@ -0,0 +1,18 @@ +/********************* 有任何问题欢迎反馈给我 liuweiself@126.com ****************************************/ +/*************** https://github.com/waynezxcv/Gallop 持续更新 ***************************/ +/******************** 正在不断完善中,谢谢~ Enjoy ******************************************************/ + + + + + +#import +#import "Gallop.h" + + +@interface ImageDemoTableViewCell : UITableViewCell + + +@property (nonatomic,strong) LWLayout* layout; + +@end diff --git a/Demo/LWAsyncDisplayViewDemo/ImageDemoTableViewCell.m b/Demo/LWAsyncDisplayViewDemo/ImageDemoTableViewCell.m new file mode 100644 index 0000000..3a3084f --- /dev/null +++ b/Demo/LWAsyncDisplayViewDemo/ImageDemoTableViewCell.m @@ -0,0 +1,49 @@ +/********************* 有任何问题欢迎反馈给我 liuweiself@126.com ****************************************/ +/*************** https://github.com/waynezxcv/Gallop 持续更新 ***************************/ +/******************** 正在不断完善中,谢谢~ Enjoy ******************************************************/ + + + + + + +#import "ImageDemoTableViewCell.h" + + +@interface ImageDemoTableViewCell () + +@property (nonatomic,strong) LWAsyncDisplayView* displayView; + +@end + + +@implementation ImageDemoTableViewCell + + + +- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; + if (self) { + + self.backgroundColor = [UIColor whiteColor]; + self.displayView = [[LWAsyncDisplayView alloc] initWithFrame:CGRectZero]; + [self.contentView addSubview:self.displayView]; + + } + return self ; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + self.displayView.frame = self.bounds; +} + +- (void)setLayout:(LWLayout *)layout { + if (_layout != layout) { + _layout = layout; + + self.displayView.layout = self.layout; + } +} + +@end diff --git a/Demo/LWAsyncDisplayViewDemo/CornerRadiusViewController.h b/Demo/LWAsyncDisplayViewDemo/ImageDemoViewController.h old mode 100755 new mode 100644 similarity index 86% rename from Demo/LWAsyncDisplayViewDemo/CornerRadiusViewController.h rename to Demo/LWAsyncDisplayViewDemo/ImageDemoViewController.h index c385fc5..2ffb72f --- a/Demo/LWAsyncDisplayViewDemo/CornerRadiusViewController.h +++ b/Demo/LWAsyncDisplayViewDemo/ImageDemoViewController.h @@ -5,8 +5,9 @@ + #import -@interface CornerRadiusViewController : UIViewController +@interface ImageDemoViewController : UIViewController @end diff --git a/Demo/LWAsyncDisplayViewDemo/ImageDemoViewController.m b/Demo/LWAsyncDisplayViewDemo/ImageDemoViewController.m new file mode 100644 index 0000000..93965ec --- /dev/null +++ b/Demo/LWAsyncDisplayViewDemo/ImageDemoViewController.m @@ -0,0 +1,232 @@ +/********************* 有任何问题欢迎反馈给我 liuweiself@126.com ****************************************/ +/*************** https://github.com/waynezxcv/Gallop 持续更新 ***************************/ +/******************** 正在不断完善中,谢谢~ Enjoy ******************************************************/ + + + + + + +#import "ImageDemoViewController.h" +#import "ImageDemoTableViewCell.h" + + + + + + +@interface ImageDemoViewController () + + +@property (nonatomic,strong) UITableView* tableView; +@property (nonatomic,strong) NSMutableArray* dataSource; + +@end + +@implementation ImageDemoViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + [self.view addSubview:self.tableView]; + self.title = @"LWImageStorage使用示例"; +} + + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.dataSource.count; +} + + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString* cellIdentifier = @"cellIdentifier"; + ImageDemoTableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; + if (!cell) { + cell = [[ImageDemoTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; + } + LWLayout* layout = [self.dataSource objectAtIndex:indexPath.row]; + cell.layout = layout; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + return cell; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return 130.0f; +} + +- (UITableView *)tableView { + if (_tableView) { + return _tableView; + } + _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain]; + _tableView.delegate = self; + _tableView.dataSource = self; + return _tableView; +} + +- (NSMutableArray *)dataSource { + if (_dataSource) { + return _dataSource; + } + _dataSource = [[NSMutableArray alloc] init]; + + { + + LWTextStorage* textStorage = [[LWTextStorage alloc] init]; + textStorage.frame = CGRectMake(15.0f, 15.0f, self.view.bounds.size.width/2 - 30.0f,100.0f); + textStorage.text = @"加载本地图片,默认图片会直接绘制在LWAsyncDisplayView上,减少View的层级。"; + textStorage.vericalAlignment = LWTextVericalAlignmentCenter; + + + LWImageStorage* imageStorage = [[LWImageStorage alloc] init]; + imageStorage.contents = [UIImage imageNamed:@"test"]; + imageStorage.backgroundColor = [UIColor grayColor]; + imageStorage.contentMode = UIViewContentModeScaleAspectFill; + imageStorage.frame = CGRectMake(self.view.bounds.size.width/2 + 15.0f, 15.0f, self.view.bounds.size.width/2 - 30.0f, 100.0f); + + + LWLayout* layout = [[LWLayout alloc] init]; + [layout addStorage:imageStorage]; + [layout addStorage:textStorage]; + [_dataSource addObject:layout]; + } + + + { + + LWTextStorage* textStorage = [[LWTextStorage alloc] init]; + textStorage.frame = CGRectMake(15.0f, 15.0f, self.view.bounds.size.width/2- 30.0f,100.0f); + textStorage.text = @"加载本地图片,并设置圆角半径"; + textStorage.vericalAlignment = LWTextVericalAlignmentCenter; + + + LWImageStorage* imageStorage = [[LWImageStorage alloc] init]; + imageStorage.contents = [UIImage imageNamed:@"test"]; + imageStorage.backgroundColor = [UIColor grayColor]; + imageStorage.cornerRadius = 50.0f; + imageStorage.cornerBackgroundColor = [UIColor whiteColor]; + imageStorage.cornerBorderColor = [UIColor redColor]; + imageStorage.cornerBorderWidth = 5.0f; + imageStorage.contentMode = UIViewContentModeScaleAspectFill; + imageStorage.frame = CGRectMake(self.view.bounds.size.width/2 + 15.0f, 15.0f, self.view.bounds.size.width/2 - 30.0f, 100.0f); + + + LWLayout* layout = [[LWLayout alloc] init]; + [layout addStorage:imageStorage]; + [layout addStorage:textStorage]; + [_dataSource addObject:layout]; + } + + { + LWTextStorage* textStorage = [[LWTextStorage alloc] init]; + textStorage.frame = CGRectMake(15.0f, 15.0f, self.view.bounds.size.width/2- 30.0f,100.0f); + textStorage.text = @"加载本地图片,并进行模糊处理"; + textStorage.vericalAlignment = LWTextVericalAlignmentCenter; + + + LWImageStorage* imageStorage = [[LWImageStorage alloc] init]; + imageStorage.contents = [UIImage imageNamed:@"test"]; + imageStorage.backgroundColor = [UIColor grayColor]; + imageStorage.isBlur = YES; + imageStorage.contentMode = UIViewContentModeScaleAspectFill; + imageStorage.frame = CGRectMake(self.view.bounds.size.width/2 + 15.0f, 15.0f, self.view.bounds.size.width/2 - 30.0f, 100.0f); + + + LWLayout* layout = [[LWLayout alloc] init]; + [layout addStorage:imageStorage]; + [layout addStorage:textStorage]; + [_dataSource addObject:layout]; + } + + { + LWTextStorage* textStorage = [[LWTextStorage alloc] init]; + textStorage.frame = CGRectMake(15.0f, 15.0f, self.view.bounds.size.width/2 - 30.0f,100.0f); + textStorage.text = @"加载网络图片"; + textStorage.vericalAlignment = LWTextVericalAlignmentCenter; + + + LWImageStorage* imageStorage = [[LWImageStorage alloc] init]; + imageStorage.contentMode = UIViewContentModeScaleAspectFill; + imageStorage.frame = CGRectMake(self.view.bounds.size.width/2 + 15.0f, 15.0f, self.view.bounds.size.width/2 - 30.0f, 100.0f); + imageStorage.contents = [NSURL URLWithString:@"http://img4.bitautoimg.com/autoalbum/files/20101220/862/13374086240035_1469891_15.JPG"]; + imageStorage.clipsToBounds = YES; + + + LWLayout* layout = [[LWLayout alloc] init]; + [layout addStorage:imageStorage]; + [layout addStorage:textStorage]; + [_dataSource addObject:layout]; + } + + { + + LWTextStorage* textStorage = [[LWTextStorage alloc] init]; + textStorage.frame = CGRectMake(15.0f, 15.0f, self.view.bounds.size.width/2 - 30.0f,100.0f); + textStorage.text = @"加载网络图片,并设置圆角半径,处理后的图片将直接缓存,下次加载时就无需再次处理而是直接读取缓存了。"; + textStorage.vericalAlignment = LWTextVericalAlignmentCenter; + + + LWImageStorage* imageStorage = [[LWImageStorage alloc] init]; + imageStorage.contentMode = UIViewContentModeScaleAspectFill; + imageStorage.frame = CGRectMake(self.view.bounds.size.width/2 + 15.0f, 15.0f, self.view.bounds.size.width/2 - 30.0f, 100.0f); + imageStorage.contents = [NSURL URLWithString:@"http://img4.bitautoimg.com/autoalbum/files/20101220/862/13374086240035_1469891_15.JPG"]; + imageStorage.clipsToBounds = YES; + imageStorage.cornerRadius = 50.0f; + imageStorage.cornerBorderColor = [UIColor orangeColor]; + imageStorage.cornerBorderWidth = 5.0f; + + + + LWLayout* layout = [[LWLayout alloc] init]; + [layout addStorage:imageStorage]; + [layout addStorage:textStorage]; + [_dataSource addObject:layout]; + + } + + { + + LWTextStorage* textStorage = [[LWTextStorage alloc] init]; + textStorage.frame = CGRectMake(15.0f, 15.0f, self.view.bounds.size.width/2 - 30.0f,100.0f); + textStorage.text = @"加载网络图片,并进行模糊处理,处理后的图片将直接缓存,下次加载时就无需再次处理而是直接读取缓存了。"; + textStorage.vericalAlignment = LWTextVericalAlignmentCenter; + + + LWImageStorage* imageStorage = [[LWImageStorage alloc] init]; + imageStorage.contentMode = UIViewContentModeScaleAspectFill; + imageStorage.frame = CGRectMake(self.view.bounds.size.width/2 + 15.0f, 15.0f, self.view.bounds.size.width/2 - 30.0f, 100.0f); + imageStorage.contents = [NSURL URLWithString:@"http://img4.bitautoimg.com/autoalbum/files/20101220/862/13374086240035_1469891_15.JPG"]; + imageStorage.clipsToBounds = YES; + imageStorage.isBlur = YES; + + LWLayout* layout = [[LWLayout alloc] init]; + [layout addStorage:imageStorage]; + [layout addStorage:textStorage]; + [_dataSource addObject:layout]; + + } + + { + + LWTextStorage* textStorage = [[LWTextStorage alloc] init]; + textStorage.frame = CGRectMake(15.0f, 15.0f, self.view.bounds.size.width/2 - 30.0f,100.0f); + textStorage.text = @"加载网络GIF图片"; + textStorage.vericalAlignment = LWTextVericalAlignmentCenter; + + LWImageStorage* imageStorage = [[LWImageStorage alloc] init]; + imageStorage.contentMode = UIViewContentModeScaleAspectFill; + imageStorage.frame = CGRectMake(self.view.bounds.size.width/2 + 15.0f, 15.0f, self.view.bounds.size.width/2 - 30.0f, 100.0f); + imageStorage.contents = [NSURL URLWithString:@"http://wx2.sinaimg.cn/bmiddle/784fda03gy1fcw8zl4zqrg209h04x7wi.gif"]; + imageStorage.clipsToBounds = YES; + + LWLayout* layout = [[LWLayout alloc] init]; + [layout addStorage:imageStorage]; + [layout addStorage:textStorage]; + [_dataSource addObject:layout]; + + } + + return _dataSource; +} + + +@end diff --git a/Demo/LWAsyncDisplayViewDemo/MomentsViewController.m b/Demo/LWAsyncDisplayViewDemo/MomentsViewController.m index 48e84d5..d29608d 100755 --- a/Demo/LWAsyncDisplayViewDemo/MomentsViewController.m +++ b/Demo/LWAsyncDisplayViewDemo/MomentsViewController.m @@ -91,6 +91,7 @@ - (void)viewWillDisappear:(BOOL)animated { - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; + if (self.isNeedRefresh) { [self refreshBegin]; } @@ -523,7 +524,7 @@ - (NSArray *)fakeDatasource { @"statusID":@"8", @"commentList":@[@{@"from":@"SIZE潮流生活", @"to":@"waynezxcv", - @"content":@"nice~使用Gallop。支持异步绘制,让滚动如丝般顺滑。"}], + @"content":@"使用Gallop适合包含文字、图片高性能的展示型界面的构建。"}], @"isLike":@(NO), @"likeList":@[@"waynezxcv"]}, @@ -533,11 +534,12 @@ - (NSArray *)fakeDatasource { @"avatar":@"http://tva4.sinaimg.cn/crop.0.0.700.700.50/006qdyzsjw8fashgddslaj30jg0jg0wb.jpg", @"content":@"#GIF#少女时期的东方教主#林青霞#", @"date":@"1459668442", - @"imgs":@[@"http://ww3.sinaimg.cn/bmiddle/006qdyzsly1fctmnzwqcwg307505pasc.gif"], + @"imgs":@[@"http://ww3.sinaimg.cn/bmiddle/006qdyzsly1fctmnzwqcwg307505pasc.gif", + @"http://ww3.sinaimg.cn/bmiddle/006qdyzsly1fctmo1wpw5g307505p1kx.gif"], @"statusID":@"22", @"commentList":@[@{@"from":@"someone", @"to":@"waynezxcv", - @"content":@"gif同样流畅"}], + @"content":@"Gif也能获得优秀的体验。"}], @"isLike":@(NO), @"likeList":@[@"waynezxcv"]}, @@ -555,13 +557,13 @@ - (NSArray *)fakeDatasource { @"statusID":@"1", @"commentList":@[@{@"from":@"SIZE潮流生活", @"to":@"", - @"content":@"使用Gallop来快速构建图文混排界面。享受如丝般顺滑的滚动体验。"}, + @"content":@"哈哈哈..."}, @{@"from":@"waynezxcv", @"to":@"SIZE潮流生活", @"content":@"哈哈哈哈"}, @{@"from":@"SIZE潮流生活", @"to":@"waynezxcv", - @"content":@"nice~使用Gallop。支持异步绘制,让滚动如丝般顺滑。"}], + @"content":@"使用Gallop能尽量保持滚动时的FPS在60hz"}], @"isLike":@(NO), @"likeList":@[@"waynezxcv",@"伊布拉希莫维奇",@"权志龙",@"郜林",@"扎克伯格"]}, @@ -575,7 +577,7 @@ - (NSArray *)fakeDatasource { @"statusID":@"1", @"commentList":@[@{@"from":@"伊布拉西莫维奇", @"to":@"", - @"content":@"使用Gallop来快速构建图文混排界面。享受如丝般顺滑的滚动体验。"}], + @"content":@"手动再见..."}], @"isLike":@(NO), @"likeList":@[@"waynezxcv",@"Gallop"]}, @@ -601,7 +603,7 @@ - (NSArray *)fakeDatasource { @"content":@"哈哈哈哈"}, @{@"from":@"SIZE潮流生活", @"to":@"waynezxcv", - @"content":@"nice~使用Gallop。支持异步绘制,让滚动如丝般顺滑。"}], + @"content":@"打得不错。"}], @"isLike":@(NO), @"likeList":@[@"waynezxcv"]}, @@ -623,7 +625,7 @@ - (NSArray *)fakeDatasource { @"content":@"哈哈哈哈"}, @{@"from":@"SIZE潮流生活", @"to":@"waynezxcv", - @"content":@"nice~使用Gallop。支持异步绘制,让滚动如丝般顺滑。"}], + @"content":@"+++"}], @"isLike":@(NO), @"likeList":@[@"Tim Cook"]}, @@ -640,7 +642,7 @@ - (NSArray *)fakeDatasource { @"content":@"哈哈哈哈"}, @{@"from":@"SIZE潮流生活", @"to":@"waynezxcv", - @"content":@"nice~使用Gallop。支持异步绘制,让滚动如丝般顺滑。"}], + @"content":@"打得不错。"}], @"isLike":@(NO), @"likeList":@[@"Tim Cook"]}, @@ -676,7 +678,7 @@ - (NSArray *)fakeDatasource { @"content":@"哈哈哈哈"}, @{@"from":@"SIZE潮流生活", @"to":@"waynezxcv", - @"content":@"nice~使用Gallop。支持异步绘制,让滚动如丝般顺滑。"}], + @"content":@"打得不错。"}], @"isLike":@(NO), @"likeList":@[@"waynezxcv"]}, @@ -696,7 +698,7 @@ - (NSArray *)fakeDatasource { @"content":@"哈哈哈哈"}, @{@"from":@"SIZE潮流生活", @"to":@"waynezxcv", - @"content":@"nice~使用Gallop。支持异步绘制,让滚动如丝般顺滑。"}], + @"content":@"打得不错。"}], @"isLike":@(NO), @"likeList":@[@"waynezxcv"]}, diff --git a/Demo/LWAsyncDisplayViewDemo/RootViewController.m b/Demo/LWAsyncDisplayViewDemo/RootViewController.m index ad94135..e557f59 100755 --- a/Demo/LWAsyncDisplayViewDemo/RootViewController.m +++ b/Demo/LWAsyncDisplayViewDemo/RootViewController.m @@ -7,9 +7,12 @@ #import "RootViewController.h" #import "RichTextDemo1ViewController.h" -#import "CornerRadiusViewController.h" #import "MomentsViewController.h" #import "ArticleListViewController.h" +#import "ImageDemoViewController.h" + + + @@ -60,7 +63,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N cell.textLabel.text = @"LWImageStorage使用示例"; break; case 2: - cell.textLabel.text = @"使用Gallop构建Feeds示例"; + cell.textLabel.text = @"使用Gallop构建Feed List 示例"; break; case 3: cell.textLabel.text = @"使用Gallop进行HTML解析示例"; @@ -79,7 +82,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath } break; case 1:{ - CornerRadiusViewController* vc = [[CornerRadiusViewController alloc] init]; + ImageDemoViewController* vc = [[ImageDemoViewController alloc] init]; [self.navigationController pushViewController:vc animated:YES]; } break; diff --git a/Gallop/LWAsyncDisplayLayer.h b/Gallop/LWAsyncDisplayLayer.h index 6ceead0..8be11de 100755 --- a/Gallop/LWAsyncDisplayLayer.h +++ b/Gallop/LWAsyncDisplayLayer.h @@ -1,18 +1,18 @@ /* https://github.com/waynezxcv/Gallop - + Copyright (c) 2016 waynezxcv - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -71,7 +71,7 @@ @protocol LWAsyncDisplayLayerDelegate /** - * 异步绘制协议的代理方法 + * 异步绘制协议的协议方法 * @return 返回一个异步绘制任务的抽象LWAsyncDisplayTransaction对象,可以通过这个对象的属性来得到将要开始绘制时,绘制时,和绘制完成时的回调。 */ - (LWAsyncDisplayTransaction *)asyncDisplayTransaction; diff --git a/Gallop/LWAsyncDisplayView.h b/Gallop/LWAsyncDisplayView.h index b34f458..ff5dbfc 100755 --- a/Gallop/LWAsyncDisplayView.h +++ b/Gallop/LWAsyncDisplayView.h @@ -31,6 +31,7 @@ @class LWAsyncDisplayView; @class LWTextStorage; @class LWImageStorage; +@class LWAsyncImageView; @protocol LWAsyncDisplayViewDelegate @@ -94,7 +95,6 @@ typedef void(^LWAsyncDisplayViewAutoLayoutCallback)(LWImageStorage* imageStorage @property (nonatomic,strong,readonly) UILongPressGestureRecognizer* longPressGesture;//长按手势 - /** * 移除高亮显示 * diff --git a/Gallop/LWAsyncDisplayView.m b/Gallop/LWAsyncDisplayView.m index f367bf0..9508ec2 100755 --- a/Gallop/LWAsyncDisplayView.m +++ b/Gallop/LWAsyncDisplayView.m @@ -35,6 +35,14 @@ of this software and associated documentation files (the "Software"), to deal + +struct LWAyncDisplayStatus { + BOOL needLayout : 1; + BOOL needDisplay : 1; + BOOL needClenup : 1; +}; + + @interface LWAsyncDisplayView () @property (nonatomic,strong) NSMutableArray* reusePool;//这个数组用来存放暂时不使用的LWAsyncImageView @@ -51,6 +59,7 @@ @implementation LWAsyncDisplayView { CGPoint _touchBeganPoint; NSArray* _textStorages; NSArray* _imageStorages; + struct LWAyncDisplayStatus _displayFlag; } @@ -76,12 +85,18 @@ - (void)setup { self.layer.opaque = YES; self.layer.contentsScale = [GallopUtils contentsScale]; self.displaysAsynchronously = YES; + _showingHighlight = NO; _highlight = nil; _touchBeganPoint = CGPointZero; _highlightAdjustPoint = CGPointZero; _textStorages = nil; _imageStorages = nil; + + _displayFlag.needClenup = YES; + _displayFlag.needLayout = YES; + _displayFlag.needDisplay = YES; + [self addGestureRecognizer:self.longPressGesture]; } @@ -98,12 +113,10 @@ - (void)_cleanImageViewAddToReusePool { [self.imageContainers removeAllObjects]; } - - (void)setImageStoragesResizeBlock:(void(^)(LWImageStorage* imageStorage, CGFloat delta))resizeBlock { - //遍历imageStorages绘制 + //遍历imageStorages for (NSInteger i = 0; i < _imageStorages.count; i ++) { @autoreleasepool { - LWImageStorage* imageStorage = _imageStorages[i]; if ([imageStorage.contents isKindOfClass:[UIImage class]] && imageStorage.localImageType == LWLocalImageDrawInLWAsyncDisplayView) { @@ -124,7 +137,6 @@ - (void)setImageStoragesResizeBlock:(void(^)(LWImageStorage* imageStorage, CGFlo container.frame = imageStorage.frame; container.hidden = NO; [container lw_setImageWihtImageStorage:imageStorage resize:resizeBlock completion:nil]; - [self.imageContainers addObject:container]; } } @@ -144,7 +156,6 @@ - (LWAsyncImageView *)_dequeueReusableImageContainerWithIdentifier:(NSString *)i #pragma mark - Display - (LWAsyncDisplayTransaction *)asyncDisplayTransaction { - LWAsyncDisplayTransaction* transaction = [[LWAsyncDisplayTransaction alloc] init]; transaction.willDisplayBlock = ^(CALayer *layer) { for (LWTextStorage* textStorage in _textStorages) { @@ -176,7 +187,6 @@ - (void)_drawStoragesInContext:(CGContextRef)context inCancelled:(LWAsyncDisplay if (isCancelledBlock()) { return; } - //这个代理方法调用需要用户额外绘制的内容 [self.delegate extraAsyncDisplayIncontext:context size:self.bounds.size isCancelled:isCancelledBlock]; } @@ -449,7 +459,6 @@ - (UILongPressGestureRecognizer *)longPressGesture { if (_longPressGesture) { return _longPressGesture; } - _longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressHandler:)]; @@ -474,10 +483,24 @@ - (void)setLayout:(LWLayout *)layout { } [self _cleanImageViewAddToReusePool]; + [self _cleanupAndReleaseModelOnSubThread]; - _highlightAdjustPoint = CGPointZero; - _touchBeganPoint = CGPointZero; - _showingHighlight = NO; + _layout = layout; + _imageStorages = self.layout.imageStorages; + _textStorages = self.layout.textStorages; + + [self.layer setNeedsDisplay]; + + __weak typeof(self) weakSelf = self; + [self setImageStoragesResizeBlock:^(LWImageStorage* imageStorage,CGFloat delta) { + __strong typeof(weakSelf) swself = weakSelf; + if (swself.auotoLayoutCallback) { + swself.auotoLayoutCallback(imageStorage,delta); + } + }]; +} + +- (void)_cleanupAndReleaseModelOnSubThread { id oldLayout = _layout; LWTextHighlight* oldHighlight = _highlight; @@ -489,6 +512,10 @@ - (void)setLayout:(LWLayout *)layout { _textStorages = nil; _highlight = nil; + _highlightAdjustPoint = CGPointZero; + _touchBeganPoint = CGPointZero; + _showingHighlight = NO; + //在子线程释放之前的对象 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ [oldLayout class]; @@ -496,20 +523,8 @@ - (void)setLayout:(LWLayout *)layout { [oldImageStorages class]; [oldHighlight class]; }); - - _layout = layout; - _imageStorages = self.layout.imageStorages; - _textStorages = self.layout.textStorages; - - [self.layer setNeedsDisplay]; - - __weak typeof(self) weakSelf = self; - [self setImageStoragesResizeBlock:^(LWImageStorage* imageStorage,CGFloat delta) { - __strong typeof(weakSelf) swself = weakSelf; - if (swself.auotoLayoutCallback) { - swself.auotoLayoutCallback(imageStorage,delta); - } - }]; } + + @end diff --git a/Gallop/LWAsyncImageView+Display.m b/Gallop/LWAsyncImageView+Display.m index 314eace..13f008a 100644 --- a/Gallop/LWAsyncImageView+Display.m +++ b/Gallop/LWAsyncImageView+Display.m @@ -30,11 +30,17 @@ of this software and associated documentation files (the "Software"), to deal +static CGSize _sizeFitWithAspectRatio(CGFloat aspectRatio, CGSize constraints); +static CGSize _sizeFillWithAspectRatio(CGFloat sizeToScaleAspectRatio, CGSize destinationSize); +static void _croppedImageBackingSizeAndDrawRectInBounds(CGSize sourceImageSize,CGSize boundsSize,UIViewContentMode contentMode,CGRect cropRect,BOOL forceUpscaling,CGSize* outBackingSize,CGRect* outDrawRect); + + @implementation LWAsyncImageView (Display) - (void)lw_setImageWihtImageStorage:(LWImageStorage *)imageStorage resize:(LWHTMLImageResizeBlock)resizeBlock completion:(LWAsyncCompleteBlock)completion { + if ([imageStorage.contents isKindOfClass:[UIImage class]]) { [self _setLocalImageWithImageStorage:imageStorage resize:resizeBlock completion:completion]; } else { @@ -42,39 +48,148 @@ - (void)lw_setImageWihtImageStorage:(LWImageStorage *)imageStorage resize:(LWHTM } } - - (void)_setLocalImageWithImageStorage:(LWImageStorage *)imageStorage resize:(LWHTMLImageResizeBlock)resizeBlock completion:(LWAsyncCompleteBlock)completion { - UIImage* image = (UIImage *)imageStorage.contents; - if (imageStorage.isBlur) { + if (imageStorage.needRerendering) { dispatch_async(dispatch_get_global_queue(0, 0), ^{ - UIImage* blurImage = [image lw_applyBlurWithRadius:20 - tintColor:RGB(0, 0, 0, 0.15f) - saturationDeltaFactor:1.4 - maskImage:nil]; + UIImage* processedImage = [self _reRenderingImageWitImageStorage:imageStorage]; dispatch_async(dispatch_get_main_queue(), ^{ - self.image = blurImage; - resizeBlock(imageStorage,0); - completion(); + self.image = processedImage; + if (resizeBlock) { + resizeBlock(imageStorage,0); + } + if (completion) { + completion(); + } }); }); + } else { + UIImage* image = (UIImage *)imageStorage.contents; self.image = image; - resizeBlock(imageStorage,0); - completion(); + if (resizeBlock) { + resizeBlock(imageStorage,0); + } + if (completion) { + completion(); + } + } +} + +- (UIImage *)_reRenderingImageWitImageStorage:(LWImageStorage *)imageStorage { + + UIImage* image = (UIImage *)imageStorage.contents; + if (!image) { + return nil; + } + + @autoreleasepool { + + if (imageStorage.isBlur) { + image = [image lw_applyBlurWithRadius:20 + tintColor:RGB(0, 0, 0, 0.15f) + saturationDeltaFactor:1.4 + maskImage:nil]; + } + + BOOL forceUpscaling = NO; + BOOL cropEnabled = YES; + BOOL isOpaque = imageStorage.opaque; + UIColor* backgroundColor = imageStorage.backgroundColor; + UIViewContentMode contentMode = imageStorage.contentMode; + CGFloat contentsScale = imageStorage.contentsScale; + CGRect cropDisplayBounds = CGRectZero; + CGRect cropRect = CGRectMake(0.5, 0.5, 0, 0); + BOOL hasValidCropBounds = cropEnabled && !CGRectIsNull(cropDisplayBounds) && !CGRectIsEmpty(cropDisplayBounds); + CGRect bounds = (hasValidCropBounds ? cropDisplayBounds : imageStorage.bounds); + CGSize imageSize = image.size; + CGSize imageSizeInPixels = CGSizeMake(imageSize.width * image.scale, imageSize.height * image.scale); + CGSize boundsSizeInPixels = CGSizeMake(floorf(bounds.size.width * contentsScale), floorf(bounds.size.height * contentsScale)); + BOOL contentModeSupported = contentMode == UIViewContentModeScaleAspectFill || + contentMode == UIViewContentModeScaleAspectFit || + contentMode == UIViewContentModeCenter; + CGSize backingSize = CGSizeZero; + CGRect imageDrawRect = CGRectZero; + + CGFloat cornerRadius = imageStorage.cornerRadius; + UIColor* cornerBackgroundColor = imageStorage.cornerBackgroundColor; + UIColor* cornerBorderColor = imageStorage.cornerBorderColor; + CGFloat cornerBorderWidth = imageStorage.cornerBorderWidth; + + if (boundsSizeInPixels.width * contentsScale < 1.0f || boundsSizeInPixels.height * contentsScale < 1.0f || + imageSizeInPixels.width < 1.0f || imageSizeInPixels.height < 1.0f) { + return nil; + } + + if (!cropEnabled || !contentModeSupported) { + backingSize = imageSizeInPixels; + imageDrawRect = (CGRect){.size = backingSize}; + + } else { + _croppedImageBackingSizeAndDrawRectInBounds(imageSizeInPixels, + boundsSizeInPixels, + contentMode, + cropRect, + forceUpscaling, + &backingSize, + &imageDrawRect); + } + if (backingSize.width <= 0.0f || backingSize.height <= 0.0f || + imageDrawRect.size.width <= 0.0f || imageDrawRect.size.height <= 0.0f) { + return nil; + } + + UIGraphicsBeginImageContextWithOptions(backingSize,isOpaque,contentsScale); + if (nil == UIGraphicsGetCurrentContext()) { + return nil; + } + + if (isOpaque && backgroundColor) { + [backgroundColor setFill]; + UIRectFill(CGRectMake(0, 0, backingSize.width, backingSize.height)); + } + + UIBezierPath* cornerPath = [UIBezierPath bezierPathWithRoundedRect:imageDrawRect + cornerRadius:cornerRadius * contentsScale]; + + UIBezierPath* backgroundRect = [UIBezierPath bezierPathWithRect:imageDrawRect]; + if (cornerBackgroundColor) { + [cornerBackgroundColor setFill]; + } + [backgroundRect fill]; + [cornerPath addClip]; + + + [image drawInRect:imageDrawRect]; + + if (cornerBorderColor) { + [cornerBorderColor setStroke]; + } + [cornerPath stroke]; + [cornerPath setLineWidth:cornerBorderWidth]; + + CGImageRef processedImageRef = (UIGraphicsGetImageFromCurrentImageContext().CGImage); + UIGraphicsEndImageContext(); + return [UIImage imageWithCGImage:processedImageRef]; } } - (void)_setWebImageWithImageStorage:(LWImageStorage *)imageStorage resize:(LWHTMLImageResizeBlock)resizeBlock completion:(LWAsyncCompleteBlock)completion { + NSURL* url; UIImage* placeholder = imageStorage.placeholder; BOOL needResize = imageStorage.needResize; CGFloat cornerRaiuds = imageStorage.cornerRadius; UIColor* cornerBgColor = imageStorage.cornerBackgroundColor; - UIColor* borderColor = imageStorage.cornerBackgroundColor; + UIColor* borderColor = imageStorage.cornerBorderColor; CGFloat borderWidth = imageStorage.cornerBorderWidth; CGSize imageSize = imageStorage.frame.size; UIViewContentMode contentMode = imageStorage.contentMode; BOOL isBlur = imageStorage.isBlur; + BOOL isFadeShow = imageStorage.isFadeShow; + + if (isFadeShow) { + [self.layer removeAnimationForKey:@"fadeshowAnimation"]; + } if ([imageStorage.contents isKindOfClass:[NSString class]]) { url = [NSURL URLWithString:imageStorage.contents]; @@ -86,8 +201,13 @@ - (void)_setWebImageWithImageStorage:(LWImageStorage *)imageStorage resize:(LWHT return; } - __weak typeof(self) weakSelf = self; + SDWebImageOptions options = 0; + + if ([[url.absoluteString lowercaseString] hasSuffix:@".gif"]) { + options |= SDWebImageProgressiveDownload; + } + __weak typeof(self) weakSelf = self; [self lw_asyncSetImageWithURL:url placeholderImage:placeholder cornerRadius:cornerRaiuds @@ -97,19 +217,21 @@ - (void)_setWebImageWithImageStorage:(LWImageStorage *)imageStorage resize:(LWHT size:imageSize contentMode:contentMode isBlur:isBlur - options:0 + options:options progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL *targetURL) { } completed:^(UIImage* image, NSData* data, NSError* error) { + if (!image) { if (completion) { completion(); } return ; } + //LWHTMLDisplayView会根据图片大小自适应,这里根据图片的宽高比例计算出高度需要调整的差值delta __strong typeof(weakSelf) sself = weakSelf; if (needResize) { @@ -118,6 +240,17 @@ - (void)_setWebImageWithImageStorage:(LWImageStorage *)imageStorage resize:(LWHT resizeBlock(imageStorage,delta); } + if (isFadeShow) { + + [self.layer removeAnimationForKey:@"fadeshowAnimation"]; + CATransition* transition = [CATransition animation]; + transition.duration = 0.15; + transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; + transition.type = kCATransitionFade; + [self.layer addAnimation:transition forKey:@"fadeshowAnimation"]; + + } + if (completion) { completion(); } @@ -137,5 +270,92 @@ - (CGFloat)_resizeImageStorage:(LWImageStorage *)imageStorage image:(UIImage *)i } - @end + + + +static void _croppedImageBackingSizeAndDrawRectInBounds(CGSize sourceImageSize, + CGSize boundsSize, + UIViewContentMode contentMode, + CGRect cropRect, + BOOL forceUpscaling, + CGSize* outBackingSize, + CGRect* outDrawRect) { + size_t destinationWidth = boundsSize.width; + size_t destinationHeight = boundsSize.height; + CGFloat boundsAspectRatio = (float)destinationWidth / (float)destinationHeight; + + CGSize scaledSizeForImage = sourceImageSize; + BOOL cropToRectDimensions = !CGRectIsEmpty(cropRect); + + if (cropToRectDimensions) { + scaledSizeForImage = CGSizeMake(boundsSize.width / cropRect.size.width, boundsSize.height / cropRect.size.height); + } else { + if (contentMode == UIViewContentModeScaleAspectFill) + scaledSizeForImage = _sizeFillWithAspectRatio(boundsAspectRatio, sourceImageSize); + else if (contentMode == UIViewContentModeScaleAspectFit) + scaledSizeForImage = _sizeFitWithAspectRatio(boundsAspectRatio, sourceImageSize); + } + if (forceUpscaling == NO && (scaledSizeForImage.width * scaledSizeForImage.height) < (destinationWidth * destinationHeight)) { + destinationWidth = (size_t)roundf(scaledSizeForImage.width); + destinationHeight = (size_t)roundf(scaledSizeForImage.height); + if (destinationWidth == 0 || destinationHeight == 0) { + *outBackingSize = CGSizeZero; + *outDrawRect = CGRectZero; + return; + } + } + + CGFloat sourceImageAspectRatio = sourceImageSize.width / sourceImageSize.height; + CGSize scaledSizeForDestination = CGSizeMake(destinationWidth, destinationHeight); + if (cropToRectDimensions) { + scaledSizeForDestination = CGSizeMake(boundsSize.width / cropRect.size.width, boundsSize.height / cropRect.size.height); + } else { + if (contentMode == UIViewContentModeScaleAspectFill) + scaledSizeForDestination = _sizeFillWithAspectRatio(sourceImageAspectRatio, scaledSizeForDestination); + else if (contentMode == UIViewContentModeScaleAspectFit) + scaledSizeForDestination = _sizeFitWithAspectRatio(sourceImageAspectRatio, scaledSizeForDestination); + } + + CGRect drawRect = CGRectZero; + if (cropToRectDimensions) { + drawRect = CGRectMake(-cropRect.origin.x * scaledSizeForDestination.width, + -cropRect.origin.y * scaledSizeForDestination.height, + scaledSizeForDestination.width, + scaledSizeForDestination.height); + } else { + if (contentMode == UIViewContentModeScaleAspectFill) { + drawRect = CGRectMake(((destinationWidth - scaledSizeForDestination.width) * cropRect.origin.x), + ((destinationHeight - scaledSizeForDestination.height) * cropRect.origin.y), + scaledSizeForDestination.width, + scaledSizeForDestination.height); + + } else { + drawRect = CGRectMake(((destinationWidth - scaledSizeForDestination.width) / 2.0), + ((destinationHeight - scaledSizeForDestination.height) / 2.0), + scaledSizeForDestination.width, + scaledSizeForDestination.height); + } + } + *outDrawRect = drawRect; + *outBackingSize = CGSizeMake(destinationWidth, destinationHeight); +} + +static CGSize _sizeFillWithAspectRatio(CGFloat sizeToScaleAspectRatio, CGSize destinationSize) { + CGFloat destinationAspectRatio = destinationSize.width / destinationSize.height; + if (sizeToScaleAspectRatio > destinationAspectRatio) { + return CGSizeMake(destinationSize.height * sizeToScaleAspectRatio, destinationSize.height); + } else { + return CGSizeMake(destinationSize.width, floorf(destinationSize.width / sizeToScaleAspectRatio)); + } +} + +static CGSize _sizeFitWithAspectRatio(CGFloat aspectRatio, CGSize constraints) { + CGFloat constraintAspectRatio = constraints.width / constraints.height; + if (aspectRatio > constraintAspectRatio) { + return CGSizeMake(constraints.width, constraints.width / aspectRatio); + } else { + return CGSizeMake(constraints.height * aspectRatio, constraints.height); + } +} + diff --git a/Gallop/LWAsyncImageView+WebCache.m b/Gallop/LWAsyncImageView+WebCache.m index 6428298..6b457e7 100644 --- a/Gallop/LWAsyncImageView+WebCache.m +++ b/Gallop/LWAsyncImageView+WebCache.m @@ -66,7 +66,6 @@ - (void)lw_asyncSetImageWithURL:(NSURL *)url self.image = placeholder; }); } - if (url) { __weak typeof(self) weakSelf = self; id operation = [[SDWebImageManager sharedManager] @@ -92,16 +91,13 @@ - (void)lw_asyncSetImageWithURL:(NSURL *)url completedBlock(image,data,error); return; } - dispatch_async(dispatch_get_global_queue(0, 0), ^{ - SDImageFormat imageFormat = [NSData sd_imageFormatForImageData:data]; if (imageFormat == SDImageFormatGIF) { //GIF LWGIFImage* gif = [[LWGIFImage alloc] initWithGIFData:data]; dispatch_main_async_safe(^{ - if (gif && (options & SDWebImageAvoidAutoSetImage) && completedBlock) { completedBlock(gif,data,error); return; diff --git a/Gallop/LWImageProcessor.m b/Gallop/LWImageProcessor.m index 95daebd..5ffcaff 100755 --- a/Gallop/LWImageProcessor.m +++ b/Gallop/LWImageProcessor.m @@ -63,18 +63,14 @@ + (NSString *)lw_imageTransformCacheKeyForURL:(NSURL *)url borderWidth:(CGFloat)borderWidth contentMode:(UIViewContentMode)contentMode isBlur:(BOOL)isBlur { - //将圆角和模糊的相关属性值写入到一个字符串中,以kLWImageProcessorPrefixKey开头。 - if (!url) { return nil; } - CGFloat cr = -1; CGFloat cg = -1; CGFloat cb = -1; CGFloat ca = -1; - if (cornerBackgroundColor) { CGFloat cornerComponents[4]; [self getRGBComponents:cornerComponents @@ -106,7 +102,6 @@ + (NSString *)lw_imageTransformCacheKeyForURL:(NSURL *)url blur = 1; } - //生成绘制信息标识的字符串 NSString* imageStransformCacheKey = [NSString stringWithFormat: @@ -134,7 +129,7 @@ + (UIImage *)lw_cornerRadiusImageWithImage:(UIImage*)img withKey:(NSString *)key //从标识字符串中,依次去除圆角半径和模式的相关属性值,对原图进行处理 if (key && [key hasPrefix:[NSString stringWithFormat:@"%@", - kLWImageProcessorPrefixKey]]) { + kLWImageProcessorPrefixKey]]) { NSString* infoString = [key substringFromIndex:kLWImageProcessorPrefixKey.length]; NSArray* arr = [infoString componentsSeparatedByString:@","]; @@ -201,6 +196,8 @@ + (UIImage *)lw_cornerRadiusImageWithImage:(UIImage*)img withKey:(NSString *)key maskImage:nil]; } + + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(NULL, (int)width, diff --git a/Gallop/LWImageStorage.h b/Gallop/LWImageStorage.h index 0172f1b..44c5b14 100755 --- a/Gallop/LWImageStorage.h +++ b/Gallop/LWImageStorage.h @@ -79,18 +79,3 @@ typedef NS_ENUM(NSUInteger, LWLocalImageType){ @end -@interface LWImageStorageCornerRadiusConfig : NSObject - - - -@end - - -@interface LWImageStorageBlurConfig : NSObject - - - - -@end - - diff --git a/Gallop/LWImageStorage.m b/Gallop/LWImageStorage.m index 1a8f1df..1ce87bc 100755 --- a/Gallop/LWImageStorage.m +++ b/Gallop/LWImageStorage.m @@ -113,7 +113,6 @@ - (id)init { } - (BOOL)needRerendering { - //这个图片设置了圆角的相关属性,需要对原图进行处理 if (self.cornerBorderWidth != 0 || self.cornerRadius != 0) { return YES; @@ -146,6 +145,8 @@ - (void)lw_drawInContext:(CGContextRef)context isCancelled:(LWAsyncDisplayIsCanc if ([self.contents isKindOfClass:[UIImage class]] && self.localImageType == LWLocalImageDrawInLWAsyncDisplayView) { + + UIImage* image = (UIImage *)self.contents; BOOL isOpaque = self.opaque; UIColor* backgroundColor = self.backgroundColor; @@ -198,6 +199,8 @@ - (void)lw_drawInContext:(CGContextRef)context isCancelled:(LWAsyncDisplayIsCanc [cornerBorderColor setStroke]; [cornerPath stroke]; } + + } } diff --git a/Gallop/SDWebImageManager+Gallop.m b/Gallop/SDWebImageManager+Gallop.m index a401bf4..a9c942b 100755 --- a/Gallop/SDWebImageManager+Gallop.m +++ b/Gallop/SDWebImageManager+Gallop.m @@ -69,7 +69,6 @@ @implementation SDWebImageManager(Gallop) url = nil; } - __block SDWebImageCombinedOperation *operation = [SDWebImageCombinedOperation new]; __weak SDWebImageCombinedOperation *weakOperation = operation; @@ -134,6 +133,7 @@ @implementation SDWebImageManager(Gallop) downloaderOptions &= ~SDWebImageDownloaderProgressiveDownload; downloaderOptions |= SDWebImageDownloaderIgnoreCachedResponse; } + SDWebImageDownloadToken *subOperationToken = [self.imageDownloader downloadImageWithURL:url options:downloaderOptions diff --git a/README.md b/README.md index a01cdca..979e2de 100755 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ -# Gallop v0.5.1 +# Gallop v0.6.0 @@ -25,12 +25,12 @@ Gallop is a powerful rich text framework which support Asynchronous rendering.yo * easily draw text frame bouding, drawing the hollow words, sets the text vertical Alignment property, etc * easy to parse the expression in the text, like http(s) link, @ user, # theme #, phone number. * fast to sets the image corner radius property and blur processing, can be processed directly after the image to provide a cache, without repeated processing, improve performance. - +* support GIF. ## Requirements -* web image download and cache depends on [SDWebImage](https://github.com/rs/SDWebImage) 'SDWebImage', '~>3.7'. +* web image download and cache depends on [SDWebImage](https://github.com/rs/SDWebImage) 'SDWebImage', '~> 4.0'. * HTML parsing depends on the libxml2 library. @@ -46,6 +46,11 @@ Gallop is a powerful rich text framework which support Asynchronous rendering.yo ## Modifications +v0.6.0 + +* depend on SDWebImage 4.0 +* fixed bugs. + v0.5.1 * Use "- (id)initWithCallbackQueue:(dispatch_queue_t)callbackQueue" istead of "- (LWTransaction *)initWithCallbackQueue:(dispatch_queue_t)callbackQueue". @@ -338,10 +343,12 @@ Gallop是使用异步绘制的富文本、图文混排框架。只需要使用 * 绘制文本边框、绘制空心字、设置垂直方向Alignment等。 * 便捷地解析文本中的表情、http(s)链接、@用户、#主题#、电话号码。 * 快捷实现对网络、本地图片圆角和模糊处理等,能对处理过后的图片直接提供缓存,无需重复处理。 +* 支持GIF显示 + ## 依赖 -* 网络图片加载、缓存部分依赖于[SDWebImage](https://github.com/rs/SDWebImage) 'SDWebImage', '~>3.7' +* 网络图片加载、缓存部分依赖于[SDWebImage](https://github.com/rs/SDWebImage) 'SDWebImage', '~>4.0' * HTML解析依赖libxml2库 @@ -357,6 +364,11 @@ Gallop是使用异步绘制的富文本、图文混排框架。只需要使用 ## 更新说明 +v0.6.0 + +* 依赖于SDWebImage 4.0 + + v0.5.1 * "- (id)initWithCallbackQueue:(dispatch_queue_t)callbackQueue" -> "- (LWTransaction *)initWithCallbackQueue:(dispatch_queue_t)callbackQueue" diff --git a/pics/architecture.png b/pics/architecture.png old mode 100755 new mode 100644 index d3f0e6e..e1c71c0 Binary files a/pics/architecture.png and b/pics/architecture.png differ