zoukankan      html  css  js  c++  java
  • IOS 简洁输入框的实现

    我们在朋友圈,qq空间或微博的app看到这样的操作,点击回复,在视图的下面立即显示一个输入框。输入我们的文字后点击发送就可以。那么这个小小的输入框是怎么实现的呢

    我也试着自己写了一个小小对话框,先看一下样式

    主要的功能有

    • 有一个placeholder的文字作为提示,点击输入文字后消失,当删除后文字为空的时候,重新出现。
    • 文本框下面有一条蓝色线表示输入的框范围,类似我们微信里面的那个绿色的输入框
    • 文本框需要跟随键盘上下浮动,再输入文字后能自动调整大小和位置
    • 右边的发送按钮,在没有文字的时候是灰色的,提示无法发送,当输入文本框不为空的时候,可以发送,用蓝色来表示,而且需要根据左边的输入框高度变化而变化
    • 顶部有一条和底部视图分界的线
    • 在输入完成后,点击键盘的完成或者点击发送按钮能输出文字

    通过功能区分我们可以大致将该视图分成三个部分,第一个是分割线,宽度为1的UIView,第二个是类似html中的具有placeHolder功能的输入框,最后是按钮button。

    输入文本框的实现

    输入框是由UILabel+UITextView+UIImageView(蓝色线)实现的,UITextView的内容长度变化可以通过监听UITextViewTextDidChangeNotification来判断当前输入框的输入字数。
    先建一个类继承UITextView
    添加placeText和placeColor到头文件由于外部改变placetext内容,现在添加UILable

    -(void)PlaceTextLabel{
        if (self.placeText.length>0) {
            if (!_placeTextLab) {
                CGRect frame=CGRectMake(8,8, self.bounds.size.width-16, 0);
                _placeTextLab=[[UILabel alloc]initWithFrame:frame];
                _placeTextLab.font=self.font;
                _placeTextLab.backgroundColor=[UIColor clearColor];
                _placeTextLab.textColor=self.placeColor;
                _placeTextLab.tag=999;
                _placeTextLab.alpha=0;
                _placeTextLab.lineBreakMode=NSLineBreakByWordWrapping;
                _placeTextLab.numberOfLines=0;
                [self addSubview:_placeTextLab];
            }
            
            _placeTextLab.text=self.placeText;
            [_placeTextLab sizeToFit];
            [_placeTextLab setFrame:CGRectMake(8, 8, CGRectGetWidth(self.bounds)-16, CGRectGetHeight(_placeTextLab.frame))];
        }
        if (self.text.length==0 && self.placeText.length>0) {
            [[self viewWithTag:999]setAlpha:1.0];
        }
    }
    
    

    用Photoshop做一个单行像素的类似蓝线的图片,保存为png格式,必须设置图片的UIImageView的图片显示模式

    -(void)addLineView{
        [_subLine removeFromSuperview];
        _subLine=[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"subline.png"]];
        [_subLine setContentMode:UIViewContentModeScaleToFill];
        [self addSubline:_subLine];
        
    }
    

    UITextView的设置会相对麻烦一些,重写初始化代码

    -(instancetype)initWithFrame:(CGRect)frame PlaceText:(NSString *)placeText PlaceColor:(UIColor *)placeColor{
        self=[super initWithFrame:frame];
        if (self) {
            self.scrollEnabled=NO;
            
            _placeText=placeText;
            _placeColor=placeColor;
            _Textnil=YES;
            [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(TextChange:) name:UITextViewTextDidChangeNotification object:nil];
            
        }
        return self;
    }
    

    由于输入框会随着输入的文字而不断增高,我们需要把这个值传递给父视图,让父视图也能根据内容而增大,可以通过委托来,但是委托又有点重量级,这里我们可以用更简单的block

    这里首先我想到的是通过监听UITextViewTextDidChangeNotification来实时监测输入,输入实时变化引起高度的实时变化。但是不幸的是我掉坑里了,我发现当我们输入一行到头以后再输入一个字符换行后,这个时候高度居然没有变。再输入这一行的第二个字符时候,高度值才发生变化。我想应该是高度变化之前,已经发送了通知所以导致我们的高度变化其实不是实时的,如果这样就不能用这种方式了,所幸的我们还可以使用UITextView的一个简单函数

     CGSize size= [self sizeThatFits:CGSizeMake(self.contentSize.width, 1000.0)];
    

    这样size就是我们要的大小了。

    -(void)TextChange:(NSNotification *)notification{
        if (self.text.length==0) {
            _Textnil=YES;
        }else{
            _Textnil=NO;
        }
        [self addLineView];
        
        if (self.placeText.length==0) {
            return;
        }
        [UIView animateWithDuration:0.5 animations:^{
            if (_Textnil) {
                [[self viewWithTag:999]setAlpha:1.0];
            }else{
                [[self viewWithTag:999] setAlpha:0];
            }
            
            
        }];
        
    }
    -(void)addSubline:(UIView *)view{
        CGSize size= [self sizeThatFits:CGSizeMake(self.contentSize.width, 1000.0)];
        if (view) {
            CGRect frame=CGRectMake(2, size.height-3, self.bounds.size.width-4, 3.0);
            view.frame=frame;
        }
        [self addSubview:view];
        self.viewSize(size);//先判断一下更好。。。
    }
    
    

    这里使用block传递size,我们先声明一个block的私有变量,再写一个方法用来赋值,block的实现也是由调用该对象的类创建的。然后像委托一样调用就可以,AFNetwork中我们可以到处看到block而不像他的前辈ASIhttprequest到处是委托。

    组装

    主要的输入框完工后,就能组装了,先新建一个UIview子类。UIView需要和键盘高度保持一致。需要监听键盘滑出滑入的通知UIKeyboardWillChangeFrameNotification,实时改变输入框的高度

    -(void)keyboardWillShow:(NSNotification *)notification{
        NSDictionary *userInfo=[notification userInfo];
        NSTimeInterval boardAnimationDuration=[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
        CGRect frame=[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey]CGRectValue];
        [UIView animateWithDuration:boardAnimationDuration delay:0.0f options:UIViewAnimationOptionCurveEaseInOut animations:^{
            CGFloat keyBoardY=frame.origin.y;
            CGFloat keyBoardHeigh=frame.size.height;
            maxy=[UIScreen mainScreen].bounds.size.height-keyBoardHeigh;
            CGRect frame=self.frame;
            frame.origin.y=keyBoardY-CGRectGetHeight(self.frame);
            self.frame=frame;
            
        } completion:^(BOOL finished) {
            nil;
        }];
    }
    

    这里的maxY是指输入框的y方向的标准位置。在没有键盘的情况下是[UIScreen mainScreen].bounds.size.height,在有键盘的情况是键盘的y值,在输入框字符变化的时候实时改变他的高度

    如下面图所示

    -(void)TextViewDidChange:(CGSize)size{
        self.frame=CGRectMake(0, self.frame.origin.y, self.frame.size.width,size.height+6*2);
        self.frame=CGRectMake(0,maxy-self.frame.size.height, self.frame.size.width, self.frame.size.height);
        _Inputview.frame=CGRectMake(10, 6, self.frame.size.width-K_right_padding, size.height);
        
    }
    

    以上是比较重要的UIView高度自适应变化的问题

    这里button与外部类的调用关系也采用的是block的方式

    @property (nonatomic,copy)void(^sendText)(NSString *);
    
    -(void)sendMessage:(void (^)(NSString * text))inputText{
        if (inputText) {
            self.sendText=inputText;
        }
    }
    
    -(void)buttonClick{
        [self sendInputText];
    }
    -(void)sendInputText{
        if (_Inputview.Textnil) {
            return;
        }else{
    		if(self.sendText){
            self.sendText(_Inputview.text);
            _Inputview.text=@"";
    		}
        }
    }
    

    最后附上我的sourceCode,献给那些在ios道路上一起默默前进的小白们,我也是小白,求宽恕的对待O(∩_∩)O

  • 相关阅读:
    CF1305 Ozon Tech Challenge 2020 游戏存档
    CF1310A Recommendations 题解
    CF755G PolandBall and Many Other Balls 题解
    关于后缀自动机
    具体数学学习笔记
    Flask-SQLAlchemy中解决1366报错
    常用的SQLalchemy 字段类型
    flask_model防止循环引用
    navicate远程访问ubuntu上的mysql数据库
    flask运行环境搭建(nginx+gunicorn)
  • 原文地址:https://www.cnblogs.com/keithmoring/p/4256130.html
Copyright © 2011-2022 走看看