How to forbid WKWebView's horizontal bounce? - ios

As the gif showed blow,I want to forbid the horizontal bounce,it's so ugly.

You can use this to stop bounces:
self.webView.scrollView.bounces = false
Update:
To disable only horizontal bounce, you can use this code:
First set the webview's scrollview delegate to self
self.webView.scrollView.delegate = self
and then implement it like this.
extension UIViewController: UIScrollViewDelegate{
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
if(scrollView.contentOffset.x < 0){
scrollView.setContentOffset(CGPoint.init(x: 0, y: scrollView.contentOffset.y), animated: false)
}else if (scrollView.contentOffset.x >= scrollView.contentSize.width - scrollView.frame.size.width) {
scrollView.setContentOffset(CGPoint.init(x: scrollView.contentSize.width - scrollView.frame.size.width, y: scrollView.contentOffset.y), animated: false)
}
}
}
Hope it helps.

Related

How to hide a UIView while scrolling?

I am trying to achieve this effect.
I am trying to hide a view, as the user scrolls up, and reveal it as the user scrolls down.
I do not know how to go about this.
I have tried looking as the scrollView didScroll function, but I am lost as how to set this up. Any advice?
I solved like this:
private var lastContentOffset: CGFloat = 0
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
lastContentOffset = scrollView.contentOffset.y
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if lastContentOffset > scrollView.contentOffset.y {
UIView.animate(withDuration: 0.25, animations: { [weak self] in
self?.addDeviceButton.alpha = 1.0
self?.addDeviceButton.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
}, completion: nil)
} else if lastContentOffset < scrollView.contentOffset.y {
UIView.animate(withDuration: 0.25, animations: { [weak self] in
self?.addDeviceButton.alpha = 0
self?.addDeviceButton.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
}, completion: nil)
}
}
Hiding content on scroll
Please check this library it do exactly what your attached gif do.
The other way around would be from the gif file attached by you would be.
Add search bar on top. And make hiding part as a header and aligned the search bar and tableview to get that animation.
You need to set up the container view for the scroll view and the view you want to hide as the delegate for the scroll view, registering this class to conform to the UIScrollViewDelegate protocol.
You also need to keep track of the scroll view’s content offset property, and setvthis to the initial offset of the scroll view when it is created:
fileprivate var scrollOffset : CGPoint
Then, as you say, use the scrollViewDidScroll method:
internal func scrollViewDidScroll(_ scrollView: UIScrollView) {
let delta : CGPoint = CGPoint(x: scrollView.contentOffset.x - scrollOffset.x,
y: scrollView.contentOffset.y - scrollOffset.y)
if delta.y > 0, subviewToFade.isDescendant(of: self) {
// fade out subviews and remove
else if delta < 0, !subviewToFade.isDescendant(of: self) {
// add subviews and fade back in
}
scrollOffset = scrollView.contentOffset
}
Hope that helps.
here is my constraints
func scrollViewDidScroll(_ scrollView: UIScrollView) {
setPosition(scrollView)
}
func setPosition(_ scrollView:UIScrollView) {
if scrollView.contentOffset.y >= 20 {
self.parentTopViewcontraints.constant = -95 // set postition till you want to hide your view
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
}else if scrollView.contentOffset.y <= 200 {
self.parentTopViewcontraints.constant = 0 //set back
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
}
}

How to keep UIButton floating AFTER scrollViewDidScroll(_ scrollView: UIScrollView) reached bottom?

The following is the current implementation. The grey button is floating on the scroll view. Is there a way to make the button appear once the yellow view (end of scroll view) is reached. Then keep it floating on the screen at the very bottom.
I'm using the following code:
override func scrollViewDidScroll(scrollView: UIScrollView) {
if (scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)) {
//reached bottom - how to show button below yellow
// and keep it floating as shown above
}
}
Adding additional code of what I've tried so far:
#IBOutlet weak var btnScroll: UIButton!
var startingFrame : CGRect!
var endingFrame : CGRect!
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if (scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)) && self.btnScroll.isHidden {
self.btnScroll.isHidden = false
self.btnScroll.frame = startingFrame // outside of screen somewhere in bottom
UIView.animate(withDuration: 1.0) {
self.btnScroll.frame = self.endingFrame // where it should be placed
}
}
}
func configureSizes() {
let screenSize = UIScreen.main.bounds
let screenWidth = screenSize.width
let screenHeight = screenSize.height
startingFrame = CGRect(x: 0, y: screenHeight+100, width: screenWidth, height: 100)
endingFrame = CGRect(x: 0, y: screenHeight-100, width: screenWidth, height: 100)
}
override func viewDidLoad() {
super.viewDidLoad()
configureSizes()
}
If I understand you right you want to put button on the position which shown on the gif
Try this code:
override func scrollViewDidScroll(scrollView: UIScrollView) {
if (scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)) && self.button.isHidden {
self.button.isHidden = false
self.button.frame = startingFrame // outside of screen somewhere in bottom
UIView.animate(withDuration: 1.0) {
self.button.frame = yourFrame // where it should be placed
}
}
}
UPDATE
add this code to hide your button before animation will show it
override func viewDidLoad() {
super.viewDidLoad()
self.button.isHidden = true
...
}

UIScrollView doesn't scroll upwards sometimes

I am using 2 scroll Views When the inner Scroll View is scrolled upwards, outer scrollView also moves upwards(positive contentoffset.y) and when inner SV's contentoffset.y goes less than y, both scroll Views come back to their original positions.
Here is the code:
//secondView is a UIView inside outerScrollView and above inner SV(scrollView).
var scollView: UIScrollView!
var yOffset: CGFloat!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.automaticallyAdjustsScrollViewInsets = true
self.outerScrollView.delegate = self
self.scrollView = UIScrollView(frame: CGRect(x: 0, y: self.secondView.frame.origin.y + self.secondView.frame.height, width: self.view.frame.width, height: self.view.frame.height - (264)))
self.scrollView.delegate = self
self.outerView.addSubview(self.scrollView)
self.scrollView.setContentOffset(CGPoint.zero, animated: true)
}
func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
if (scrollView == self.scrollView) {
if (scrollView.contentOffset.y > 0) {
if (self.outerScrollView.contentOffset.y <= 0 ) {
let contentnOffset:CGPoint = CGPoint(x: 0.0, y: self.yOffset)
DispatchQueue.main.async {
self.outerScrollView.setContentOffset(contentnOffset, animated: true)
self.scrollView.frame.size = CGSize(width: self.view.frame.width, height: self.view.frame.height - self.qLabel.frame.height - 9)
if (scrollView.contentSize.height < self.view.frame.height - self.qLabel.frame.height - 9) {
let downPanGesture: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(self.handlePan))
downPanGesture.direction = .down
self.scrollView.addGestureRecognizer(downPanGesture)
}
}
}
} else {
DispatchQueue.main.async {
self.outerScrollView.setContentOffset(CGPoint.zero, animated: true)
self.scrollView.frame.size = CGSize(width: self.view.frame.width, height: self.view.frame.height - (self.scrollView.frame.origin.y))
}
}
}
}
Although everything works fine, there is just 1 small problem. After the inner scrollView is scrolled upwards and contentoffset has changed and I want to keep on scrolling this view, it sometimes just doesn't scroll(upwards). So, I have to first scrooll it downwards and then it will again start scrolling fine. It only happens rarely but it's quite annoying.
Can anybody tell me what could be the possible problem?
Thanks!
P.S. I have tried all other scrollView's delegate methods like didenddecelerating() or didenddragging() etc.

I know how to disable bouncing of uitableview on top only - but how can I do it only on the bottom?

I managed to disable bouncing effect when user scrolls to the top. I would like to reverse it somehow so that the bouncing effect is disabled on the bottom. Could you help me with modifying my code for that purpose?
var lastY: CGFloat = 0.0
func scrollViewDidScroll(scrollView: UIScrollView) {
let currentY = scrollView.contentOffset.y
let currentBottomY = scrollView.frame.size.height + currentY
if currentY > lastY {
//"scrolling down"
tableView.bounces = true
} else {
//"scrolling up"
// Check that we are not in bottom bounce
if currentBottomY < scrollView.contentSize.height + scrollView.contentInset.bottom {
tableView.bounces = false
}
}
lastY = scrollView.contentOffset.y
}
Did you try setting bounce and VerticalBounce property to NO.
You can set these properties programatically like
In Swift
tableView.bounces = false
tableView.alwaysBounceVertical = false
In Objective-C
tableView.bounces = NO;
tableView.alwaysBounceVertical = NO;
OR
if you want to do it from Storyboard. Make you tableview setting like below :
You can try this code
override func scrollViewDidScroll(scrollView: UIScrollView)
{
if scrollView.contentOffset.y <= 0
{
scrollView.contentOffset = CGPointZero
}
}
Try this:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == tableView {
if (self.tableView.contentOffset.y >= (self.tableView.contentSize.height - self.tableView.bounds.size.height))
{
scrollView.contentOffset = CGPoint(x: 0, y: (self.tableView.contentSize.height - self.tableView.bounds.size.height))
}
}
}

Disable bottom bounce in UITableView with UIRefreshControl

I want to disable UITableView bottom bounce, I can't use standard "bounce" property in storyboard, bcs UIRefreshControl needs top bounce for work. So I have tried this solution:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.frame.size.height) {
[scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x, scrollView.contentSize.height - scrollView.frame.size.height)];
}
}
It works fine if content height bigger then size of screen, but crashes in other case:
As u see on picture above UIRefreshControl is not hidden (and there are only 3 cells in uitableview with blank space on bottom if UIRefreshControll is hidden). I have tried to resolve this problem by adding UIRefreshControl height to my method but it didn't help either:
override func scrollViewDidScroll(scrollView: UIScrollView) {
if scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.frame.size.height - self.refreshControl!.frame.size.height {
scrollView.setContentOffset(CGPoint(x: scrollView.contentOffset.x, y: scrollView.contentSize.height - scrollView.frame.size.height + self.refreshControl!.frame.size.height), animated: false)
}
}
I am having blank space at top and RefreshControl stops working:
What am I doing wrong? Thx.
P.S. My viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
self.refreshControl = UIRefreshControl()
self.refreshControl!.attributedTitle = NSAttributedString(string: "Обновление")
self.refreshControl!.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
self.edgesForExtendedLayout = UIRectEdge.None;
tableView.allowsMultipleSelectionDuringEditing = false;
tableView.tableFooterView = UIView()
// menu button
if self.revealViewController() != nil {
menuButton.target = self.revealViewController()
menuButton.action = "revealToggle:"
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
}
At the moment I found pretty dumb solution:
override func scrollViewDidScroll(scrollView: UIScrollView) {
if scrollView.contentSize.height > self.view.frame.size.height && scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.frame.size.height {
scrollView.setContentOffset(CGPoint(x: scrollView.contentOffset.x, y: scrollView.contentSize.height - scrollView.frame.size.height), animated: false)
}
}
I disable bounce only if contentSize.height > self.view.frame.size.height , hope some1 knew how to do it better.

Resources