說到圖文混排,馬上想到的是用第三方的,RTLabel,RcLabel,coretext,等等一些方式。這些東西确實管用。可也得看資料源是什麼。
我現在着手的項目,類似于讨論區,主要由文章構成,圖文混排不可避免。而傳回的資料是帶html的 ,資料字段是
message,在這裡放個圖會更加清楚:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2QvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2Lc1zaXp1MKhlWyZ0VlZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DM5cTOyIDMyETOxcDM0EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
紅色箭頭所指的就是圖檔,我需要做的就是把這段代碼轉化成圖文混排。
我看了半天,發現一個規律:有圖檔的地方是html語言有"<img id= "這樣的東西,如果是表情則是 "<img src"。馬上想到用正規表達式,把有這些的地方找出來 擷取 NSRange 這樣圖檔的位置就找到了。
然後在這個位置放入圖檔,完美!!!
扯淡!!!!
忽略了一個問題,我展示的内容肯定是剔除出html的,那這些NSRange已經不是之前的位置了。是以把片擺上去也是不行。
後來發現,在去除掉html語言之後有圖檔的位置會變為"\r\n\n\n\n\n\n\r\n",這是和傳回資料本身有關的東西。這時候一個解決的思路就是通過這些特殊的符号,把文本分開方法:
NSArray *components = [stringContent1componentsSeparatedByString:@"\r\n\n\n\n\n"];
這樣的話就把一大段的字元分割開了。圖檔的URL是單獨給出來的,是以隻需要按順序排列 字元串-圖檔-字元串-圖檔-。這個過程需要注意圖檔的個數和數組的count值之間的關系,不然程式很容易崩潰。 這時候需要做的就是按順序排下來就行,label自适應然後放上圖檔。 如果想要圖檔點選放大,加上屬性
imageView.userInteractionEnabled =YES;
_messageLabel.userInteractionEnabled =YES;
這個方法能夠成功的前提是分割字元非正常律,那問題将會很簡單。
然而,現實很殘酷,有各種情況出現。你永遠不知道下一個文章的作者圖檔會怎麼擺出來。是以隻能節哀。
在此可以分享一下正規表達式和去除html語言的方法:
- (void *)rexget:(NSString *)staString{
NSString *emotion =@"<img src=\\\"static/image/smiley/default/\\w+";
// NSString *parten = @"(\\s)*(\\[)(\\s)*(self)(\\s)*(.)(\\s)*(label)(\\s)*(setText)(\\s)*(:)(\\s)*(@)(\\s)*(\".*\")(\\s)*(\\])(\\s)*(;)(\\s)*";
NSError* error =NULL;
NSRegularExpression *reg1 = [NSRegularExpressionregularExpressionWithPattern:emotionoptions:nilerror:&error];
NSArray* match1 = [reg1matchesInString:staStringoptions:NSMatchingCompletedrange:NSMakeRange(0, [staStringlength])];
if (match1.count !=0)
{
NSMutableString *str1 = [NSMutableStringstringWithString:staString];
NSInteger lastIndex =0;
for (NSTextCheckingResult *matcin match1)
{
NSRange range = [matcrange];
// NSLog(@"%lu,%lu,%@",(unsigned long)range.location,(unsigned long)range.length,[staString substringWithRange:range]);
}
}
}
-(NSString *)filterHTML:(NSString *)html
{
NSScanner * scanner = [NSScannerscannerWithString:html];
NSString * text =nil;
while([scannerisAtEnd]==NO)
{
//找到标簽的起始位置
[scanner scanUpToString:@"<"intoString:nil];
//找到标簽的結束位置
[scannerscanUpToString:@">"intoString:&text];
//替換字元
html = [html stringByReplacingOccurrencesOfString:[NSStringstringWithFormat:@"%@>",text]withString:@""];
}
// NSString * regEx = @"<([^>]*)>";
// html = [html stringByReplacingOccurrencesOfString:regEx withString:@""];
return html;
}
效果圖:
問題仍然存在,再接再厲
從上面的圖可以看出 圖和文字之間有大片的空白,解決這個問題很簡單
while([str11rangeOfString:@"\n\n"].length>0){
[str11deleteCharactersInRange: [str11rangeOfString: @"\n\n"]];
}
while([str11rangeOfString:@"\r\n"].length>0){
[str11deleteCharactersInRange: [str11rangeOfString: @"\r\n"]];
}
str11為你所分割的字元串,通過這個過濾之後,内容便會變的緊湊
在這之後需要對承載這些子視圖的_messageLabel的frame重新定義,這樣才能保證加在圖檔上的手勢不會出錯。 這個問題的用了很長時間才找到。
_messageLabel.frame =CGRectMake(_messageLabel.left,_userImage.bottom +10, _messageLabel.width, height);
最後: 相應的對行高進行一下改變之後,圖文混排完美解決。
總結: 相對于一些第三方庫來說,這個辦法無疑是笨的,但卻是最簡單的。不需要倒入什麼第三方的庫。隻是對label重新布局,也能更廣泛的适用。
整個問題下來用了斷斷續續用了四天。找了很多第三方的東西,雖然沒怎麼用上,但也有一些收獲。 之後再寫一些關于他們的。 至此!