Source: http://osx.wdfiles.com/local--files/icon:iruler/iRuler.png

Source: http://osx.wdfiles.com/local–files/icon:iruler/iRuler.png


I was supposed to detect the event when scroller/page of a webview reaches bottom so that i can show one decent translate animation of another small view(like an ad banner). That view will be overlayed definitely and when web page scrolls above center of page then view will hide via translate animation. I came up with a simple solution to detect scroll position. I made an subclass of webview and override onScrollChanged method. Inside this method i am checking scrollY position with the height of content height.

@Override
	public void  onScrollChanged (int l, int t, int oldl, int oldt){
		int height = (int) Math.floor(this.getContentHeight() * this.getScale());
		if(this.getScrollY() >= height){
			Log.i("THE END", "reached");
		}
	}

I could get content height from getContentHeight but i need to keep zoom level of page in mind too so i have multiplied scale factor. Now whenever scrollY reaches height then page end has been reached. It is not so, because we haven’t checked for offset value. That offset value is height of the scroller according to theory if scrollY is the exact Y coordinates of scroller :P. I tried many ways to calculate the height but still i am missing something. I checked the reference documentation and found lots of helpful stuffs. I’l cover everything that i used where i failed and had success. First i used getBottom and getTop, according to doc it returns top and bottom position relative to parent, since parent on my case was “relative layout” with “match_parent”. I would calculate the heght of scroller:

int webViewHeight = this.getBottom() - this.getTop();

Now i have height of content and height of web view so i calculated the height of the scroller from this:

int scrollerHeight = (webViewHeight * webViewHeight) / height; //height is content height

I calculated detection of end reach with this condition:

if(this.getScrollY() + scrollHeight >= height){
	Log.i("THE END", "reached");
}

But it wasn’t any way near to perfection 😛 I logged the values and saw that calculation for view of webview was getting wrong output. Even getBottom was no way near accurate since it was returning way low value than expected with respect to my 7 inch nexus tablet density.

Next, i used getMeasuredHeight() and this one gave me accurate value. So i applied same above calculation with new height of web view and result still not very accurate. After all this i did small change to my formula and BINGO!!

public void  onScrollChanged (int l, int t, int oldl, int oldt){
	int height = (int) Math.floor(this.getContentHeight() * this.getScale());
	int webViewHeight = this.getMeasuredHeight();
	if(this.getScrollY() + webViewHeight >= height){
		Log.i("THE END", "reached");
	}
}

Yes above code worked absolutely accurate and am still analyzing the formula on above condition :P, i.e offset here is height of the webview but not height of scroll [sighs]. I would love to hear your opinion on this. You can optimize the above code though i just wanted to share the idea behind.