• [iOS] 输入框高度随输入内容变化


    一般,类似聊天软件的输入框默认都是显示一行的,在用户输入过程中根据输入文字的内容来改变输入框的高度,以便显示全部文字。像微信,QQ的输入框就是这样的。那么这个效果应该怎么实现呢?

    新博客:wossoneri.com

    实现这个效果的关键点只有两点:

    1. 获取正在输入内容在UITextView占用了多少行
    2. UITextView动态改变大小

    一开始,为了解决第一个问题,我一直在考虑怎么获取换行事件,发现只用捕捉 输入即可,但这样又有一个麻烦,就是删除行怎么办?所以感觉这个思路太麻烦

    对于第一点,有一个方便的计算方法,就是获取UITextView内容的高度比上UITextView的字体的高度,即可得到当前的行数。

    这里有一个技巧,那就是不要用UITextViewbound.size.height获取其高度,因为这个获取的高度跟你输入的文字总高度并没有任何关系。

    要知道,UITextView是继承UIScrollView的。

    NS_CLASS_AVAILABLE_IOS(2_0) @interface UITextView : UIScrollView <UITextInput>
    

    这一点你可以不知道,但根据平时的操作经验,一个UITextView输入文字过多时是可以用手上下拖动浏览内容的,所以可以猜想是和UIScrollView有关系。

    另一个类似的输入框UITextField不支持换行哦,设置什么lineBreakMode啊,lineNumber(好像没这个属性)啊都不可以换行!我以前在这上面栽过跟头。UITextField输入满了会把文字顶到前面看不见的地方,但还不支持左右拖动!这一点比Android体验要差!

    好了,知道其集成UIScrollView就好办了,因为UITextView只有在输入内容超过其显示范围才可以拖动,那就知道输入文字的bound就是UIScrollViewcontentSize。这样就知道输入内容的总大小了。

    那每一行的高度呢?

    按我以前的经验,行高差不多是字体大小的 4/3 倍.这样设值显示效果一般都挺好。所以可以设值一个宏定义来处理与字体相关的高度。

    当然,我的经验是因为过去没有这方面经验的笨办法,正确的办法是使用FontlineHeight属性:

    // The height of text lines (measured in points). (read-only)
    @property(nonatomic,readonly)        CGFloat   lineHeight NS_AVAILABLE_IOS(4_0);
    

    OK,知道每行的高度,就可以计算当前有多少行文字了,在

    - (void)textViewDidChange:(UITextView *)textView
    

    代理方法中计算高度即可。

    对于第二点,根据计算出的高度重绘界面布局即可。这里我用的是自动布局,每次高度改变就刷新布局关系就行。下面放部分代码:

    我把输入框和一些其他组件封装为一个控件,在类中声明代理:

    @protocol EssayEditDelegate <NSObject>
    
    @optional
    - (void) onTextViewLineCountChangeTo:(NSInteger)lines;
    
    @end
    

    在每次输入内容的时候计算行数,声明一个变量保存上一次的行数,两次行数不一致即为发生换行

    (void)textViewDidChange:(UITextView *)textView {
    
        NSInteger numLines = textView.contentSize.height / textView.font.lineHeight;
        if (numLines != rows) {
            rows = numLines;
            //发生换行
            if (_delegate && [_delegate respondsToSelector:@selector(onTextViewLineCountChangeTo:)]) {
                [_delegate onTextViewLineCountChangeTo:rows];
            }
        }
    
    	......
    }
    

    在外部实现代理方法,更新界面

    #pragma mark - Essay delegate
    - (void)onTextViewLineCountChangeTo:(NSInteger)lines {
        rowCount = lines;
        [self remakeConstraint];
    }
    
    - (void)remakeConstraint {
        NSInteger toobarHeight;
        NSInteger rows = rowCount > DEFAULT_ROW_COUNT ? rowCount : DEFAULT_ROW_COUNT;
        toobarHeight = (ESSAY_EDIT_FONT_SIZE / 2 * 3) * rows + MARGIN_BUTTON * 2;
    
        [toolBarView mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.left.bottom.right.equalTo(self);
            make.top.equalTo(quesImageView.mas_bottom);
            make.height.mas_equalTo(toobarHeight);
        }];
    }
    
  • 相关阅读:
    Android组件界面设计工具 DroidDraw
    ExtAspNet官方示例网站和官方论坛速度归来!
    [原创]FineUI秘密花园(四) — 页面级别的配置
    [翻译]OAuth入门指南 2. 协议工作流
    ExtAspNet v2.3.4 发布了
    [翻译]JavaScript秘密花园 Type Casting,undefined,eval,setTimeout,Auto Semicolon Insertion 全部完成PDF打包下载
    [原创]祝贺《JavaScript 秘密花园》中文翻译被官方正式采纳
    [原创]使用 Google Chart 在线服务实现软件版本发布时间线图
    [原创]ExtAspNet新春贺岁版 文件上传控件、复选框列表控件、完善布局管理、表格的行扩展列、完整的100多个中文示例、30多处BUG修正与功能增强、《ExtAspNet秘密花园》系列文章
    ExtAspNet v2.3.5 发布了
  • 原文地址:https://www.cnblogs.com/rossoneri/p/5199469.html
Copyright © 2020-2023  润新知