Ok, I have a complicated scenario here. I have a scrollview which scrolls horizontally and contains tiles, 1 centered on the screen at a time with the user still able to see if there are more to the left or right by way of having the edges of the 2 views visible on either side. I am able to add the views programmatically to the scrollview and have paging work properly, so the user can swipe back and forth between them. Another requirement is to have an initial animation where the first view slides in, then is bounced off to the left by the second view. I accomplished this by using a series of UIView animations, and it works well.
Here is my problem: After the animation completes, you cannot scroll left to get to the first UIView that was created. I suspect that this is because it was animated out to the left of the content area of the scrollview. I have tried to increase the contentSize of the scrollview, but I still get the same behavior.Once the initial scrollview has been moved off to the left, I cannot swipe to page to it.
Is there a common pattern I could use to accomplish this in a better way?
It sounds to me like you're animating the child view's frame to the left so that the x coordinate of that first view's frame is negative, instead of animating the scroll view's contentOffset to the right. If that's the case, is there a reason you aren't just setting the scroll view's contentOffset inside an animation block? If there is a reason, what if after the animation completes you "fix up" the content offset and the frames of the child views so that none of the views are in a negative position.
But, I guess I have more questions than answers right now, so it might help to post the code showing how you do your animations to make it easier to answer your question.
Related
I'd like to have an interactive animation where a view transitions from one set of constraints to another as the user drags up/down the screen. The background image should shrink vertically (easy), and the profile image should change from being horizontally and vertically aligned to the background image to being anchored to the top and left corners of the background image. Is this possible?
Yes, it is possible, and you can see this effect in the Avvo app, for example (in the lawyer profile screen). The trick here is to smoothly transition from one set of constraints to another.
Here's an outline of how to do this:
add a UIScrollView. Add the view you want to animate as a subview to the scroll view.
Make your view controller implement
UIScrollViewDelegate
In the delegate method
scrollViewDidScroll(_:), update the constraints' constants as
needed.
Also in that method, when contentOffset crosses a
threshold value, flip to a different set of constraints, by setting
their active property to true or false.
To keep the view (the headshot image, in my example), pinned to the top as you scroll, just continuously update its top spacing constraints based on the contentOffset.y value.
Achieving a perfectly smooth transition may take some trial and error, but it definitely can be done!
Here are the screenshots showing the transition as you scroll up:
Imagine the situation when you have UITableView placed into UIScrollView.
If you tap on table view and begin vertical moving - UITableView become first responder and will scroll vertically. But if you will move finger horizontally - UIScrollView become first responder and will scroll horizontally.
I have similar situation but instead of UIScrollView I have simple UIView object that intercept - (void)touchesMoved: events and make moving (kinda self made ScrollView).
But how I can do the same trick that UIScrollView do - determine horizontal moving and take away first responder status from UITableView???
Thanks in advance!!!
You could try overriding canBecomeFirstResponder in your view and returning the appropriate value at the appropriate time.
Have you tried throwing a UIPanGestureRecodnizer on the view. You should then be able to set a #selector which will allow you to handle the event in question. Also with pan you can choose to only change the x element and leave the y element alone. Further more with the pan element attached to a view you will not have to worry about having a first responder. Pan elements can a lot of the time be used as a swiping element if you had acceleration and or deceleration. Beyond that I would say you could also add a UISwipeGestureRecognizer element left and right but I do not think you get information such as how far the user swiped meaning, if you want the screen to snap back when the user has not made it far enough to the right or left then you will not have that option. Also, swipe will not give the same effect as the UIScrollView but UIPanGestureRecognizer can, if you do a little extra coding. The extra coding would be observing the position of the x value and then using a little bit of animation for the view to snap to the right or left when the user lets go of the view. Other then that the view should and will follow the finger if you set the x properly.
I would like to be able to build a scroll view capable of scrolling an unbounded (infinite) distance (this is question number one, how to do this with the contentSize property). The reason for this is so that I can implement a scrolling calendar view, which the user can use to scroll through time along a single axis.
Now, I need to put a view/s in there to mark the dates as they scroll by. My second question is how to implement a view like this in a scroll view. I could have a long view, 3 or 4 times wider than the scrollview frame and just reposition and update that every time the scrolling stops, faking a continuous bar. Any other ideas?
Thanks!
I know it's been a while since you posted this question, but just for future reference:
At WWDC 2011, Apple gave a great presentation called "Session 104 - Advanced Scroll View Techniques". The video can be seen from developer.apple.com or from iTunes.
The main concept:
1 - Start off with a subview that is larger than your scrollView's bounds.
2 - In -layoutSubViews from the scrollView, you check whether the contentOffset in the direction you want to scroll infinitely is past some threshold that you specify (this doesn't have to be any specific value, it could be 1 point in the extreme).
3 - If this is the case, you reset the contentOffset to zero, and you adjust the subview's frame by the same amount.
These last two steps happen within the same run loop cycle, hence the transition will not be visible. Beware that the scrollBar will jump, though. But as your scrollView is infinite, there is no visual feedback the scrollBars could give, anyway, so you'd better hide them when you've finished implementing this.
Not sure it can be... You could try CGSizeZero
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIScrollView_Class/Reference/UIScrollView.html#//apple_ref/occ/instp/UIScrollView/contentSize
contentSize
The size of the content view. #property(nonatomic) CGSize contentSize Discussion
The unit of size is points. The default size is CGSizeZero.
The real question is do you truely want "infinate" or do you want mostly infinate and just make the view ungodly large? Or do you want auto-resizing.
Also a continuous bar for an infinite scrollview? The bar would never move as it wouldn't get any closer to the beginning or the end... You could make a bar that dragging to the right would go into the future and dragging it to the left would go back and then just always reposition it in the center.... Other then that I dunno what would make sense here.
Looping UIScrollView Horizontally sounds like the same sort of problem, hopefully my comments there might give you some ideas as well.
Making an 'infinite' scrollview doesn't work - the memory requirements get way too large. The best way to do it is fake it.
3 screen scrollview:
|---|---|---|
| | | |
|---|---|---|
Make a scrollview that is 3 times as large as one screen, then when the user finishes scrolling to the next third of the scrollview, move the scroll position back to the center third and scoot the content over to the left. This happens so fast that there is no visible feedback to the user that the scrollview & content was just recentered.
Similarly, when the user scrolls back to the first third, change the scroll position to the center third and move all the content to the right.
For memory management, you should only load as much content as will fit onto those three screens. When you scroll to the next third, you'll reposition, and load the next screen of content.
They "brush" the subject in this thread, but it does not really answer much:Stackoverflow UIScrollView question
I have a UIScrollView and a UIPageControl working together to present a set of views.
(Standard "Home screen" swipe style, in lack of better words)
Each of these views, inside the scrollView, has a thin menu in the bottom part, that can also be swiped from side to side. If anyone remember the previous FaceBook app, this also had a menu that could be swiped horizontally, however, not incased in another scrollView, but the idea is similar.
So the outer scrollView will scroll the entire view, including the view containing the inner scrollView, but the inner scrollView will only change a menu inside the view.
I already did a proof of concept test of this, what happens, is that delegate methods gets called in both the scrollViews no matter where on the screen the swipe takes place, and the innermost scrollView will crash the app when swiped left to right, but not right to left…
I sort of get the feeling that this can be done, but that Im going about it the wrong way.
Is there a way to set which area of the screen reacts to swipes? i.e. decide that the upper ¾ of the screen will call one set of delegate methods and the bottom ¼ will call another set.
Maybe through some sort of mediator that catches the swipes before they are "processed" and then determines which scrollView should react?
Hope someone can point me in a good direction on this one, thanks:)
What about de-nesting the scroll views? Instead of embedding a scrollview inside another scrollview, make them same-level siblings of a parent UIView.
In support of your nesting though, I can think of the App Store app which lets you scroll screen shots horizontally while the app description scrolls vertically.
I'm working on an iPhone game, and trying to use a UIScrollView to display some icons, which I then want to enable the user to drag off the bar being scrolled, onto another view (basically, dragging them from their hand into play on the game board). The problem is that the UIScrollView clips everything outside it's own bounds.
Here is a picture of what I'm trying to do:
Functionally, it actually works, in that you can drag the icons up to the white board fine...but you can't see them as you are dragging...which is not acceptable.
Does anyone know if you can temporarily disable the clipping that a scroll view does, or is there some way to get around it? Hacky or not, I would really like to make it happen.
Does anyone have any other possible solutions for this? Or maybe any alternate approaches? I've considered if maybe a page view might work, but haven't tried it yet...and it's not at all as good of a solution as the scroll view.
Worst case I can just go back to not having the bar scrollable, but that really puts a damper on some of my game mechanics, and I'm really not too excited about that.
I think you're looking for the clipsToBounds property of UIView. I've used it successfully with UIScrollView:
scrollView.clipsToBounds = NO;
However, the dragging you want to do from the scroll view to the game view may require you to remove the icon view from the scroll view, place it in the superview at a position corresponding to its visible position within the scroll view (calculated using the scroll view's origin and content offset), and have that track the user's finger movements. On a release of the touch, either drop it on the game view at the proper position or return it to the scroll view.
I'm not 100% sure I understand the question but I think you should look into the z order of the scrollview and the whiteboard. It may be that the drag is just going behind the whiteboard.
Failing that, it would be useful to see all the bounds of your view heirarchy.
I also think a better solution allround might be to create a "sprite" to animate underneath the players finger - you could offset the drawpoint of the sprite from the touchlocation so that the player can see what they are dragging.