你的位置:首页 > 操作系统

[操作系统]iOS开发之自定义输入框(利用UITextField及UITextView)


最近在做项目的时候经常自定义一些输入框,今天在这里分享给大家。

我的思路就是继承于系统的控件然后利用drawRect重画里面的控件。

那么drawRect是怎么工作的呢?

drawRect的工作原理:
首先苹果是不推荐我们直接使用drawRect进行工作的,直接调用他也是没有任何效果的。苹果要求我们调用UIView类中的setNeedsDisplay方法,则程序会自动调用drawRect方法进行重绘。(调用setNeedsDisplay会自动调用drawRect)。

在UIView中,重写drawRect: (CGRect) aRect方法,可以自己定义想要画的图案.且此方法一般情况下只会画一次.也就是说这个drawRect方法一般情况下只会被调用一次。
当某些情况下想要手动重画这个View,只需要掉用[self setNeedsDisplay]方法即可.
drawRect调用是在Controller->loadView, Controller->viewDidLoad 两方法被调用之后调用的.所以不用担心在控制器中,这些View的drawRect就开始画了.这样可以在控制器中设置一些值给View(如果这些View draw的时候需要用到某些变量值).

 

1.如果在UIView初始化时没有设置rect大小,将直接导致drawRect不被自动调用。
2.该方法在调用sizeThatFits后被调用,所以可以先调用sizeToFit计算出size。然后系统自动调用drawRect:方法。
3.通过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:。
4.直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect不能为0.
以上1,2推荐;而3,4不提倡

 

1.首先是可以多行输入的输入框(继承于UITextView,效果如下)

#pragma mark -- 初始化时调用 --- (instancetype)initWithFrame:(CGRect)frame {  if (self = [super initWithFrame:frame]) {    /**     * 初始化的时候为属性设置默认值     */    self.placeholder   = @"请输入文字";    self.placeholderColor = [UIColor lightGrayColor];    self.placeholderFont = [UIFont systemFontOfSize:14];        /**     * 用textVeiw添加通知,当textView发生变化的时候会调用textChanged方法     */    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];  }  return self;}#pragma mark -- 重绘(为textVeiw加上placeholder) --- (void)drawRect:(CGRect)rect {  //如果文字消失了就会绘制placeholder  if (self.text.length == 0) {    CGRect placeholderRect = CGRectZero;    placeholderRect.origin.x = 10;    placeholderRect.origin.y = 5;    placeholderRect.size.width = self.frame.size.width-10;    placeholderRect.size.height = self.frame.size.height-5;    [self.placeholder drawInRect:placeholderRect withAttributes:@{                              NSFontAttributeName:_placeholderFont,                              NSForegroundColorAttributeName:_placeholderColor                              }];  }  [super drawRect:rect];}#pragma mark -- 文字改变的时候会调用该方法- (void)textChanged:(NSNotification *)notification {  /**   * 在文字改变的时候就重绘   */  [self setNeedsDisplay];}#pragma mark -- 移除通知- (void)dealloc {  [[NSNotificationCenter defaultCenter] removeObserver:self];}

如果想自定义更多样式,可以给attribute多加一些属性就可以了!!!

2.自定义符合要求的输入框(继承于UITextField,效果如下)

 

 上面左视图只有两个圆角而且离上下左都有1px的间距,并且placeholder是在右边的。

- (instancetype)initWithFrame:(CGRect)frame {  if (self = [super initWithFrame:frame]) {    /**     * 初始化属性,设置默认值     */    _placeholderFont = [UIFont systemFontOfSize:16];    _placeholderColor = [UIColor lightGrayColor];        CGFloat height = frame.size.height;    UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 1, height-1, height-2)];    leftView.backgroundColor = [UIColor redColor];        UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Icon"]];    imageView.frame = CGRectMake(0, 0, height-1, height-2);    [leftView addSubview:imageView];        //利用这个方法可以使左视图只有两个圆角    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:leftView.bounds byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerTopLeft cornerRadii:CGSizeMake(5, 5)];    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];    maskLayer.frame = leftView.bounds;    maskLayer.path = maskPath.CGPath;    leftView.layer.mask = maskLayer;    self.leftView = leftView;    self.leftViewMode = UITextFieldViewModeAlways;            NSLog(@"%s",__func__);  }  return self;}//这两个方法我也不知道有什么用,如果有知道的可以联系我告诉我一下/*#pragma mark -- 重置边界区域- (CGRect)borderRectForBounds:(CGRect)bounds {  CGRect borderRect = [super borderRectForBounds:bounds];    return borderRect;}#pragma mark -- 重置文字区域- (CGRect)textRectForBounds:(CGRect)bounds {  CGRect textRect = [super textRectForBounds:bounds];    return textRect;}*/#pragma mark -- 重置placeholder- (CGRect)placeholderRectForBounds:(CGRect)bounds {  CGRect placeholderRect = [super placeholderRectForBounds:bounds];  /**   * 使placeholder居右   */  CGFloat placeholderWidth = [self.placeholder boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:_placeholderFont} context:nil].size.width;  placeholderRect.origin.x += placeholderRect.size.width-placeholderWidth-5;  return placeholderRect;}#pragma mark -- 重置编辑区域- (CGRect)editingRectForBounds:(CGRect)bounds {  CGRect editingRect = [super editingRectForBounds:bounds];  return editingRect;}#pragma mark -- 重置删除按钮区域- (CGRect)clearButtonRectForBounds:(CGRect)bounds {  CGRect clearButtonRect = [super clearButtonRectForBounds:bounds];    return clearButtonRect;}#pragma mark -- 重置左视图区域- (CGRect)leftViewRectForBounds:(CGRect)bounds {  CGRect leftViewRect = [super leftViewRectForBounds:bounds];  leftViewRect.origin.x += 1;  return leftViewRect;}#pragma mark -- 重置右视图区域- (CGRect)rightViewRectForBounds:(CGRect)bounds {  CGRect rightViewRect = [super rightViewRectForBounds:bounds];    return rightViewRect;}#pragma mark -- 重绘文字(这个方法他成为第一响应者之后才调用的)- (void)drawTextInRect:(CGRect)rect {  [super drawTextInRect:rect];  self.textColor = [UIColor purpleColor];}#pragma mark -- 重绘placeholder

//在第一次显示的时候是先调用了placeholderRectForBounds:这个方法,然后再调用该方法

//之后显示的时候都是在调用了placeholderRectForBounds:方法之后,调用该方法,之后再调用placeholderRectForBounds:方法,这就会使placeholder的位置发生偏移(当他成为第一响应者的时候就不会居中对齐了,如果有知道怎么解决的,请联系我一下,谢谢!!!)
- (void)drawPlaceholderInRect:(CGRect)rect {  [super drawPlaceholderInRect:rect];  /**   * 调用kvo修改系统的_placeholderLabel的属性   */  [self setValue:_placeholderColor forKeyPath:@"_placeholderLabel.textColor"];  [self setValue:_placeholderFont forKeyPath:@"_placeholderLabel.font"];}

如果有需要这个demo的,可以去我的空间下载,也可以加我qq:357898849,一起交流一下哦!!!