MMRichImageCell.m 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. //
  2. // MMRichImageCell.m
  3. // RichTextEditDemo
  4. //
  5. // Created by aron on 2017/7/19.
  6. // Copyright © 2017年 aron. All rights reserved.
  7. //
  8. #import "MMRichImageCell.h"
  9. #import "UtilMacro.h"
  10. #import "MMRichImageModel.h"
  11. #import "MMRichTextConfig.h"
  12. #import "MMTextView.h"
  13. @interface MMRichImageCell () <MMTextViewDelegate, UITextViewDelegate, MMRichImageUploadDelegate>
  14. @property (nonatomic, strong) MMTextView* textView;
  15. @property (nonatomic, strong) UIImageView* imageContentView;
  16. @property (nonatomic, strong) UIProgressView *progressView;
  17. @property (nonatomic, strong) TDButton *reloadButton;
  18. @property (nonatomic, strong) MMRichImageModel* imageModel;
  19. @end
  20. @implementation MMRichImageCell
  21. - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
  22. self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
  23. if (self) {
  24. [self setupUI];
  25. }
  26. return self;
  27. }
  28. - (void)setupUI {
  29. [self addSubview:self.textView];
  30. [self addSubview:self.imageContentView];
  31. [self addSubview:self.progressView];
  32. [self addSubview:self.reloadButton];
  33. [self.textView mas_makeConstraints:^(MASConstraintMaker *make) {
  34. make.left.top.right.equalTo(self);
  35. make.bottom.equalTo(self).priority(900);
  36. }];
  37. [self.imageContentView mas_makeConstraints:^(MASConstraintMaker *make) {
  38. make.edges.equalTo(self.textView);
  39. }];
  40. [self.progressView mas_makeConstraints:^(MASConstraintMaker *make) {
  41. make.left.equalTo(self).offset(MMEditConfig.editAreaLeftPadding + MMEditConfig.imageDeltaWidth/2);
  42. make.right.equalTo(self).offset(-(MMEditConfig.editAreaRightPadding + MMEditConfig.imageDeltaWidth/2));
  43. make.top.equalTo(self).offset(MMEditConfig.editAreaTopPadding);
  44. make.height.equalTo(@(4));
  45. }];
  46. [self.reloadButton mas_makeConstraints:^(MASConstraintMaker *make) {
  47. make.top.mas_equalTo(self.imageContentView.mas_top);
  48. make.right.mas_equalTo(self.imageContentView.mas_right);
  49. }];
  50. [self.reloadButton setCurrentButtonHotSize:CGSizeZero];
  51. }
  52. - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
  53. [super setSelected:selected animated:animated];
  54. }
  55. - (void)updateWithData:(id)data {
  56. if ([data isKindOfClass:[MMRichImageModel class]]) {
  57. MMRichImageModel* imageModel = (MMRichImageModel*)data;
  58. // 设置旧的数据delegate为nil
  59. _imageModel.uploadDelegate = nil;
  60. _imageModel = imageModel;
  61. // 设置新的数据delegate
  62. _imageModel.uploadDelegate = self;
  63. CGFloat width = [MMRichTextConfig sharedInstance].editAreaWidth;
  64. NSAttributedString* imgAttrStr = [_imageModel attrStringWithContainerWidth:width];
  65. self.textView.attributedText = imgAttrStr;
  66. self.imageContentView.image = _imageModel.image;
  67. // 重新设置TextView的约束
  68. [self.textView mas_remakeConstraints:^(MASConstraintMaker *make) {
  69. make.left.top.right.equalTo(self);
  70. make.bottom.equalTo(self).priority(900);
  71. make.height.equalTo(@(imageModel.imageContentHeight));
  72. }];
  73. [self.imageContentView mas_remakeConstraints:^(MASConstraintMaker *make) {
  74. make.left.equalTo(self).offset(_imageModel.imageFrame.origin.x);
  75. make.top.equalTo(self).offset(_imageModel.imageFrame.origin.y);
  76. make.height.equalTo(@(_imageModel.imageFrame.size.height));
  77. make.width.equalTo(@(_imageModel.imageFrame.size.width));
  78. }];
  79. self.reloadButton.hidden = YES;
  80. self.progressView.hidden = YES;
  81. // 根据上传的状态设置图片信息
  82. if (_imageModel.isDone) {
  83. self.progressView.hidden = YES;
  84. self.progressView.progress = _imageModel.uploadProgress;
  85. self.reloadButton.hidden = YES;
  86. } else if (_imageModel.isFailed) {
  87. self.progressView.hidden = YES;
  88. self.progressView.progress = _imageModel.uploadProgress;
  89. self.reloadButton.hidden = NO;
  90. } else if (_imageModel.uploadProgress > 0) {
  91. self.progressView.hidden = NO;
  92. self.progressView.progress = _imageModel.uploadProgress;
  93. self.reloadButton.hidden = YES;
  94. }
  95. }
  96. }
  97. - (void)mm_beginEditing {
  98. BOOL result = [self.textView becomeFirstResponder];
  99. // NSLog(@"result = %d", result);
  100. }
  101. - (void)mm_endEditing {
  102. BOOL result = [self.textView resignFirstResponder];
  103. // NSLog(@"result = %d", result);
  104. }
  105. - (void)getPreFlag:(BOOL*)isPre postFlag:(BOOL*)isPost richFlag:(BOOL*)isRich model:(RichModel *)model;
  106. {
  107. NSRange selRange = self.textView.selectedRange;
  108. if (isRich) {
  109. if (model && ![model isKindOfClass:[NSNull class]]) {
  110. *isRich = YES;
  111. }else{
  112. *isRich = NO;
  113. }
  114. }
  115. // 设置标记值
  116. if (isPre) {
  117. if (selRange.location == 0) {
  118. *isPre = YES;
  119. } else {
  120. *isPre = NO;
  121. }
  122. }
  123. if (isPost) {
  124. if (selRange.location+selRange.length == _textView.text.length) {
  125. *isPost = YES;
  126. } else {
  127. *isPost = NO;
  128. }
  129. }
  130. }
  131. #pragma mark - ......::::::: lazy load :::::::......
  132. - (MMTextView *)textView {
  133. if (!_textView) {
  134. _textView = [MMTextView new];
  135. _textView.font = MMEditConfig.defaultEditContentFont;
  136. _textView.textContainerInset = UIEdgeInsetsMake(MMEditConfig.editAreaTopPadding, MMEditConfig.editAreaLeftPadding, MMEditConfig.editAreaBottomPadding, MMEditConfig.editAreaRightPadding);
  137. _textView.scrollEnabled = NO;
  138. _textView.allowsEditingTextAttributes = YES;
  139. _textView.delegate = self;
  140. _textView.mm_delegate = self;
  141. }
  142. return _textView;
  143. }
  144. - (UIImageView *)imageContentView {
  145. if (!_imageContentView) {
  146. _imageContentView = [UIImageView new];
  147. _imageContentView.contentMode = UIViewContentModeScaleAspectFit;
  148. _imageContentView.clipsToBounds = YES;
  149. }
  150. return _imageContentView;
  151. }
  152. - (UIProgressView *)progressView {
  153. if (!_progressView) {
  154. _progressView = [UIProgressView new];
  155. _progressView.progressTintColor = [UIColor redColor];
  156. _progressView.backgroundColor = [UIColor lightGrayColor];
  157. }
  158. return _progressView;
  159. }
  160. - (TDButton *)reloadButton {
  161. if (!_reloadButton) {
  162. _reloadButton = [[TDButton alloc] init];
  163. [_reloadButton setImage:[UIImage imageNamed:@"频道关闭"] forState:UIControlStateNormal];
  164. [_reloadButton addTarget:self action:@selector(onReloadBtnClick:) forControlEvents:UIControlEventTouchUpInside];
  165. }
  166. return _reloadButton;
  167. }
  168. - (void)onReloadBtnClick:(UIButton*)sender {
  169. if ([self.delegate respondsToSelector:@selector(mm_reloadItemAtIndexPath:)]) {
  170. [self.delegate mm_reloadItemAtIndexPath:[self curIndexPath]];
  171. }
  172. }
  173. #pragma mark - ......::::::: UITextViewDelegate :::::::......
  174. - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
  175. // 处理换行
  176. if ([text isEqualToString:@"\n"] || text.length > 0) {
  177. if (range.location == 0 && range.length == 0) {
  178. // 在前面添加换行
  179. if ([self.delegate respondsToSelector:@selector(mm_preInsertTextLineAtIndexPath:textContent:)]) {
  180. [self.delegate mm_preInsertTextLineAtIndexPath:[self curIndexPath]textContent:text];
  181. }
  182. } else if (range.location == 1 && range.length == 0) {
  183. // 在后面添加换行
  184. if ([self.delegate respondsToSelector:@selector(mm_postInsertTextLineAtIndexPath:textContent:)]) {
  185. [self.delegate mm_postInsertTextLineAtIndexPath:[self curIndexPath] textContent:text];
  186. }
  187. } else if (range.location == 0 && range.length == 2) {
  188. // 选中和换行
  189. }
  190. }
  191. if (![text isEqualToString:@"\n"] && text.length > 0) {
  192. if (range.location == 1 && range.length == 0) {
  193. // 在后面添加换行
  194. if ([self.delegate respondsToSelector:@selector(mm_postInsertTextLineAtIndexPath:textContent:)]) {
  195. [self.delegate mm_postInsertTextLineAtIndexPath:[self curIndexPath] textContent:text];
  196. }
  197. }
  198. }
  199. // 处理删除
  200. if ([text isEqualToString:@""]) {
  201. NSRange selRange = textView.selectedRange;
  202. if (selRange.location == 0 && selRange.length == 0) {
  203. // 处理删除
  204. if ([self.delegate respondsToSelector:@selector(mm_preDeleteItemAtIndexPath:)]) {
  205. [self.delegate mm_preDeleteItemAtIndexPath:[self curIndexPath]];
  206. }
  207. } else if (selRange.location == 1 && selRange.length == 0) {
  208. // 处理删除
  209. if ([self.delegate respondsToSelector:@selector(mm_PostDeleteItemAtIndexPath:)]) {
  210. [self.delegate mm_PostDeleteItemAtIndexPath:[self curIndexPath]];
  211. }
  212. } else if (selRange.location == 0 && selRange.length == 2) {
  213. // 处理删除
  214. if ([self.delegate respondsToSelector:@selector(mm_preDeleteItemAtIndexPath:)]) {
  215. [self.delegate mm_preDeleteItemAtIndexPath:[self curIndexPath]];
  216. }
  217. }
  218. }
  219. return NO;
  220. }
  221. - (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
  222. // textView.inputAccessoryView = [self.delegate mm_inputAccessoryView];
  223. if ([self.delegate respondsToSelector:@selector(mm_shouldShowAccessoryView:)]) {
  224. [self.delegate mm_shouldShowAccessoryView:YES];
  225. }
  226. if ([self.delegate respondsToSelector:@selector(mm_updateActiveIndexPath:)]) {
  227. [self.delegate mm_updateActiveIndexPath:[self curIndexPath]];
  228. }
  229. return YES;
  230. }
  231. - (BOOL)textViewShouldEndEditing:(UITextView *)textView {
  232. textView.inputAccessoryView = nil;
  233. return YES;
  234. }
  235. #pragma mark - ......::::::: MMRichImageUploadDelegate :::::::......
  236. // 上传进度回调
  237. - (void)uploadProgress:(float)progress {
  238. dispatch_async(dispatch_get_main_queue(), ^{
  239. self.progressView.hidden = NO;
  240. [self.progressView setProgress:progress];
  241. self.reloadButton.hidden = YES;
  242. });
  243. }
  244. // 上传失败回调
  245. - (void)uploadFail {
  246. dispatch_async(dispatch_get_main_queue(), ^{
  247. [self.progressView setProgress:0.01f];
  248. self.reloadButton.hidden = NO;
  249. if ([self.delegate respondsToSelector:@selector(mm_uploadFailedAtIndexPath:)]) {
  250. [self.delegate mm_uploadFailedAtIndexPath:[self curIndexPath]];
  251. }
  252. });
  253. }
  254. // 上传完成回调
  255. - (void)uploadDone {
  256. dispatch_async(dispatch_get_main_queue(), ^{
  257. [self.progressView setProgress:1.0f];
  258. self.progressView.hidden = YES;
  259. self.reloadButton.hidden = NO;
  260. if ([self.delegate respondsToSelector:@selector(mm_uploadDonedAtIndexPath:)]) {
  261. [self.delegate mm_uploadDonedAtIndexPath:[self curIndexPath]];
  262. }
  263. });
  264. }
  265. @end