Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

how to float to sides in ASStackLayoutSpec #858

Closed
MarvinNazari opened this issue Nov 18, 2015 · 15 comments
Closed

how to float to sides in ASStackLayoutSpec #858

MarvinNazari opened this issue Nov 18, 2015 · 15 comments

Comments

@MarvinNazari
Copy link
Contributor

Hi, i have a set of buttons in a ASDisplayNode, is there any way i could make them float to sides (like button to left side, and more button to right side)

this is my code

class STCellFooterView: ASDisplayNode {

private let likeButtonNode: ASButtonNode
private let moreButtonNode: ASButtonNode

init(string: String? = nil) {

    likeButtonNode = ASButtonNode()
    likeButtonNode.setImage(UIImage(named: "like_dark_flow"), forState: ASButtonStateNormal)

    moreButtonNode = ASButtonNode()
    moreButtonNode.setImage(UIImage(named: "more_dark"), forState: ASButtonStateNormal)

    super.init()

    addSubnode(likeButtonNode)
    addSubnode(moreButtonNode)
}

override func layoutSpecThatFits(constrainedSize: ASSizeRange) -> ASLayoutSpec! {

    let buttonLayout = ASStackLayoutSpec(direction: .Horizontal, spacing: 13, justifyContent: .Start, alignItems: .Center, children: [likeButtonNode, moreButtonNode])

    return ASInsetLayoutSpec(
        insets:UIEdgeInsetsMake(0, 13, 13, 13),
        child: buttonLayout)        
}
}

this is how it shows now:

Image

but i want it like this:

Image

Thanks.

@smiLLe
Copy link

smiLLe commented Nov 18, 2015

Correct solution #848

Until then you can try to create an ASDisplayNode (spacerNode) with flexGrow = YES and set the children to [likeButtonNode, spacerNode, moreButtonNode]

@nguyenhuy are there any other approaches atm?

@MarvinNazari
Copy link
Contributor Author

Hi @smiLLe,
I changed to this but still no luck.

let spacer = ASDisplayNode()
spacer.flexGrow = true

let buttonLayout = ASStackLayoutSpec(direction: .Horizontal, spacing: 13, justifyContent: .Start, alignItems: .Center, children: [likeButtonNode, spacer, moreButtonNode])

return ASInsetLayoutSpec(
            insets:UIEdgeInsetsMake(0, 13, 13, 13),
            child: buttonLayout)

@smiLLe
Copy link

smiLLe commented Nov 18, 2015

Uhm, i guess it is because your InsetLayoutSpec does not grow. It takes the width of it's subnodes.

@nguyenhuy
Copy link
Contributor

@smiLLe Besides "space between", using a flexGrow spacer is the best approach that I know of.

@MarvinNazari What is the constrained size passed to your cell nodes, especially the minimum width? flexGrow is only taken into account if, after the first layout calculation, the horizontal stack takes less space than the minimum width. If you are using a collection view, the default minimum width is 0. In this case, you need to provide a different constrained size:

func collectionView(collectionView: ASCollectionView!, constrainedSizeForNodeAtIndexPath indexPath: NSIndexPath!) -> ASSizeRange {
    let width = collectionView.bounds.width;
    return ASSizeRangeMake(CGSizeMake(width, 0), CGSizeMake(width, CGFloat.max)) // Always fill the collection view width
}

@nguyenhuy
Copy link
Contributor

Oh, and the spacer can be an ASLayoutSpec instance. It's cheaper than a display node.

@MarvinNazari
Copy link
Contributor Author

I use UITableView how can i set the constrainedSizeForNodeAtIndexPath for UITableView

@nguyenhuy
Copy link
Contributor

Oh, then the constrained size passed to your cell node should be correct. Something must not be right with your layout code. Could you please share your cell node as well, because I think this footer node is wrapped inside a cell node, no? The layout code of your footer looks correct to me. Happy to help you debug if you can share more.

And you may want to take a look at the SocialLayoutApp, especially here. PostNode is a cell node used inside a table view that also uses a spacer to push some nodes away from each other horizontally.

@MarvinNazari
Copy link
Contributor Author

here is the project

@nguyenhuy
Copy link
Contributor

Got it. Because your horizontal stack of the footer node (H) is used inside a vertical stack of the cell node (V), V asks H to measure with a min width of 0.

To force H to fill the entire width of V, you can set its alignSelf to "stretch" (footerNode.alignSelf = .Stretch).

Let me know if my explanation isn't clear enough and I will try my best to make it clearer :)

@smiLLe
Copy link

smiLLe commented Nov 18, 2015

@nguyenhuy didn't know ASLayoutSpec is cheaper , thanks :) I come from CK and until today i did not use ASDK.

I think @MarvinNazari is missing a Stretch for the footerNode

@nguyenhuy
Copy link
Contributor

@smiLLe: IIRC, CK*LayoutComponents are subclasses of CKComponent and basically have everything CKComponent has, including a backing view.

In ASDK, both ASLayoutSpec and ASDisplayNode conform to ASLayoutable protocol. But unlike an ASDisplayNode, an ASLayoutSpec doesn't have any backing store (view/layer) and many other properties. It just purely provides some layout properties (that ASLayoutable requires) and an algorithm for laying out its ASLayoutable children. In fact, it only exists during a layout pass and is thrown away right after an ASLayout object is calculated.

You got the "Stretch" thing right after me :) Thanks for answering questions lately and welcome to the community.

@smiLLe
Copy link

smiLLe commented Nov 18, 2015

@nguyenhuy Thanks for this detailed answer. I am following ASDK for quite a while now and you contributed some really cool stuff! I have lots of layouting experience in CK and want to help people as much as possible.

@nguyenhuy
Copy link
Contributor

You're welcome. And thanks for the kind words. The layout system is powerful but has quite a steep learning curve. Any help is really appreciated 👍

@MarvinNazari
Copy link
Contributor Author

yeah! that solved it! thanks for the help 👍

@lakhman
Copy link

lakhman commented Apr 1, 2016

If it helps others, the OP updated the github repo, the commit with the fix is here:

https://github.com/MarvinNazari/AsyncTest/commit/506c711f23b97ea42e581c1899b389d4d0763dc9

It helped me out, the line I needed when init'ing my subnode was:

self.alignSelf = .Stretch

This allows the subnode to stretch full width, call this on your parent node if your want that to stretch full width also.
also, if you haven't already, this is a good time to play with the spacing properties to see how they add spacing before and after. Once you have your node stretched, you can play with the following to add spacing if required.

subnodeLeft.spacingBefore = 3.0 // Add spacing before the left aligned node
subnodeRight.spacingAfter = 3.0 // Add spacing before the left aligned node

If you need padding top and bottom, you can use the inset layout spec.

This post helped me, I was searching for: (keywords)
AsyncDisplayKit full width node
AsyncDisplayKit stretch node full width
AsyncDisplayKit layout sizing width
AsyncDisplayKit add padding

👍

peter-iakovlev pushed a commit to peter-iakovlev/AsyncDisplayKit that referenced this issue Jul 21, 2018
* Introduce ASRecursiveUnfairLock and tests

* Document it and put underscores to scare people away

* Increment changelog

* Integrate it with ASDN::Mutex behind experiment

* Rename the experiment

* Love these license headers oh so much

* Move internal header because we have to

* Address Jon's feedback
aimalygin pushed a commit to aimalygin/AsyncDisplayKit that referenced this issue Sep 16, 2020
- Followup to facebookarchive#1742
- At Pinterest this shipped with D516974 in late 02/2020
- As discussed in facebookarchive#858 this is iOS10 or later, so the runtime `gMutex_unfair` check is still necessary for Texture.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants