Android Question Persist webview through orientation change

barx

Well-Known Member
Licensed User
Is there a way in b4a to persist a webview when the orientation is changed?

We can obviously get the url and reload it, but what if the user has entered some data and then decides to rotate. All is lost.

Searching on net shows the use of manifest edit
B4X:
android:configChanges="orientation|screenSize"
but it requires

B4X:
onconfigurationchange()
something that doesn't seem to be inplemented in b4a

Another option documented in java is to

B4X:
  protected void onSaveInstanceState(Bundle outState) {
      webView.saveState(outState);
  }
and

B4X:
public void onCreate(final Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.blah);
  if (savedInstanceState != null)
      ((WebView)findViewById(R.id.webview)).restoreState(savedInstanceState);
}
If this method is possible with JavaObject or Reflector, I have no idea how to do it.

Ideas?
 

Erel

Administrator
Staff member
Licensed User
You can prevent the activity from being destroyed with the first option you posted.

You can then handle the change by adding the HeightChanged event with IME library.
 

barx

Well-Known Member
Licensed User
You can prevent the activity from being destroyed with the first option you posted.

You can then handle the change by adding the HeightChanged event with IME library.
Been playing with this and the results are sketchy are best. Especially as the keyboard is not always on show.

Also, the webview disappears, lol. Basically, load app in portrait, no problem Rotate device, the webview persists but it does not fill the width even though in the HeightChanged event I set the width to 100%x. Rotate the screen back and it disappears all togther, I'm assuming it goes off screen to the left.

Is there a way to implement onConfigurationChange?
 

warwound

Expert
Licensed User
Basically, load app in portrait, no problem Rotate device, the webview persists but it does not fill the width even though in the HeightChanged event I set the width to 100%x.
I'd guess that 100%x after the orientation change is the same as 100%x before the orientation change.
By handling the configuration change yourself, b4a hasn't updated it's Activity width and height properties.
Try logging 100%x before and after orientation change - do you see the same values?

Rotate the screen back and it disappears all togther, I'm assuming it goes off screen to the left.
Start the Android SDK Hierarchy Viewer, locate your WebView and take a look at it's layout properties to see where it's been moved to.

Martin.
 

Erel

Administrator
Staff member
Licensed User
See this example:

Add this line to the manifest editor:
B4X:
SetActivityAttribute(Main, android:configChanges, "orientation|screenSize")
B4X:
Sub Globals
   Private ime1 As IME
   Private WebView1 As WebView
   Private ActivityParent As JavaObject
End Sub

Sub Activity_Create(FirstTime As Boolean)
   WebView1.Initialize("WebView1")
   Activity.AddView(WebView1, 0, 0, 100%x, 100%y)
   ime1.Initialize("ime1")
   ime1.AddHeightChangedEvent
   WebView1.LoadUrl("http://www.google.com")
   Dim jo As JavaObject = Activity
   jo.RunMethodJO("getContext", Null).RunMethodJO("getWindow", Null).RunMethod("setSoftInputMode", _
     Array As Object(0x20))
   ActivityParent = jo.RunMethodJO("getParent", Null)
End Sub
Sub IME1_HeightChanged (NewHeight As Int, OldHeight As Int)
   CallSubDelayed(Me, "AfterChange")
End Sub

Sub AfterChange
   Dim ajo As Panel = Activity
   Dim width As Int = ActivityParent.RunMethod("getMeasuredWidth", Null)
   Dim height As Int = ActivityParent.RunMethod("getMeasuredHeight", Null)
   If width = 0 OR height = 0 Then Return
   ajo.Width = width 'update the "activity" width and height
   ajo.Height = height
   WebView1.Width = width
   WebView1.Height = height
End Sub

Sub Activity_Resume
   AfterChange
End Sub
onConfigurationChanged will not behave differently than this solution. The difficult part is to reset the activity width and height.
 
Last edited:

Baris Karadeniz

Active Member
Licensed User
See this example:
B4X:
Sub Globals
   Private ime1 As IME
   Private WebView1 As WebView
   Private ActivityParent As JavaObject
End Sub

Sub Activity_Create(FirstTime As Boolean)
   WebView1.Initialize("WebView1")
   Activity.AddView(WebView1, 0, 0, 100%x, 100%y)
   ime1.Initialize("ime1")
   ime1.AddHeightChangedEvent
   WebView1.LoadUrl("http://www.google.com")
   Dim jo As JavaObject = Activity
   jo.RunMethodJO("getContext", Null).RunMethodJO("getWindow", Null).RunMethod("setSoftInputMode", _
     Array As Object(0x20))
   ActivityParent = jo.RunMethodJO("getParent", Null)
End Sub
Sub IME1_HeightChanged (NewHeight As Int, OldHeight As Int)
   CallSubDelayed(Me, "AfterChange")
End Sub

Sub AfterChange
   Dim ajo As Panel = Activity
   Dim width As Int = ActivityParent.RunMethod("getMeasuredWidth", Null)
   Dim height As Int = ActivityParent.RunMethod("getMeasuredHeight", Null)
   If width = 0 OR height = 0 Then Return
   ajo.Width = width 'update the "activity" width and height
   ajo.Height = height
   WebView1.Width = width
   WebView1.Height = height
End Sub

Sub Activity_Resume
   AfterChange
End Sub
onConfigurationChanged will not behave differently than this solution. The difficult part is to reset the activity width and height.
I tried the codes above but when orientation changes webview comes to its original state. I mean everything is lost. How can I solve this problem?
 

Erel

Administrator
Staff member
Licensed User
Please upload a small project with the relevant code (File - Export as zip).
 

Erel

Administrator
Staff member
Licensed User
Add this line to the manifest editor:
B4X:
SetActivityAttribute(Main, android:configChanges, "orientation|screenSize")
 

Baris Karadeniz

Active Member
Licensed User
Sorry, In which part I need to write that line?

B4X:
<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="app.taksim"
    android:versionCode="2"
    android:versionName=""
    android:installLocation="internalOnly">
   
    <uses-sdk android:minSdkVersion="5" android:targetSdkVersion="19"/>
    <supports-screens android:largeScreens="true"
        android:normalScreens="true"
        android:smallScreens="true"
        android:anyDensity="true"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <application
        android:icon="@drawable/icon"
        android:label="TAKSİ'M">
        <activity
            android:windowSoftInputMode="stateHidden"
            android:launchMode="singleTop"
            android:name=".main"
            android:label="TAKSİ'M"
            android:screenOrientation="unspecified">
            <intent-filter>
               <action android:name="android.intent.action.MAIN" />
               <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
           
        </activity>
        <service android:name=".starter">
        </service>
        <receiver android:name=".starter$starter_BR">
        </receiver>
    </application>
</manifest>
 

Baris Karadeniz

Active Member
Licensed User
Orientation ok but there is something wrong with the label at the top of webview. I wrote this problem here because I think it is related to the codes written for orientation. I used label at the top of webview to write page name. When the screen is vertically, the text written on the label is horizontally centered. But when I rotate phone vertically, the label text stays centered at the left part (50%left, 50%right) of screen. Is this because of orientation codes written #5? If you say that this is not related with the orientation codes, I will write a new thread.
 

Erel

Administrator
Staff member
Licensed User
I don't recommend using the solution in this thread unless it is critical that the WebView will not be reloaded. It breaks that standard program flow as the Activity is not recreated as it should be.
 

Erel

Administrator
Staff member
Licensed User
You can use this code. However you will need to manually update the layout. Another possible solution is to lock this specific activity orientation.
 
Top