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.
Related
I have a view which is using single touch events (single finger) for drawing (lines, cycles, text, and so on).
Now I want to put this view inside of UIScrollView, which will allow zooming and panning. Of course two fingers are required to perform both zooming and panning.
What is the pattern do do that? I've found only examples when contents of UIScrollView accepts only single clicks (it contains only a buttons). Nothing what to do when contents require also touch moves.
Access the panGestureRecognizer property on the UIScrollView, and set its minimumNumberOfTouches property to two:
myScrollView.panGestureRecognizer.minimumNumberOfTouchesRequired = 2;
I'm thinking you should begin with scrolling disabled for scrollview and user interaction enabled for both. Then in touchesBegan: you should check for number of touch points. If it's only one (aka user wants to draw) you do nothing (disabling interaction for scrollview would disable it for all subviews as well). However, if the number of touch points is greater than one, enable scrolling then do
[UIView setUserInteractionEnabled: NO]
This way, no lines should be drawn on the UIView when you pinch or zoom with two fingers on the UIScrollView.
I helped developed an app that required a signature plate with in a scroll view, and a scroll view's subviews are weird to touch events, sometimes you have to hold your finger there for it to pass through the scroll view and reach the inner views, so there was a bit of a lag... but what i ended up doing was subclassing a UIScrollView and overriding the
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {}
method and if the touch landed with in the frame of the signature plate it would
[scrollView setScrollEnabled:NO]; and the drawing happened sooner and more smoother... the only problem is they couldn't scroll the scroll view from that box.. basically i created a dead spot with in the scroll view
but, that's a little wonky, i think a UITableView might work better for you... just make it 1 giant table cell, i think you will get better results....
Don't forget to enable 'Multiple Touch' for these features.
I am implementing a Google+ type iPhone application. The UI consists of a number of screen-sized panels, and the user can move through these panels horizontally by swiping left or right. I am not using a UIScrollView for this, but am instead implementing it as a series of UIViews on top of a master UIView - I override the touches... events for the UIViews and pass them on to the master UIView to handle repositioning the panels.
My code works perfectly as long as each panel is just an empty UIView (or if it only contains controls that don't pick up touch events, like a UILabel). The problem I'm facing is when I try to put a UITableView on one of the panels. Because the UITableView picks up the touch events, this is interfering with my own code that uses the touch events to slide the panels horizontally.
I have tried two approaches, neither of which is working perfectly:
First approach: I subclass UITableView, overriding the touch... events (touchesBegan, touchesMoved, and touchesEnded). In the overrides, I pass the events on to self.nextResponder and then to super. On my table, I also set canCancelContentTouches = NO;. This works somewhat - if I start swiping with a perfectly horizontal movement, the underlying panel containing the table view moves left and right. However, if I begin the process by swiping vertically, the table view begins scrolling up and down and no horizontal movement happens at all until I lift my finger. Also, if I begin swiping horizontally the left-right movement of the panel happens, but until I life my finger no vertical scrolling of the table view is possible (I'm trying to get a solution where vertical movement scrolls the table view and horizontal movement moves the underlying panel left-right). BTW, without the canCancelContentTouches = NO; call, the touch events stop coming altogether as soon as the table view is scrolled even a little bit.
Second approach: I subclass a UIView, set it's background color to transparent, and then place it over top of the view containing the UITableView. In this overlay subclass, I override the touch events and 1) pass them on to the underlying UITableView and then 2) pass the touch events on to the underlying UIView that handles the left-right swiping. With the approach, the left-right panel movement works perfectly. With the table view, unfortunately, the passed-through touch events allow me to click the table view and change the selected row (so I know the events are at least partially going through), but I can't scroll the table view up or down.
Any suggestions for how to do this correctly are welcome.
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.
This is more of a check as I believe this is right but its a lot of work if I'm wrong.
I want to basically achieve fixed positioning with a scrollView. I want to have a list along the top that is always visible, scrolls horizontal only and then a scrollview beneath that to move around the information which scrolls both vertically and horizontally.
I figure I need to subclass UIScrollView and overwrite touchesBegan, touchesMoved and touchesEnded to send the touch to both UIScrollViews.
Is this right or off track?
Cheers
Overriding the touch events on a scroll view is probably not what you want to do. Instead you can simply use a single scroll view, and then in the parent view's -layoutSubviews or in the scroll view's delegate methods you can move the list so it's always at the same vertical position (use the scroll view's contentOffset property to determine where that should be). Both the delegate method and -layoutSubviews is called before the drawing actually occurs after the scroll view scrolls, so by always repositioning your view where you want it to be, it will appear to remain fixed to the user.
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.