I'm making an App for iPad.
But I faced some troubles because of Touch Event of ScrollView.
I have tried with iphone sample code [link], but I can't get what I want through this sample.
The reason is that my app is only for iPad.
I add my sketchy pic.
-- image link : https://lh5.googleusercontent.com/-x7TsXmxv1XU/TsYSkEh-3VI/AAAAAAAAAB8/ECn3MjiFF6Y/s512/IMG_20111118_170519.jpg
I add UIScrollView on ViewController, and add UIViews on this UIScrollView.
UIViews on this UIScrollView must be hidden outside of UIScrollView. But can't be hidden. #.#
And I can't use touch event on UIScrollView - left and right.
What I want is how to use touch event on scroll view.
I searched about this in Stack Overflow and google.
I could find many articles, but unfortunately I can't understand clearly.
Please explain me more easily. I'm a beginner programmer.
make your scrollview to clip subviews by it's bounds:
scrollView.clipToBounds = YES;
this will resolve your "un-hidden views" issue
Related
Sample Project
This is a sample project that showing the issue. It's storyboard based, but method of building interface doesn't matter. It's UIViewController with UIScrollView for entire screen and 128 pts height view that is on top of this UIScrollView.
Inside scroll view there is an UIView that has 2000 pts height and UIButton in the center.
Initial State
After light scroll
At the bottom of UIScrollView
Link here: https://github.com/JakubMazur/UITestsDemo
Problem
I'm trying to tap this green button with XCUITest using app.buttons["Tap Me!"].tap()
XCUITest get identifiers from elements on screen for entire scroll view that works fine.
According to this reply on a thread on Apple Developer Forum written by Apple Framework Engineer I shouldn't scroll manually to get to the button and yes, this is partially true.
What is happening when code from (1) is executed is that button is scrolled just enough to be visible on screen but it's still not hittable, because other (purple view) is on top of UIScrollView
What is working
If I run a test written like this:
func testThatDoWorkButItsSlow() {
app.scrollViews.firstMatch.swipeUp()
app.buttons[buttonLabel].tap()
}
that is scrolling up and then looks for a button this will work, but it's slow and so inaccurate that is hardly usable.
What I cannot do
Disabling userInteractions on purple view. In real example I still need touches for this (purple) view.
Questions
Is there a way to use precise scrolling in XCTest for this case?
Or is there a way to set contentOffset scrollview to other value that will make this button more centered on a screen compared to action of tap()?
Or there is a way to fast scroll to the bottom (without animations) and maybe moving only up for each element?
My recommendation here would be to use the XCUICoordinate.press(forDuration:thenDragTo:) method to scroll.
https://developer.apple.com/documentation/xctest/xcuicoordinate/1615003-press
You can create a XCUICoordinate for the yellow view, then drag it slightly upwards to expose the button and make it hittable.
In most cases, the automatic scroll should work, but it seems like in this case a manual scroll/drag is necessary.
The UI Testing should replicate human interactions. You cannot expect from a human being to scroll "153px", you can just expect to "scroll until".
You can try something like :
while (!app.buttons["Tap Me!"].isHittable) {
app.swipeUp()
}
NB: You may also want to add a condition to leave the while loop if you can't find the button after a reasonable amount of attempts
I've been searching for a way to pin views/images to the top of a UIScrollView when scrolling. However the posts/articles I came across are not in swift 3. I'm not sure if I'm typing my question in the web correctly. So my question is how can we achieve the same behavior as a UITableView or UICollectionView. When you scroll, a section will stick to the top until another section pushes it up. I'm wondering would we be able to use views/image and pin them at the top of the UIScrollView. Down below is a screenshot of a UIScrollView that has 4 views.
So when scrolling I would like to pin the first view/image to the top until another view/image pushes it. Also would it be possible to determine which view sticks to the top. So lets say I only want the red views to stick until another red view pushes it. Been looking for a way to achieve this type of behavior for a while now.
Please help, would really appreciate any help provided at this point. Thanks.
A few ways to do this, but you can use the scrollView delegate’s scrollViewDidScroll to capture the contentOffset and use a combination of the target view’s origin/center/transform properties to keep the view where you want it.
There’s a neat video explaining how to do this that Apple released during WWDC 2010, called something like “Advanced Scroll View Behavior”, if I remember correctly. It’s definitely worth a watch.
I've been reading similar posts all morning, but could not find an answer to my problem.
As title says, I have several UIButton-s in UIView that is a child of a UIScrollView. I set the contentSize for the scrollview, and I can scroll and see all contents of UIView, however, I cannot click any of the buttons that are not visible originally (buttons that are visible from the beginning work just fine).
I tried setting the frame of the child UIView, and interactions are enabled inn all views.
Anything else that I'm missing?
thank you!!!
I have a main menu with a list of buttons. On the bottom I have a bar that the user can flick up to the top via a scrollview. Whats underneath that bar however is a uiwebview. So when the user tries to scroll in the uiwebview, the bar and webview just snaps back down. Also, the uibuttons won't work when the bar is down because the scrollview is sitting over them. How do i make the scroll only work when the user touches the bar and make the buttons on my menu work when the bar is down?
Thanks in Advance!
Where you want the scrollView to "work" (maybe when user flicks the bar up) have the following code:
scrollView.userInteractionEnabled = YES;
and wherever you don't want the scrollView to register any user actions (like when the bar is down) just do the opposite and set it to NO.
So if I understand correctly, you want the UIScrollView to respond to touches in only a certain part of the frame (the bar)?
I would suggest taking a look at one of my previous answers to a similar problem, here.
In particular, see:
This answer to the SO question Touch and pull down a view. It uses the hitTest:withEvent: method to determine whether the scrollview responds to a touch or leaves it for the view under it to respond to.
This answer to the question Drag Down UIView in iOS 5 works in a similar way, using pointInside:withEvent: to make the UIScrollView only respond to touches in a given area.
This answer to the question Event handling for iOS - how hitTest:withEvent: and pointInside:withEvent: are related? gives a good overview of how hitTest:withEvent: and pointInside:withEvent: work together.
Hopefully i can explain this clearly. I have a UIWebView and I've added a UIToolbar to it's scrollView (another works [webView.scrollView addSubview:myToolbar];). So everything is fine and dandy until i try to pinch zoom that's when the toolbar stays in the corner of the screen, so basically it doesn't stay in the middle. If you haven't guessed already, I'm trying to make a duplicate of safari's behavior. I need to have the UIToolbar to not be affected by the pinch gesture. Any ideas on how to do this? I've read other posts but it doesn't seem to really give an answer. Any help is appreciated :)
You have to create a parent UIView, say rootV, in which you embed myToolbar at the top, and then webView.
This stops the pinching from affecting myToolbar, however this make it stick at the top, and not move beyond the screen when the user scrolls vertically myWebView.
To get the same behavior as Safari, you have to check the vertical scrolling in myWebView, and based on it you expand up or down the size of rootV. Assuming you fixed the height of myToolbar but made webView fill the rest, it should just work.