当前位置: 首页 > news >正文

手把手教你实现微信聊天框随文本升高

当当当当,我胡汉三又回来了。今天介绍实现聊天的聊天框随文本升高,效果图如下

效果

接下来让我们一步一步实现这个功能吧

Part1 实现textView自动升高

1.创建一个UITextView的分类 UITextView+AutoRise

@interface UITextView (AutoRise)

@property (nonatomic, assign) CGFloat defaultHeight;
@property (nonatomic, assign) CGFloat maxHeight;
@property (nonatomic, copy) void (^handler)(CGFloat expectHeight);

- (void)addAutoRiseHandlerWithdefaultHeight:(CGFloat)defaultHeight maxHeight:(CGFloat)maxHeight handler:(void (^)(CGFloat expectHeight))handler;

@end

接下来实现
- (void)addAutoRiseHandlerWithdefaultHeight:maxHeight:handler:方法

- (void)addAutoRiseHandlerWithdefaultHeight:(CGFloat)defaultHeight maxHeight:(CGFloat)maxHeight handler:(void (^)(CGFloat))handler
{
    
    self.defaultHeight = defaultHeight;
    self.maxHeight = maxHeight;
    self.handler = handler;
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange:) name:UITextViewTextDidChangeNotification object:nil];
}

因为是在分类中添加属性,所以需要使用runtime的关联对象(AssociatedObject)来添加。

- (CGFloat)maxHeight
{
    return [objc_getAssociatedObject(self, UITextRiseMaxHeight) floatValue];
}

- (CGFloat)defaultHeight
{
    return  [objc_getAssociatedObject(self, UITextRiseDefaultHeight) floatValue];
}

- (void (^)(CGFloat))handler
{
    return objc_getAssociatedObject(self, UITextRiseHandler);
}

-(void)setDefaultHeight:(CGFloat)defaultHeight
{
    objc_setAssociatedObject(self, UITextRiseDefaultHeight, @(defaultHeight), OBJC_ASSOCIATION_RETAIN);
    
    
}

- (void)setMaxHeight:(CGFloat)maxHeight
{
    objc_setAssociatedObject(self, UITextRiseMaxHeight, @(maxHeight), OBJC_ASSOCIATION_RETAIN);
}

- (void)setHandler:(void (^)(CGFloat))handler
{
    objc_setAssociatedObject(self, UITextRiseHandler, handler, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

现在我们来实现textChange:方法

- (void)textChange:(NSNotification *)noti
{
    UITextView *inputTextView = noti.object;
    
    if (inputTextView != self) {
        return;
    }
    CGFloat expectHeight = 0.f;
    CGSize contentSize = inputTextView.contentSize;

    if(contentSize.height <= self.defaultHeight){
        
        expectHeight = self.defaultHeight;
        
    }else{
        expectHeight = contentSize.height;
        expectHeight = expectHeight > self.maxHeight ? self.maxHeight : expectHeight;
        
        if (expectHeight < self.maxHeight) {
            [inputTextView setContentOffset:CGPointMake(0, 0) animated:NO];
        }
    }

    if (self.handler) {
        self.handler(expectHeight);
    }
}

2.在StoryBoard中添加一个TextView,并设置好约束

将高度约束关联到控制器

关联

3.在ViewDidLoad:中根据自己的需求设置自动升高

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [_textView addAutoRiseHandlerWithdefaultHeight:_textViewHeightConstraint.constant maxHeight:100 handler:^(CGFloat expectHeight) {
        _textViewHeightConstraint.constant = expectHeight;
        [_textView layoutIfNeeded];
    }];
}

至此自动升高就完成了。

 

Part2 聊天中的聊天框实现

1.在StoryBoard中创建一个控制器(省略)
2.在控制器中添加一个view作为聊天的背景框 bottomBackgroundView
为背景设置一个背景色,并且设置好约束,见图

3.在bottomBackgroundView中添加一个textView

为textView添加好约束,见图

4.将添加的控件与控制器关联

5.在控制器中设置处理代码

- (void)viewDidLoad {
    [super viewDidLoad];
    
    __weak typeof(self)weakSelf = self;
    
    CGFloat defaultHeight = _bottomBackgroundViewHeightConstraint.constant - 8 * 2;//默认高度
    
    [_textView addAutoRiseHandlerWithdefaultHeight:defaultHeight maxHeight:100.f handler:^(CGFloat expectHeight) {
        __strong typeof(weakSelf) strongSelf = weakSelf;
        strongSelf.bottomBackgroundViewHeightConstraint.constant = expectHeight + 8 * 2;
        [strongSelf.bottomBackgroundView layoutIfNeeded];
    }];
}

效果如下:

你可以从这里下载[demo]

 

转载于:https://www.cnblogs.com/pretty-guy/p/5783545.html

相关文章:

  • packge-info.java
  • Java 线程 — ThreadLocal
  • 前端学数据库之数据表操作
  • [转]C#中捕捉对话框的文本内容 EnumChildWindows
  • (转)LINQ之路
  • 创建dialog
  • SQL Scripts Template Files Path
  • OS命令注入中的空格
  • //解决validator验证插件多个name相同只验证第一的问题
  • IE6 jQuery append()函数 与 JS appendChild(elem) 函数 报错原因
  • 管理者的最基本职责是什么?
  • spark
  • redis查看数据
  • C# 获取listview中选中一行的值
  • 火锅惹的祸
  • AWS实战 - 利用IAM对S3做访问控制
  • codis proxy处理流程
  • EOS是什么
  • javascript面向对象之创建对象
  • JavaScript设计模式之工厂模式
  • Java精华积累:初学者都应该搞懂的问题
  • React as a UI Runtime(五、列表)
  • -- 查询加强-- 使用如何where子句进行筛选,% _ like的使用
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 简单易用的leetcode开发测试工具(npm)
  • 聚类分析——Kmeans
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 我的业余项目总结
  • 我看到的前端
  • 与 ConTeXt MkIV 官方文档的接驳
  • 栈实现走出迷宫(C++)
  • Python 之网络式编程
  • ​ 全球云科技基础设施:亚马逊云科技的海外服务器网络如何演进
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • # Apache SeaTunnel 究竟是什么?
  • #pragma预处理命令
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (分布式缓存)Redis持久化
  • (四)图像的%2线性拉伸
  • .cfg\.dat\.mak(持续补充)
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • /usr/bin/env: node: No such file or directory
  • @EnableAsync和@Async开始异步任务支持
  • @property python知乎_Python3基础之:property
  • [2019/05/17]解决springboot测试List接口时JSON传参异常
  • [20190401]关于semtimedop函数调用.txt
  • [2021 蓝帽杯] One Pointer PHP
  • [Android] 240204批量生成联系人,短信,通话记录的APK