你就累到死,自动行高的实现

开采中会大量的使用 UITableView,当大家有相当的多的cell,每一行都有八个UITextView 用来进展多少重一些的文本编辑,今年,你的成品经营猛然给您说,我期待以此 UITextView会随着书写内容的尺寸而机关的抓好。(꒪ꇴ꒪哈?

** 时隔半个月,终于来更新第二篇了,大家有木有很期待! **

在付出中时时会高出那样的供给:修改客户、商品等音信时出于内容过多须求折行呈现。本篇小说消除了在二个动态的UITabelView中,cell会遵照每行TextView输入的原委实时改变cell和TabelView的高度。那是自身想要的功效:

花时间写了个德姆o,满含相比较完善从UIView,UILabel,UIImageView的自适应到UITextView,UITableView,UICollectionView,UIScrollView都有,能够下载学习一下。Demo地址
小心不包容demo恐怕会不知所云!

因为自身本身也找了持久,参照过外人写的部分,然则到小编那边都不是特意的实用,非常是开展数量刷新的时候,如若您的行高需求改变,你去 reloadData那个时候,键盘会失去响应。固然你那个时候重新将键盘设置为 firstResponser,这年你的键盘依旧会闪一下,不是很自然。所以写了有个别小的 demo ,上边包车型客车具体代码也是本着这一个 demo 的,点击这里下载

1、效果:

功能一、让系统TextView自带placeholder属性

图片 1image

效果二、自动更动中度,类似聊天输入框

图片 2image

意义三、支持输入图片

图片 3image

图片 4最后效果

图片 5

  1. 先是对 TextView 的输入实行监听,推断输入的字数的略微
  2. 基于 UITextView 的篇幅的多少去动态的改造 UITextView 的 frame
  3. 监听 UITextView 的冲天变化,假设 UITextView 比你的 cell 还要高的时候,你必要动态的去立异您的 UITableViewCell 的中度
2、使用方法:

将UITextView WZB.h和UITextView WZB.m拖入工程

只要求在要求采纳的地方直接导入头文件UITextView WZB.h,你的UITextView就全部了那三大成效

// 直接设置placeholder属性即可 textView.placeholder = @"i love you"; [self.view addSubview:textView]; 

图片 6image

比如想要计算高度,只要求调用那几个措施就能够,你必要在block回调里手动退换textView的惊人

/* 自动高度的方法,maxHeight:最大高度, textHeightDidChanged:高度改变的时候调用 */- autoHeightWithMaxHeight:maxHeight textViewHeightDidChanged:(textViewHeightDidChangedBlock)textViewHeightDidChanged;

如图

图片 7image

插入图片的章程如下:

/* 添加一张图片 image:要添加的图片 */- addImage:(UIImage *)image;/* 添加一张图片 image:要添加的图片 size:图片大小 */- addImage:(UIImage *)image size:size;/* 插入一张图片 image:要添加的图片 size:图片大小 index:插入的位置 */- insertImage:(UIImage *)image size:size index:(NSInteger)index;/* 添加一张图片 image:要添加的图片 multiple:放大/缩小的倍数 */- addImage:(UIImage *)image multiple:multiple;/* 插入一张图片 image:要添加的图片 multiple:放大/缩小的倍数 index:插入的位置 */- insertImage:(UIImage *)image multiple:multiple index:(NSInteger)index;

申明写的很理解,效果如下:

图片 8image

落实地点效果的基本原理:
  • 在 cell 中安装好 textView 的 Autolayout,让 cell 能够依靠剧情自适应大小
  • textView 中输入内容,依照内容更新 textView 的冲天
  • 调用 tableView 的 beginUpdates 和 endUpdates,重新总结 cell 的莫斯中国科学技术大学学
  • 将 textView 更新后的数据保存,避防 tableView 滚动超越一屏再滚回来 textView 中的数据又不刷新成原本的数量了。

autolayoutdemo.gif

先辈已经有了现存的车轱辘,所以无需您重新的造轮子。这里找到二个很好的电动换行的 TextView大家须要利用这些来成功大家接下去的行事

3、达成差不离原理:

使用runtime为textView增添如下属性

// 占位文字static const void *WZBPlaceholderViewKey = &WZBPlaceholderViewKey;// 占位文字颜色static const void *WZBPlaceholderColorKey = &WZBPlaceholderColorKey;// 最大高度static const void *WZBTextViewMaxHeightKey = &WZBTextViewMaxHeightKey;// 高度变化的blockstatic const void *WZBTextViewHeightDidChangedBlockKey = &WZBTextViewHeightDidChangedBlockKey;// 动态添加属性的本质是: 让对象的某个属性与值产生关联objc_setAssociatedObject(self, WZBPlaceholderViewKey, placeholderView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);objc_setAssociatedObject(self, WZBTextViewMaxHeightKey, [NSString stringWithFormat:@"%lf", maxHeight], OBJC_ASSOCIATION_COPY_NONATOMIC);objc_setAssociatedObject(self, WZBTextViewHeightDidChangedBlockKey, textViewHeightDidChanged, OBJC_ASSOCIATION_COPY_NONATOMIC);objc_setAssociatedObject(self, WZBPlaceholderColorKey, placeholderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

监听

 // 监听文字改变 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewTextChange) name:UITextViewTextDidChangeNotification object:self]; // 这些属性改变时,都要作出一定的改变,尽管已经监听了TextDidChange的通知,也要监听text属性,因为通知监听不到setText: NSArray *propertys = @[@"frame", @"bounds", @"font", @"text", @"textAlignment", @"textContainerInset"]; // 监听属性 for (NSString *property in propertys) { [self addObserver:self forKeyPath:property options:NSKeyValueObservingOptionNew context:nil]; } 

当文字发生变化的时候

- textViewTextChange { self.placeholderView.hidden = (self.attributedText.length > 0 && self.attributedText); if (self.maxHeight >= self.bounds.size.height) { // 计算高度 NSInteger currentHeight = ceil([self sizeThatFits:CGSizeMake(self.bounds.size.width, MAXFLOAT)].height); NSInteger lastheight = ceil(self.maxHeight   self.textContainerInset.top   self.textContainerInset.bottom); // 如果高度有变化,调用block if (currentHeight != lastheight) { self.scrollEnabled = currentHeight >= self.maxHeight; if (self.textViewHeightDidChanged) { self.textViewHeightDidChanged((currentHeight >= self.maxHeight ? self.maxHeight : currentHeight)); } } }}

增加图片是用的NSTextAttachment

- addImage:(UIImage *)image size:size index:(NSInteger)index multiple:multiple { NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText]; NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init]; textAttachment.image = image; CGRect bounds = textAttachment.bounds; if (!CGSizeEqualToSize(size, CGSizeZero)) { bounds.size = size; textAttachment.bounds = bounds; } else if (multiple > 0.0f) { textAttachment.image = [UIImage imageWithCGImage:textAttachment.image.CGImage scale:multiple orientation:UIImageOrientationUp]; } else { CGFloat oldWidth = textAttachment.image.size.width; CGFloat scaleFactor = oldWidth / (self.frame.size.width - 10); textAttachment.image = [UIImage imageWithCGImage:textAttachment.image.CGImage scale:scaleFactor orientation:UIImageOrientationUp]; } NSAttributedString *attrStringWithImage = [NSAttributedString attributedStringWithAttachment:textAttachment]; [attributedString replaceCharactersInRange:NSMakeRange withAttributedString:attrStringWithImage]; self.attributedText = attributedString; // 记得走下这两个方法 [self textViewTextChange]; [self refreshPlaceholderView];}
一、计划工作

创造项目,自定义创立UITabelViewCell勾选XIB。

iOS8后头 使用AutoLayout是特别方便的,更况且iOS11都要发布了,不会还想着协理iOS7吧!(iOS7也是永葆autolayout的,只是有部分坑及与iOS8API的分化)。

 [textView wzb_autoHeightWithMaxHeight:300 textViewHeightDidChanged:^(CGFloat currentTextViewHeight) { //在此处我们已经对 UITextView 完成了监听,接下来我们就可以修改 UITextView 的 frame 了}];

__weak typeof WeakSelf = self;__weak typeof WeakTextView = textView; [textView wzb_autoHeightWithMaxHeight:300 textViewHeightDidChanged:^(CGFloat currentTextViewHeight) { CGRect frame = WeakTextView.frame; frame.size.height = currentTextViewHeight; [UIView animateWithDuration:0.2 animations:^{ WeakTextView.frame = frame; } completion:^(BOOL finished) { }]; }];
4、GitHub源码地址:UITextView-WZB
二、为cell中的textView加多约束

为了查看方便本人给textView增多了肉桂色背景

图片 9Autolayout

怎么为控件加多约束不打听的校友上午加加点好好学,这里不做过多介绍。

⚠️注意:设置 UITextView 的 scrollEnable 为 NO。那一点很要紧,假使不设置为 NO,当UITextView 输入内容超越大家 约束的 frame 后,重新恢复设置 textView 的万丈会失灵,并出现滚动条。

图片 10设置 UITextView 的 scrollEnable 为 NO

iOS8自此,对于UIScrollView及UITableView,UICollectionViewCell的可观自适应解决了大家直接脑瓜疼的变高难题!!!

大家必要对单元格的惊人实行封存,然后在刷新行高的时候把中度抽出来赋值。所以大家还索要多个封存中度的字典dicHeight

1、效果:

图片 11经常展现在分界面上图片 12从显示器上面弹出图片 13做键盘突显

三、实操

1、让UITextView服从代理UITextViewDelegate

图片 14加上代理

2、在 TextViewCell.m 中实现- textViewDidChange:(UITextView *)textView,每一趟 textView 内容更换的时候,就再一次总括贰次 textView 的大小,并让 table view 更新的高峰度。

//每次 textView 内容改变的时候,就重新计算一次 textView 的大小,并让 tableView 更新高度。- textViewDidChange:(UITextView *)textView{ CGRect bounds = textView.bounds; // 计算 text view 的高度 CGSize maxSize = CGSizeMake(bounds.size.width, CGFLOAT_MAX); CGSize newSize = [textView sizeThatFits:maxSize]; bounds.size = newSize; textView.bounds = bounds; // 让 table view 重新计算高度 UITableView *tableView = [self tableView]; [tableView beginUpdates]; [tableView endUpdates]; }- (UITableView *)tableView{ UIView *tableView = self.superview; while (![tableView isKindOfClass:[UITableView class]] && tableView) { tableView = tableView.superview; } return (UITableView *)tableView;}

到近些日子结束已经达成了 textView 改造内容自动更新 cell 中度的作用,本文章未有关系到计算 cell 中度的代码,因为总括 cell 中度的行事总体付出 iOS 8 的 autolayout 自动测算了,那让大家少写了累累令人难熬的代码。

假设你还不用,那么您感觉您是偷懒了,懒得去学,其实你在付出中浪费了越多的光阴与头脑细胞。

 __weak typeof WeakSelf = self;__weak typeof WeakTextView = textView;// 最大高度为300 改变高度的 block[textView wzb_autoHeightWithMaxHeight:300 textViewHeightDidChanged:^(CGFloat currentTextViewHeight) { CGRect frame = WeakTextView.frame; frame.size.height = currentTextViewHeight; [UIView animateWithDuration:0.2 animations:^{ WeakTextView.frame = frame; } completion:^(BOOL finished) { }]; NSString *key = [NSString stringWithFormat:@"%@",indexPath]; NSNumber *height = [NSNumber numberWithFloat:currentTextViewHeight]; if (WeakSelf.dicHeight[key]) { NSNumber *oldHeight = self.dicHeight[key]; if (oldHeight.floatValue != height.floatValue) { [WeakSelf.dicHeight setObject:height forKey:key]; } } else{ [WeakSelf.dicHeight setObject:height forKey:key]; } [WeakSelf.tableview beginUpdates]; [WeakSelf.tableview endUpdates]; }];
2、使用办法:

将WZBDatePicker.h和WZBDatePicker.m拖入工程

只必要在供给使用的地方直接导入头文件WZBDatePicker.h,然后调用上边那么些措施就可以

/* 显示方法 view:如果WZBDatePickerInputView传拥有inputView的控件,其他传普通的view,pickerType:显示方式 resultDidChange:滑动picker的时候调用 block参数age:年龄,constellation:星座 **/ [WZBDatePicker showToView:self.view pickerType:WZBDatePickerNormal resultDidChange:^(NSString *age, NSString *constellation){ // to do }]; 

typedef NS_ENUM(NSInteger, WZBDatePickerType) { WZBDatePickerNormal = 0, // 普通的显示在界面上 WZBDatePickerInputView = 1, // 做键盘显示 WZBDatePickerBottomPop // 从视图底部弹出};@interface WZBDatePicker : UIView/* 显示方法 view:如果WZBDatePickerInputView传拥有inputView的空间,其他传普通的view,pickerType:显示方式 resultDidChange:滑动picker的时候调用 block参数age:年龄,constellation:星座 **/  (instancetype)showToView:view pickerType:(WZBDatePickerType)pickerType resultDidChange:(NSString *age, NSString *constellation))resultDidChange;/* 设置初始时间 **/- setCurrentDate:date;/* 隐藏 **/- hidden;/* 是否有黑色半透明遮罩,默认没有,在pickerType!=WZBDatePickerBottomPop时不起任何作用 **/@property (nonatomic, assign, getter=isEnableDarkMask) BOOL enableDarkMask; 

h文件中提供了这个点子和质量,注释写的很明亮,能够向来动用。

假使做键盘呈现,需求如此:

/* 显示方法 view:如果WZBDatePickerInputView传拥有inputView的空间,其他传普通的view,pickerType:显示方式 resultDidChange:滑动picker的时候调用 block参数age:年龄,constellation:星座 **/ [WZBDatePicker showToView:self.textField pickerType:WZBDatePickerInputView resultDidChange:^(NSString *age, NSString *constellation){ self.textField.text = [NSString stringWithFormat:@"%@--%@", age, constellation]; }];

潜心,参数view,必需传带有inputView的控件,例如UITextField或UITextView等

四、滑动UITabelView导致数据的来得难题

为了以免万一 tableView 过长,导致滚动后再度加载 cell,会让 textView 中的内容还原的主题材料,大家理应在革新了 textView 的剧情之后保存数据。*(要是是在编写状态下,还索要思念裁撤编辑后的来得以前的数额。 能够保留三个原有数据的别本,假设客户撤销编辑,就安装 data 为原来数据的副本。本效率就不做牵线了,有意思味的同学能够团结敲一下,增加贰个撤废编辑开关事件,然后两三行代码解决)*

1、为了在 textView 内容更新后能让 TableViewController 中的 data 更新,要求为 cell 增加三个通报,在 textView 更新后调用,TableViewController 中收受 布告音信后更新 data。这里笔者用的是代理Delegate。修改过后的TextViewCell.h

#import <UIKit/UIKit.h>@class TextViewCell;@protocol TextViewCellDelegate <NSObject>- textViewCell:(TextViewCell *)cell didChangeText:(NSString *)text;@end@interface TextViewCell : UITableViewCell@property (weak, nonatomic) id<TextViewCellDelegate> delegate;@property (nonatomic, strong) NSIndexPath *indexPath;- setCellTitle:(NSString *)title cellContentInfo:(NSString *)info;@property (weak, nonatomic) IBOutlet UITextView *detailTitleTV;@end

2、在 TextView.m- textViewDidChange:(UITextView *)textView中添加 delegate 的调用

- textViewDidChange:(UITextView *)textView{ [self.delegate textViewCell:self didChangeText:textView.text]; // 计算 text view 的高度 ... // 让 table view 重新计算高度 ...}

3、最后在 TableViewController.m 的末尾达成 TextViewCellDelegate的方法,更新data

#pragma mark - TextViewCellDelegate- textViewCell:(TextViewCellCell *)cell didChangeText:(NSString *)text{ NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; NSMutableArray *data = [self.detailTitleArr mutableCopy]; data[indexPath.row] = text; self.detailTitleArr = [data copy];}

图片 15最终效果

骨子里英特网那样封装好的第三方有那么些,可是三个粗略的遵守就去集成那一个臃肿的第三方甚是不妥,不仅仅损耗费时间间还扩张代码费用,借使不符合自身供给的还得做修改。所以也提示大家不能够为了快而集成二个冗余臃肿的第三方,为随后的开采和保卫安全扩展资金!

打完手工业!

UIView的自适应

UIView能够依附其subviews自动适配自个儿的宽高,也正是一旦其subviews能有分明的足足的束缚消息,那么view的宽高就能够被鲜明了

我们运用beginUpdatesendUpdates 。不使用 reloadData。具体的因由看本人事先写的干什么不用 ReloadData。

3、达成大约原理:

当中是一个tableView,tableView的headerView是二个label,呈现音信。tableView的footerView是个UIDatePicker,彰显日期。这样写是因为正如好调节中间两行cell的显得与隐蔽,headerView和footerView也不用单独保管size

监听picker的滚动,并刷新tableView或然调用block更新时间,假诺是键盘,遮盖了中档两行cell,所以无需刷新tableView

- dateDidChanged:(UIDatePicker *)datePicker { self.checkedDate = datePicker.date; self.pickerType == WZBDatePickerInputView ? [self upData] : [self.tableView reloadData];}

假如enableDarkMask为yes,背景颜色产生半透明颜色,况且启用单击掌势

- setEnableDarkMask:enableDarkMask { _enableDarkMask = enableDarkMask; if (self.pickerType == WZBDatePickerBottomPop) { self.backgroundColor = self.isEnableDarkMask ? [UIColor colorWithWhite:0 alpha:0.2] : [UIColor clearColor]; }}

UILabel的自适应

神跡假诺想UILabel的文字增加变宽变高,要如何促成?其实UILabel是多个相比极其的成分,只要设置了步长约束,中度就能够自适应了(UILabel设置lines=0表示自动换行,具体数字是限量多少行)。如大家给UILabel设置约束宽度不赶上200,然后动态改变它上边包车型大巴文字,它就自适应了中度

AutoLayout是永葆富文本的,也便是说大家设置约束的时候不限制其高度的话,是会活动适配的!!!(@奋起的小黄鹂 谢谢你的上报)

图片 16

截屏内容在demo中有全体代码

永不怪笔者页面搞得五光十色,还不是为着让控件更分明嘛哈哈

接下去就能够修改行高了

4、GitHub源码地址:WZBDatePicker

UIImageView

看看网络海人民广播电视台湾大学人问怎么管理图片自适应的主题材料,举例固定imageView的上升的幅度,中度依据互联网获取的image来动态改造。很不满,UIImageView并从未自行布局。大家得以让后台重返宽高,大概要求到image对象后,依据image的size来获得宽高。然后遵照宽高的缩放比例来适配

[self.imageViewRef mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self.contentView);
}];

customCell.imageViewRef.image = image;
[customCell.imageViewRef mas_updateConstraints:^(MASConstraintMaker *make) {
    make.height.mas_equalTo([UIScreen mainScreen].bounds.size.width * image.size.height / image.size.width);
 }];
-tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ NSString *key = [NSString stringWithFormat:@"%@",indexPath]; if(self.dicHeight[key]){ NSNumber *number = self.dicHeight[key]; if (number.floatValue > 44) { return number.floatValue; } } return 44; }
1、效果:

图片 17带有文字闪动渐变的label

UITextView的万丈自适应

要点:

  • UITextView的惊人自适应只须求不限定其height
  • scrollEnabled = NO 独有不足滚动才会自行扩展在那之中度
  • 若textView的始末产生偏移,请看UITextView内容偏移的标题管理
- (UITextView *)textView
{
    if (!_textView) {
        _textView = [[UITextView alloc] init];
        _textView.backgroundColor = [UIColor grayColor];
        _textView.scrollEnabled = NO;
        _textView.font = [UIFont systemFontOfSize:20];
    }
    return _textView;
}

- (void)makeContraints
{
    WEAKSELF
    [self.textView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.right.equalTo(weakSelf.view);
        make.top.mas_equalTo(100);
        make.height.greaterThanOrEqualTo(@100);
    }];
}

通过那么些您就足以省略的领会为什么不能够用 reloadData了。使用的时候把自动行高的哪儿注释掉。轻便的输入一些事物做一些品尝吧。

2、使用方法:

将WZBGradualLabel.h和WZBGradualLabel.m拖入工程

只要求在需求选取的地点直接导入头文件WZBGradualLabel.h,然后调用上面那些情势就能够

/* * frame:label的frame * title:text * duration:时间间隔 * gradualWidth:渐变颜色的宽 * superView:label的父控件 **/ [WZBGradualLabel gradualLabelWithFrame:{10, 450, WZBScreenWidth - 20, 40} title:@"123456789012345678901234567890" duration:2 superview:self.view]; 

图片 18效果

上边是提供的有个别属性和方法

/*/* 渐变颜色色值,有默认值 **/@property (nonatomic, strong) NSArray *gradualColors;/* * frame:label的frame * title:text * duration:时间间隔 * gradualWidth:渐变颜色的宽 * superView:label的父控件 **/  (instancetype)gradualLabelWithFrame:frame title:(NSString *)title duration:(NSTimeInterval)duration gradualWidth:gradualWidth superview:superview;/* * frame:label的frame * title:text * superView:label的父控件 **/  (instancetype)gradualLabelWithFrame:frame title:(NSString *)title superview:superview;/* * frame:label的frame * title:text * duration:时间间隔 * superView:label的父控件 **/  (instancetype)gradualLabelWithFrame:frame title:(NSString *)title duration:(NSTimeInterval)duration superview:superview;/* * frame:label的frame * title:text * gradualWidth:渐变颜色的宽 * superView:label的父控件 **/  (instancetype)gradualLabelWithFrame:frame title:(NSString *)title gradualWidth:gradualWidth superview:superview; 

h文件中提供了那些方法和属性,注释写的很清楚,全体办法能够一向动用。colors是个数组,能够安装渐变层的颜料,至少传入三个值

UITableViewCell的自适应

*兼容iOS7 时
systemLayoutSizeFittingSize来取高。步骤是先在数额model中增加贰个height的性情用来缓存高,然后在table view的heightForRowAtIndexPath代理里static贰个只早先化三回的Cell实例,然后依照model内容填充数据,最后依照cell的contentView的systemLayoutSizeFittingSize的法门获得到cell的高,然后缓存给model的height

//还是那个熟悉的高度的代理,iOS8之后就少用它吧
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    static CustomCell *cell;
    //只初始化一次cell
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        cell = [tableView dequeueReusableCellWithIdentifier:"CustomCell"];
    });
    DataModel *model = self.dataArray[(NSUInteger) indexPath.row];
    [cell makeupData:model];

    if (model.cellHeight <= 0) {
        //使用systemLayoutSizeFittingSize获取高度
        model.cellHeight = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height   1;
    }
    return model.cellHeight;
}

在 iOS 8 中cell 如果有一个确定的宽度/高度,autolayout 会自动根据 cell 中的内容计算出对应的高度/宽度。

要让 table view 的 cell 自适应内容,有多少个宗旨:

  1. 安装的 AutoLayout 约束必需让 cell 的 contentView 知道什么自动延展。关键点是 contentView 的 4 个边都要安装连接到剧情的自律,何况内容是会动态改造尺寸的。

  2. UITableView 的 rowHeight 的值要设置为 UITableViewAutomaticDimension

  3. 贯彻tableView.estimatedRowHeight属性恐怕estimatedHeightForRowAtIndexPath代理。

//需要设置的两句代码:一点计算 cell 高度的代码都没有!!连heightForRowAtIndexPath都不用实现
 _tableView.estimatedRowHeight = 80;
_tableView.rowHeight = UITableViewAutomaticDimension;

UITableView-FDTemplateLayoutCell 是贰个举世出名的cell高度缓存的库,能够削减系统总结行高的次数,让UITableView滑动更通畅。

 //模拟数据刷新-textViewDidChange:(UITextView *)textView{//1.reloadData//[self.tableview reloadData]; //2.reloadindexpath // NSIndexPath *index = [NSIndexPath indexPathForRow:0 inSection:0]; // [self.tableview reloadRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationTop];//3.beginupdate & endupdate// [self.tableview beginUpdates];// [self.tableview endUpdates]; }
3、完成大致原理:

图片 19规律深入分析

实则看来层级图,它是有三层的,最尾部的label正是您要来得的label,中间有层黑灰的片段,这几个其实是渐变层view,最上层的label是渐变层的文字

 self.gradientLayer.mask = self.label.layer; 

那句话是安装渐变图层的mask为label图层,那样就足以用文字裁剪渐变图层了,只保留文字的有的

至于动画改换,小编用的是三个UIView动画,动态改动中间层View和渐变层label的x值,view是增加在底层label上的,上层label是增加在中间view上的,先让view在父控件的最左侧,上层label在此view的右侧,说白了就是让上层label和底部label完全重合,为了维持这一情况,中间的view向右走,上层label必得以同样的值向左走!具体请看代码:

- changX { __block CGRect frame1 = self.leftView.frame; __block CGRect frame2 = self.label.frame; frame1.origin.x = -self.gradualWidth; frame2.origin.x = self.gradualWidth; self.leftView.frame = frame1; self.label.frame = frame2; [UIView animateWithDuration:self.duration animations:^{ frame1.origin.x = self.bounds.size.width; self.leftView.frame = frame1; frame2.origin.x = -self.bounds.size.width; self.label.frame = frame2; }];}

kvo监听那一个属性,也是为了维持上层label和后面部分label能完全重叠的动静,以便帮助客户对label实行文字对其、文字改换、文字换行、字体大小、frame、换行以及attributedText等操作

// kvo监听属性for (NSString *property in self.propertys) { [self addObserver:self forKeyPath:property options:NSKeyValueObservingOptionNew context:nil];}- observeValueForKeyPath:(NSString *)keyPath ofObject:object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:context { if ([keyPath isEqualToString:@"text"]) { self.label.text = self.text; } else if ([keyPath isEqualToString:@"font"]) { self.label.font = self.font; } else if ([keyPath isEqualToString:@"textAlignment"]) { self.label.textAlignment = self.textAlignment; } else if ([keyPath isEqualToString:@"attributedText"]) { self.label.attributedText = self.attributedText; } else if ([keyPath isEqualToString:@"frame"]) { self.label.frame = {self.label.frame.origin, self.frame.size}; } else if ([keyPath isEqualToString:@"numberOfLines"]) { self.label.numberOfLines = self.numberOfLines; }}

UITextView 在Cell中的高度自适应

亟需textView中度自适应的须要时常表现为---UITextView嵌套在Cell中

//  TextViewCell.m
//cell初始化
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self.contentView addSubview:self.textView];
         __weak typeof(self) weakSelf = self;
        [self.textView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.edges.equalTo(weakSelf.contentView);
        }];
    }
    return self;
}

-(UITextView *)textView
{
    if (!_textView) {
        _textView = [[UITextView alloc]init];
        _textView.backgroundColor = [UIColor greenColor];
        _textView.font = [UIFont systemFontOfSize:20];
        //scrollEnabled 必须设置为NO,否则sizeToFit适配不了
        _textView.scrollEnabled = NO;
        _textView.delegate = self;
    }
    return _textView;
}

//实现变高的关键所在
-(void)textViewDidChange:(UITextView *)textView
{
    [textView sizeToFit];
    UITableView *tableView = [self tableView];
    [tableView beginUpdates];
    [tableView endUpdates];
}

- (UITableView *)tableView
{
    UIView *tableView = self.superview;

    while (![tableView isKindOfClass:[UITableView class]] && tableView) {
        tableView = tableView.superview;
    }

    return (UITableView *)tableView;
}

//tableView的代码
-(UITableView *)tableView
{
    if (!_tableView) {
        _tableView = [[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStylePlain];
        _tableView.delegate = self;
        _tableView.dataSource = self;

        [_tableView registerClass:[TextViewCell class] forCellReuseIdentifier:@"TextViewCell"];

//自适应cell需要的代码
        _tableView.estimatedRowHeight = 40;
        _tableView.rowHeight = UITableViewAutomaticDimension;

    }
    return _tableView;
}

UITableView 作为 iOS 开垦中用到的比较多的控件,在切切实实的利用香港中华总商会会冒出美妙绝伦标难点,自动行高这里终于是脱坑了。先写到这里

4、GitHub源码地址:WZBGradualLabel

UICollectionViewCell的自适应

在 collection view 中也能让 cell 自适应内容大小,假设 UICollectionView 的 layout 是二个 UICollectionViewFlowLayout,只要求将 layout.itemSize = ... 改成 layout.estimatedItemSize = ...。 只要设置了 layout 的 estimatedItemSize,collection view 就能够依照 cell 里面包车型地铁 autolayout 约束去显著cell 的分寸

原理:

  1. collection view 依据 layout 的 estimatedItemSize 算出估计的 contentSize,有了 contentSize collection view 就从头展示

  2. collection view 在展现的历程中,就要被出示的 cell 根据 autolayout 的牢笼算出自适应内容的 size

  3. layout 从 collection view 里获得更新过的 size attribute

  4. layout 重回最终的 size attribute 给 collection view

  5. collection 使用那一个最后的 size attribute 突显 cell

//只需要实现估算高度,cell会根据其subviews自动获取大小。
//也就是说cell的subviews需要有足够的约束信息推断出cell的size

layout.estimatedItemSize = CGSizeMake(SCREEN_WIDTH/2 , 150);

举例落成:

图片 20

collectionview.gif

自然你也能够把它当tableview用

1、效果:

洋洋app用到了这种html元素效果,写了个demo效果如下:

图片 21image

UIScrollView的自适应

UIScrollView也足以自适应,自适应UIScrollView就无需大家再总括contentSize了。
然则要专一的是:UIScrollView的contentSize是凭借它的subView来测算的,约等于其subViews本身必需能够规定大小。

UIView *container = [UIView new];
[scrollView addSubview:container];
[container mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(scrollView);
    //这里的宽度的意思是:contentSize的宽固定,高度变化,竖直方向滑动
    make.width.equalTo(scrollView);
}];

总结:

AutoLayout 已经是从事情发展的趋势看必得采取行动了,曾经它扩充了代码量,使十分的多人还停留在frame不舍得转过来,今后吧,它能够急剧的实惠开辟者,还足以省非常多代码。只要多加练习,对于iOS的布局就不会再那么恐怖了!

2、使用方法:

只必要一行代码 ,能够自定义文字颜色、背景颜色、合併单元格、点击事件等操作

/** * 创建一个表格 * line:列数 * columns:行数 * data:数据 */ [v1 wzb_drawListWithRect:v1.bounds line:4 columns:3 datas:@[@"", @"语文", @"数学", @"英语", @"王晓明", @"100.5", @"128", @"95", @"李小华", @"100.5", @"128", @"95", @"张爱奇", @"100.5", @"128", @"95"]]; 

/** * 创建一个表格 * line:列数 * columns:行数 * data:数据 */- wzb_drawListWithRect:rect line:(NSInteger)line columns:(NSInteger)columns datas:(NSArray *)datas;/** * 创建一个表格 * line:列数 * columns:行数 * data:数据 * lineInfo:行信息,传入格式:@{@"0" : @"3"}意味着第一行创建3个格子 */- wzb_drawListWithRect:rect line:(NSInteger)line columns:(NSInteger)columns datas:(NSArray *)datas lineInfo:(NSDictionary *)lineInfo;/** * 创建一个表格 * line:列数 * columns:行数 * data:数据 * colorInfo:颜色信息,传入格式:@{@"0" : [UIColor redColor]}意味着第一个格子文字将会变成红色 */- wzb_drawListWithRect:rect line:(NSInteger)line columns:(NSInteger)columns datas:(NSArray *)datas colorInfo:(NSDictionary *)colorInfo;/** * 创建一个表格 * line:列数 * columns:行数 * data:数据 * colorInfo:颜色信息,传入格式:@{@"0" : [UIColor redColor]}意味着第一个格子文字将会变成红色 * lineInfo:行信息,传入格式:@{@"0" : @"3"}意味着第一行创建3个格子 */- wzb_drawListWithRect:rect line:(NSInteger)line columns:(NSInteger)columns datas:(NSArray *)datas colorInfo:(NSDictionary *)colorInfo lineInfo:(NSDictionary *)lineInfo;/** * 创建一个表格 * line:列数 * columns:行数 * data:数据 * colorInfo:颜色信息,传入格式:@{@"0" : [UIColor redColor]}意味着第一个格子文字将会变成红色 * lineInfo:行信息,传入格式:@{@"0" : @"3"}意味着第一行创建3个格子 * backgroundColorInfo:行信息,传入格式:@{@"0" : [UIColor redColor]}意味着第一个格子背景颜色变成红色 */- wzb_drawListWithRect:rect line:(NSInteger)line columns:(NSInteger)columns datas:(NSArray *)datas colorInfo:(NSDictionary *)colorInfo lineInfo:(NSDictionary *)lineInfo backgroundColorInfo:(NSDictionary *)backgroundColorInfo;/** * 获取第index个格子的label */- (UILabel *)getLabelWithIndex:(NSInteger)index;/** * 画一条线 * frame: 线的frame * color:线的颜色 * lineWidth:线宽 */- wzb_drawLineWithFrame:frame lineType:(WZBLineType)lineType color:(UIColor *)color lineWidth:lineWidth;

.h文件中提供了那几个办法,用法看注释就可以,getLabelWithIndex:方法是赢得第index个格子,举个例子您有13个格子,[view getLabelWithIndex:0];是获得第三个格子,能够对其开展任何操作,比方本身在第多少个表格中获得左手八个label,增添单击掌势进行跳转

3、完成大致原理:
/** * 创建一个表格 * line:列数 * columns:行数 * data:数据 * colorInfo:颜色信息,传入格式:@{@"0" : [UIColor redColor]}意味着第一个格子文字将会变成红色 * lineInfo:行信息,传入格式:@{@"0" : @"3"}意味着第一行创建3个格子 * backgroundColorInfo:行信息,传入格式:@{@"0" : [UIColor redColor]}意味着第一个格子背景颜色变成红色 */- wzb_drawListWithRect:rect line:(NSInteger)line columns:(NSInteger)columns datas:(NSArray *)datas colorInfo:(NSDictionary *)colorInfo lineInfo:(NSDictionary *)lineInfo backgroundColorInfo:(NSDictionary *)backgroundColorInfo { NSInteger index = 0; CGFloat x = rect.origin.x; CGFloat y = rect.origin.y; CGFloat h =  * rect.size.height / columns; NSInteger newLine = 0; for (NSInteger i = 0; i < columns; i  ) { // 判断合并单元格 if  { for (NSInteger a = 0; a < lineInfo.allKeys.count; a  ) { // 新的列数 NSInteger newColumn = [lineInfo.allKeys[a] integerValue]; if (i == newColumn) { newLine = [lineInfo[lineInfo.allKeys[a]] integerValue]; } else { newLine = line; } } } else { newLine = line; } for (NSInteger j = 0; j < newLine; j  ) { // 线宽 CGFloat w =  * rect.size.width / newLine; CGRect frame = {x   w * j, y   h * i, w, h}; // 画线 [self wzb_drawRectWithRect:frame]; // 创建label UILabel *label = [[UILabel alloc] initWithFrame:frame]; // 文字居中 label.textAlignment = NSTextAlignmentCenter; [self addSubview:label]; // 判断文字颜色 UIColor *textColor = [colorInfo objectForKey:[NSString stringWithFormat:@"%zd", index]]; if (!textColor) { textColor = [UIColor grayColor]; } label.textColor = textColor; // 判断背景颜色 UIColor *backgroundColor = [backgroundColorInfo objectForKey:[NSString stringWithFormat:@"%zd", index]]; if (!backgroundColor) { backgroundColor = [UIColor clearColor]; } label.backgroundColor = backgroundColor; // 字体大小 label.font = [UIFont systemFontOfSize:13]; // label文字 label.text = datas[index]; // label的tag值 label.tag = WZBTag   index; index  ; } }}

那是着力代码,在那之中做了联合单元格、文字颜色、背景颜色、等剖断。画线是用的贝塞尔曲线和CAShapeLayer,代码在底下,每一个单元格里都创设了label展现文字。小编还提供了措施画一条直线,相信项目中过多页面有个别地点需求画一条直线, - wzb_drawLineWithFrame:frame lineType:(WZBLineType)lineType color:(UIColor *)color lineWidth:lineWidth本条形式能够很便利的完结这一须要

- wzb_drawLineWithFrame:frame lineType:(WZBLineType)lineType color:(UIColor *)color lineWidth:lineWidth { // 创建贝塞尔曲线 UIBezierPath *linePath = [[UIBezierPath alloc] init]; // 线宽 linePath.lineWidth = lineWidth; // 起点 [linePath moveToPoint:CGPointMake]; // 重点:判断是水平方向还是垂直方向 [linePath addLineToPoint: lineType == WZBLineHorizontal ? CGPointMake(frame.size.width, 0) : CGPointMake(0, frame.size.height)]; // 创建CAShapeLayer CAShapeLayer *lineLayer = [CAShapeLayer layer]; // 颜色 lineLayer.strokeColor = color.CGColor; // 宽度 lineLayer.lineWidth = lineWidth; // frame lineLayer.frame = frame; // 路径 lineLayer.path = linePath.CGPath; // 添加到layer上 [self.layer addSublayer:lineLayer];}

上面画了一下随便颜色的线条,最后效果是那样:

图片 22image

4、GitHub源码地址:UIView-WZB

怎么着,这个你学会怎么用了呢?

请不要珍惜,顺手点个喜欢依然关心一下吧!你的协理是自己最大的重力!此种类小说再三创新,还有个别牛X控件因为尚未封装完善,被作者拿下来放到下篇小说,您能够关怀本人以便及时查阅本人的摩登篇章可能您还足以投入大家的群,我们开庭日期待你的加盟哦!

图片 23咱俩的社区

本文由星彩网app下载发布于计算机编程,转载请注明出处:你就累到死,自动行高的实现

TAG标签: 星彩网app下载
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。