你真的瞭解UITextView嗎?

来源:http://www.cnblogs.com/wujy/archive/2016/08/25/5807646.html
-Advertisement-
Play Games

一:首先查看一下關於UITextView的定義 UITextView是繼承於UIScrollView,並且遵循UITextInput的協議;而UIScrollView是繼承於UIView,並且遵循NSCoding協議;上面有些屬性跟UITextField是一樣的,就沒有標註出來;關於UITextIn ...


一:首先查看一下關於UITextView的定義

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

@property(nullable,nonatomic,weak) id<UITextViewDelegate> delegate;
@property(null_resettable,nonatomic,copy) NSString *text;
@property(nullable,nonatomic,strong) UIFont *font;
@property(nullable,nonatomic,strong) UIColor *textColor;
@property(nonatomic) NSTextAlignment textAlignment;    
@property(nonatomic) NSRange selectedRange;  //選中範圍

@property(nonatomic,getter=isEditable) BOOL editable; //    是否可以編輯

@property(nonatomic,getter=isSelectable) BOOL selectable NS_AVAILABLE_IOS(7_0); // 是否可以選中

@property(nonatomic) UIDataDetectorTypes dataDetectorTypes NS_AVAILABLE_IOS(3_0);  //屬性可以設定使電話號碼、網址、電子郵件和符合格式的日期等文字變為鏈接文字

@property(nonatomic) BOOL allowsEditingTextAttributes NS_AVAILABLE_IOS(6_0); // 預設值為NO 是否允許更改字元屬性字典
@property(null_resettable,copy) NSAttributedString *attributedText NS_AVAILABLE_IOS(6_0); //富文本
@property(nonatomic,copy) NSDictionary<NSString *, id> *typingAttributes NS_AVAILABLE_IOS(6_0); 

//滾動到文本的某個段落
- (void)scrollRangeToVisible:(NSRange)range;


@property (nullable, readwrite, strong) UIView *inputView;             
@property (nullable, readwrite, strong) UIView *inputAccessoryView;

@property(nonatomic) BOOL clearsOnInsertion NS_AVAILABLE_IOS(6_0); // 設置是否允許再次編輯時在內容中間插入內容

- (instancetype)initWithFrame:(CGRect)frame textContainer:(nullable NSTextContainer *)textContainer NS_AVAILABLE_IOS(7_0) NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;

//則定義了一個矩形區域用於存放已經進行了排版並設置好屬性的文字
@property(nonatomic,readonly) NSTextContainer *textContainer NS_AVAILABLE_IOS(7_0);
@property(nonatomic, assign) UIEdgeInsets textContainerInset NS_AVAILABLE_IOS(7_0);
//用於管理NSTextStorage其中的文字內容的排版佈局
@property(nonatomic,readonly) NSLayoutManager *layoutManager NS_AVAILABLE_IOS(7_0);
//NSTextStorage保存並管理UITextView要展示的文字內容,該類是NSMutableAttributedString的子類,由於可以靈活地往文字添加或修改屬性
@property(nonatomic,readonly,strong) NSTextStorage *textStorage NS_AVAILABLE_IOS(7_0);

//鏈接文本的樣式設置
@property(null_resettable, nonatomic, copy) NSDictionary<NSString *, id> *linkTextAttributes NS_AVAILABLE_IOS(7_0);

@end

UITextView是繼承於UIScrollView,並且遵循UITextInput的協議;而UIScrollView是繼承於UIView,並且遵循NSCoding協議;上面有些屬性跟UITextField是一樣的,就沒有標註出來;關於UITextInput的協議也可以見關於UITextField裡面的內容;包含一些鍵盤響應及相應的通知處理知識點;

知識點1:關於UIDataDetectorTypes此屬性可以設定使電話號碼、網址、電子郵件和符合格式的日期等文字變為鏈接文字

typedef NS_OPTIONS(NSUInteger, UIDataDetectorTypes) {
    UIDataDetectorTypePhoneNumber                              = 1 << 0,          // Phone number detection
    UIDataDetectorTypeLink                                     = 1 << 1,          // URL detection
    UIDataDetectorTypeAddress NS_ENUM_AVAILABLE_IOS(4_0)       = 1 << 2,          // Street address detection
    UIDataDetectorTypeCalendarEvent NS_ENUM_AVAILABLE_IOS(4_0) = 1 << 3,          // Event detection

    UIDataDetectorTypeNone          = 0,               // No detection at all
    UIDataDetectorTypeAll           = NSUIntegerMax    // All types
};
實例:

textView.dataDetectorTypes = UIDataDetectorTypeAll;

UIDataDetectorTypeAll可以檢測檢測電話、網址和郵箱。符合條件的文本中的內容就會高亮;

知識點2:設置鏈接樣式的運用實例

UITextView * textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 100, 300, 50)];

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"這是一個鏈接:www.123456.com"];
[attributedString addAttribute:NSLinkAttributeName
                         value:@"url1://www.baidu.com"
                         range:NSMakeRange(7, 14)];


NSDictionary *linkAttributes = @{NSForegroundColorAttributeName: [UIColor greenColor],
                                  NSUnderlineColorAttributeName: [UIColor lightGrayColor],
                                  NSUnderlineStyleAttributeName: @(NSUnderlinePatternSolid)};


textView.linkTextAttributes = linkAttributes;
textView.attributedText     = attributedString;
textView.delegate           = self;
textView.editable           = NO; // 可編輯狀態不能點擊鏈接
[self.view addSubview:textView];
// 要實現代理
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange {
    if ([[URL scheme] isEqualToString:@"url1"]) {
        NSString * url = [URL host];

        NSLog(@"%@",url);

        // 在這裡利用url做點什麼事情......

        return NO;
    }
    return YES;
}

知識點3UITextView: 響應鍵盤的 return 事件

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
    if ([text isEqualToString:@"\n"]){ //判斷輸入的字是否是回車,即按下return
        //在這裡做你響應return鍵的代碼
        [textView resignFirstResponder];  
        return NO; //這裡返回NO,就代表return鍵值失效,即頁面上按下return,不會出現換行,如果為yes,則輸入頁面會換行
    }
    return YES;
}

知識點4:如何優雅的讓UITextView根據輸入文字實時改變高度

  // 初始化控制項
  self.contentTextView = [[UITextView alloc]initWithFrame:CGRectMake((kMainBoundsWidth-250)/2, kMainBoundsHeight/2-50, 250, 39)];
  self.contentTextView .layer.cornerRadius = 4;
  self.contentTextView .layer.masksToBounds = YES;
  self.contentTextView .delegate = self;
  self.contentTextView .layer.borderWidth = 1;
  self.contentTextView .font = [UIFont systemFontOfSize:14];
  self.contentTextView .layer.borderColor = [[[UIColor lightGrayColor] colorWithAlphaComponent:0.4] CGColor];
  //加下麵一句話的目的是,是為了調整游標的位置,讓游標出現在UITextView的正中間
  self.contentTextView.textContainerInset = UIEdgeInsetsMake(10,0, 0, 0);
  [self.view addSubview:self.contentTextView ];
//計算輸入文字高度的方法,之所以返回的高度值加22是因為UITextView有一個初始的高度值40,但是輸入第一行文字的時候文字高度只有18,所以UITextView的高度會發生變化,效果不太好

  - (float) heightForTextView: (UITextView *)textView WithText: (NSString *) strText{
    CGSize constraint = CGSizeMake(textView.contentSize.width , CGFLOAT_MAX);
    CGRect size = [strText boundingRectWithSize:constraint
                                             options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                          attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:14]}
                                             context:nil];
    float textHeight = size.size.height + 22.0;
    return textHeight;
}
//每次輸入文字後調用該方法,此時輸入的文字並不在textView.text中,而在另一個參數text中,走完該方法後每次輸入的文字才加入到textView.text中。解決方案是將textView.text和text文字拼接起來
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    CGRect frame = textView.frame;
    float height;
    if ([text isEqual:@""]) {

        if (![textView.text isEqualToString:@""]) {

            height = [ self heightForTextView:textView WithText:[textView.text substringToIndex:[textView.text length] - 1]];

        }else{

            height = [ self heightForTextView:textView WithText:textView.text];
        }
    }else{

            height = [self heightForTextView:textView WithText:[NSString stringWithFormat:@"%@%@",textView.text,text]];
    }

    frame.size.height = height;
    [UIView animateWithDuration:0.5 animations:^{

            textView.frame = frame;

        } completion:nil];

    return YES;
}

知識點5textView其實是沒有PlaceHolder,如何設置PlaceHolder如下:

#import <UIKit/UIKit.h>

@interface UIPlaceHolderTextView : UITextView
@property (nonatomic, strong) NSString *placeholder;
@property (nonatomic, strong) UIColor *placeholderColor;

-(void)textChanged:(NSNotification*)notification;
@end
#import "UIPlaceHolderTextView.h"

@interface UIPlaceHolderTextView()
@property (nonatomic, strong) UILabel *placeHolderLabel;
@end

@implementation UIPlaceHolderTextView
CGFloat const UI_PLACEHOLDER_TEXT_CHANGED_ANIMATION_DURATION = 0.25;

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
#if __has_feature(objc_arc)
#else
    [_placeHolderLabel release]; _placeHolderLabel = nil;
    [_placeholderColor release]; _placeholderColor = nil;
    [_placeholder release]; _placeholder = nil;
    [super dealloc];
#endif
}

- (void)awakeFromNib
{
    [super awakeFromNib];

    if (!self.placeholder) {
        _placeholder = @"";
    }
    
    if (!self.placeholderColor) {
        [self setPlaceholderColor:[UIColor lightGrayColor]];
    }
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
}

- (id)initWithFrame:(CGRect)frame
{
    if( (self = [super initWithFrame:frame]) )
    {
        _placeholder = @"";
        [self setPlaceholderColor:[UIColor lightGrayColor]];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
    }
    return self;
}

- (void)textChanged:(NSNotification *)notification
{
    if([[self placeholder] length] == 0)
    {
        return;
    }
    
    [UIView animateWithDuration:UI_PLACEHOLDER_TEXT_CHANGED_ANIMATION_DURATION animations:^{
        if([[self text] length] == 0)
        {
            [[self viewWithTag:999] setAlpha:1];
        }
        else
        {
            [[self viewWithTag:999] setAlpha:0];
        }
    }];
}

- (void)setText:(NSString *)text {
    [super setText:text];
    [self textChanged:nil];
}

- (void)drawRect:(CGRect)rect
{
    if( [[self placeholder] length] > 0 )
    {
        UIEdgeInsets insets = self.textContainerInset;
        if (_placeHolderLabel == nil )
        {
            
            _placeHolderLabel = [[UILabel alloc] initWithFrame:CGRectMake(insets.left+5,insets.top,self.bounds.size.width - (insets.left +insets.right+10),1.0)];
            _placeHolderLabel.lineBreakMode = NSLineBreakByWordWrapping;
            _placeHolderLabel.font = self.font;
            _placeHolderLabel.backgroundColor = [UIColor clearColor];
            _placeHolderLabel.textColor = self.placeholderColor;
            _placeHolderLabel.alpha = 0;
            _placeHolderLabel.tag = 999;
            [self addSubview:_placeHolderLabel];
        }
        _placeHolderLabel.text = self.placeholder;
        [_placeHolderLabel sizeToFit];
        [_placeHolderLabel setFrame:CGRectMake(insets.left+5,insets.top,self.bounds.size.width - (insets.left +insets.right+10),CGRectGetHeight(_placeHolderLabel.frame))];
        [self sendSubviewToBack:_placeHolderLabel];
    }
    
    if( [[self text] length] == 0 && [[self placeholder] length] > 0 )
    {
        [[self viewWithTag:999] setAlpha:1];
    }
    
    [super drawRect:rect];
}
- (void)setPlaceholder:(NSString *)placeholder{
    if (_placeholder != placeholder) {
        _placeholder = placeholder;
        [self setNeedsDisplay];
    }
    
}

@end

二:代理方法的內容

@protocol UITextViewDelegate <NSObject, UIScrollViewDelegate>

@optional

// 將要開始編輯
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView;
// 將要結束編輯
- (BOOL)textViewShouldEndEditing:(UITextView *)textView;

// 開始編輯
- (void)textViewDidBeginEditing:(UITextView *)textView;
// 結束編輯
- (void)textViewDidEndEditing:(UITextView *)textView;

// 文本將要改變
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
// 文本發生改變
- (void)textViewDidChange:(UITextView *)textView;
// 焦點發生改變
- (void)textViewDidChangeSelection:(UITextView *)textView;

// 是否允許對文本中的URL進行操作
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange NS_AVAILABLE_IOS(7_0);
// 是否允許對文本中的富文本進行操作
- (BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment inRange:(NSRange)characterRange NS_AVAILABLE_IOS(7_0);

 


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

-Advertisement-
Play Games
更多相關文章
  • 前言: 昨天的文章中簡單的介紹了Egret白鷺引擎從安裝到基本的使用配置等問題,今天著重介紹H5小游戲開發的起步階段,如Wing面板的使用,素材的處理,類的說明,開始佈局等等。 整體概況: 根據上一篇文章的提示,我們找到index.html,將幀率data-frame-rate修改成60。根據設計圖 ...
  • 截止到ES6,共有6種聲明變數的方法,分別是var 、function以及新增的let、const、import和class; 我們通常的賦值方法是: es6給我們提供了一種嶄新賦值方式:解構賦值; 例如我們需要聲明3個變數,我們用傳統的賦值方式和解構賦值做一個比較; es5: es6: 是不是很方 ...
  • 原文:Angus Croll 譯文:伯樂線上專欄作者 - 古魯伊 鏈接:http://web.jobbole.com/87534/ 點擊 → 瞭解如何加入專欄作者 我們從一些小測試開始。以下情況都會彈出什麼結果? 題 1: function foo(){ function bar() { retur ...
  • UICollectionViewCell定製Button 效果 特點 1.能夠動態設置每行顯示的按鈕的個數,以及控制項的擺放格式 2.實現單選或者多選的功能,實現點擊事件 3.自定製按鈕的顯示樣式 用法 1.下載源碼後,將文件中的GridCollectionView.h/.m文件, CustomCol ...
  • 一、說明 今天給角色精靈增加了子彈發射功能,增加了子彈與敵對精靈的碰撞檢測,當角色精靈子彈與敵對精靈碰撞後,它們都會從屏幕上消失。 二、場景層SKScene的修改 1、 在初始化場景層的方法中增加下麵代碼 self.physicsWorld.contactDelegate = self; self. ...
  • 蘋果在iOS6中禁用了[UIDevice uniqueIdentifier],在iOS7中又把mac地址的獲取給堵上了。沒辦法,畢竟人家是老大,說不讓你用,你也沒辦法。在這邊總結一下現有的一部分UDID獲取方法(有蘋果推薦的,也有第三方的),目的在於拋磚,沒有切實的說明哪種方法好用。用哪種方法,完全 ...
  • 1.當你在androidmanifest裡面定義了一個或多個action時 你使用隱式意圖其他activity或者service時,規定你隱式裡面的action必須匹配XML中定義的action,可以只匹配XML文件一個就行 2.當你在androidmanifest裡面定義了一個或多個categor ...
  • 項目簡介 小食光定位為一款集美食,社交,LBS服務於一體的美食推薦APP。為你發現周邊美食的同時提供一個吃貨分享的平臺。 APP截圖 功能模塊 美食推薦 :提供基礎的美食信息查詢; 商家推薦 : 基於用戶當前位置推薦周邊的人們店家; 百度地圖API :提供基礎的周邊店家檢索,定位服務; 美食分享:美 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...