I am getting some Images from the API and i don't know the number and now i want to test the UI in Android through Appium and i want to scroll down to the Last image. How can I do this and also I don't know the what the title from the API is coming so that I can ScrollTo("Title") and also i am not able to swipe to the last. Is there anyway?
There is no way to know for sure whether you've scrolled to the last using appium because there is no UI reporting for the edges of a scrollview.
One way to know that you've reached the end of a scroll view without relying on devs is to compare the list of all children of the scrollview every time you swipe. If all children are exactly the same, you've reached the end. An example xpath for this would look like //android.widget.View[#content-desc="Your scrollview]//*, which would grab all children and descendants. Once you have a list to compare, check the content of all children nodes. This will only work if there's something unique in these items. If all items are completely general, there will be nothing to compare and this won't be reliable. Ask devs to add content descriptions or accessibility data to the items if possible.
Another option would be to have the devs embed a uniquely id'd invisible view at the top and bottom of the scrollview. That way, if it can be found by the driver, you know that you've reached the very edge of the view. If there are already unique elements at the edges of your scrollview, you can use those.
In the end, the devs of the application can really help out the process of scrolling, but hopefully the trick of comparing the current scrollview's children can help you.
You can use the screen dimensions to scroll down:
public void scrollDown() {
Dimension size = driver.manage().window().getSize();
int x = size.getWidth() / 2;
int starty = (int) (size.getHeight() * 0.60);
int endy = (int) (size.getHeight() * 0.10);
driver.swipe(x, starty, x, endy, 2000);
}
You can store all the images into a list using its available locator. Then use driver.scrollToExact(list.get(list.size()).getAttribute("name"));
Example:
List<mobileElement> images = driver.findElementsByClass("<locator>");
driver.scrollToExact(images.get(images.size()).getAttribute("name"));
or
driver.scrollToExact(images.get(images.size()).getText());
#Test
public void testScroll()throws Exception
{
for(int i=0;i<4;i++)
{
Thread.sleep(2000);
if (driver.findElement(By.name("end_item")).isDisplayed())
{
driver.findElement(By.name("end_item")).click();
break;
}
else
{
horizontalScroll();
}
}
}
public void verticalScroll()
{
size=driver.manage().window().getSize();
int y_start=(int)(size.height*0.60);
int y_end=(int)(size.height*0.30);
int x=size.width/2;
driver.swipe(x,y_start,x,y_end,4000);
}
The above example works with vertical scroll and it is based on the example given at this blog for horizontal scroll
http://qaautomated.blogspot.in/2016/02/how-to-do-horizontal-scroll-in-appium.html
I hope this works for you.
To do this you must know resource id or cont-desc of scrollable element. You also need to know className of your scrollable element.
If you have cont-desc in scrollable list
try {
String scrollableList="your con-desc of scrollable List";
String elementClassName="android.something.something";
String anyText="any text";
driver.findElement(MobileBy.AndroidUIAutomator(
"new UiScrollable(new UiSelector().description(\"" + scrollableList + "\")).getChildByText("
+ "new UiSelector().className(\"" + elementClassName + "\"), \"" + anytext + "\")"));
}catch (Exception e){
System.out.println("Cannot scroll further");
}
If you have resource-id in scrollable list
try {
String scrollableList="your con-desc of scrollable List";
String elementClassName="android.something.something";
String anyText="any text";
driver.findElement(MobileBy.AndroidUIAutomator(
"new UiScrollable(new UiSelector().resourceId(\"" + scrollableList + "\")).getChildByText("
+ "new UiSelector().className(\"" + elementClassName + "\"), \"" + anytext + "\")"));
}catch (Exception e){
System.out.println("Cannot scroll further");
}
If the screen cannot be scroll further it will throw error which will be catched by catch block.
Related
This function is my function
private void previewCapturedImage(){
Log.d("ChildCount", "content child count before:" + mSelectedImagesContainer.getChildCount());
mSelectedImagesContainer.removeAllViews();
Log.d("ChildCount", "content child count after:" + mSelectedImagesContainer.getChildCount());
Iterator<Uri> iterator = mMedia.iterator();
ImageInternalFetcher imageFetcher = new ImageInternalFetcher(this, 500);
while (iterator.hasNext()) {
Uri uri = iterator.next();
// showImage(uri);
Log.i(TAG, " uri: " + uri);
if (mMedia.size() >= 1) {
mSelectedImagesContainer.setVisibility(View.VISIBLE);
}
View imageHolder = LayoutInflater.from(this).inflate(R.layout.media_layout, null);
// View removeBtn = imageHolder.findViewById(R.id.remove_media);
// initRemoveBtn(removeBtn, imageHolder, uri);
ImageView thumbnail = (ImageView) imageHolder.findViewById(R.id.media_image);
if (!uri.toString().contains("content://")) {
// probably a relative uri
uri = Uri.fromFile(new File(uri.toString()));
}
imageFetcher.loadImage(uri, thumbnail);
mSelectedImagesContainer.addView(imageHolder);
// set the dimension to correctly
// show the image thumbnail.
int wdpx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 150, getResources().getDisplayMetrics());
int htpx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());
thumbnail.setLayoutParams(new FrameLayout.LayoutParams(wdpx, htpx));
}
}
In the second line mSelectedImagesContainer.removeAllViews(), I am trying to clear the view of all existing children views. but it is not working as expected.
So basically this parent container mSelectedImagesContainer has a horizonal list of images that was passed from one more activity.
Also the output of the logging is accurate, it clears all the childviews but for some reason main activity still shows the old images that were previously selected in the viewgroup.
If anything else is needed please let me know. I have not posted the full code since it's quite large. Anyways, if needed I can post it here with the XML's.
Just an info, I am working on a poly-clicker library, for the image picker and a custom scroll view for images.
Screenshots
1) Here I selected 2 images
2) And these images displayed perfectly in the scroll view
3) Now i selected a different set of images i.stack.imgur.com/sw5hz.jpg
4) However, the first selection is still not cleared from the view i.stack.imgur.com/lKovI.jpg
Answer posted in comments by #Shaishav, where the iterator was passed with a hashset which needed to be cleared, so reinitializing the variable "mMedia" did the job.
I am trying to put a link on a textview, but when I click this link the application breaks!! This is my code:
final TextView msg = (TextView)view_aux.findViewById(R.id.accordion_msg);
msg.setText(Html.fromHtml(dbStructure.getMsg()));
msg.setTypeface(tF);
msg.setTextColor(Color.DKGRAY);
msg.setMovementMethod(LinkMovementMethod.getInstance());
Where dbStructure.getMsg() returns a String. This String could be something like:
< a href="/reference/android/widget/RelativeLayout.html">RelativeLayout< /a>
lets child views specify their position relative to the parent view or to each other (specified by ID). So you can align two elements by right border, or make one below another, centered in the screen, centered left, and so on.
It seems nice, but the app stops when I press it.
EDIT
The error thrown ActivityNotFoundException.
the link you are trying to open is broken
/reference/android/widget/RelativeLayout.html
there is nothing corresponding to the above link.
replace it with the proper url like this
http://developer.android.com/reference/android/widget/RelativeLayout.html
Thank you very much for every one... the problem is (as #Antonio #danidee #TheRedFox and #Arslan say) the format of the url... it doesn´t start with http.
With permission from you all, I am going to answer my own question:
final TextView msg = (TextView)view_aux.findViewById(R.id.accordion_msg);
String msg_text = dbStructure.getMsg();
if(msg_text.contains("href=\"")) {
String[] msg_aux = msg_text.split("<a href=\"");
if (!msg_aux[1].toLowerCase().startsWith("http"))
msg_aux[1] = "href=\"http://" + msg_aux[1];
else
msg_aux[1] = "href=\"" + msg_aux[1];
msg_text = msg_aux[0] + msg_aux[1];
}
msg.setText(Html.fromHtml(msg_text));
msg.setTypeface(tF);
msg.setTextColor(Color.DKGRAY);
msg.setMovementMethod(LinkMovementMethod.getInstance());
Thank you.
EDIT on the code, these lines:
else
msg_aux[1] = "href=\"" + msg_aux[1];
I have a couple of EditTexts arranged on rows and columns.Those EditTexts contain product name,quantity and price and a TextView that shows the total in real time(calculates it each time you write on one of the EditTexts)
I've setup a a button on each row that when clicked sets visibility of the row(3EditTexts for product name,price and quantity) to GONE.
My problem is that after i set the visibility to GONE,though there are no more EditTexts it still calculates their values from before being GONE.
My question now is,what happens when the EditTexts are set to visibility.GONE ?
My app calculates in real time,so when something happens to an EditText,he calculates again..but it's like the values are still there...Isn't this supposed to be the difference between invisible and gone ?
I'll show you the way i calculate(it is called even after you press the X button to erase the EditTexts,not only when you change values inside EditTexts)
public void calculeaza() {
totaltest = 0;
prod = new String[allprod.size()];
pret = new String[allpret.size()];
cant = new String[allcant.size()];
for (int m = 0; m < allprod.size(); m++) {
prod[m] = allprod.get(m).getText().toString();
if (prod[m].matches("")) {
prod[m] = " - ";
}
}
for (int j = 0; j < allcant.size(); j++) {
cant[j] = allcant.get(j).getText().toString();
if (cant[j].matches("")) {
cant[j] = Float.toString(0);
}
}
for (int k = 0; k < allpret.size(); k++) {
pret[k] = allpret.get(k).getText().toString();
if (pret[k].matches("")) {
pret[k] = Float.toString(0);
}
}
for (int l = 0; l < allpret.size(); l++) {
Float temp = Float.parseFloat(cant[l]) * Float.parseFloat(pret[l]);
totaltest = totaltest + temp;
TextView totalf = (TextView) findViewById(R.id.total);
totalf.setText(String.format("Total: %.2f", totaltest));
}
}
Lines Straight from Android dev site..
View.GONE This view is invisible, and it doesn't take any space for layout purposes.
View.INVISIBLE This view is invisible, but it still takes up space for layout purposes.
i.e it retains EditText object even after Gone..
You can reinitialise edittext if you dont want it to retain its value...or setText = ""
Above quoted is the only difference...
Hope this helps...
I'm not really seeing in the code you posted anything I can use to answer this question, but there does appear to be some confusion as to what setVisibility does:
INVISIBLE elements are not seen on the page, but they still take up space (there's a hole where they would be)
GONE elements have no visible effect on the screen, from the user's perspective they aren't there. However they are still part of the view.
If you want to remove the object from the view, then you need to call removeView() on its parent.
It may still take up memory after it has been removed from the view, in case your code has kept references to it in any variables.
It may still take up memory after there are no further references to it, at least until the garbage collector gets around to it.
I'm hoping the rather generalized statements above help clarify the situation.
I have a 10-field average lap calculator. However, in testing, someone said they normally only run X laps in practice, vs. 10 (let's say 7).
I think I could use an if statement, but there'd be at least 10 of them and a bunch of clumsy code, and I'm not sure on arrays/switch statements exactly. I think all of those might be possible, but my low level of experience has yet to fully comprehend these useful tools.
CURRENT CODE:
double tenLapAvgVar = ((lap1Var + lap2Var + lap3Var + lap4Var + lap5Var + lap6Var + lap7Var + lap8Var + lap9Var + lap10Var) / 10);
So essentially, if someone leaves a field or fields blank, I want to calculate the average based on the populated fields, not 10 (if they leave 3 fields blank, calculate based on 7, for instance). Any help you guys could provide would be much appreciated, thanks!
You could have an ArrayList<EditText> object and a method which iterates over it and adds up the values. Something like:
public double getLapAverage()
{
int noOfCompletedLaps = 0;
double lapAve = 0;
double lapsTotal = 0;
for(EditText text : textBoxes)
{
if(text.getText().toString().length() > 0)
{
//psuedo code, and assuming text is numerical
lapsTotal += Double.parse(text.getText().toString());
noOfCompletedLaps++;
}
}
if( noOfCompletedLaps > 0)
{
lapAve = lapsTotal / noOfCompletedLaps;
}
return lapAve;
}
Maybe it would be better if you used an array instead of 10 different variables.
Then you can use a for statement and initialize them to 0, afterwords let the user fill the array and count how many are not zero.
Finally sum up all the array and divide by the count you previously calculated.
I have in my layout.xml a TextView with "id = txtLog".
Where do the test results from my application using:
Log.i("Result:", "Value of x = " + x);
for show result in LogCat.
It is possible to show these results "Log.i" within the TextView?
Note: I left a space at the bottom of my application to show the TextView.
Like a console.
I would like to display these messages on TextView.
If possible create a scroll bar and display every time I use Log.i
I am a beginner, do not know if it is possible. Yet thanks.
I would think
myTextView.setText(myTextView.getText() + "Value of x = " + x + "\n");
would work.
EDIT:
Also, to make the TextView scrollable, you need to set a movement method like so:
myTextView.setMovementMethod(new ScrollingMovementMethod());
EDIT 2:
If you want the information to go to both Log.i and a TextView, then you need a method that holds a reference to the TextView you want to update.
public static void LogToView(TextView myTextView, String title, String message) {
Log.i(title, message);
myTextView.setText(myTextView.getText() + title + ": Value of x = " + x + "\n");
}
Put that in whatever class or in your Activity class. Use it instead of Log.i and the message will be passed to both.