I've began iOS development recently and have created a basic layout using Interface Builder. However, I've noticed that my UIScrollView is causing my UITextField and UIButton to be unclickable (up to a certain point).
Here is a screenshot. Everything above the red line is clickable and responds to touch events, but everything below is/does not.
I decided to move my UIScrollView down a few pixels, and noticed this "red line" moved down as well. After shrinking the height of the UIScrollView from 589px to 550px, I am now able to click anywhere on the button/in the text field (since the theoretical "red line" is now just below the button). Here is that screenshot:
So, my question is, why was the UIScrollView doing this to my UITextField and UIButton? It seems as though it was overlapping the text field and button somehow, despite it appearing to be physically below them. Is there any way to avoid this "overlap" without having to sacrifice those 39 pixels I gave up to prevent the "overlap"?
Write this code in viewDidLoad function
[self.view sendSubviewToBack:scrolView];
Hope this helps you..
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
Whenever I tap on my UITextView on my testing device, the text is pushed far to the right as demonstrated in the gif below.
I can't see why this behaviour is happening, within my Storyboard I have tried to disable scrolling and have applied constraints to ensure that the width of the UITextView is only ever the width of the device, yet this still happens. The UITextView has not been subclassed or had any additional attributes applied to it via code.
If anybody has had this problem before it would be great to get some insight around how I could remedy it.
EDIT Constraints for the text view.
I'm trying to make UIMenuController to display copy&paste menu when the UITextView got long pressed. It works if there is only one UITextView on the screen. However, if there are multiple UITextViews on the screen, long press on the active UITextView (The one is the firstResponder) triggers magnifying glass to be shown, when finger is released, the copy&paste menu is displayed, however, the menu is dismissed automatically in less than one second.
The following is the view hierarchy:
UIView -> UIImageView -> MyUIView -> UITextView
|__> MyUIView -> UITextView
I set userInteractionEnabled and editable of non-active UITextViews to NO. Any idea on how to make the copy&paste menu stay?
I am using Xcode 4.6.3 and test it on iPhone 4S with iOS 7.0
Apparently, whenever there's a change in firstResponder, UIMenuController gets dismissed!
In order to track the source of the change, if other, you can listen to UIMenuControllerWillHideMenuNotification and check who's dismissing the menu.
I found a solution. I didn't have enough details in the question, that's probably why there was no answers.
The key missing piece is that I subclassed UITextView and it overrides layoutSubviews (see buggy margin behavior with dynamically resizing UITextView). The solution is simply removing layoutSubviews function, and I used krafter's suggestion to address UITextView cut off issue.
I have a strange problem. The designers provided me with a design (no change possible) that puts a button quite near a slider.
For the sake of explanation, let's talk about left side.
The button only registers the tap from approx. two thirds of its width from the left. If I tap further to the right, the tap is registered in the slider.`
Even if I change the Z order of those controls in IB, it still happens.
Why and what would be the solution to make the whole area of the button register the tap for itself?
You should respect the Apple HCI guidelines, they are there for a reason. Have a word with the designers ;-j
I've got an app where I allow the user to add events to a list. The method I use to do this is via a form that I show the user in a UIPopOver.
The form has the following components (in this order, top to bottom):
Event Description Label (UILabel)
Event Description (UITextField)
Event Details Label (UILabel)
Event Details (UITextView)
Event Time Label (UILabel)
Event Time (UIDatePicker)
Save Event (Custom Button)
Cancel (Custom Button)
I'd prefer not to show a screen shot since it's a sensitive app. :-)
So........
All is well when I first show the UIPopOver. Everything appears as I wish. The overall layout is about 650 pixels tall, which is just tall enough to take up pretty much the whole screen (vertically) when in landscape mode.
When the user tries to interact with the `UIDatePicker`, everything goes swimmingly (well).
When the user taps into the Event Description (`UITextField`) field, the keyboard appears and the `UIPopOver` shrinks so that basically the `UIDatePicker` and buttons are hidden. I consider this OK, since they re-appear when the keyboard is dismissed.
The problem I am having is when the user tries to interact with the `UITextView`:
When the view of the `UIPopOver` has its `backgroundColor` property set to `[UIColor whiteColor]`, the `UITextView` initially appears with a thin black border. I like this.
When the user taps in the `UITextView` to begin editing, the `UIPopOver` resizes to accommodate the keyboard and, during the transition, the black border "shrinks up" and disappears. This is in spite of my shocks and struts being set so that all dimensions/directions are fixed and it is "glued" to the top-left.
Following this, when the user dismisses the keyboard, the border sort of restores itself to its previous position, but it now adds a thick black border on the bottom that completely obscures the label placed between the `UITextView` and the `UIDatePicker`.
When I change the background of the view of the `UIPopOver` to "`ScrollView` Textured Background Color", the border "disappearing trick" is at least less noticeable, but the black border at the bottom (following keyboard dismissal) is still present.
Questions
Has anyone encountered something like this before?
Does anyone think it's just an IB error and that I need to re-build my XIB?
Anybody got any other ideas? Googling for this issue came up fairly empty for me. If you think of better terms and find something, please let me know (gently).
Boy, I'm a stupid stupid!!! It turns out I had forgotten that I placed the UITextView inside of a UIView (inset 1 pixel on all sides) and set the background of the UIView to be black so that I could get a border effect on the UITextView. Once I remembered that, setting the shocks/struts of THAT UIView turned out to be the solution.
Sorry for wasting your time!