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,一起交流一下哦!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM