iOS 13 Voice Control UIScrollView - ios

The iOS13 Voice Control feature has a command 'Scroll Down'. This command works for UITableViews but does not seem to work for UIScrollViews with scrollable content.
Is this intended?
Intended or not, is there a way to enable this command to work on a UIScrollView?
Example: a UILabel with a lot of text inside a UIScrollView (constraints are correct - it scrolls and is acknowledged by Voice Over saying 'Page 1 of 3' when active)

This command works for UITableViews but does not seem to work for UIScrollViews with scrollable content.
... only if this content is a huge UILabel content that must be scrollable: add many other elements (sliders, buttons...) and you'll notice that scrolling is enabled.
About that, in the TextKit Best Practices (2018 WWDC video), it's highly recommended to use a UITextView for this purpose:
Is there a way to enable this command to work on a UIScrollView?
Switch the label and your scroll view for a text view instead to make the Voice Control feature work with your specific use case.
Otherwise, it works with many other elements different from UILabel: the scroll view knows its content size and when it has to scroll down/up but the Voice Control feature doesn't recognize the label content as an element to directly interact with inside a scroll view.
I tested with a button and a huge UILabel as you did:
Scroll down that worked to reach the end of my label.
Scroll up that never works.
The label seems to be a kind of empty box that Voice Control ignores in a scroll view: to enable this command in a scroll view, just replace your label by a text view.
Now, if your use case is a single UILabel in a UIScrollView, remove them to display a UITextView instead.
EDIT
Here's the Xcode screenshot to make the UITextView scrolling work with the VoiceControl feature:
... with the results hereunder:
As you can notice, this is just a blank project with a simple text view: iOS recognizes this single element and acts as desired when Scroll down and Scroll up are vocalized.

Related

XCUITests: Can't tap element on scrollview while views are stack on each other

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

Custom Page Control with Paging Scrollview

Instead of the standard dots that Apple provides for a page control, I want to have something like this. However I don't want it to be in an infinite loop were you can circle around. All I care about is the scrollable text on top, not the parallax image.
Currently I have a paging scrollview that contains three view controllers so my custom page control will have only three words: Main, Today, Settings.
The way I see this being built is the following:
Subclass UIView and insert three UIButton's and evenly space them. The title of the buttons will be Main, Today, Settings.
Insert this UIView as child of scrollview (or maybe not)
Make UIView the width of the iPhone screen
Not sure about here now -> as you scroll the scrollview shift the UIView on and off the screen so that the UIButton will be centered in one of the view controllers in the scrollview.
Am I on right track or does anyone have a demo to this?
Yes. You are on right track. You can use scrollView for this exact purpose. You have to make use of scrollViewDelegate methods for this. The below link will explain you how to do that.
How to make Paging with scrollView.

iOS8 When using VoiceOver content of the collection view is scrolled to beginning

I have simple collection view created programmatically with build in horizontal layout and 50 items. When I enable VoiceOver to speak content of each cell, scroll position is changed to beginning on first item.
I would like to preserve scroll position. Am I missing something when VoiceOver is enabled?
With voice over disabled it works without issues.
Good to mention it works without issues on iOS7. I am using xcode 6.

How can I make/program a UIlabel to scroll horizontally upon user input?

I'm making a simple calculator in iOS, and I want the user to be able to scroll the label horizontally when the end gets truncated.
How would I go about doing this? My original idea was to make two buttons that would move the label left or right by using stringpadtoLength type of method, but that seemed inefficient.
I see two ways of building this.
Use a UITextView and always return NO from -textFieldShouldBeginEditing:. This should get you 90% the way there very fast.
Build a custom control using a UIScrollView which contains a UILabel that uses -sizeToFit. This will be a bit more work, but will do exactly what you expect.
I went for Jefferey's second suggestion because I thought it would give a "cleaner" result. Turns out, it's not that easy to implement. Here's what you have to be careful about when you're putting a single-line UILabel inside of UIScrollView, in order to be able to scroll horizontally through the text.
The parent UIViewController should have the box "Adjust scroll view
insets" unchecked. If you forget this your text may be placed below the content of the UIScrollView, meaning that you can only see it if you hold it while over-scrolling down.
Call [self.toolboxItemNameLabel sizeToFit]; in your UIViewController's viewDidLoad in order to set the right size for your UILabel. This ensures that the scrolling is comfortable, going from the left to the right of the text.
When using autolayout, you must add constraints for the leading and trailing space to container of the UILabel which is inside of the UIScrollView. Thanks to this great post for the answer.

How to ensure that only a certain section of a UIScrollView appears to slide?

I use a UIScrollView that has horizontal sliding enabled.
The Heading of the scroll view is Instructions for Using this App
And below that, I have instructions, one instruction per "page".
When the user scrolls horizontally, new instructions show. However, during this horizontal scrolling, the "Instructions for Using this App" from the second page also appears to move.
Instructions for Using this App <--- I do not want this to appear to slide
1. Instruction number 1. XYZ...
more text more text more text
more text more text more text <--- I want only this to slide
How to achieve this?
You can place separate UIView (probably UILabel in your case) on top of your UIScrollView, so your UI hierarchy will be something like:
UIView (screen)
UILabel (header)
UIScrollView (scrolled content)

Resources