When you rotate your device and the screen changes orientation, Android usually destroys your application's existing Activities and Fragments and recreates them. Android does this so that your application can reload resources based on the new configuration.
If you want the activity to not restart during screen orientation change, you can use the below AndroidManifest. xml. Please note the activity android:configChanges=”orientation|screenSize” attribute. This attribute makes the activity not restart when change screen orientation.
If you want to manually handle orientation changes in your app you must declare the "orientation" , "screenSize" , and "screenLayout" values in the android:configChanges attributes. You can declare multiple configuration values in the attribute by separating them with a pipe | character.
If you do not want the WebView to reload on orientation changes simply override onConfigurationChanged in your Activity class:
@Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
}
And set the android:configChanges attribute in the manifest:
<activity android:name="..."
android:label="@string/appName"
android:configChanges="orientation|screenSize"
for more info see:
http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange
https://developer.android.com/reference/android/app/Activity.html#ConfigurationChanges
Edit: This method no longer works as stated in the docs
Original answer:
This can be handled by overrwriting onSaveInstanceState(Bundle outState)
in your activity and calling saveState
from the webview:
protected void onSaveInstanceState(Bundle outState) {
webView.saveState(outState);
}
Then recover this in your onCreate after the webview has been re-inflated of course:
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.blah);
if (savedInstanceState != null)
((WebView)findViewById(R.id.webview)).restoreState(savedInstanceState);
}
The best answer to this is following Android documentation found here Basically this will prevent Webview from reloading:
<activity android:name=".MyActivity"
android:configChanges="keyboardHidden|orientation|screenSize|layoutDirection|uiMode"
android:label="@string/app_name">
Edit(1/4/2020): You don't need this optional code, the manifest attribute is all you need, leaving optional code here to keep answer complete.
Optionally, you can fix anomalies (if any) by overriding onConfigurationChanged
in the activity:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
I've tried using onRetainNonConfigurationInstance (returning the WebView), then getting it back with getLastNonConfigurationInstance during onCreate and re-assigning it.
Doesn't seem to work just yet. I can't help but think I'm really close though! So far, I just get a blank/white-background WebView instead. Posting here in the hopes that someone can help push this one past the finish line.
Maybe I shouldn't be passing the WebView. Perhaps an object from within the WebView?
The other method I tried - not my favorite - is to set this in the activity:
android:configChanges="keyboardHidden|orientation"
... and then do pretty much nothing here:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// We do nothing here. We're only handling this to keep orientation
// or keyboard hiding from causing the WebView activity to restart.
}
THAT works, but it might not be considered a best practice.
Meanwhile, I also have a single ImageView that I want to automagically update depending on the rotation. This turns out to be very easy. Under my res
folder, I have drawable-land
and drawable-port
to hold landscape/portrait variations, then I use R.drawable.myimagename
for the ImageView's source and Android "does the right thing" - yay!
... except when you watch for config changes, then it doesn't. :(
So I'm at odds. Use onRetainNonConfigurationInstance and the ImageView rotation works, but WebView persistence doesn't ... or use onConfigurationChanged and the WebView stays stable, but the ImageView doesn't update. What to do?
One last note: In my case, forcing orientation isn't an acceptable compromise. We really do want to gracefully support rotation. Kinda like how the Android Browser app does! ;)
Best way to handle orientation changes and Preventing WebView reload on Rotate.
@Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
}
With that in mind, to prevent onCreate() from being called every time you change orientation, you would have to add android:configChanges="orientation|screenSize" to the AndroidManifest.
or just ..
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"`
I appreciate this is a little late, however this is the answer that I used when developing my solution:
AndroidManifest.xml
<activity
android:name=".WebClient"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize" <--- "screenSize" important
android:label="@string/title_activity_web_client" >
</activity>
WebClient.java
public class WebClient extends Activity {
protected FrameLayout webViewPlaceholder;
protected WebView webView;
private String WEBCLIENT_URL;
private String WEBCLIENT_TITLE;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_client);
initUI();
}
@SuppressLint("SetJavaScriptEnabled")
protected void initUI(){
// Retrieve UI elements
webViewPlaceholder = ((FrameLayout)findViewById(R.id.webViewPlaceholder));
// Initialize the WebView if necessary
if (webView == null)
{
// Create the webview
webView = new WebView(this);
webView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
webView.getSettings().setSupportZoom(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
webView.setScrollbarFadingEnabled(true);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setPluginState(android.webkit.WebSettings.PluginState.ON);
webView.getSettings().setLoadsImagesAutomatically(true);
// Load the URLs inside the WebView, not in the external web browser
webView.setWebViewClient(new SetWebClient());
webView.setWebChromeClient(new WebChromeClient());
// Load a page
webView.loadUrl(WEBCLIENT_URL);
}
// Attach the WebView to its placeholder
webViewPlaceholder.addView(webView);
}
private class SetWebClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.web_client, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}else if(id == android.R.id.home){
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
if (webView.canGoBack()) {
webView.goBack();
return;
}
// Otherwise defer to system default behavior.
super.onBackPressed();
}
@Override
public void onConfigurationChanged(Configuration newConfig){
if (webView != null){
// Remove the WebView from the old placeholder
webViewPlaceholder.removeView(webView);
}
super.onConfigurationChanged(newConfig);
// Load the layout resource for the new configuration
setContentView(R.layout.activity_web_client);
// Reinitialize the UI
initUI();
}
@Override
protected void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
// Save the state of the WebView
webView.saveState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState){
super.onRestoreInstanceState(savedInstanceState);
// Restore the state of the WebView
webView.restoreState(savedInstanceState);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With