Let's say that I have a WebView:
#Override
public void onPageFinished(WebView view, String url)
{
Log.d(TAG, "Finished: " + url);
super.onPageFinished(view, url);
Log.d(TAG, "webView.getContentHeight(): " + webView.getContentHeight());
Log.d(TAG, "webView.getHeight(): " + webView.getHeight());
Log.d(TAG, "view.getContentHeight(): " + view.getContentHeight());
}
where it returns:
webView.getContentHeight(): 4059
webView.getHeight(): 1746
Now, I'd like to chop off bottom 500 pixels of the web contents (e.g. 4059 px --> become 3559 px) while still maintaining it's viewable webview height 1746.
Could anyone give me an idea? I'd sincerely appreciate that!
John
Not sure what you're trying to accomplish - changing the "contentHeight" requires changing the content and re-loading the page.
So I assume you are trying to prevent the content from being seen, in which case you can override scrollTo and prevent the scroll from going past a specific margin of content like so:
int myMargin = 500;
Then:
#Override
public void scrollTo(int x, int y){
int maxScroll = webView.getContentHeight() - myMargin;
if (y > maxScroll) {
super.scrollTo(x, maxScroll);
} else {
super.scrollTo(x,y);
}
}
Related
How can I swipe scroll to bottom in an android app using appium?
I tried using
driver.swipe(300,800,300,500,2);
driver.scrollTo("string")
But above did not helped. Can anyone suggest me some generic solution ?
A generic solution will be scrolling using dimensions. use the below code
public void scroll() throws IOException {
try {
Dimension dimensions = driver.manage().window().getSize();
System.out.println("Size of screen= " +dimensions);
int Startpoint = (int) (dimensions.getHeight() * 0.5);
System.out.println("Size of scrollStart= " +Startpoint );
int scrollEnd = (int) (dimensions.getHeight() * 0.2);
System.out.println("Size of cscrollEnd= " + scrollEnd);
driver.swipe(0, Startpoint,0,scrollEnd,1000);
} catch (IOException e) {
}
}
add this to ur code and simply use scroll(); in ur test case. Modify the decimal values given in the code to nmeet your requirements
I am automating android app using appium (java).For scrolling on native components, I use scrollTo() and scrollToExact() methods.But in case of webView inside the app ; these methods are not working.
UPDATE:
I have tried these two methods also:
public static void scrollNavigation(AppiumDriver<MobileElement> wd, String widID, String target, String direction)
{
JavascriptExecutor js = (JavascriptExecutor) wd;
HashMap<String, String> swipeObject = new HashMap<String, String>();
swipeObject.put("text", target);
swipeObject.put("direction", direction);
swipeObject.put("element", widID);
js.executeScript("mobile: scrollTo", swipeObject);
wait(200);
}
public static void swipeUpElement(AppiumDriver<MobileElement> driver, MobileElement element, int duration)
{
int topY = element.getLocation().getY();
int bottomY = topY + element.getSize().getHeight();
int centerX = element.getLocation().getX() + (element.getSize().getWidth()/2);
driver.swipe(centerX, bottomY, centerX, topY, duration);
}
But in both these I need element- but on the page I cannot find any element except the webview.I am using UiAutomator to capture the IDs.Any suggestions / link / workaround will be helpful
ELements arent displaced uniquely in web view. U need to develop mathematical logic to get screen size and scroll according to them, use the below code,
public void scroll() throws IOException {
try {
Dimension dimensions = driver.manage().window().getSize();
System.out.println("Size of Window= " +dimension);
int scrollStart = (int) (dimension.getHeight() * 0.5);
System.out.println("Size of scrollStart= " +scrollStart);
int scrollEnd = (int) (dimension.getHeight() * 0.2);
System.out.println("Size of cscrollEnd= " + scrollEnd);
driver.swipe(0,scrollStart,0,scrollEnd,1000);
Application_Log.info("Screen Swiped " );
} catch (IOException e) {
Assert.fail("Swipe failed");
}
}
Try switching to native context driver.context("NATIVE_APP"); before scroll .
If it does not work then give a try for JavascriptExecutor like below sample
MobileElement element = driver.findElement(By.xpath("element-xpath"));
JavascriptExecutor js = (JavascriptExecutor) driver;
HashMap scrollObject = new HashMap();
scrollObject.put("direction", "down");
scrollObject.put("element", element);
js.executeScript("mobile: scroll", scrollObject);
I am using gview of Google Docs to display document files but I cannot get scroll position as well as set scroll offset to force document view jump to any positions.
Here is my code:
String url = "https://dl.dropbox.com/s/8wubzwsbcafqxmt/GMAT-Vocabulary-List.pdf?dl=0";
webView.loadUrl("https://docs.google.com/viewer?url=" + url + "&embedded=true");
public boolean onTouchEvent(final MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_MOVE) {
int xPos = webView.getScrollX();
int yPos = webview.getScrollY();
Log.d("Scroll", "xPos = " + xPos + ";yPos = " + yPos);
}
return false;
}
The logcat is always like this: "xPos = 0;yPos = 0".
And nothing happens when I set webView position like this:
webView.setScrollY(1000);
I have no idea why!
I searched and tried many solutions but this problem is still not resolved. Could you please show me some ways to resolve this problem.
Thank you in advance!
I had been debugged the following code for whole day, and have no idea why it doesn't work as expected.
import com.nineoldandroids.animation.ObjectAnimator;
import com.nineoldandroids.animation.PropertyValuesHolder;
import com.nineoldandroids.animation.ValueAnimator;
private void animateThumbCoorToMatchCurrentIndixes() {
float newThumbLeftCoor = this.indexToCoor(this.thumbLeftIndex);
float newThumbRightCoor = this.indexToCoor(this.thumbRightIndex);
PropertyValuesHolder thumbLeftPropertyValuesHolder = PropertyValuesHolder.ofFloat("thumbLeftCoor", this.thumbLeftCoor, newThumbLeftCoor);
PropertyValuesHolder thumbRightPropertyValuesHolder = PropertyValuesHolder.ofFloat("thumbRightCoor", this.thumbRightCoor, newThumbRightCoor);
Log.i("CHEOK", "Animate " + this.thumbLeftCoor + " -> " + newThumbLeftCoor);
Log.i("CHEOK", "Animate " + this.thumbRightCoor + " -> " + newThumbRightCoor);
ValueAnimator valueAnimator = ObjectAnimator.ofPropertyValuesHolder(this, thumbLeftPropertyValuesHolder, thumbRightPropertyValuesHolder);
valueAnimator.setDuration(getResources().getInteger(android.R.integer.config_shortAnimTime));
valueAnimator.setRepeatCount(0);
valueAnimator.setInterpolator(new DecelerateInterpolator());
Log.i("CHEOK", "Animation duration = " + valueAnimator.getDuration());
valueAnimator.start();
}
// Do not remove this code. It is used for reflection call for animation.
#SuppressWarnings("unused")
private void setThumbLeftCoor(float thumbLeftCoor) {
this.thumbLeftCoor = thumbLeftCoor;
Log.i("CHEOK", "SET thumbLeftCoor " + thumbLeftCoor);
this.postInvalidate();
}
// Do not remove this code. It is used for reflection call for animation.
#SuppressWarnings("unused")
private void setThumbRightCoor(float thumbRightCoor) {
this.thumbRightCoor = thumbRightCoor;
Log.i("CHEOK", "SET thumbRightCoor " + thumbRightCoor);
this.postInvalidate();
}
My console log is as follow :
Animate 636.0985 -> 0.0
Animate 679.27057 -> 578.0
Animation duration = 200
However, methods setThumbLeftCoor and setThumbRightCoor never get triggered.
Anyone have idea why it happens so?
All the while, by having setThumbLeftCoor and setThumbRightCoor as private method work for my case.
Just that recently, a child class is being derived from the above class.
To make the above code work as it is, changing setThumbLeftCoor and setThumbRightCoor to public method is required. (Even protected won't work)
My guess is, this is due to limitation of "reflection"
Suppose when a field is loaded, its empty. When the user types 1, it says 0.01, then he types another 0 after the 1 (10) it becomes 0.10. When he types another 1, it becomes 1.10.
Just like entering the price of a product. How do I do that on Android? I'm quite stumped to be honest since I've never tried something like this. Is there some special input method for this?
Here's the code I wrote for myself:
private String addCurrencySign(String digits) {
String string = "£";
// Amount length greater than 2 means we need to add a decimal point
if (digits.length() > 2) {
String pound = digits.substring(0, digits.length() - 2); // Pound part
String pence = digits.substring(digits.length() - 2); // Pence part
string += pound + "." + pence;
} else if (digits.length() == 1) {
string += "0.0" + digits;
Log.d(TAG, "length 1 " + string);
} else if (digits.length() == 2) {
string += "0." + digits;
Log.d(TAG, "length 2 " + string);
}
return string;
}
This addCurrencySign method is triggered each time when user trying to type on the number pad. The number pad is consist of several digit buttons (just like POS handheld or calculator).
Since you don't need to build a keypad with buttons, could you try intercept the keyboard events, which is described in Handling Keyboard Actions and maybe write something like this:
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_0:
return true;
case KeyEvent.KEYCODE_1:
return true;
case KeyEvent.KEYCODE_2:
return true;
case KeyEvent.KEYCODE_3:
return true;
......
default:
return super.onKeyUp(keyCode, event);
}
}
Maybe you don't have to use switch clause, my idea is to intercept the key entering 0~9 digits and for each 0~9, call addCurrencySign method.
Use:
TextWatcher watcher = new TextWatcher(){
afterTextChanged(Editable s){}
beforeTextChanged(CharSequence s, int start, int count, int after){}
onTextChanged(CharSequence s, int start, int before, int count){}
}
yourEditText.addTextChangedListener(watcher);
Here you will find more info about TextWatcher http://developer.android.com/reference/android/text/TextWatcher.html
OK guys.. I have a temporary workaround. This can't be termed as the perfect solution but its a workaround that works well in my case.
I couldn't figure out a way to stop the stackoverflow error. My workaround? Make the EditText field take input, but display the currency output onto a TextView, and make the EditText disappear from the UI so the user can't see that he is typing just 1234 instead of 12.34.
Here is the code. The addCurrencySign function comes from #ss1271.
amountpaid.addTextChangedListener(new TextWatcher()
{
#Override public void onTextChanged(CharSequence s, int start, int before, int count)
{
amount.setText(addCurrencySign(s.toString()));
}
#Override public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
}
#Override public void afterTextChanged(Editable s)
{
}
});
Here's the function that the user posted. It works very well.
private String addCurrencySign(String digits)
{
String string = "&"; // Your currency
// Amount length greater than 2 means we need to add a decimal point
if (digits.length() > 2)
{
String pound = digits.substring(0, digits.length() - 2); // Pound
// part
String pence = digits.substring(digits.length() - 2); // Pence part
string += pound + "." + pence;
}
else if (digits.length() == 1)
{
string += "0.0" + digits;
Log.d("TextWatcher", "length 1 " + string);
}
else if (digits.length() == 2)
{
string += "0." + digits;
Log.d("TextWatcher", "length 2 " + string);
}
return string;
}
Here's the 'invisible' edittext:
<EditText
android:id="#+id/amoundpaid"
android:layout_width="1dp"
android:layout_height="1dp"
android:background="#00000000"
android:ems="10"
android:inputType="number"
android:textColor="#00ffffff" >
<requestFocus />
Here's the field that will show the output text (with currency sign and proper decimal point value):
<TextView
android:id="#+id/amount"
android:layout_width="210dp"
android:layout_height="50dp"
android:background="#80000000"
android:gravity="center|center_vertical"
android:textColor="#ffffff"
android:text=""
android:textAppearance="?android:attr/textAppearanceMedium" />
I know this is not a optimum solution, but it works. I needed the functionality and this is what I had to do to get it. If someone can fix the stackoverflow error, please post and mods will change the answer to that one (once its verified).