How to Save Current URL & Page Position

cbanks

Active Member
Licensed User
Longtime User
I currently use the code below to save the url of the current page to a variable. It doesn't save where on the page the user was reading, just the url. How do I save the current position on the page along with the url?

Sub WebView1_PageFinished (Url As String)
pagerestore=Url
End Sub
 

warwound

Expert
Licensed User
Longtime User
I think you have two possible solutions here:

Save and restore the scroll position of the WebView.
That is - treat the WebView as a View and restore it's Y scroll position.

Or save and restore the scroll position of the loaded webpage in the WebView.

The first option look better to me as option two would involve more code...

Option 2 would require that the loaded webpage contains javascript that sends the webpage's scroll position to a B4A Sub every time the webpage scroll changes.
Then on reloading the webpage you'd use B4A to execute some javascript after the webpage has reloaded to restore the scroll position.

Option1 requires that in Activity_Pause you save the WebView Y scroll position and then once the webpage has been reloaded (Sub WebView1_PageFinished) you restore the Y scroll.

Look at this page: android - Getting document position in a WebView? - Stack Overflow

B4X:
'Activity module
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.

   Dim ScrollPerCent As Float
End Sub

Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.
   Dim Reflector1 As Reflector
   Dim WebView1 As WebView
End Sub

Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
      ScrollPerCent=0
   End If

   WebView1.Initialize("WebView1")
   Activity.AddView(WebView1, 0, 0, 100%x, 100%y)
   Reflector1.Target=WebView1
End Sub

Sub Activity_Resume
   WebView1.LoadUrl("http://www.b4x.com/forum/basic4android-updates-questions/14185-how-save-current-url-page-position.html")
End Sub

Sub Activity_Pause (UserClosed As Boolean)
   Dim ContentHeight As Int
   Dim ScrollY As Int
   
   ContentHeight=Reflector1.RunMethod("getContentHeight")
   ScrollY=Reflector1.RunMethod("getScrollY")
   
   ScrollPerCent=ScrollY/ContentHeight
   
   Log("Pause: "&ContentHeight&", "&ScrollY&", "&ScrollPerCent)
End Sub

Sub WebView1_PageFinished (Url As String)
   If ScrollPerCent<>0 Then
      Dim ContentHeight As Int
      Dim ScrollY As Int
      
      ContentHeight=Reflector1.RunMethod("getContentHeight")
      ScrollY=ContentHeight*ScrollPerCent
      
      Reflector1.RunMethod3("scrollTo", 0, "java.lang.int", ScrollY, "java.lang.int")
      Log("Resume: "&ContentHeight&", "&ScrollY&", "&ScrollPerCent)
   End If
End Sub

That code nearly works!
It restores the Y scroll position of the WebView as a percentage of the WebView's ContentHeight.

Isn't there a bug with the emulator where it executes Pause or Resume Subs twice on orientation change?
Look in the log and you'll see ContentHeight on the emulator sometimes reported as zero causing ScrollY/ContentHeight to equal infinite (NaN in the log).

The code also needs updating to take account of the WebView's zoom scale if zoom is enabled in your WebView.

Anyway i've attached the code to this post so experiment with it and post again if you need more help.

Martin.

Reflection library is available here: http://www.b4x.com/forum/additional...pdates/6767-reflection-library.html#post39256
 

Attachments

  • WebViewScrollPosition.zip
    5.8 KB · Views: 338
Last edited:
Upvote 0

cbanks

Active Member
Licensed User
Longtime User
warwound, I implemented the code you gave, but it only works about half the time. It seems like it must be executing the scroll code before the page is really finished loading. I can get it to work better by using a timer to wait a second before it uses the scroll code. Any ideas?
 
Last edited:
Upvote 0

warwound

Expert
Licensed User
Longtime User
Hi.

I've not made any progress on this yet.

Have you tried Roeschti's library?

An app i am writing now has a WebView and i want to preserve the WebView's scroll position on orientation change so i shall spend some time on this over the next few days and report back with my progress.

Martin.
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
Let me update this thread with my (lack of) progress!

I've attached a sample project to this post, here's the code:

B4X:
'Activity module
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.

   Dim ScrollX, ScrollY As Float
End Sub

Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.
   Dim Reflector1 As Reflector
   Dim WebView1 As WebView
   Dim WebViewXtender1 As WebViewXtender
End Sub

Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
      ScrollX=0
      ScrollY=0
   End If

   WebView1.Initialize("WebView1")
   Activity.AddView(WebView1, 0, 0, 100%x, 100%y)
   WebView1.LoadUrl("http://www.b4x.com/forum/basic4android-updates-questions/14185-how-save-current-url-page-position.html")
   
   Reflector1.Target=WebView1
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
   Dim ContentHeight As Int
   Dim Scale As Float
   Log("Activity_Pause")
   If UserClosed=False Then
      ContentHeight=Reflector1.RunMethod("getContentHeight")
      If ContentHeight>0 Then
         Scale=WebViewXtender1.getScale(WebView1)
         Log("Activity_Pause Scale: "&Scale)
         
         ScrollX=WebViewXtender1.getScrollX(WebView1)
         ScrollY=WebViewXtender1.getScrollY(WebView1)
         Log("Activity_Pause Absolute (pixel) position: "&ScrollX&", "&ScrollY)
         
         ScrollX=ScrollX/Scale
         ScrollY=ScrollY/Scale
         
         Log("Activity_Pause Scaled saved position: "&ScrollX&", "&ScrollY)
      Else
         Log("Activity_Pause ContentHeight is ZERO, saved position NOT updated")
      End If
   End If
End Sub

Sub WebView1_PageFinished (Url As String)
   Dim ContentHeight As Int
   Dim Scale As Float
   Log("WebView1_PageFinished")
   
   ContentHeight=Reflector1.RunMethod("getContentHeight")
   If ContentHeight=0 Then
      Log("WebView1_PageFinished ContentHeight is ZERO do not try to restore scroll position")
   End If
   
   If ContentHeight>0 AND (ScrollX<>0 OR ScrollY<>0) Then
      Scale=WebViewXtender1.getScale(WebView1)
      Log("WebView1_PageFinished Scale: "&Scale)
      ScrollX=ScrollX*Scale
      ScrollY=ScrollY*Scale
      WebViewXtender1.scrollTo(WebView1, ScrollX, ScrollY)
      Log("WebView1_PageFinished Restored scaled position: "&ScrollX&", "&ScrollY)
      ScrollX=0
      ScrollY=0
   End If
End Sub

I'm using Roeschti's WebViewXtended library to get the WebView's ScrollX, ScrollY and Scale properties.
And i'm using the Reflection library to get the WebView's ContentHeight.

The whole process of saving and restoring the WebView's scroll position is hurdle after hurdle.

Getting and setting the WebView's scroll position is no real technical problem BUT there are practical problems...

PROBLEM: With a local HTML webpage in android assets the Sub WebView1_PageFinished is generally(!) executed before the webpage has been rendered and the WebView has a ContentHeight of zero at that point.
A webpage loaded over the internet takes longer to load and render so by the time the Sub WebView1_PageFinished is executed the WebView does have a ContentHeight of more than zero pixels.

While the WebView's ContentHeight is zero pixels there is no point restoring the last scroll position.
If the ContentHeight is zero in Sub WebView1_PageFinished the code now needs to wait until the ContentHeight is more than zero (the webpage has now been rendered) and then restore the scroll position.

PROBLEM: The default behaviour of a WebView is to load and render a webpage at full zoom (not in "overview mode").
See Targeting Screens from Web Apps | Android Developers.
Full zoom seems to vary with portrait and landscape aspect ratios so the saved scroll position of a WebView from one orientation will not exactly match the desired scroll position to restore in the other orientaion.

If you have control over the webpages that you are loading then you can set the viewport meta tag in those pages so as to better target the mobile browser, here's the attributes available with the Android WebView:

B4X:
<meta name="viewport"
      content="
          height = [pixel_value | device-height] ,
          width = [pixel_value | device-width ] ,
          initial-scale = float_value ,
          minimum-scale = float_value ,
          maximum-scale = float_value ,
          user-scalable = [yes | no] ,
          target-densitydpi = [dpi_value | device-dpi |
                               high-dpi | medium-dpi | low-dpi]
          " />

I experimented with the viewport meta tag on a local webpage in android assets but as the Sub WebView1_PageFinished was tending to execute before the webpage had been rendered had no success at getting the webpage to render consistently in both portrait and landscape orientation.

The attached project does not work perfectly - it restores the scroll position approximately.
I did previously have the code so that it was very nearly perfect but made some changes and couldn't revert back to the nearly working version after i'd made those changes! :signOops:

I'll experiment more later and keep this thread updated.

Martin.
 

Attachments

  • WebViewScrollPosition.zip
    6 KB · Views: 308
Upvote 0

Roeschti

Member
Licensed User
Longtime User
Yeah that's true, that's why i made the progress property in my library. I use it within a timer, wich gets enabled after LoadUrl or Click on a link:

Sub tmrLoad_Tick
'Handle tick events
DoEvents
lblProgress.Text = wvx.getProgress(webView1) & "%"
DoEvents
If lblProgress.Text = "100%" Then
'Loading finished!
tmrLoad.Enabled = False
End If
End Sub

If you like I can add ContentHeight to my library, this done in 2min.
 
Upvote 0

juanjo3691

Member
Licensed User
Longtime User
Problem with Scroll position

Hello, first of all i want to say that i am new in this languaje. Sorry. I have a two little problems with the Wardbound code. With my simple code I need to click two times (problem 1) in the Url button for scrolling the html page at any position ( in my example i put scrolly = 150, but can be anyone not zero), because if i click only one time this do nothing. When i click the Html button never functions (problem 2). Anyone knows why this ? Thanks to all.

'Activity module
Sub Process_Globals
Dim ScrollX, ScrollY As Float
End Sub

Sub Globals
Dim Reflector1 As Reflector
Dim WebView1 As WebView
Dim ButtonUrl, ButtonHtml As Button
Dim WebViewXtender1 As WebViewXtender
Dim sb As StringBuilder
End Sub

Sub Activity_Create(FirstTime As Boolean)
WebView1.Initialize("WebView1")
ButtonUrl.Initialize ("ButtonUrl")
ButtonHtml.Initialize ("ButtonHtml")
Activity.AddView(WebView1, 0, 0, 100%x, 80%y)
Activity.AddView(ButtonUrl, 0, WebView1.Top + WebView1.Height, Activity.Width / 2, 40 )
Activity.AddView(ButtonHtml, ButtonUrl.left + ButtonUrl.Width, WebView1.Top + WebView1.Height, Activity.Width / 2, 40 )
ButtonUrl.Text = "Load Url"
ButtonHtml.Text = "Load Html"
CreateHtml
WebView1.Color = Colors.Black
Reflector1.Target=WebView1
End Sub

Sub CreateHtml
HtmlCSS = "table {width: 100%; filter: alpha(opacity=0);-moz-opacity: .20; background-color: trasparent; font-size: 20px; text-align: left; }" _
& " th { font-weight: bold; background-color: transparent; border-bottom: 1px solid transparent; }" _
& "td,th {padding: 3px 4px; }" _
& ".odd { background-color: rgb(0,0,0); border-bottom: 1px solid transparent } .odd td {border-bottom: 1px solid transparent; }" _
& "a { text-decoration:none; color: rgb(255,255,255); border-bottom: 1px solid transparent }"

sb.Initialize
sb.Append("<html><body>").Append(CRLF)
sb.Append("<style type='text/css'>").Append(HtmlCSS).Append("</style>").Append(CRLF)
sb.Append("<table>").Append(CRLF)

For row = 0 To 50
sb.Append("<tr>")
sb.Append("<td>")
sb.Append("<a href='http://").Append(row).Append(".")
sb.Append(row)
sb.Append(".com'>").Append(row).Append("</a>")
sb.Append("</td>")
sb.Append("</tr>").Append(CRLF)
Next
sb.Append("</table></body></html>")
File.WriteString (File.DirDefaultExternal, "Lista.html", sb)
End Sub

Sub ButtonUrl_Click
WebView1.LoadUrl ("file:" & File.DirDefaultExternal & "/Lista.html")
End Sub

Sub ButtonHtml_Click
WebView1.LoadHtml(sb)
End Sub

Sub Activity_Pause (UserClosed As Boolean)
Dim ContentHeight As Int
Dim Scale As Float
If UserClosed = False Then
ContentHeight = Reflector1.RunMethod("getContentHeight")
If ContentHeight > 0 Then
ScrollX = WebViewXtender1.getScrollX(WebView1)
ScrollY = WebViewXtender1.getScrollY(WebView1)
End If
End If
End Sub

Sub WebView1_PageFinished (Url As String)
Dim ContentHeight As Int
ScrollY = 150
ContentHeight = Reflector1.RunMethod("getContentHeight")
If ContentHeight>0 AND (ScrollX<>0 OR ScrollY<>0) Then
WebViewXtender1.scrollTo(WebView1, ScrollX, ScrollY)
End If
End Sub
 
Upvote 0

canalrun

Well-Known Member
Licensed User
Longtime User
... The whole process of saving and restoring the WebView's scroll position is hurdle after hurdle.

PROBLEM: With a local HTML webpage in android assets the Sub WebView1_PageFinished is generally(!) executed before the webpage has been rendered ...

Hello,
I am also having a problem setting the scroll position in a web view – sometimes it works sometimes it doesn't.

The functions are being called correctly and the parameters are correct, my guess is it is a problem similar to that mentioned above where the WebView PageFinished is called before it is done rendering, hence scrolling has no effect.

Have you made any progress on this issue? Is there a way to tell when a web view is really done?

I see the WebViewExtender library has a GetProgress, but it does not state whether this progress gives the same result as PageFinished or whether it includes the rendering also.

Is there a way to test when a WebView is actually finished?

Thanks,
Barry.
 
Upvote 0
Top