I started using Xamarin UI Test for my Automated tests nearly 9 months ago. Recent updates to the UI of the app I'm working on made it so the elements behind Appbar and Navbar are considered displayed on the screen, which leads to a Tap on the Appbar/Navbar and not the actual element, I asked the devs on my team if there's anything they can do but they couldn't change that weird behaviour from those 2 elements. I've been looking for a way to scroll an element to the center/middle of the view but in vain. Does anyone know how I can accomplish this centred scroll? or a solution for this issue?
Here's the code I usually use :
app.ScrollDownTo(x=>x.Id("Element ID"));
I use Appcenter to run my tests on multiple devices, this is the method I use when I encounter this problem, I can make it work for one device but it probably does not work on other screen sizes :
//I scroll little by little until I find my element
for( int i = 0; app.Query(x=>x.Id("Element ID")).length == 0 && i<10; i++){
//this code performs a very small scroll gesture
app.ScrollDown(x=>x.ClassFull("UIScrollView"));
}
Thanks a lot for your help.
Related
I have been working on figuring out what is going on with my game's UI for at least two days now, and no progress.
Note that this is a mobile game, but I was asked to build for Windows for visualization and presentation purpose.
So the problem is that when I run my game on the Unity Editor, Android, iOS and Mac platforms the UI works just perfect, but then when I run the game on Windows the UI still works fine UNTIL I load a specific scene.
This specific scene is a loading screen (between main menu and a level) when the level finished async loading, a method called MoveObjects is called in a script in the loading screen, to move some objects that where spawned in the loading screen scene into the level scene (this is not the issue though, since I already try without this method and the problem on the UI persist).
Once the logic of this MoveObjects method is done, a start button is enabled in the loading screen, for the player to click and start playing (I did try moving the start button to the level scene, since maybe it not been a child of the currently active scene could be the issue, but the problem still persist). Is at this point that the UI is partially broken, what I mean with this is, that I can see buttons (and some other UI elements like a scrollbar) changing color/state when the mouse moves over them, but I cannot click on them anymore (the button wont even change to the pressed state).
Also note that I tried creating a development build to see if there was any errors in the console, and I notice that this problem is also affecting the old UI system, so I was not able to interact with the development console anymore.
Also also, note that if I grab and drag the scrollbar before this issue appear, and I keep holding down on the scrollbar until this happens, the mouse gets stuck on the scrollbar, meaning that I cannot interact with the UI anymore, but the scrollbar will still move with the mouse.
I already check that this things are not the source of the problem:
Missing EventSystem, GraphicRaycaster or InputModule.
Another UI element blocking the rest of the UI.
Canvas is Screen Space - Overlay so there is no need for a camera reference.
I only have one EventSystem.
Time.timeScale is 1.
I am not sure what else I could try, so if anyone has any suggestions, I would appreciate it. Thanks.
P.S: I am sorry to say that I cannot share any code or visual material or examples due to the confidentiality.
A major source for a non-working UI for me has always been another (invisible) UI object blocking the raycast (a transparent Image, or a large Text object with raycast on).
Here's a snippet I put together based on info found elsewhere, I often use it to track objects that are masking the raycast in complex UI situations. Place the component on a text object, make sure it's at least few lines tall, as the results will be displayed one under another.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
[RequireComponent(typeof(Text))]
public class DebugShowUnderCursor : MonoBehaviour
{
Text text;
EventSystem eventSystem;
List<RaycastResult> list;
void Start()
{
eventSystem = EventSystem.current;
text = GetComponent<Text>();
text.raycastTarget=false;
}
public List<RaycastResult> RaycastMouse(){
PointerEventData pointerData = new PointerEventData (EventSystem.current) { pointerId = -1, };
pointerData.position = Input.mousePosition;
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(pointerData, results);
return results;
}
void Update()
{
list= RaycastMouse();
string objects="";
foreach ( RaycastResult result in list)
objects+=result.gameObject.name+"\n";
text.text = objects;
}
}
I am using xcode 8.3.3, swift, and XCTest. I am wondering what the best approach to handle scrolling is when you plan to run your tests against multiple simulators and have a list displayed. Since the screen size may change based on the simulator being used, the element you want to select to scroll up on may or may not be displayed.
If I have a list with x # of elements, how do I best approach which element to use to scroll the list up to have the next set of elements displayed on the screen so that the tests will run on multiple simulators of different screen sizes?
When we do "po XCUIApplication()" we see all the elements in the list, so in order to know which one is the last one displayed on the screen, we would have to look through each element and do a checked like isDisplayed or something to find the last element currently displayed ... but I was hoping there is a better approach?
If the element you want to use is displayed when you do po XCUIApplication() then you should just be able to tap() it without having to scroll it into view. The framework will handle the scrolling automatically if it can find the element.
Here is an article I wrote discussing how to use SBTUITestTunnel for scrolling:
https://rlukasik.medium.com/using-sbtuitesttunnel-for-scrolling-in-xcuitests-2e166440ca73
I'm going around in circles trying to solve this.
Basically I have a tab control on my Firemonkey android app and can swipe left or right to change tabs and it works fine.
I would like to enhance the swiping so it behaves more like the android app drawer. What I mean by that is if you longtap and slowly slide your finger left or right the screen contents moves left/right with your finger as opposed to what I have now where it only moves a whole screen at a time and not slowly underneath your finger.
A THorzScrollBox is close to the effect I want but it doesn't "snap" onto a single screen but instead can leave your screen half and half on two pages.
Am I making sense here?
I'm using XE8 but I couldn't get it working on earlier versions either!
Many thanks,
Ian.
If someone is interested i just created a new TTabcontrol who enhance the swiping
you can see the code source here
(svn) https://svn.code.sf.net/p/alcinoe/code/
and the demo is here :
(svn) https://svn.code.sf.net/p/alcinoe/code/demos/ALFmxControls
any remark will be welcome :)
i continue also my logic: create a suite of firemonkey control who are very fast to draw, independant of OpenGL and that don't work with the style (i find the style in firemonkey very inefficient and horribly complicated to maintain), so i create this tabcontrol as a descendant of Tcontrol and not as a descendant of TStyleControl.
i think it much (much) more simple to create the title (ie: button) of the tab myself with basic component like trectangle + ttext than updating the so complicated Stylebook for each plateform (ioe, android, windows, macos, etc)
if you compare the unit of my Tabcontrol (ALFmxTabControl.pas) with the unit of the delphi TabControl (Fmx.TabControl.pas) then you will see that i use 3.5x less line of code (1018 vs 3550), and less line of code = always better
please vote for this feature request here :
https://quality.embarcadero.com/browse/RSP-15576
Trying the THorzScrollBox.AniCalculations.SetTargets(...).
eg.
1.Open FMX.HorizontalScroll Sample : CPP\Mobile Snippets\HorizontalScroll
2.Add Form Event : OnResize
3.Write the code :
#include <FMX.InertialMovement.hpp>
void __fastcall THorizontalScrollForm::FormResize(TObject *Sender)
{
TAniCalculations::TTarget target[4];
// Set ths size and position of your slides.
Image1->SetBounds(0, 0, HorzScrollBox1->Width, HorzScrollBox1->Height);
Image2->SetBounds(HorzScrollBox1->Width, 0, HorzScrollBox1->Width, HorzScrollBox1->Height);
Image3->SetBounds(HorzScrollBox1->Width*2, 0, HorzScrollBox1->Width, HorzScrollBox1->Height);
Image4->SetBounds(HorzScrollBox1->Width*3, 0, HorzScrollBox1->Width, HorzScrollBox1->Height);
// Assign the check point(your slides' top-left conner).
target[0].TargetType = TAniCalculations::TTargetType::Other;
target[0].Point = TPointD(1, 0);
target[1].TargetType = TAniCalculations::TTargetType::Other;
target[1].Point = TPointD(HorzScrollBox1->Width, 0);
target[2].TargetType = TAniCalculations::TTargetType::Other;
target[2].Point = TPointD(HorzScrollBox1->Width*2, 0);
target[3].TargetType = TAniCalculations::TTargetType::Other;
target[3].Point = TPointD(HorzScrollBox1->Width*3, 0);
HorzScrollBox1->AniCalculations->SetTargets(target, 3);
}
I'm writing a simple dictionary app which gives suggestions for words as you type. The suggestions are displayed in a ListBox and each time the query changes, about 10 suggestions should appear.
Unfortunately, performance is low at the moment. It takes almost a second for the results to appear and I don't understand why. EQATEC Profiler shows that my methods are running smoothly. I've confirmed this by putting a Stopwatch around my code. I've also experimented with the number of suggestions, and performance does increase with fewer items.
This leads me to conclude that rendering the ListBox (which I presume happens outside of my methods) is to blame for the lack of performance.
Does rendering 10 items in a ListBox really take more than 250ms?
How can I quickly put a small number of words on the screen?
Edit:
The way I fill my ListBox is very straightforward. Is it the right way?
resultsListBox.Items.Clear();
foreach (string s in suggestions.Words)
{
resultsListBox.Items.Add(s);
}
resultsListBox.SelectedIndex = suggestions.MatchIndex;
What you see here is really it: default ListBox, String items, no templates. Do I violate one of these principals?
Ensure you have the item data template in a fixed sized container (grid).
Avoid/remove using complex converters, when the same information can be easily provided by the data object.
Avoid/remove nested structures, example listbox in a listbox item.
Strongly recommended to not use user control inside the data template.
Avoid/remove custom controls from the data template
The link below contains a demonstration of the ListBox performance in a simple project.
The project also shows an alternative (faster) way to display a list, using a Grid with Buttons. This list is not scrollable and therefore not a real solution.
http://www.mediafire.com/?jypcfm4cs3nvo5c
Remember to run the project on a device, because the emulator has very different performance. I've tested it on the Samsung Omnia 7.
It sounds like you're creating your own AutoCompleteBox. Is there a specific reason for not using the one in the Toolkit?
I would expect the time taken to update the listbox to be dependent upon: how you're updating it; the complexity of the listbox; and whatever-else is on the page.
In that you haven't provided details about any of these it could be possible that it will take this long.
Edit
As an alternative to the AutoCompleteBox (In theory you shouldn't need to scroll the results of this--just enter more characters to filter further.) I've done some experimentation and the following seems to work best. It uses a StackPanel inside a ScrollViewer and reuses the existing items, rather than creating new ones.
<ScrollViewer Height="629" Margin="0,139,0,0" Width="480">
<StackPanel Name="listBox1" />
</ScrollViewer>
cs:
private void InitializeResultsGrid()
{
...
for (int i = 0; i < 26; i++)
{
...
listBox1.Children.Add(new TextBlock());
and
private void SlowFill(string baseStr)
{
for (int i = 0; i < buttons.Count; i++)
{
(listBox1.Children[i] as TextBlock).Text = baseStr + (char)(i + 'a');
}
When I timed it, it was slightly slower than using the Grid but the performace seemed fine to me on an LG-E900
I want to persist the user's location in the document he or she is browsing, then bring them back to that spot when they return from tombstoning or between sessions.
My first approach was to wrap the browser component in a scrollviewer, but it turns out it handles its own scrolling and the scrollviewer never changes its verticaloffset.
My guess is that the browser component must have a scrollviewer or something like it embedded in it. I need to get the verticaloffset and scroll to an offset.
Any guesses how to get there?
My next approach would be a painful mish-mash of javascript and c# to figure out where they are...
Because of the way the WebBrowser control is built you'll need to track scrolling in Javascript then pass the location to managed code to handle storage of that value.
On resuming you'll need to have the managed code pass the scroll position to a Javascript function to reset the scroll position.
That's the theory but I haven't looked at the funcitonality around javascript scrolling events in the WebBrowser yet. That's the only place I can see possible problems.
Would be good to hear how you get on.
I've accepted Matt's answer, but I want to put in some details here. I'm also going to blog about how I did it once I'm completely done.
Since the WebBrowser component is essentially a black-box, you don't have as much control as I would like. Having said that, it is possible to get and set the vertical offset.
Javascript lets you ask for the value, but different browsers use different variations on HOW to ask. For THIS case I only have one browser to worry about.
First I make a couple of simple javascript functions:
function getVerticalOffset() {
return document.body.scrollTop;
}
function setVerticalOffset(offset) {
document.body.scrollTop = offset;
}
Next I call into the WebBrowser using the InvokeScript method on the browser object.
I'll post an update here with a link to my blog when I get the full write-up done.
I have been writing an eBook reader and had a similar question. Code for setting a scroll position has been easy enough to find.
Code for setting vertical scroll position:
string script = string.Format("window.scrollBy(0,{0});", "put your numeric value here");
wb_view.InvokeScript("eval", script);
Google didn't help much in finding solution for getting the value of current scroll position. Lacking any knowledge in javascript it took me almost two hours to get it right.
Code for getting the vertical scroll position:
var vScroll = wb_view.InvokeScript("eval",
"var vscroll = window.pageYOffset; vscroll.toString();");