標(biāo)題前面嵌入非圖片標(biāo)簽需求

需求背景:

年中促銷活動,需要添加一個標(biāo)簽讓用戶知道這個是促銷商品毅待。

我的想法

這很簡單的尚卫, 根據(jù)接口返回信息,是否顯示標(biāo)簽圖片就好了嘛尸红。 后來證實我還是太年輕吱涉。。外里。

標(biāo)簽樣式

經(jīng)過UI設(shè)計師給出幾個版本怎爵,最后給了一個在標(biāo)題前面插入一個標(biāo)簽的樣式。 注意: 這個標(biāo)簽不是一個圖片盅蝗,不是圖片鳖链。 是一個文本外加虛線邊框。樣式如圖:

UI樣式圖.png

乍一看這很簡單啊墩莫,兩個控件而已嘛芙委, 最多在第一個控件那里畫一個虛線邊框。狂秦。 但是: 實際情況不是這樣的灌侣, 后面的標(biāo)題可能有兩行!A盐省侧啼! 下一行開始要和標(biāo)簽對齊。堪簿。痊乾。

第一反應(yīng)我是拒絕的,找設(shè)計師修改原型圖戴甩。我給出幾個方案:

方案1:模仿淘寶符喝,將標(biāo)簽用中括號包起來凸顯。


天貓標(biāo)簽.png

這個字體甜孤、樣式协饲、顏色都可以隨便改, 你想怎么凸顯都行缴川。茉稠。但是產(chǎn)品不同意, 特么的換把夸。

方案2:將標(biāo)簽做成圖片而线,直接嵌套在前面。
設(shè)計師不給做, 說是有多語言膀篮,太多了嘹狞。。 還特么不行誓竿。

方案N磅网。。 都特么不行筷屡。涧偷。
產(chǎn)品說了,我不管你們怎么做毙死,反正樣式就這樣了定了燎潮。 我反饋說不好實現(xiàn)等等, 人家回一句扼倘, 京東是可以的叭贩狻!0π俊隅肥! 心里一萬只曹尼瑪奔騰跑過啊。

既然定下來這樣了袄简, 只能硬著頭皮試試腥放。

實現(xiàn)方法

方法一:

最笨的方法: 計算標(biāo)簽字符串占據(jù)的位置, 將標(biāo)題前面用空格補上相應(yīng)的字符串占據(jù)位置绿语,再講標(biāo)簽控件放到最前面覆蓋秃症。
這個不到萬不得已我是不用的哈。吕粹。

方法二: 自定義封裝控件

1.設(shè)置三個控件种柑。
控件一:標(biāo)簽;
控件二:右側(cè)標(biāo)題匹耕;
控件三:下面從標(biāo)簽開始的標(biāo)題Label聚请。(但是這個可能沒有。)
效果圖如下:


模擬圖.png

這里面有幾個困難點:
1.控件二顯示文本多少稳其,最后一個字符是哪個驶赏。
2.怎么確定有沒有第二行標(biāo)題控件。
3.第二個控件的起始字符怎么計算既鞠。

實現(xiàn)方案

寫了一個分類煤傍,算出具體每行顯示的字符,將其保存在一個數(shù)組中嘱蛋,當(dāng)數(shù)組個數(shù)大于1的時候蚯姆,就有第二個控件五续。也即可以確定第二個控件的其實字符。
寫了一個分類龄恋,傳入第一行標(biāo)題的Label計算疙驾。代碼如下:
注意:這個方法計算很多英文文本的時候,可能不太準(zhǔn)確

- (NSArray *)getSeparatedLinesFromLabel:(UILabel *)label
{
    NSString *text = [label text];
    UIFont   *font = [label font];
    CGRect    rect = [label frame];
    
    CTFontRef myFont = CTFontCreateWithName((__bridge CFStringRef)([font fontName]), [font pointSize], NULL);
    NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:text];
    [attStr addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)myFont range:NSMakeRange(0, attStr.length)];
    
    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attStr);
    
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, CGRectMake(0,0,rect.size.width,100000));
    
    CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);
    
    NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame);
    NSMutableArray *linesArray = [[NSMutableArray alloc]init];
    
    for (id line in lines)
    {
        CTLineRef lineRef = (__bridge CTLineRef )line;
        CFRange lineRange = CTLineGetStringRange(lineRef);
        NSRange range = NSMakeRange(lineRange.location, lineRange.length);
        
        NSString *lineString = [text substringWithRange:range];
        [linesArray addObject:lineString];
    }
    return (NSArray *)linesArray;
}

具體項目布局實現(xiàn)篙挽, 這個是demo荆萤,項目本身用Masonry布局,簡單一些铣卡。 下面代碼共參考:

- (void)resetViewsConstraints {
    //1.計算標(biāo)簽label的大小
    self.preLabel.frame = CGRectMake(0, 0, self.preLabel.intrinsicContentSize.width + 5, self.preLabel.intrinsicContentSize.height);
    
    //2.計算標(biāo)題
    self.titleLabel.frame = CGRectMake(0, 0, self.view.frame.size.width - CGRectGetMaxX(self.preLabel.frame), self.titleLabel.intrinsicContentSize.height);
    
    //3. 看標(biāo)題到底有多少 ==== 1>.一行, 就這樣布局  2>.多行偏竟, 添加subLabel煮落, 計算subLabel的第一個字符是什么
//     CGFloat count = self.titleLabel.intrinsicContentSize.height / self.titleLabel.font.lineHeight;
//    if (count > 1) {
//        [self.backGorundLabel addSubview:self.subLabel];
//    }
    //標(biāo)題行數(shù) 字符串?dāng)?shù)組
    NSArray *lineStrArray = [self getSeparatedLinesFromLabel:self.titleLabel];
    
    if (lineStrArray.count > 2) {
        [self.backGorundLabel addSubview:self.subLabel];
        self.titleLabel.text = lineStrArray[0];
        NSMutableString *lineStr = [NSMutableString string];
        [lineStrArray enumerateObjectsUsingBlock:^(NSString *text, NSUInteger idx, BOOL * _Nonnull stop) {
            if (idx > 0) {
                [lineStr appendString:text];
            }
        }];
        self.subLabel.text = lineStr;
        self.subLabel.frame = CGRectMake(0, CGRectGetMaxY(self.titleLabel.frame), self.view.frame.size.width, 30);
        self.backGorundLabel.frame = CGRectMake(0, 100, self.view.frame.size.width, CGRectGetMaxY(self.subLabel.frame));
    }else {
        self.backGorundLabel.frame = CGRectMake(0, 100, self.view.frame.size.width, CGRectGetMaxY(self.titleLabel.frame));
    }
}

以上就是我自己想到實現(xiàn)的方法∮荒保可能有點挫蝉仇,但是能滿足產(chǎn)品需求了。殖蚕。

更優(yōu)方案
方法三:首行縮進方法

對接上面代碼過程中轿衔, 想到了一個更好的辦法。也是基于方法一的改進睦疫。
既然能計算出標(biāo)簽控件的大小害驹, 那我使用首行縮進方法不就完美解決了嘛。蛤育。 O(∩_∩)O哈哈~ 哈哈哈哈 容我笑一會哈宛官。 實現(xiàn)demo:


首行縮進.png

首先計算控件的大小來確定首行縮進距離, 多語言也沒有問題瓦糕。
其次計算縮進用的富文本字典底洗。
最后直接將標(biāo)題設(shè)置為富文本,將標(biāo)簽控件放在最前面即可咕娄。

    //標(biāo)簽寬度亥揖,即縮進距離。 這里為了更好的展示圣勒,加了10的偏移量
    CGFloat headIndent = [self.preLabel sizeThatFits:CGSizeMake(self.preLabel.intrinsicContentSize.width, 200)].width + 10;

    //縮進富文本
    NSDictionary *attDict = [self settingAttributesWithLineSpace:5.0f FirstLineHeadIndent:headIndent LabelFont:[UIFont systemFontOfSize:14.0] LabelTextColor:self.titleLabel.textColor];

    NSAttributedString *string = [[NSAttributedString alloc] initWithString:self.titleString attributes:attDict];
    //設(shè)置標(biāo)題
    self.titleLabel.attributedText = string;

這里面有一個縮進富文本分類方法:

- (NSDictionary *)settingAttributesWithLineSpace:(CGFloat)lineSpace FirstLineHeadIndent:(CGFloat)headIndent LabelFont:(UIFont *)font LabelTextColor:(UIColor *)textColor; {
    //分段樣式
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    //行間距
    paragraphStyle.lineSpacing = lineSpace;
    //首行縮進
    paragraphStyle.firstLineHeadIndent = headIndent;
    //富文本樣式
    NSDictionary *attributeDic = @{
                                   NSFontAttributeName : font,
                                   NSParagraphStyleAttributeName : paragraphStyle,
                                   NSForegroundColorAttributeName : textColor
                                   };
    return attributeDic;
}

結(jié)束

至此檀葛,這個看似很簡單的需求完成了。這個功能應(yīng)該很多平臺都會用颅和,可以借鑒參考阻课, 有更好的方案,也希望告知旁趟,感謝昼激。

結(jié)語

遇到問題不要抗拒庇绽, 試著去解決。 沒有解決不了的問題橙困!
方案有N多種瞧掺,不要滿足,試著找更優(yōu)的方案凡傅。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末辟狈,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子夏跷,更是在濱河造成了極大的恐慌哼转,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件槽华,死亡現(xiàn)場離奇詭異壹蔓,居然都是意外死亡,警方通過查閱死者的電腦和手機猫态,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門佣蓉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人亲雪,你說我怎么就攤上這事勇凭。” “怎么了义辕?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵虾标,是天一觀的道長。 經(jīng)常有香客問我终息,道長夺巩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任周崭,我火速辦了婚禮柳譬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘续镇。我一直安慰自己美澳,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布摸航。 她就那樣靜靜地躺著制跟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪酱虎。 梳的紋絲不亂的頭發(fā)上雨膨,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音读串,去河邊找鬼聊记。 笑死撒妈,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的排监。 我是一名探鬼主播狰右,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼舆床!你這毒婦竟也來了棋蚌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤挨队,失蹤者是張志新(化名)和其女友劉穎谷暮,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞒瘸,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡坷备,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了情臭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡赌蔑,死狀恐怖俯在,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情娃惯,我是刑警寧澤跷乐,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站趾浅,受9級特大地震影響愕提,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜皿哨,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一浅侨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧证膨,春花似錦如输、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至崔步,卻和暖如春稳吮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背井濒。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工灶似, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留列林,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓喻奥,卻偏偏與公主長得像席纽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子撞蚕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,060評論 2 355