日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

iostext添加点击事件_iOS给UILabel添加点击事件

發(fā)布時間:2023/11/27 生活经验 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iostext添加点击事件_iOS给UILabel添加点击事件 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言:筆者最近需要實現(xiàn)給UILabel中的鏈接添加點擊事件的功能。使用so.com查了下,發(fā)現(xiàn)TTTAttributedLabel的封裝程度比較好。整理了TTTAttributedLabel的基本使用,并部分實現(xiàn)了。

TTTAttributedLabel的基本使用

把TTTAttributedLabel.h及TTTAttributedLabel.m放到項目中

遵守TTTAttributedLabelDelegate協(xié)議

// 遵守TTTAttributedLabelDelegate協(xié)議

@interface ViewController ()

復(fù)制代碼

創(chuàng)建TTTAttributedLabel實例及相應(yīng)配置

創(chuàng)建TTTAttributedLabel實例,添加相應(yīng)的配置。

- (void)setupTTTAttributedLabel {

TTTAttributedLabel *attriLabel = [[TTTAttributedLabel alloc] initWithFrame:CGRectZero];

attriLabel.font = [UIFont systemFontOfSize:32.0];

attriLabel.numberOfLines = 0;

// Automatically detect links when the label text is subsequently changed

attriLabel.enabledTextCheckingTypes = NSTextCheckingTypeLink;

// Delegate methods are called when the user taps on a link (see `TTTAttributedLabelDelegate` protocol)

attriLabel.delegate = self;

// Repository URL will be automatically detected and linked

attriLabel.text = @"Fork me on GitHub! (https://github.com/mattt/TTTAttributedLabel/)";

NSRange range = [attriLabel.text rangeOfString:@"me"];

// Embedding a custom link in a substring

[attriLabel addLinkToURL:[NSURL URLWithString:@"http://github.com/mattt/"] withRange:range];

[self.view addSubview:attriLabel];

attriLabel.frame = CGRectMake(20.0, 100.0, 300.0, 200.0);

}

實現(xiàn)TTTAttributedLabelDelegate代理方法

在如下代理方法中查看當(dāng)前點擊的鏈接。

//! 實現(xiàn)代理方法

- (void)attributedLabel:(TTTAttributedLabel *)label didSelectLinkWithURL:(NSURL *)url {

NSLog(@"url信息:%@", url);

}

TTTAttributedLabel部分實現(xiàn)

設(shè)置attriLabel.text = @"Fork me on GitHub! (https://github.com/mattt/TTTAttributedLabel/)";查看了TTTAttributedLabel的大概實現(xiàn)流程。

設(shè)置TTTAttributedLabel用戶交互可用。

self.userInteractionEnabled = YES;

TTTAttributedLabel鏈接指定了替代鏈接樣式

TTTAttributedLabel為鏈接指定了替代鏈接樣式為藍(lán)色和帶下劃線。

相關(guān)代碼為:

NSMutableDictionary *mutableLinkAttributes = [NSMutableDictionary dictionary];

[mutableLinkAttributes setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCTUnderlineStyleAttributeName];

if ([NSMutableParagraphStyle class]) {

[mutableLinkAttributes setObject:[UIColor blueColor] forKey:(NSString *)kCTForegroundColorAttributeName];

} else {

[mutableLinkAttributes setObject:(__bridge id)[[UIColor blueColor] CGColor] forKey:(NSString *)kCTForegroundColorAttributeName];

}

self.linkAttributes = [NSDictionary dictionaryWithDictionary:mutableLinkAttributes];

使用NSDataDetector檢測label.text中的鏈接

NSArray *results = [dataDetector matchesInString:[(NSAttributedString *)text string] options:0 range:NSMakeRange(0, [(NSAttributedString *)text length])];

NSArray *類型的results副本中會有l(wèi)abel中文本的鏈接信息。

<__nsarraym>(

{20, 44}{https://github.com/mattt/TTTAttributedLabel/}

)

// label.text中的URL

(lldb) po ((NSLinkCheckingResult *)[results lastObject]).URL

https://github.com/mattt/TTTAttributedLabel/

// label.text中的URL 的range

(lldb) po ((NSLinkCheckingResult *)[results lastObject]).range

location=20, length=44

“自動檢測”鏈接

當(dāng)我們設(shè)置了attriLabel.text = @"Fork me on GitHub! (https://github.com/mattt/TTTAttributedLabel/)";時,會發(fā)現(xiàn)https://github.com/mattt/TTTAttributedLabel/自動轉(zhuǎn)換鏈接形式。自動檢測出label.text中的文本中有url信息是依次在- (NSArray *)addLinksWithTextCheckingResults:(NSArray *)results attributes:(NSDictionary *)attributes及- (void)addLinks:(NSArray *)links的實現(xiàn)中做的處理。

首先通過在- (NSArray *)addLinksWithTextCheckingResults:(NSArray *)results attributes:(NSDictionary *)attributes方法中封裝鏈接文本屬性信息媒介TTTAttributedLabelLink。

再通過在- (void)addLinks:(NSArray *)links方法中根據(jù)TTTAttributedLabelLink傳遞過來的文本屬性及URL位置信息,設(shè)置label.attributedText以達(dá)到能夠自動檢測出label.text中url的目的。

另外我們自行添加addLinkToURl

- (void)addLinks:(NSArray *)links {

...

self.attributedText = mutableAttributedString;

...

}

添加鏈接到指定range

以[attriLabel addLinkToURL:[NSURL URLWithString:@"http://github.com/mattt/"] withRange:range];為例。可以發(fā)現(xiàn)TTTAttributedLabel內(nèi)部實現(xiàn)是

[self addLinkWithTextCheckingResult:[NSTextCheckingResult linkCheckingResultWithRange:range URL:url]];直到

[self addLinkWithTextCheckingResult:result attributes:self.linkAttributes];就和上述的“自動檢測”鏈接的內(nèi)容是一樣的。

點擊標(biāo)簽的鏈接文字后,查找到對應(yīng)url

這部分內(nèi)容主要分為touchesBegan方法中查找點擊的位置的鏈接,touchesMoved方法中比對觸摸到標(biāo)簽上的位置移動后,當(dāng)前位置的鏈接和touchesBegan方法中找到的鏈接是否一樣,最后在touchesEnded中把點擊的鏈接以為塊和代理的方式傳遞出去。

下邊簡單說明下筆者查看touchesBegan方法中查找點擊鏈接的內(nèi)容。

獲取到當(dāng)前點擊的點

[touch locationInView:self]

在- (TTTAttributedLabelLink *)linkAtPoint:(CGPoint)point方法中獲取到當(dāng)前點鏈接

首先在- (CFIndex)characterIndexAtPoint:(CGPoint)p方法中找到點擊的位置的字符的索引,然后通過- (TTTAttributedLabelLink *)linkAtCharacterIndex:(CFIndex)idx方法中找到對應(yīng)的字符的索引的TTTAttributedLabelLink實例(其中包含當(dāng)前點擊點的鏈接信息)

[self linkAtPoint:[touch locationInView:self]];

TTTAttributedLabelLink *result = [self linkAtCharacterIndex:[self characterIndexAtPoint:point]];

獲取到當(dāng)前點擊位置的字符的索引

筆者感覺其中難理解的地方為獲取到當(dāng)前點擊位置的字符的索引。相關(guān)內(nèi)容如下:

將當(dāng)前點的坐標(biāo)轉(zhuǎn)換為對應(yīng)的UILabel中的文字坐標(biāo)轉(zhuǎn)換為針對于UILabel自身坐標(biāo)系的點坐標(biāo);

p = CGPointMake(p.x - textRect.origin.x, p.y - textRect.origin.y);

另一個是把iOS做左上角為原點坐標(biāo)轉(zhuǎn)換為CT坐標(biāo)系的左下角為原點坐標(biāo)的調(diào)整。

p = CGPointMake(p.x, textRect.size.height - p.y);

根據(jù)當(dāng)前標(biāo)簽相對自身坐標(biāo)系frame和屬性鏈接創(chuàng)建CT坐標(biāo)系所需的frame

CGMutablePathRef path = CGPathCreateMutable();

CGPathAddRect(path, NULL, textRect);

CTFrameRef frame = CTFramesetterCreateFrame([self framesetter], CFRangeMake(0, (CFIndex)[self.attributedText length]), path, NULL);

確定UILabel當(dāng)前在CT坐標(biāo)系顯示占用的行數(shù)CFArrayGetCount(lines)

NSInteger numberOfLines = self.numberOfLines > 0 ? MIN(self.numberOfLines, CFArrayGetCount(lines)) : CFArrayGetCount(lines);

遍歷CT坐標(biāo)中文字的每一行,找到當(dāng)前點擊點所在的行,計算出點擊點相對于當(dāng)前行的坐標(biāo),并計算出當(dāng)前索引。

CGPoint relativePoint = CGPointMake(p.x - lineOrigin.x, p.y - lineOrigin.y);

idx = CTLineGetStringIndexForPosition(line, relativePoint);

其中還有ascent(字形最高點到baseline的推薦距離)和下降(字形最低點到baseline的推薦距離)相關(guān)的內(nèi)容等。筆者不了解,有興趣的話,可以查看CoreText相關(guān)內(nèi)容,如深入理解Core Text投放引擎

CFIndex idx = NSNotFound;

CGPoint lineOrigins[numberOfLines];

CTFrameGetLineOrigins(frame, CFRangeMake(0, numberOfLines), lineOrigins);

for (CFIndex lineIndex = 0; lineIndex < numberOfLines; lineIndex++) {

CGPoint lineOrigin = lineOrigins[lineIndex];

CTLineRef line = CFArrayGetValueAtIndex(lines, lineIndex);

// Get bounding information of line

CGFloat ascent = 0.0f, descent = 0.0f, leading = 0.0f;

CGFloat width = (CGFloat)CTLineGetTypographicBounds(line, &ascent, &descent, &leading);

CGFloat yMin = (CGFloat)floor(lineOrigin.y - descent);

CGFloat yMax = (CGFloat)ceil(lineOrigin.y + ascent);

// Apply penOffset using flushFactor for horizontal alignment to set lineOrigin since this is the horizontal offset from drawFramesetter

CGFloat flushFactor = TTTFlushFactorForTextAlignment(self.textAlignment);

CGFloat penOffset = (CGFloat)CTLineGetPenOffsetForFlush(line, flushFactor, textRect.size.width);

lineOrigin.x = penOffset;

// Check if we've already passed the line

if (p.y > yMax) {

break;

}

// Check if the point is within this line vertically

if (p.y >= yMin) {

// Check if the point is within this line horizontally

if (p.x >= lineOrigin.x && p.x <= lineOrigin.x + width) {

// Convert CT coordinates to line-relative coordinates

CGPoint relativePoint = CGPointMake(p.x - lineOrigin.x, p.y - lineOrigin.y);

idx = CTLineGetStringIndexForPosition(line, relativePoint);

break;

}

}

}

復(fù)制代碼

總結(jié)

以上是生活随笔為你收集整理的iostext添加点击事件_iOS给UILabel添加点击事件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。