iOS開發之自定義輸入框(利用UITextField及UITextView)

来源:http://www.cnblogs.com/wuhongxing/archive/2016/01/22/5152054.html
-Advertisement-
Play Games

最近在做項目的時候經常自定義一些輸入框,今天在這裡分享給大家。我的思路就是繼承於系統的控制項然後利用drawRect重畫裡面的控制項。那麼drawRect是怎麼工作的呢?drawRect的工作原理:首先蘋果是不推薦我們直接使用drawRect進行工作的,直接調用他也是沒有任何效果的。蘋果要求我們調用UI...


最近在做項目的時候經常自定義一些輸入框,今天在這裡分享給大家。

我的思路就是繼承於系統的控制項然後利用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,一起交流一下哦!!!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 利用轉場動畫實現(這裡不說轉場動畫),主要就是幾個坐標的轉換:將cell上的imageView快照生成一個snapView(直接創建一個ImageVIew也一樣), 在將cell上image的frame 坐標轉換到containerView上,在將snapView放大到目標尺寸 (首先你要知道轉場動...
  • 一、日誌工具類 Log.java 1 public class L 2 { 3 private L() 4 { 5 /* 不可被實例化 */ 6 throw new UnsupportedOperationException("Ca...
  • 在這個大冬天里默默敲著鍵盤,勿噴.今天學習swift過程中,學習到閉包,發現閉包和oc的block中有很多的相同之處,又重新學習了一下並且學習了一些高級點的用法,內容如下:1.block格式說明:(返回類型)(^塊名稱)(參數類型) = ^(參數列表) {代碼實現};//如果沒有參數,等號後面參數列...
  • 通過自定義輪播圖控制項,學習自定義控制項,本文介紹如何創建輪播圖控制項,方便以後使用,本控制項帶計時器,預設時間間隔是5.0秒,同時支持設置左右方向輪播,也支持手勢滑動切換,另外還可以指定從下標為currentPage的圖片開始輪播
  • 一、Shape的用法 :shape用於設定形狀,可以在selector,layout等裡面使用,有6個子標簽,各屬性如下: 填充:設置填充的顏色 間隔:設置四個方向上的間隔 大小:設置大小 圓角:同時設置五個屬性,則Radius屬性無效 android:Radius="20dp" 設置...
  • 在文章《Android程式員從小白到大神必讀資料彙總(一)》裡面介紹了幾篇Android入門和提升效率的技術資料,今天小編收集了5篇進階的資料,趕緊來看看吧!另外,歡迎大家加入工程師博主交流群:391519124,交流博客經驗和技術一、Android開發相見恨晚的方法和介面 Android開發中,有...
  • 1.Stream 與IRandomAccessStream轉換 2.為Group創建Person的示例代碼 3.FaceIdentify 介面調用出現問題
  • 別再使用stringByAddingPercentEscapesUsingEncoding 當遇到發送網路請求的參數中有漢字的情況,很多人一股腦地使用 進行轉義,這樣帶有漢字的urlString就會將每個漢字轉成相應的unicode編碼對應的3個%形式,這叫urlEncode(每個能寫後端的語言都....
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...