Reputation: 22317
My app has a webview and some buttons inside a LinerLayout.
the problem is, I want the buttons to be on bottom in portrait mode and on left in landscape mode while the webview maintains it's state.
Two different layout doesn't work as it force recreation of the activity that refresh the webview. for now I use android:configChanges="orientation" in activity tag so webview doesn't get refreshed on orientation change.
Is there anyway to replace the layout of buttons on the change of screen mode?
portrait mode
landscape mode
Upvotes: 16
Views: 50488
Reputation: 1
Add in the manifest
<activity android:name=".MyActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:label="@string/app_name">
and
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Resources.getSystem().getDisplayMetrics().widthPixels>
Resources.getSystem().getDisplayMetrics().heightPixels)
setContentView(R.layout.activity_layout1);
else setContentView(R.layout.activity_layout2);
...
}
and
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
setContentView(R.layout.activity_layout1);
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
setContentView(R.layout.activity_layout2);
}
}
Documents here: https://developer.android.com/guide/topics/resources/runtime-changes.html
Upvotes: 0
Reputation: 22317
I tested fragments, but dealing with fragment makes things much more complex and the fragment itself needs saving and restoring which may not work in a webview which has javascript state, So I searched more and find a nice article somewhere and with some modification I came to a solution which I suggest:
First, add android:configChanges="orientation|screenSize|keyboard|keyboardHidden"
so the app handles the config changes instead of android.
Make two different layout for landscape and portrait. In both layouts instead of webview place a FrameLayout which acts as a placeholder for the webview.
Define initUI method like this and put everything related to UI initialization in this method:
public void initui()
{
setContentView(R.layout.main);
if (wv == null) wv = new WebView(this);
((LinearLayout)findViewById(R.id.webviewPlace)).addView(wv);
findViewById(R.id.home).setOnClickListener(this);
}
If the webview doesn't exist yet it will be created and after setContentView(R.layout.main)
it will be added to the layout. Any other UI customization you need came after this.
and in onConfigurationChanged
:
@Override
public void onConfigurationChanged(Configuration newConfig)
{
((LinearLayout)findViewById(R.id.webviewPlace)).removeAllViews();
super.onConfigurationChanged(newConfig);
initUI();
}
In onConfigChange
the webview is removed from old placeholder and initui
will be called which will add it back to the new layout.
In oncreate()
call initui()
so the ui will be initialized for the first time.
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
initUI()
}
I wish it would be helpful for someone.
Upvotes: 16
Reputation: 1849
If you are using android:configChanges="orientation|screenSize"
In manifest,it ignores the XML in "layout-land". If you create a different XML for landscape don't use the android:configChanges="orientation|screenSize"
tag for that activity in manifest.
Upvotes: 13
Reputation: 733
You can add values-(configuration that you require - eg. land,portrait) folder under resources and mention the layout you need for this configuration.. It's as simple as that.
Please checkout the below link for further information- http://developer.android.com/training/multiscreen/screensizes.html#TaskUseAliasFilters
Upvotes: -1
Reputation: 944
Try to use this code:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.activity_splash);
}
Upvotes: 3
Reputation: 22306
Make your view a relative layout. When the orientation changes just adjust the layout params for each view in code. Have your buttons be contained in a linear layout
As in..
Portrait
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
buttonLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
buttonLinearLayout.setLayoutParams(lp);
LayoutParams webParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
lp.addRule(RelativeLayout.ABOVE, R.id.buttons);
webView.setLayoutParams(webParams);
Landscape
LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
buttonLinearLayout.setOrientation(LinearLayout.VERTICAL);
buttonLinearLayout.setLayoutParams(lp);
LayoutParams webParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
lp.addRule(RelativeLayout.TO_RIGHT_OF, R.id.buttons);
webView.setLayoutParams(webParams);
Make sure the LayoutParams you are using are the RelativeLayout params (always use the Layoutparams of the view's parent)
Upvotes: 1
Reputation: 18863
put that at layout-land
for the layouts you want as landscape.
The idea is, you shouldn't really use configChange="orientation"
because it has its downsides. You can find a detailed post here . You should manually handle your state if you want to change your layout. Of course you can programmaiclly do this but if you want to use xml to do this. You can maintain you webView with fragments.
Upvotes: 7