I have a simple activity with a boolean. I want it to change from portrait to landscape if and only if that boolean is false (only if the screen changes orientation, of course).
I tried this:
#Override
public void onConfigurationChanged(final Configuration newConfig) {
super.onConfigurationChanged((listening) ? getListeningConfiguration(newConfig)
: newConfig);
setContentView(R.layout.medidor);
preconfigureLayout();
}
public Configuration getListeningConfiguration(final Configuration c) {
c.orientation = Configuration.ORIENTATION_PORTRAIT;
return c;
}
But it simply won't work.
How can I force an activity to remain in portrait state unless I tell it it can change?
In manifest file in activity tag add
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait"
That will keep your activity in portrait mode. then use your code for orientation change.
Just call this to keep it in portrait:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
That should do the trick
Related
I am trying to lock the orientation of an entire app on phone sized layouts to portrait only but allow both portrait and landscape on tablet sized layouts.
I know that I can attribute the Activity to use a specific orientation but this is applied on both layout sizes.
[Activity(
Label = "Brs.Members.Droid"
, MainLauncher = true
, Icon = "#mipmap/icon"
, Theme = "#style/Theme.Splash"
, NoHistory = true
, ScreenOrientation = ScreenOrientation.Portrait)]
public class SplashScreen : MvxSplashScreenActivity
{
public SplashScreen() : base(Resource.Layout.SplashScreen)
{
}
}
Is there a method to only exclude landscape layouts on phone size devices?
Try the code below,check your device if it is tablet first and then set the orientation:
[Activity(Label = "MyOrientationDemo", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
if (!isPad(this))
{
RequestedOrientation = ScreenOrientation.Portrait;
}
SetContentView (Resource.Layout.Main);
}
public static bool isPad(Context context)
{
return (context.Resources.Configuration.ScreenLayout& ScreenLayout.SizeMask)>= ScreenLayout.SizeLarge;
}
}
What you can do is to first check if the device is tablet and then lock the orientation to portrait at run time.
Here is a useful post post to determine if the device is tablet :
Determine if the device is a smartphone or tablet?
So here is what you can do :
Create a values resource file with the qualifier of Smallest screen width equal to 600dp. (sw600dp)
Inside the file set the boolean value of isTablet to true :
<resources>
<bool name="isTablet">true</bool>
</resources>
Then inside the normal values file (without the screen size qualifier) set the value of isTablet to false :
<resources>
<bool name="isTablet">false</bool>
</resources>
Then get the isTablet value in onCreate and set the orientation accordingly :
boolean isTablet = getResources().getBoolean(R.bool.isTablet);
if (!isTablet) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
I want to make my application compatible with Android Nougat and specifically with the density change and the font size change.
What I am doing in my tests is:
Launch the application
Put it in Multi-Window mode (top part of a Pixel C, portrait mode, on emulator)
Put some filters on a list in my application
Change the display size or the font size through the second half of my screen with the settings app
If I don't listen for configuration changes with the density value in the manifest, it recreates my activity (which is not good because I have some filters on and I lose them).
If I listen to them, the densityDpi value is the same in the newConfig value passed as a parameter than the one I get with getResources().getConfiguration().densityDpi.
My current line on the manifest is as below :
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboardHidden|density"
I have tried something like this:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// some code
if(mOldConfiguration != null && newConfig.densityDpi!= mOldConfiguration.densityDpi){
// Neither densityDpi nor fontScale works, they are always the same
}
if(mOldConfiguration != null && newConfig.fontScale != mOldConfiguration.fontScale){
// I will later have a method which will recreate the activity with my filters saved
recreate();
}
mOldConfiguration = newConfig;
}
I already listen to other configuration changes but can't figure out how to detect in this method that the change was a density / font size change.
You can listen to density changes by add this line in the Manifest file:
android:configChanges="density"
In the activity, you can get the new configuration value when having a change:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.e("TRUNGDH", newConfig.densityDpi + "<= densityDpi");
}
With font size changes, you can add some code like this:
android:configChanges="fontScale"
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.e("TRUNGDH", newConfig.fontScale + "<= fontScale");
}
In my app I have MainActivty which should always be viewed in protrait. If I turn the device to landscape I switch to TrendsActivity (to show some graphs). This is done by the folliwing code in MainActivty:
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
{
Intent intent = new Intent(this, TrendsActivity.class);
startActivity(intent);
}
}
Then when I switch back to portait i simply call this in TrendsActivity:
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
{
finish();
}
}
This finishes the activity an automaticly moves back to MainActivity. So far so good. But if I press the back button while in TrendsActivity I come back to MainActivity in landscape mode, and I don't want that. I tried to call the following code in MainActivity:
#Override
protected void onRestart()
{
super.onRestart();
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}
This does not work, because now the onConfigurationChanged() if MainActivity is never called...
What to do?
Don't you think you might be achieving a much cleaner design by simply specifying an alternate xml for landscape mode and letting your MainActivity behave accordingly? Even without this, launching another activity on orientation change isn't going to be what most users would expect.
use this in
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
in onResume() of MainActivty
You can try to set your orientation in android manifest only, try below code
android:screenOrientation="portrait"
so exactly your code in manifest looks something like
<activity
android:name=".yourActivityName"
android:screenOrientation="portrait"
</activity>
You should add this to the AndroidManifest:
android:configChanges="orientation"
this way you tell Android to call onConfigurationChanged when there is a change in the orientation.
I solved this by changing the code in my MainActivity to just change the layout XML like fremmedehenvendelser suggested (Tusen takk!)
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
{
//setTheme(android.R.style.Theme_NoTitleBar_Fullscreen);
setContentView(R.layout.activity_trends);
}
else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
{
setContentView(R.layout.activity_main);
}
}
Next problem is to set the theme to make this layout show in fullscreen. The code which is commented out does not work... Before I had this in my manifest for TrendsActivity
android:theme="#android:style/Theme.NoTitleBar.Fullscreen"
I have create dialog box which will be displayed first when i start application (which is coded in onCreate method ) and then question and answer will be displayed on textview
so to solve problem of orientation (so dialog box again not displayed when orientation change) i have used Manifest with:
android:configChanges="keyboardHidden|orientation"
I have res/layout-land, res/layout-port
but to change only COLOR of background
I have used onConfigurationChanged in my Activity (it get's called on rotation).
so now when orientation change the dialog box will not appear again and background is redrawn but the question and answer which is initialized on onCreate() will not display
so how to maintain
Using android:configChanges="keyboardHidden|orientation" means that your activity handles a configuration change itself, and the system will not change the layout.. take a lokk at http://developer.android.com/guide/topics/resources/runtime-changes.html
To reset the text view, in case of not using android:configChanges="keyboardHidden|orientation":
#Override
public Object onRetainNonConfigurationInstance() {
final MyDataObject data = collectMyLoadedData();
//here get the text from the text view, and any other info
return data;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final MyDataObject data = (MyDataObject) getLastNonConfigurationInstance();
if (data != null) {
//get the text and set it in the text view
}
}
When you change the orientation of the devide, android continue the execution without calling onCreate again, but if you put the code in onResume, this code will executed again.
In OnCreate add for your main layout as
LinearLayout lv=(LinearLayout)findViewById(R.id.mainlayout);
lv.setBackgroundColor(android.R.color.black); // for default potrait or landscape view and after that add this in that activity
#Override
public void onConfigurationChanged(Configuration newConfig) {
Configuration c = getResources().getConfiguration();
if(c.orientation == Configuration.ORIENTATION_PORTRAIT ) {
// portrait
lv.setBackgroundColor(android.R.color.black);
} else if(c.orientation == Configuration.ORIENTATION_LANDSCAPE ){
// landscape
lv.setBackgroundColor(android.R.color.white);
}
}
and also add this in menifest in your activity defined
android:configChanges="keyboardHidden|orientation"
Did you use onSaveInstanceState to save the data and onRestoreInstanceState for retriving the data?
If you have done this then you can display the same dialog box in onRestoreInstanceState.
Well I have a question for you. How did you kept the background color unchanged when changing the orientations? And what to do if the color is unknown or a random color?
Here's my MAIN ACTIVITY
public static boolean popupStatus=false;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (savedInstanceState != null){
popupStatus = savedInstanceState.getBoolean("Open");
}
setContentView(R.layout.main);
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean("Open", DateTimePicker.openPopup);
super.onSaveInstanceState(savedInstanceState);
}
I have DateTimePicker.java class which has 1 button and 1 Textview. Clicking on button, my another class Calendar.java get populated in PopupWindow and this Popup window displays my class Calendar.java . I have created different layouts of my Calendar.java class for portrait and landscape mode. Here's DateTimePicker.java some snippet of code,
public static boolean openPopup = false;
textView = new TextView(this.getContext());
this.addView(textView, layoutParams);
button = new Button(this.getContext());
button.setText("C");
this.addView(button, layoutParams1);
button.setOnClickListener(this);
if(Main.popupStatus){
button.performClick();
}
public void onClick(View v) {
if(Main.popupStatus){
new Handler().postDelayed(new Runnable() {
public void run() {
openCalendar();
}
}, 100);
}
else{
openCalendar();
}
private void openCalendar() {
Calendar calendar = new Calendar(this.getContext());
if(portrait.equals(orientation)){
pw = new PopupWindow(calendarLayout, 245, 284, true);
}
else{
pw = new PopupWindow(calendarLayout, 295, 240, true);
}
pw.setOutsideTouchable(false);
pw.showAtLocation(this, Gravity.NO_GRAVITY, 10, 80);
openPopup = true;
}
public void closeCalendar(){
pw.dismiss();
openPopup = false;
}
Main.XML contain DateTimePicker .
Actually I wanted my Popup window to be opened up even when orientation gets changed at run time, so I have done it through setting flag openPopup = true; in openCalendar() method and if it is opened and orientation gets changed at run time, this flag will be saved in onSaveInstanceState() method. After orientation will change, it will be checked in onCreate() and popup will be opened up for respective orientation mode. I hope you got my point.
PROBLEM: Initially When I click on button in Portrait mode, popup window pops up for portrait layout. then without dismissing popup window, I change the orientation to landscape. And after changing, I can see my popup window as intact and appears on screen of landscape layout. Till now it works fine. But IF popup window is opened up in landscape mode and then I change the orientation to portrait, popup window of portrait layout didn't come up and I see FORCE CLOSE message:/ Please help since I am working behind it so long and getting no clue. I would be very grateful to you all. Thanks!
P.S.: Changing orientation means I am pressing ctrl+F11 and changing orientation of Emulator
The emulator has an odd feature (some consider it a bug) in which changing from landscape to portrait in the emulator causes two configuration changes and two restarts of your activity. (One configuration change is the orientation and the other is an emulated change in the keyboard state.) The timing of the configuration changes frequently causes crashes like this. Try adding this attribute:
android:configChanges="keyboard|keyboardHidden"
to your <activity> tag in the manifest. See if that improves the situation.
Make sure you have your layout defined in layout-land folder and ensure onCreate is not called again and again. android:configChanges="keyboard|keyboardHidden" Put this in your manifest file so that the state is retained when you change orientation