I need to handle display rotation in android and I know about handling Activity.onConfigurationChange with android:configChanges flags in manifest, but it does not work for me.
Unfortunately, onConfigurationChange is handled only when I change device orientation from portrait to landscape and vice versa, but it is not handled when I change orientation directly from landscape to landscape inverted i.e. from rotation 90 to 270. So, I need some callback, that will be called when result of android.view.Display.getRotation() changes. Any ideas?
When your orientation changes , Android system will create a new View and your app probably getting crashes.reason behind this is your background thread is trying to change the state on the previous one .
the another reason is that your background thread isn't on the UI thread.
my suggestion is that to making one handler that volatile and updating it when the screen orientation changes.
Related
I'm trying to make a UI which when the device is rotated, the icons get rotated.
Normally, when a device is rotated the onXXX lifecycle methods get called, and I'd like to avoid this when the screen orientation changes and would like to rotate the icons on the main UI instead. How can I go about achieving this?
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.
I have an activity with the fallowing property in manifest
android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
While doing orientation change screen size adjustment is delaying some times.
Suppose if I am trying to config from Portrait to landscape
The screen showing portrait only after some time (2 to 3 secs) the screen getting resize to landscape. even same thing happening for Landscape to portrait also.
The above delay is making some confusion to the user.
So kindly please suggest any solution/suggestions to solve this problem.
Thanks in advance
When you specify "orientation|keyboard|keyboardHidden|screenSize" in configChanges it means that the action to be performed when there is a change in the above mentioned properties when a activity is in foreground has been handled in the activity itself (using the onConfigurationChanged())
There may be some tedious task ie being performed in the activity's onConfigurationChanged() of your activity which is resulting in the delay. If not the device may be slow and is takes time to change orientation
Your view gets remeasured and rebuilt from scratch, if the layout is complex that's the time it takes.
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 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.