Asyncdisplaykit: [ASTextNode] Support for extending a backgroundColor around text.

Created on 28 Jan 2016  路  5Comments  路  Source: facebookarchive/AsyncDisplayKit

I need to be able to configure how much space goes between the text and the edges of the node, respecting the background color of the node.

With node.borderWidth the border is added inside the edges of the node, overlaying the text if it's too thick. I'm trying to add an "outer border" to ASTextNode.

I have created a custom node subclassing ASControlNode and overriding layoutSpecThatFits so I can "wrap" an ASTextNode with ASInsetLayoutSpec inside an ASStackLayoutSpec. This works for my needs because it respects the background color and other parameters of the parent (ASControlNode).

Is there a better way of achieving this? Maybe subclassing ASTextNode? Or is there any parameter that I'm missing?

Please reply with your thoughts!

Here's my code, it works great for what I'm trying to achieve, but I don't feel like this is the best solution:

// ASCustomTextNode
// Workaround for ASTextNode with padding (as in CSS)
//
//  -------------
// |  ---------  <-- UIEdgeInsets
// | |titleNode| |
// |  ---------  | <-- ASControlNode
//  -------------

class ASCustomTextNode: ASControlNode {

    let titleNode: ASTextNode!    
    var insets: UIEdgeInsets!

    override init() {
        titleNode = ASTextNode()
        titleNode.layerBacked = true

        insets = UIEdgeInsets()

        super.init()

        addSubnode(titleNode)
    }

    override func layoutSpecThatFits(constrainedSize: ASSizeRange) -> ASLayoutSpec {
        return ASStackLayoutSpec(
            direction: .Horizontal,
            spacing: 0,
            justifyContent: .Center,
            alignItems: .Center,
            children: [
                ASInsetLayoutSpec(
                    insets: insets,
                    child: titleNode
                )
            ]
        )
    }

}
ASTextNode

Most helpful comment

@jsspalding @aaronschubert0 - The community is planning an exciting long term road map for the project and getting organized around how to deliver these feature requests. We are moving to a new issue tracker with more sophisticated planning capabilities (check out www.realArtists.com and their new product: Ship!).

If you are interested in helping contribute to this component or any other, don鈥檛 hesitate to send me an email at [email protected]. If you would like to contribute for a few weeks, I can also add you to our Ship bug tracker so that you can see what everyone is working on and actively coordinate with us.

As always, keep filing issues and submitting pull requests here on Github and we will only move things to the new tracker if they require long term coordination.

All 5 comments

@JoSpalding This is what I would do as well (if you are using this node in a lot of places). Otherwise just wrap your ASTextNode in a ASInsetLayoutSpec when needed. The layout spec is actually based on the CSS box model, so ASInsetLayoutSpec is comparable to CSS margins.

@aaronschubert0 Thanks for replying! Actually what I'm trying to do is add padding, not margins, to an ASTextNode, so just wrapping the ASTextNode in a ASInsetLayoutSpec does not solves my use case.

I made this picture to better illustrate what I'm doing with my ASCustomTextNode.

untitled-1

@JoSpalding it turns out the solution you created is the most efficient way to do this. If we made the text node itself large enough to draw its background color in that larger rectangle, we would have to allocate a larger backing store and draw the pixels using the CPU. Your solution is better in that a view or node that has a background color set on it does not actually allocate /any/ backing store, or do any drawing, but rather is used by a hint in the compositor to have the GPU very efficiently applying that color in that area.

You can't get both drawing and the free backgroundColor on the same layer / view / node object due to the limitations of the iOS system.

So although it would be nice to support this in ASTextNode itself, it can't be done very easily without adding an additional overhead for text nodes that don't require it, namely an extra level in the hierarchy with extra views required.

It would be possible to do something like only add the additional of view when it is needed, but this would require more extensive rearchitecting to remove all of the logic out of the text note class itself, and have some way of both drawing directly in a single node, or containing that drawing to a sub node if we need to expand the background color.

If you would like to think of a nice name for your bordered color text component, I would be open to including it in the framework! Out of curiosity, can you explain your use case for this a little bit more?

@appleguy what a nice technical explanation! Thank you for checking this and taking time to answer.
My use case is really simple and aesthetic, it's just to make tags with some "room to breath".

For example, take a look at this tags and buttons:
Tags

I'm not sure if i did something wrong, but I can remember trying to achieve this using ASButtonNode setting a preferredFrameSize calculating the size of the string plus X points without luck.
I'm not even sure if ASButtonNode is considering preferredFrameSize, it seems that only ASImageNode is affected by this property, right?

By the way, I'm a huge fan of your work on ASDK and it's awesome to be able to contribute to the project (as minor as this is).
Thank you again for your feedback! It's amazing for someone that is starting a career on iOS dev.

@jsspalding @aaronschubert0 - The community is planning an exciting long term road map for the project and getting organized around how to deliver these feature requests. We are moving to a new issue tracker with more sophisticated planning capabilities (check out www.realArtists.com and their new product: Ship!).

If you are interested in helping contribute to this component or any other, don鈥檛 hesitate to send me an email at [email protected]. If you would like to contribute for a few weeks, I can also add you to our Ship bug tracker so that you can see what everyone is working on and actively coordinate with us.

As always, keep filing issues and submitting pull requests here on Github and we will only move things to the new tracker if they require long term coordination.

Was this page helpful?
0 / 5 - 0 ratings