SwiftUI XCTest - How to increase velocity of scrolling? - swift

I wrote a method that allows me to scroll list of elements on the screen for UI testing:
func scrollToElement(element: XCUIElement, maxScrolls: Int = 10) {
var numberOfScrolls = 0
while !element.isHittable, numberOfScrolls < maxScrolls {
app.swipeUp()
numberOfScrolls += 1
}
}
Everything works fine but it takes too much time for the UI test to verify ie. wait until every scrolled view will be checked whether the element is available.
Is there any possible method or way to increase the velocity of scrolling?
Thanks in advance!

Related

Unity - How to scroll a scrollbar for a ScrollRect smoothly?

I have a ScrollRect to which I add content to. When it reaches the point where the content is longer than the ScrollRect (ie when the ScrollBar's value changes from 0), I want the ScrollRect to scroll all the way down (I do this by tweening the ScrollBar's value until it reaches 0). However, my problem is that I can't figure out how to do this smoothly over time.
Here's my code snippet:
public void Update() {
if (scrollbar.size < 1 || scrollbar.value > 0) {
LeanTween.value(scrollbar.value, 0, duration).setOnUpdate((float val) => {
if (scrollbar.value == 0) {
LeanTween.cancel(this.gameObject);
} else {
scrollbar.value = val / scrollAdjustment;
}
});
}
}
I tried using "Time.deltaTime" and "Time.time" in place of duration and it did not seem to matter. Here's a gif of what happens:
(In this example, I used "duration" that had the value of 5 (the idea was to have the transition take 5 seconds) and "scrollAdjustment" was 50 but it did not seem to matter what I set either of these values to.
You can see it instantly snaps to the bottom. I'd like this to be a smooth transition. Any help is appreciated!
My settings:
Then here is me scrolling with my mouse wheel while the autoscroll feature is turned off (because I'm using Rewired, I am intercepting an input called "ZoomIn" and "ZoomOut" and add "0.01f * scrollSpeed" (where scrollSpeed is 15 in this case):
You shouldn't need to add any additional code to make the scroll bar function as the way you want it to. Try deactivating your script and mess with your scroll bar. Make sure you have your Number Of Steps On Your Scrollbar Component as 0 to make it smooth. If it's still not working, send some screenshots of your scroll gameobject to see if the rect is the problem or something else.

Call a method in scrollViewDidScroll with low frequency

I have a method that manage constraints, while some conditions are met. That method is placed inside scrollViewDidScroll methood:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
partiallyHideOverallViewOnScrolling(scrollView)
scrollToNewRowsIfNeeded()
}
Recently I discover freezes and weird behaviour while scrolling table, is there are possibility to call method inside scrollViewDidScroll no more then, for example, every 0.1 second?
It appears that method called 111 times on single drag down, when there is not much items in a tableView, that's quite a lot
even though Dogan Altinbas's comment suggesting to use scrollViewWillBeginDragging and scrollViewWillEndDragging sounds like the right approach to me I'd like to answer your question.
Just a quick example I created in a playground:
import UIKit
var date = Date()
while (true) {
if Date().timeIntervalSince(date) > 1 {
print("foo")
date = Date()
}
}
You'll see it'll only print once per second. I just remember the last time I fired the event I wanted to fire and go from there.
Cheers,
Dominic

In Unity, how to detect if window is being resized and if window has stopped resizing

I wanted my UI to not resize when user is still resizing the game (holding click in the window border) and only when the user has released the mouse the resize event will trigger.
I have tried to achieve it on Unity but so far I only able to detect windows size change, which my script checked every 0.5 second and if detected change it will resize the UI. But of course resizing everything caused a heavy lag, so resizing every 0.5 second is not a good option but resizing every 1 second is not a good idea either because 1 second is considered too long.
The question might be too broad but I have specified the problem as small as possible, how do I detect if user is still resizing the window? And how do I detect if user has stopped resizing the window (stop holding click at window border)?
You can't tell when someone stops dragging a window, unless you want to code a low level solution for ever desktop environment and every operating system.
Here's what worked for me with any MonoBehavior class, using the OnRectTransformDimensionsChange event:
public class StackOverflow : MonoBehaviour
{
private const float TimeBetweenScreenChangeCalculations = 0.5f;
private float _lastScreenChangeCalculationTime = 0;
private void Awake()
{
_lastScreenChangeCalculationTime = Time.time;
}
private void OnRectTransformDimensionsChange()
{
if (Time.time - _lastScreenChangeCalculationTime < TimeBetweenScreenChangeCalculations)
return;
_lastScreenChangeCalculationTime = Time.time;
Debug.Log($"Window dimensions changed to {Screen.width}x{Screen.height}");
}
}
I have some good news - sort of.
When the user resizes the window on Mac or PC,
Unity will AUTOMATICALLY re-layout everything.
BUT in fact ONLY when the user is "finished" resizing the Mac/PC window.
I believe that is what the OP is asking for - so the good news, what the OP is asking for is quite automatic.
However. A huge problem in Unity is Unity does not smoothly resize elements as the user is dragging the mouse to expand the Mac/PC window.
I have never found a solution to that problem. (A poor solution often mentioned is to check the size of the window every frame; that seems to be about the only approach.)
Again interestingly, what the OP mentions
" ..and if window has stopped resizing .."
is automatically done in Unity; in fact do nothing to achieve that.
I needed something like this for re generating a line chart, but as it has too many elements, it would be heavy to do it on every update, so I came up with this, which for me worked well:
public class ToRunOnResize : MonoBehaviour
{
private float screenWidth;
private bool screenStartedResizing = false;
private int updateCounter = 0;
private int numberOfUpdatesToRunXFunction = 15; // The number of frames you want your function to run after, (usually 60 per second, so 15 would be .25 seconds)
void Start()
{
screenWidth = Screen.width; // Identifies the screen width
}
private void Update()
{
if (Screen.width != screenWidth) // This will be run and repeated while you resize your screen
{
updateCounter = 0; // This will set 0 on every update, so the counter is reset until you release the resizing.
screenStartedResizing = true; // This lets the application know when to start counting the # of updates after you stopped resizing.
screenWidth = Screen.width;
}
if (screenStartedResizing)
{
updateCounter += 1; // This will count the updates until it gets to the numberOfUpdatesToRunXFunction
}
if (updateCounter == numberOfUpdatesToRunXFunction && screenStartedResizing)
{ // Finally we make the counter stop and run the code, in my case I use it for re-rendering a line chart.
screenStartedResizing = false;
// my re-rendering code...
// my re-rendering code...
}
}
}

Score Multiplier in Swift

I have an application that adds one to the score whenever you tap anywhere on the view. I would like to have a score multiplier that states that whenever the user is tapping faster his or her score will not just increment by one, but by a larger amount depending on how fast and/or how long they have been tapping. I've done a good bit of Googling but I have yet to find anything. Thanks in advance
Without further examples its hard to actually give you help, here is a stab
static let multiplier = 1000
struct Player {
var score: Int
var displayScore: Int {
return score * multiplier
}
}
var player = Player(score: 1)
print(player.displayScore) // 1000
player.score += 1
print(player.displayScore) // 2000

Stage scaling affecting AS3

I have some code that controls a serious of images to produce and 360 spin when dragging mouseX axis. This all worked fine with the code I have used.
I have since had to design for different platform and enlarge the size of the stage i did this by scale to stage check box in the document settings.
While the mouse down is in action the spin works fine dragging through the images as intended but when you you release and start to drag again it doesn't remember the last frame and jumps to another frame before dragging fine again? Why is it jumping like this when all I have done is change the scale of everything?
please see code use to
//ROTATION OF CONTROL BODY X
spinX_mc.stop();
var spinX_mc:MovieClip;
var offsetFrame:int = spinX_mc.currentFrame;
var offsetX:Number = 0;
var percent:Number = 0;
//Listeners
spinX_mc.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
spinX_mc.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
function startDragging(e:MouseEvent):void
{
// start listening for mouse movement
spinX_mc.addEventListener(MouseEvent.MOUSE_MOVE,drag);
offsetX = stage.mouseX;
}
function stopDragging(e:MouseEvent):void
{
("stopDrag")
// STOP listening for mouse movement
spinX_mc.removeEventListener(MouseEvent.MOUSE_MOVE,drag);
// save the current frame number;
offsetFrame = spinX_mc.currentFrame;
removeEventListener(MouseEvent.MOUSE_DOWN, startDragging);
}
// this function is called continuously while the mouse is being dragged
function drag(e:MouseEvent):void
{
trace ("Drag")
// work out how far the mouse has been dragged, relative to the width of the spinX_mc
// value between -1 and +1
percent = (mouseX - offsetX) / spinX_mc.width;
// trace(percent);
// work out which frame to go to. offsetFrame is the frame we started from
var frame:int = Math.round(percent * spinX_mc.totalFrames) + offsetFrame;
// reset when hitting the END of the spinX_mc timeline
while (frame > spinX_mc.totalFrames)
{
frame -= spinX_mc.totalFrames;
}
// reset when hitting the START of the spinX_mc timeline
while (frame <= 0)
{
frame += spinX_mc.totalFrames;
}
// go to the correct frame
spinX_mc.gotoAndStop(frame);
}
By changing
spinX_mc.addEventListener(MouseEvent.MOUSE_MOVE,drag);
offsetX = stage.mouseX;
to
spinX_mc.addEventListener(MouseEvent.MOUSE_MOVE,drag);
offsetX = mouseX;
I seem to of solved the problem and everything runs smoothly again.