I want to implement a kind of infinite UIScrollView which means the following:
If the user scrolls and the scroll view would bounce at the right or left end, the scroll view should expand itself into this direction instead of bouncing. The additional space would be filled with new data, loaded from a a delegate.
Thanks in advance,
Christian
Implement the scrollViewDidScroll: delegate method and check the scrollView's contentOffset. If the offset is close to the edge of the scrollView you increase the contentSize of the scrollView. E.g. to expand the scrollView to the right:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView.contentOffset.x + scrollView.frame.size.width > scrollView.contentSize.width - 30) {
scrollView.contentSize = CGSizeMake(scrollView.contentSize.width + 200, scrollView.contentSize.height);
}
}
Related
I set the content size so vertical scrolling becomes activated but I only want the user to be able to scroll north and not south. Any ideas on how I can accomplish this?
//set high greater than view
myScroll.contentSize = CGSize(width: myView.view.frame.width,height: myView.view.frame.height + 190)
I only want the ability to scroll up and disable the ability to scroll down which is the default direction of the scrollview
You can set the content offset of the scroll view to the bottom. i.e.,
myScroll.contentOffset = CGPoint(x: 0,y: 190) // Here 190 is the same value that represent the height increase done in contentSize.
Make a subclass of UIScrollView. Override layoutSubviews to make sure contentOffset.y only increases, except when it's beyond the end of the content range, so the scroll view can bounce at the bottom.
class MyScrollView: UIScrollView {
var priorOffset = CGPoint.zero
override func layoutSubviews() {
var offset = contentOffset
if offset.y < priorOffset.y {
let yMax = contentSize.height - bounds.height
if offset.y < yMax {
offset.y = priorOffset.y
contentOffset = offset
}
}
priorOffset = offset
super.layoutSubviews()
}
}
Result:
select your Scrollview
select identity inspector
set user define attributes (see image)
in image first 435 vertical scrolling & second 116 is horizontal scroll
Note : set your own scrolling
You can set the direction of UIPanGestureRecognizer which is attached to your UIScrollView.
Check out some popular question which has an up-to-date answer, for example this one.
Or just go with pod 'UIPanGestureRecognizerDirection'
The property bounces can limit scroll view border, but I want to limit one border, for example: I can drag over top border, but bottom can't. I have make it using two views, but I want to find a direct way.
check scrollview's content offset if it is beyond bottom bounds using scrollViewDidScroll delegate method of UIScrollView and put bounce for scrollview check so it will bounce for top bounds.
- (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)];
}
}
Note : Set scrollview delegate to self for your scrollview instance like so it will call this delegate method while scrolling . cheers :)
yourScrollviewInstance.delegate = self
I have a UITableView with a UIView on top. I want the UIView to stick to the top as the tableView cells scroll over it.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
if (self.tableView.contentOffset.y > 0) {
CGRect newframe = self.publicTopView.frame;
newframe.origin.y = -self.tableView.contentOffset.y;
self.publicTopView.frame = newframe;
NSLog(#"After: %f", self.publicTopView.frame.origin.y);
}
}
You need to set your table view header view to the view you want on top.
Add this code to you viewDidLoad
self.tableView.tableHeaderView = self.publicTopView
I'm not certain what you're trying to accomplish, but I have a guess at what is wrong. As you scroll your contentOffset will continue to change and let's say your tableView has a content size height of 1500, then your contentOffset will eventually be larger than the height of your view controllers view. Now see that you are putting that contentOffset into the origin.y of your publicTopView. So your publicTopView could possibly be moving too much, even offscreen depending on how large your tableview's content size is.
I have a ScrollView that is supposed to be scrolled only downwards. The content View's size matches scrollview identically. I use this code to prevent from scrolling up:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
#define CONTENT_OFFSET 0
NSLog(#"%f", scrollView.contentOffset.y);
//prevent from scrolling up
if (scrollView.contentOffset.y > CONTENT_OFFSET) {
scrollView.contentOffset = CGPointMake(0, CONTENT_OFFSET);
}
}
It used to work perfectly. But now for some reason scroll view starts at -44 points and is of course scrollable up to 0. In between -44 and 0 it doesn't bounce if drag ended. I'm pretty sure I have not changed anything in layout but I might have unintentionally. I think scroll view now has bigger content view for some reason. Where do I look for the origin of this problem?
There is a button at the bottom of my view controller. When the user scrolls down the button has to be attached to the scrollview at certain height.
I need to attach a button to the scrollview, immediately when the contentOffset.y reaches a particular value. -(void) scrollviewDidScroll doesn't help me as there might be a jump in contentOffset when the user is scrolling fast. Any leads on this are helpful.
Also, whenever I add a subview to the scrollview, -(void) viewDidLayoutSubviews is called. Which in turn sets the contentOffset to {0,0}. How can I achieve the functionality I need?
I needed to do the same thing with a UITableView and for me using scrollViewDidScroll worked.
I created a view called staticBar and added it as a subview of the tableView, but I had to rearrange the tableview subviews for it to appear in the right place. I don't have my code in front of me, but in -scrollViewDidScroll: it looked something like this:
- (void)scrollViewDidScroll:(UIScrollView*)scrollView
{
CGFloat staticBarAdjustedY = _staticBarY - scrollView.contentOffset.y;
CGFloat scrollViewYFloor = scrollView.frame.size.height - _staticBar.frame.size.height;
// This way maximum Y the view can have is at the base of the scrollView
CGFloat newY = MIN( staticBarAdjustedY, scrollViewYFloor);
_staticBar.frame = (CGRect){ { _staticBar.frame.origin.x, newY}, _staticBar.frame.size}
}
I will check my code later today and add more details here.
Also, you said the scrollviewDidScroll has jumps in contentOffset, but it's worth mentioning that these jumps are the same that the scrollView uses to scroll its own view. So it's not like you are "losing" frames on this delegate method.
Hope it helps.
PS: So, here is the rest of my code.
//I place my custom view as a subview of the tableView below it's last subview
//The last subview is for scroll indicators.
WTButtonsBar *buttonBar = [[WTButtonsBar alloc] init];
[self.tableView insertSubview:buttonBar belowSubview:self.tableView.subviews.lastObject];
In scrollViewDidScroll:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//In my app I needed my view to stick to the top of the screen
//thats why I use MAX here
//self.buttonsBarOriginalY is the view's position in the scrollView when it isn't attached to the top.
CGFloat newY = MAX(scrollView.contentOffset.y, self.buttonsBarOriginalY)
[_buttonsBar setFrame:(CGRect){{0, newY}, _buttonsBar.frame.size}];
}