Make static UIView sticky when UIScrollView is scr

2019-07-07 03:21发布

  • I've got a scroll view (diagram: words) that is much longer than the device height
  • At the bottom of the scroll view is some bottom content (diagram: french press) with a different background colour.
  • To separate the bottom content from the words, I've created a 1pt high UIView to act as a border (diagram: red line)
  • I have a button that sits on the bottom of the device, outside the scroll view (the scroll view is device.height - button.height). This button's background colour matches the bottom content's background colour.

The different background colours look pretty wonky without something separating the bottom button from the content view, so while the bottom content is NOT visible, I'd like the border to be sticky, and appear to be sitting above the bottom button (diagram: red line).

A small note: I'm using AutoLayout in IB, but I have an IBOutlet created for the border constraint that I can easily manipulate in code.

enter image description here

4条回答
Bombasti
2楼-- · 2019-07-07 03:49

Here is a lib that does the job: https://github.com/ericcastro/ECStretchableHeaderView

(it works with UItableView in the sample but implementation is based on UIScrollview)

You have to update the code by changing the logic: Here the view is on the top, but the whole principle is there!

查看更多
老娘就宠你
3楼-- · 2019-07-07 03:57

There are at least two simple solutions that comes to my mind firstly.

The key is to find cross point:

Content size value where red line on scroll view comes out from below of the button or goes in below the button.

Option 1: Add another red line on the top of the button and hide/show (hidden property) in the scrollViewDidScroll when the content size value approaches cross point

Option 2: Whether content size value approaches cross point remove constraints and change superview of the red line from scrollview to button or conversely. Re-add constraints for specific superview. Obviously you need to do that in the code.

查看更多
何必那么认真
4楼-- · 2019-07-07 04:00

I'd take these steps:

  1. Put the button in a view that's outside of the scrollView.
  2. Put the awesome bottom content (which I thought was a picture of Bender's head) in the same view that the button is in, and constrain it to the top, left and right edges.
  3. Set the bottom dimension of the scroll view's content insets to be equal to the height of the awesome bottom content view. This will tell the scroll view that it's ok to scroll down that many pixels below the actual end of the scrollable content.
  4. Add a UIScrollViewDelegate to the scroll view that implements, at the very least, scrollViewDidScroll(_). In this method, check the bottom-most position of the scrolling content. If that position falls somewhere in the bottom content inset that you set in step #3, stretch or otherwise reposition your awesome bottom content vertically that same amount.

If I have time, I'll whip up a sample that does just this.

查看更多
欢心
5楼-- · 2019-07-07 04:08

You could create two borders. The first one is the dynamic border at the top of the bottom content in the scroll view. The second one is the sticky border at the top of the button outside of the scroll view.

The second border should be hidden when the first border is visible. In order to do this, you should register a UIScrollViewDelegate. Implement the method scrollViewDidScroll(_:). Just check if the first border is above the second. This can be done with something like this:

if firstBorder.frame.origin.y < scrollView.contentOffset.y + scrollView.frame.height {
    // firstBorder is on the screen, hide the secondBorder...
    secondBorder.hidden = true
} else {
    secondBorder.hidden = false
}

This may be not 100% correct for you, because it's not clear whether your UIScrollView ends above the button or whether they are overlapping. Adjust it if the border hides too early or too late.

If your button is transparent, you should also hide the first border if it is not shown, because it could be under the button. Then just add the lines firstBorder.hidden = false and firstBorder.hidden = true to the code.

查看更多
登录 后发表回答