In my app I have a scrollView. It should only scroll to the right when a UIButton is clicked. Scrolling to the left should always be possible. I found a solution like this:
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView
{
if (scrollView.contentOffset.x < oldX) {
[aScrollView setContentOffset: CGPointMake(oldX, aScrollView.contentOffset.y)];
} else {
oldX = aScrollView.contentOffset.x;
}
}
This code stops it from scrolling to the left, but i can't make this work for the right side. Any ideas how this could be done?
Thanks
Related
i have a details view controller with a scrollview on it. And i have load UILabel, UIImageView on top of UIScrollView. The scrollview is set to scroll vertically only. and the view need to be able to recognize swipe left and right to navigate to next/previous page by adding
self.leftGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeRecognizer:)];
[self.leftGestureRecognizer setDirection:UISwipeGestureRecognizerDirectionLeft];
[self.view addGestureRecognizer:self.leftGestureRecognizer];
So when i swipe within UILabel, it is working. If i swipe start from UIScrollView, it is not working. I guess it is the UIScrollView conflict the swipe gesture.
In short, swipe gesture is only working on the subview but not UIScrollView .Does anyone have any idea on this?
UPDATE:
If i swipe start from scrollview first then end at UILabel, it won't recognize the swipe gesture. If i swipe within UILabel(start and end in the UILAbel) it is able to recognize.
Make sure that if the UIImage allows zooming, the swipe recognizer won't work, since it is trying to zoom. If this is the case, you will need to enable the zoom only in certain case. hope it helps.
Initialize the scroll view with scrolling disabled. Then you need to disable scrolling in the scroll view when the image is not zoomed in, and renabled it when it is zoomed in. This provides the expected behavior.
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
if (scrollView.zoomScale != 1.0) {
scrollView.scrollEnabled = YES;
} else {
scrollView.scrollEnabled = NO;
}
}
To enable zoom provide an image on a delegate.
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return myImage;
}
Also add the gesture to instance of scrollview like this -
leftGestureRecognizer.delaysTouchesBegan = YES;
[myScrollView addGestureRecognizer:leftGestureRecognizer];
OR You can try the following -
[scrollView.panGestureRecognizer requireGestureRecognizerToFail: leftGestureRecognizer]
I'm building a new project using ECSlidingViewController v2. The first time I swipe to open the left under view, it works great. But when I swipe the second time, I get an EXC_BAD_ACCESS crash. The reference is to the NSMapTable in the controller.
- (void)updateTopViewGestures {
BOOL topViewIsAnchored = self.currentTopViewPosition == ECSlidingViewControllerTopViewPositionAnchoredLeft ||
self.currentTopViewPosition == ECSlidingViewControllerTopViewPositionAnchoredRight;
UIView *topView = self.topViewController.view;
if (topViewIsAnchored) {
...
} else {
...
---> [self.customAnchoredGesturesViewMap removeAllObjects];
}
}
Taking reference from #uiroshan answer Closing ECSlidingViewController menu
You can use the following code:
- (IBAction)showSlidingMenu:(id)sender
{
[self.slidingViewController anchorTopViewToRightAnimated:YES];
if ([self.slidingViewController currentTopViewPosition] == ECSlidingViewControllerTopViewPositionAnchoredRight)
{
[self.slidingViewController resetTopViewAnimated:YES];
}
}
Here,
I am animating the top view controller to Right, so I am checking whether top view position is ECSlidingViewControllerTopViewPositionAnchoredRight
To animating the top view controller to Left
ECSlidingViewControllerTopViewPositionAnchoredLeft
I have a UIScrollView and a UITableView inside the UIScrollView.
I would like to intercept scrolling of the UITableView and only allow scrolling if the super view (UIScrollView) have reached a specific contentOffset.
I have created subclass of both UIScrollView and UITableView, how do i catch scrolling event and intercepting the scrolling while the user is still scrolling?
Example of what i'm trying to accomplish:
The UITableView is going to have a header, if i scroll down the header will collapse to 30% of original size and and stay visible at the top. After i have scrolled back to the top of the UITableView i want the header to expand. In other word i want to extend the scrolling of a UITableView with a header that can collapse/expand.
There might be better way to accomplish this, i'm open for suggestions.
There may be a better way, but this solution is working for me.
UITableView (let's call it innerScrollView) inside of UIScrollView (let's call it scrollView) inside whatever the main view is (let's call it view).
Set an outlet in your view controller for the innerScrollView (self.innerScrollView).
Set bounce in XIB or code to: scrollView.bounces = YES and innerScrollView.bounces = NO.
Set scrolling to disabled initially for the innerScrollView.
In code (viewDidLoad:) set scrollView.contentSize.height to view.frame.size.height + the 70% of the header you want to disappear. Resize innerScrollView to fill the resized contentView to the bottom.
Set your view controller as the delegate for scrollView and implement scrollViewDidScroll: as follows:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat maxYOffset = self.scrollView.contentSize.height - self.scrollView.frame.size.height;
CGFloat minInnerYOffset = self.innerScrollView.contentInset.top;
CGFloat currentYOffset = scrollView.contentOffset.y;
CGFloat newYOffsetDelta = currentYOffset - maxYOffset;
CGFloat currentInnerYOffset = self.innerScrollView.contentOffset.y;
if (scrollView.contentOffset.y >= maxYOffset) {
self.innerScrollView.scrollEnabled = YES;
self.scrollView.contentOffset = CGPointMake(0, maxYOffset);
if (currentYOffset != maxYOffset) {
self.innerScrollView.contentOffset = CGPointMake(0, currentInnerYOffset + newYOffsetDelta);
}
}
else if (currentInnerYOffset > minInnerYOffset) {
self.scrollView.contentOffset = CGPointMake(0, maxYOffset);
self.innerScrollView.contentOffset = CGPointMake(0, currentInnerYOffset + newYOffsetDelta);
}
else if (currentYOffset < scrollView.contentInset.top) {
scrollView.contentOffset = CGPointMake(0, scrollView.contentInset.top);
}
else {
self.lowerScrollView.scrollEnabled = NO;
}
}
I just whipped this up and quickly tested it. It all seems to work, but there may be some improvements and tweaks needed. Regardless, this should get you started at least.
Well, you should use the following UIScrollViewDelegate method
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
// here perform the action you need
}
I am trying to use a UIScrollView as a navigation device in my iOS application. Basically, I want the application to load specific content, based on the position of a paging-enabled UIScrollView. It is sort of like a navigation wheel.
Currently, I have a two-page (2*320) scrollview, and I am using the scrollViewDidEndDragging delegate method and contentoffset.x to load the appropriate content. I try to determine the position of the scrollview as such:
if (scrollView.contentOffset.x < 320) {
// Load content 1
}
else if (scrollView.contentOffset.x >= 320) {
// Load content 2
}
My problem is that I either do not understand how to work with contentoffset or it is not suitable to deal with my problem. Either way, I am stuck. Can someone let me know where I went wrong and/or show me a more efficient way to determine scrollview position?
I am stupid, I forgot to mention what the problem is... Basically, I cannot track the position of the scrollview. When I move to the second page it only registers changes if I go over the 620 limit (bounce rightward). But when I go back to the starting position (page 1), it does register the changes. In other words, my tracking is not accurate.
Delegate and everything else is working fine, I log them!
It's hard to say because you never specifically mentioned what the problem is, but I'll take a couple guesses at it.
If the delegate method isn't being called at all you need to remember to set the scroll views delegate:
[myScrollView setDelegate:self];
Otherwise, the problem with using scrollViewDidEndDragging to detect the scroll views offset is that it will check the offset at the point where you stop dragging which could be within the destination pages rect, or within the starting pages rect. As an alternative, I'd suggest you use scrollViewDidEndDecelerating to check the content offset as it will be called as soon as the scroll view comes to a stop at its destination page.
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (scrollView.contentOffset.x < 320) {
NSLog(#"%#",NSStringFromCGPoint(scrollView.contentOffset));
}
else if (scrollView.contentOffset.x >= 320) {
NSLog(#"%#",NSStringFromCGPoint(scrollView.contentOffset));
}
}
I think this could help you :). With scrollViewDidScroll you always get the exact position of your scrollView:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView.contentOffset.x < 320)
{
// Load content 1
}
else if (scrollView.contentOffset.x >= 320)
{
// Load content 2
}
}
NSLog(#"Position: %g", scrollView.contentOffset.x);
Do not forget the delegate UIScrollViewDelegate in your .h file.
Here a solution for getting the current position (page) as integer Value:
Use scrollViewDidEndDecelerating: methode:
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
NSLog(#"%i", (int)(_scrollView.contentOffset.x / _scrollView.frame.size.width));
}
If for any reason, you'd like to be notified before the view ended decelerating; for example, to perform animations. You can also use this:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
// Where the scroll will end (vertically)
let offSetY = targetContentOffset.pointee.y
// I've got a scroll view with paging enabled so I use this to check which "page" is selected.
if offSetY == firstPageView.frame.origin.y {
// Do something…
} else if offSetY == secondPageView.frame.origin.y {
// Do something…
}
}
Using UIScrollViewDelegate,
func scrollViewWillBeginDragging(scrollView: UIScrollView){
print("dragging begins")
print("Position: \(scrollView.contentOffset.x) , \(scrollView.contentOffset.y) ")
}
I'm trying to create functionality similar to Reeder where you are introduced to new content if you scroll below or above the content in a scroll view.
I thought I was heading in a good place with scrollViewWillEndDragging:withVelocity:targetContentOffset:
However, this just stops at the bottom.
Is there any way to detect if you are scrolling beyond the bottom or top (this is when the vertical scrollbar begins to get smaller)
Thanks!
posting comment as answer:
Check the contentOffset in scrollviewDidScroll and the moment the contetOffset is beyond your bottom/top point, add new stuff to the scrollview, and increase the content size
Maybe better solution would be something like this:
-(void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
if (targetContentOffset->y == 0 && scrollView.contentOffset.y < - someOffset) { //use someOffset if you dont want to reload immedeately on scroll to top
//dragged past top
}
if (targetContentOffset->y == scrollView.contentSize.height && scrollView.contentOffset.y > scrollView.contentSize.height + someOffset) {
//dragged past bottom
}
}