I have a service that overrides onConfigurationChanged.
It's getting called when you change orientation from portrait -> landscape and vice versa but the problem is when you are rotating from landscape -> landscape. When you are tilting your phone to the Left then you change it to the Right.
As said on many answers here on stackoverflow the manifest file should be:
android:configChanges="keyboardHidden|orientation|screenSize"
Changing orientation from side to side (Left and Right) results in the same screen size thus onConfigurationChanged never gets called.
My app relies on the accelerometer so I need to get the current orientation to adjust my values.
Any thoughts on how and why onConfigurationChanged doesn't get called?
Any thoughts on how and why onConfigurationChanged doesn't get called?
Because that's not considered to be a configuration change. Configuration changes are for where Google thinks that you will need different resources. Since the screen is the same size after the rotation as before, and since nothing else resource-wise is different, they do not consider this to be a configuration change.
Related
I have a layout that I am currently supporting orientation change by overwriting onConfigurationChanged and arranging views based on the selected orientation. Trying to support that same functionality by triggering it from a minimize/expand view button, but the orientation change getting called twice with the new and old orientations.
I have adjustConfig(int orientation) method that takes care about moving the views, hiding/showing what needed - it does the job.
#Override
public void onConfigurationChanged(Configuration newConfig) {
adjustConfig(newConfig.orientation);
super.onConfigurationChanged(newConfig);
//since fullScreeBtn blocks the orientation sensors, we enable it back
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
}
public void adjustConfig (int orientation) {
// do some hide/show work based on the orientation type
}
fullScreeBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
setRequestedOrientation(
getResources().getConfiguration().orientation ==
Configuration.ORIENTATION_LANDSCAPE ?
ActivityInfo.CREEN_ORIENTATION_PORTRAIT :
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
});
I have a full-screen/minimize button that calls to
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) or
setRequestedOrientation(ActivityInfo.CREEN_ORIENTATION_PORTRAIT) based on the orientation I want to change and that triggers in turn onConfigurationChanged which handles my configuration, so far all good, but the problem is that for example, if I am on a portrait and clicking on the button to switch to landscape, the flow works and kicks off onConfigurationChanged with new landscape configuration which makes the change, but then immediately onConfigurationChanged gets called again with the current mode which is portrait and I end up with the initial state - portrait again.
EDIT: Currently the way the code works is you can either start with rotating physically the phone and switching back and forth between portrait and landscape either taping on the minimize/full screen, but not both, since the moment I call
setRequestedOrientation in the fullScreeBtn it forces the orientation and disables the sensor listening, so when I tap on full screen it rotates the screen as I want, then I would rotate the phone to see it, but from this point I am stuck as I can't rotate back physically, only by clicking on the minimize image again.
My goal is to have a support in both the sensors and the manual option, so if I click on fullScreeBtn it would switch to landscape mode and the user would need to rotate his phone to adjust a comfortable view ,exactly like YouTube does today.
You say:
the problem is that for example, if I am on a portrait and clicking on
the button to switch to landscape, the flow works and kicks off
onConfigurationChanged with new landscape configuration which makes
the change
but then immediately onConfigurationChanged gets called again with the
current mode which is portrait and I end up with the initial state -
portrait again.
I tried to replicate your case, but unless some details are missing, I can't see why point nr. 2 would happen. So after clicking on the button to switch to landscape the app stays like that in landscape - which is also what I was expecting.
Just to make sure no important details are left:
Are you listening by any chance to the OrientationEventListener in your app?
Do you have any logic in onConfigurationChanged that sets requested orientation?
UPDATE after additional info was added:
OK, now it makes sense.
Look, in order to achieve the behaviour you want, like in Youtube, most probably you will need to involve another component in the game, it's called: OrientationEventListener.
This listener allows you to listen to changes in orientation directly from the Sensor.
It does not matter if the Activity is locked in a specific orientation or not.
However, it's a bit more complex, this listener communicates the current orientation of device in degrees, from 0 to 359, you will have to figure out what range of degrees matches a landscape or portrait orientation.
The main idea is following:
The minimize/maximize button will lock the activity in a specific orientation, just as you do it right now.
Your implementation of OrientationEventListener will listen in background to the device orientation. When device orientation will match activity orientation, meaning the device is in landscape and the activity is also in landscape (or the other way around), you reset the activity orientation back to ActivityInfo.SCREEN_ORIENTATION_SENSOR. From this point on your Activity will not be locked in a specific orientation, but start following the sensor again.
Remove setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); from onConfigurationChanged() as now this step is handled as described above.
For beginning start looking into OrientationEventListener. There are examples on SO how to use it.
My Activity has a fixed orientation in Portrait and I want it to stay in portrait.
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
It would not make sense for the activity to do it responsive.
My Problem: I have a fragment in the application which contains a textView.
I want the fragment to be responsive so that the user can read the text.
I tried to get the orientation from the onConfigurationChanged Methode but this isn´t called when I turn my device since it always stays portrait.
Now I wanted to figure out the orientation of my device and then animate the fragment to turn it. But I have not found a way to get the orientation of my device but only the one of my Activity.
I also tried to set the fragment orientation with the methode above different than the orientation of the activity but that didn´t work (the orientation was always the same as the one of the activity.) .
Now I really don´t know what to do anymore.
Does anybody know how I can get the orientation of the device independent from the orientation on the Activity? -> or has an other idea how to solve my problem?
You can use the OrientationEventListener to get the orientation angle value.
OrientationEventListener listener=new OrientationEventListener(this,SensorManager.SENSOR_DELAY_NORMAL) {
#Override
public void onOrientationChanged(int orientation) {
Log.d(tag, "Orientation = "+orientation);
}
};
listener.enable();
Based on orientation value you can determine the orientation of the device.
You could read the android sensors directly to determine orientation: Sensors Overview
Hope this helps
(But I can't really understand why you would want to do this without rotating the activity..)
I have a WebView embedded in a Fragment. In the manifest file, I have declared that the activity will handle orientation changes:
android:configChanges="orientation|screenSize"
and in the Activity, I have over-ridden onConfigurationChanged() in order to capture the orientation.
I thought this means that we have to explicitly take care of any changes in the screen orientation. But what I see is that the screen is still rotated (although the activity is not re-created).
If I use the following line:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
it does prevent the screen from being rotated, but I don't get the rotation event.
So, in short, I don't want the system to rotate the screen, and at the same time, I want to get an event from the system that the orientation has changed from portrait to landscape.
Thanks,
Rajath
If you override onConfigurationChanged(Configuration newConfig), you should be able to handle the changes.
Thanks for editing the question, what you're after is now clear to me. I've got two suggestionsScreen orientation (i.e. portrait, landscape, reversePortrait, reverseLandscape, etc) just depends on orientation of the device in 3D space. So one idea is to capture the 3D orientation of the device yourself, which is the same information that the operating system uses to make the screen orientation decision. This means that you need to capture the accelerometer and the magnetic field sensor readings. One example of capturing that information is in my answer to Android Compass that can Compensate for Tilt and Pitch.Alternatively, you might try setting up a dummy activity that exists purely to capture the screen orientation information. That activity could sit on the activity stack behind your main activity. Although I'm not sure whether activities that aren't on top of the activity stack are notified of screen orientation changes.
I would like for my activity not to rotate when the device is turned.
Using
android:screenOrientation="nosensor"
does disable orientation changes, but with one caveat: the activity switches to portrait mode. I just want it to keep the current orientation (e.g., if the screen was in landscape when the activity was started, then stay in landscape mode even when the device is rotated). This is not what "nosensor" seems to be doing. It seems to simply be the exact same behavior as "portrait". Am I using it wrong?
I've tried using setRequestedOrientation( getRequestedOrientation ), but if the current requested orientation is undefined, then my activity is going to rotate. I just want too "lock" the effective screen rotation.
What you can do is to tell Android that you are going to handle the orientation configuration change on your own. You do it by specifying orientation for the android:configChanges attribute of the activity tag.
<activity android:name=".MyActivity"
android:configChanges="orientation"
android:label="#string/app_name">
See this link for more information.
http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange
As to why nosensor would not work, is because it's mentioned as below in the documentation.
The orientation is determined without reference to a physical
orientation sensor. The sensor is ignored, so the display will not
rotate based on how the user moves the device. Except for this
distinction, the system chooses the orientation using the same policy
as for the "unspecified" setting.
and as to what unspecified is in the documentation
The default value. The system chooses the orientation. The policy it
uses, and therefore the choices made in specific contexts, may differ
from device to device.
I have an Android app with an activity that processes the orientation change (android:configChanges="keyboardHidden|orientation" in the manifest). It also has an onConfigurationChanged handler that calls the superclass.
After the device is rotated, the activity remains in portrait mode. And the whole screen is in bizarre state where the X axis goes physically bottom to top, the Y axis goes left to right, the status bar runs along the left screen edge, and all text goes physically up. It's as if the system is forced to not acknowledge the orientation change.
What I would really like to do, I'd like to avoid activity restart, but process the orientation change with few carefully placed layout property flips. However, in the abovementioned state of the GUI I cannot do that. Reloading the main layout file makes no change.
Question - how do I tell the system to switch physical orientation, so that XY axes go the way they should?
EDIT: and here's a curious data point: on all onConfigChanged calls, the newConfig.orientation is 1.
You really shouldn't use android:configChanges. This technique is considered as a last resort. Please read Handling Runtime Changes for more details.
Brief explanation: if you used android:configChanges its your responsibility to handle configuration change event and reload the UI resources for new configuration. When onConfigurationChanged() is called, getResources() already points to correct resources from new configuration. You only need to manually re-set all layouts, strings, dimensions, drawables, etc. with new (potentially changed) values.
You also didn't mention reasons why you decided to go with configChanges, instead of normal Activity workflow. This might have been useful to give you some alternatives.
The attribute android:screenOrientation="portrait" in the manifest was to blame. With this attribute present, even letting the system restart the activity won't switch the screen to true landscape mode.