iOS Creating attributed label like TTTAttributedLabel in CKLabelComponent

209 views Asked by At

I can easily use TTTAttributedlabel to have tappable url, name, etc.

1) How can I create something similar to that in CKLabelComponent?

2) Do I need to use CKTextComponent?

[CKLabelComponent newWithLabelAttributes:{
                               .string = @"This shall be context This shall be context This shall be context This shall be context",
                               .font = [UIFont fontWithName:@"Baskerville" size:14]
                           }
                           viewAttributes:{
                               {@selector(setBackgroundColor:), [UIColor clearColor]},
                               {@selector(setUserInteractionEnabled:), @NO},
                           }
                           size:{ }]
2

There are 2 answers

0
leavez On

You could make you component easily. Provide the view, implement the computeLayoutThatFits:. CKImageComponent is an example.

But at the situation of text. It may be hard, because of the layout size. Once you use TTTAttributedLabel as the render of text, you have to provide the text size manually. This is definitely not the thing you want.

As you could see, CKTextComponent, the parent of CKLabelComponent, is implemented as a subproject of ComponentKit. It handle the layout size, text rendering, text layout cache. (It's implemented with TextKit.) If you want to use TTTAttributedLabel, you have to handle all things yourself with TTTAttributedLabel. It may slow down your scroll, because CKTextComponent implement async render but TTTAttributedLabel don't.


CKTextKitEntityAttributeName may achieve your goal

0
YUI On

My way is to combine CK with TTTAttributedLabel. First, I define a struct, it contains some basic info I need to set to TTTAttributedLabel,

struct ABCKAttributeLabelData {
    NSString *content;
    UIFont *normalFont;
    UIColor *normalColor;
    UIFont *linkFont;
    UIColor *linkColor;
    NSInteger numberOfLines;
};

Then, I create a new class, named ABCKAttributeLabelComponent subclass of CKComponent, implemented initialize method as below:

+ (instancetype)newWithData:(ABCKAttributeLabelData)data {
ABCKAttributeLabelComponent *com =
[super newWithView:{
    [TTTAttributedLabel class],
    {
        {@selector(setText:), [data.content attributedStringWithStyle:
        @{NSForegroundColorAttributeName : data.normalColor,
                     NSFontAttributeName : data.normalFont,}]},
        {@selector(setLinkAttributes:), @{ NSForegroundColorAttributeName : data.linkColor,
                                           NSFontAttributeName : data.linkFont}},
        {@selector(setActiveLinkAttributes:), @{ NSForegroundColorAttributeName : data.linkColor,
                                                 NSFontAttributeName : data.linkFont}},
        {@selector(setNumberOfLines:), data.numberOfLines ?: 0},
        {@selector(setLineBreakMode:), NSLineBreakByTruncatingTail},
    }
} size:{}];

com.attributeString = [data.content attributedStringWithStyle:
        @{NSForegroundColorAttributeName : data.normalColor,
                     NSFontAttributeName : data.normalFont,}];
com.normalFont = data.normalFont;
com.numOfLine = data.numberOfLines ?: 0;

return com

Third, calculate TTTAttributedLabel's size and return. CK will call computeLayoutThatFits: method to get component size. So overwrite it.

- (CKComponentLayout)computeLayoutThatFits:(CKSizeRange)constrainedSize {
// self.attributeString,self.numOfLine and self.normalFont I saved as property in initialize method
CGSize computerSize = [self.attributeString sizeLabelToFitToSize:constrainedSize.max numberLines:self.numOfLine font:self.normalFont];
return {
    self,
    constrainedSize.clamp({
        CKCeilPixelValue(computerSize.width),
        CKCeilPixelValue(computerSize.height)
    }),
    {}
};

}

The rest of the things is to use ABCKAttributeLabelComponent.

it may not be very elegance, but it can works.