Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drawer height not adjusting to stackview holding content correctly #376

Open
jackjpark opened this issue Mar 11, 2020 · 13 comments
Open

Drawer height not adjusting to stackview holding content correctly #376

jackjpark opened this issue Mar 11, 2020 · 13 comments

Comments

@jackjpark
Copy link

jackjpark commented Mar 11, 2020

I am using a stackview inside the pulley drawer, i fill this stackview with various views.

Generally this is fine, but there are occasions when i return to the drawer screen and the pulley sets its height incorrectly, this is in the func partialRevealDrawerHeight(bottomSafeArea: CGFloat) -> CGFloat function, where i return return contentStackView.frame.height

I call self.view.layoutIfNeeded() before hand to make sure its laid out, but sometimes it seems to call this func prior to full laying out its contents, causing some views to be squashed, for example the drawer height will correctly set at 360pt, but then after returning to the view the drawer re-lays out and gets a 327pt height and squashes the content

Is there guidance on handling drawer height based on adaptive stackview's?

I used to call the below func which worked for laying the views out correctly, by re-doing the pulley drawer once the content view was fully layed out...

 override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        self.parent?.viewDidLayoutSubviews()
    }

but this causes a loop in layout in the newer version of the drawer as the library calls the same func on its content view

@amyleecodes
Copy link
Contributor

There is a function you can call when that frame changes to notify Pulley to re-query the value and perform a layout. I can’t remember naming off the top of my head, but it’s something like “set needs drawer position update” or something. Calling that will have Pulley correctly do an update for that value and relayout things. I’m not sure you could do it in viewDidLayoutSubviews, though. But I think you might be able to solve it with this next info:

Rather than returning your view’s frame, try using UIView’s sizeThatFits: or systemLayoutFittingSize: so you receive the correct size for what size the view wants to be after the layout is resolved.

@jackjpark
Copy link
Author

jackjpark commented Mar 11, 2020

There is a function you can call when that frame changes to notify Pulley to re-query the value and perform a layout. I can’t remember naming off the top of my head, but it’s something like “set needs drawer position update” or something. Calling that will have Pulley correctly do an update for that value and relayout things. I’m not sure you could do it in viewDidLayoutSubviews, though. But I think you might be able to solve it with this next info:

Rather than returning your view’s frame, try using UIView’s sizeThatFits: or systemLayoutFittingSize: so you receive the correct size for what size the view wants to be after the layout is resolved.

thanks, how would i return sizeThatFits? its a func of the uiview that takes a parameter Size? I just want to return the size the the content Stack View is at the point where the drawer gets its height?

setNeedsSupportedDrawerPositionsUpdate() i assume is the func you mentioned? this just gets allowed positions, it doesnt layout height

@amyleecodes
Copy link
Contributor

You pass sizeThatFits on your stack view a size with the correct width and CGFloat.max as the height. It will return the smallest size fitting that maximum that can fully contain the contents of the view.

setNeedsSupportedDrawerPositionsUpdate() updates positions as well as drawer position locations like this.

@jackjpark
Copy link
Author

You pass sizeThatFits on your stack view a size with the correct width and CGFloat.max as the height. It will return the smallest size fitting that maximum that can fully contain the contents of the view.

setNeedsSupportedDrawerPositionsUpdate() updates positions as well as drawer position locations like this.

I have no max height, the drawer needs to suit whatever size the stackview is rather than imposing the opposite

I may try calling setNeedsSupportedDrawerPositionsUpdate() in viewDidLayoutSubviews, can you foresee any issues with that as itll solve my issues, but as mentioned in the initial post, code similar to that caused me a lot of crashes before

@amyleecodes
Copy link
Contributor

I think you’re misunderstanding. SizeThatFits using CGFloat max as the height will return the correct height for your view (even if it hasn’t been laid out yet).

As I mentioned, I don’t think you’ll be able to call it in viewDidLayoutSubviews.

Pulley resizes it’s content view as the drawer is opened/closed/collapsed. It is not possible to just make it follow the size of your stack view automatically. This is why you need to figure out the height you want for your stack view (before layout) using something like sizeThatFits and tell Pulley what height you want.

@jackjpark
Copy link
Author

jackjpark commented Mar 11, 2020

I think you’re misunderstanding. SizeThatFits using CGFloat max as the height will return the correct height for your view (even if it hasn’t been laid out yet).

As I mentioned, I don’t think you’ll be able to call it in viewDidLayoutSubviews.

Pulley resizes it’s content view as the drawer is opened/closed/collapsed. It is not possible to just make it follow the size of your stack view automatically. This is why you need to figure out the height you want for your stack view (before layout) using something like sizeThatFits and tell Pulley what height you want.

yeah using the layoutSubviews method still causes the looping crash of child vs parent laying each other out

ive tried

 return contentStackView.sizeThatFits(CGSize(width: contentStackView.frame.width,
                                                    height: CGFloat.greatestFiniteMagnitude)).height + 54

but this produces the same result as just using frame height

@amyleecodes
Copy link
Contributor

Try using systemLayoutFittingSize, then. That one may not be properly considering Auto Layout.

@jackjpark
Copy link
Author

jackjpark commented Mar 11, 2020

Try using systemLayoutFittingSize, then. That one may not be properly considering Auto Layout.

that one seems to do the trick, its causing a crash elsewhere in my app on some code that uses the drawer drawerChangedDistanceFromBottom to pad a google map view, but it got the desired effect for the drawer content to i guess ill debug the other issue separately

@jackjpark
Copy link
Author

jackjpark commented Mar 11, 2020

Try using systemLayoutFittingSize, then. That one may not be properly considering Auto Layout.

I wondered if you might have an idea about this other issue, the drawer is calling its drawerChangedDistanceFromBottom func but the value for distance is 1.7976931348623157e+308 from the scrollView.contentOffset.y property, which causes a crash as i try to set this value as padding for my map and its reading as NaN

Any idea whats causing this odd value?

@amyleecodes
Copy link
Contributor

It’s probably resulting from Pulley starting out with a size of zero, or another layout oddity. I don’t think the sample project does that, so it may be caused by when you’re calling setNeedsDrawerPositionUpdstes and Pulley not yet being in a laid out state.

You could try to ignore when the value is out of range, or find what’s causing it to deliver that callback prematurely.

@jackjpark
Copy link
Author

It’s probably resulting from Pulley starting out with a size of zero, or another layout oddity. I don’t think the sample project does that, so it may be caused by when you’re calling setNeedsDrawerPositionUpdstes and Pulley not yet being in a laid out state.

You could try to ignore when the value is out of range, or find what’s causing it to deliver that callback prematurely.

looking at the stack trace, its the drawers own call to setDrawerPosition(position: initialDrawerPosition, animated: false) in its viewDidLoad that trips the crash, it sets drawerScrollView.setContentOffset which sets scrollViewDidScroll which calls delegate?.drawerChangedDistanceFromBottom causing the method crash

@amyleecodes
Copy link
Contributor

If it doesn’t occur in the sample project, then it’s something unique to how it’s being loaded here.

If it does occur in the sample project, file a bug report for it.

In the mean time, you can ignore out of range numbers in your method.

@jackjpark
Copy link
Author

jackjpark commented Mar 11, 2020

If it doesn’t occur in the sample project, then it’s something unique to how it’s being loaded here.

If it does occur in the sample project, file a bug report for it.

In the mean time, you can ignore out of range numbers in your method.

makes sense, how to you range check a CGFloat though? i cant see a method or clear info searching online to compare it to a range

ignore this, found I can use if (0...500).contains(distance)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants