I need to prevent restarting the activity when the user changes the orientation, so I need to set:
android:configChanges="orientation"
But in the document, there this a note on orientation,
Note: If your application targets Android 3.2 (API level 13) or
higher, then you should also declare the "screenSize" configuration,
because it also changes when a device switches between portrait and
landscape orientations.
I'm a little afraid of using with screenSize together because I only need that for orientation.
I'd like to know when the screenSize event will occur?
I set 'orientation|screenSize' together and tested with changing device's font size, but the screenSize is not changed so the activity has been reloaded.
When(in what case) the screenSize event will be called? and is there any side effects if I set the screenSize to configChanges?
I looked at the Android source code for this. The interesting bits are in ActivityRecord method crossesSizeThreshold and getConfigurationChanges. The screenSize event occurs when the dimensions of the screen changes and the change might be "important" for the application. So what does "important" mean:
When a screen resize happens for an app, Android tries to decide if the activity needs to be relaunched. If the size change is small a re-layout of the activity content might be enough, while for a bigger resize a full configuration change needs to occur.
To decide if the configuration change has to occur Android collects the app's size-sensitive resource qualifiers (e.g. layout-h400dp). If the resize crosses a qualifier boundary a configuration change occurs, while if the resize does not cross the boundary the activity is kept and only a re-layout gets executed.
Having said that, I tried to reproduce this behavior. I couldn't come up with a conclusive test because other configChanges events happened during the resize too.
My initial point still stands. It's hard to predict all possible reasons why a configuration change might occur and trying to prevent the recreation of the activity is very difficult to do. Especially with the amount of API versions and device models we have today. A well architected app that separates business logic and state from the UI layer, is still the way to go.
Related
I am having issues with orientation change in multi-window mode.
The activity doesn't restart on changing orientation when the window size is 2/3 (in multi-window mode) in a tablet device. My layout looks improper due to that.
The activity restarts properly while changing orientation when the window size is 1/2 or 1/3 the display size in multi window mode.
I tried and confirmed this with Nexus 7 and Pixel C devices in (Android Studio) Emulator with Oreo and Pie images.
My app is targeting Oreo 8.1 and I am not using 'android:configChanges' or 'android:screenOrientation' in the manifest.
Note that 2/3 window size is not square and there is a small change in screen size in both orientation and if the orientation change doesn't trigger than the screensize change should trigger activity restart.
Steps to reproduce:
Start app in debug mode in a tablet device.
Put breakpoints inside onCreate and onResume.
Put it in multi-window mode (default 1/2 size).
Rotate the device and check if breakpoints trigger (it would).
Resize window size to 2/3.
Rotate the device and check if breakpoints trigger (it doesn't!).
Am I missing something which is causing this issue? or is this a bug or something else? How can I make my activity restart in this case?
An interesting question, I never knew that there are exceptions to the orientation change process. I was able to reproduce the problem with a Pixel C emulator(Android 8.1) and an app targeting API level 26.
I suppose your screen is not just another list because in this case the difference of 12 pixels (1688 vs. 1676 if I can trust LayoutInspector) would not matter, so I wanted to add an observation which may be helpful:
My app contains a custom View, and from the logs I can see that its methods onMeasure() and onLayout() are called even if the Activity'sonCreate() is not. So this is where you can step in and do some fine tuning.
Another option is to force the Activity to be recreated. You could do so by calling the Activity method recreate() (documented here) as soon as you detect that the screen dimensions have changed. To keep track of the screen size changes, you can create a custom ViewGroup overriding onLayout() and use this as the root of your Activity's layout file.
I've been searching for a solution to this but I could only find a way to force the whole app to stay in either landscape or portrait, via the android manifest. In my app the user is able to customize his UI and one important aspect of that is the screen orientation. I'd like to create a button where the user could change the orientation and lock it that way.
Thank you for your time.
I don't think it is possible through QML but you may bind your qml button to change orientation by setting orientation of QQmlApplicationViewer object.
You may find some information here.
In my experience I remember I forced orientation only in C++.
So, you may need a class to export to QML which will toggle orientation (by setting value to the QQmlApplicationViewer and bind it with your button/checkbox in your qml interface.
My application is bitmap intensive, with pixel-exact layout (it's a sort of game, actually, and it's pretty hard to avoid this pixel-based coordinates).
What I wanted to do is to perform some layout calculations and bitmap pre-scaling in my onCrete - I use well known API - getWindowManager().getDefaultDisplay().getSize() - to retrieve the screen size and do my calculations.
However, I've just hit an unexpected problem. My activity is configured as landscape only, but if I start my application on emulator and onCreate() is called while the emulator is locked, the screen size returned by getSize() indicates portrait orientation. Once I unlock the screen, onCreate() is called again, this time correctly in line with expected landscape mode dimensions.
I'm not sure how to handle this situation. I see the following options:
for each onCreate() call perform full layout calculation and resource scaling again. This is the logically correct solution, but I don't want to the same work twice, just to throw away the first result.
if onCreate() is called for portrait mode, just do nothing, and set black background (I can see there's a silly rotate animation when I unlock the screen, so this would become pretty much a fade-in animation)
Actually I'd prefer second option, but I'm slightly afraid of any side-effects. Anyone faced this problem?
Update (2012-07-08):
I've probably assigned a slightly misleading title to this question (sorry!), as the problem is not in retrieving the dimensions itself, nor calculating the layout. It's more about the activity being first created in portrait mode, and then recreated in landscape mode again, despite being declared as landscape-only. I initially expected (reasonably, huh?) the activity to be created in landscape orientation only.
I eventually decided to fill the activity with black color when it's created in portrait mode, no side effects observed. On Android 4.0 I can see actual rotation animation when I unlock the screen - a bit strange, but well, I guess it is supposed to inform the user that she should rotate the phone. Given that in portrait mode I just fill the screen with black color, this animation looks sort of like a fade-in and rotation combined - perfectly acceptable.
Use that
DisplayMetrics dm=new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(dm);
Using this(Look code at down) only gives you screen size and if your views has static size they will be seen in different size on every different screen.
Display screen=getWindowManager().getDefaultDisplay().getSize();
How to use:
every screen has diffrent density. So use:
float density=dm.density;
with this density, you can set your views size like that:
(YOUR_ITEM_SIZE)*density;
also look here for additional information:
http://developer.android.com/reference/android/util/DisplayMetrics.html
if the emulator is locked , can't you assume that the user can't run anything anyway , so the app doesn't need to handle this end case ?
anyway , as bmavus wrote , use getMetrics for getting the screen size . also , if you need to change the screen orientation of the app , you can do so either in the manifest or in code.
for games , i would advice using opengl solutions , and if you don't have much time digging for it , you can use third party engines that can help you , such as andengine and libgdx.
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.
I am a newbie to the android world, and as of today I completed my first application.
I test my work on a physical device, and quite recently it has came to my attention that whenever I turn/rotate my device, my application tries to adapt itself to the new resolution 800x400.
Since I have designed the whole app for 400x800 resolution, this change messes up the original design, as well as sending a new call to "onCreate" method of the last activity it was on, before turning/rotating the device.
I would like to learn whether it is possible or not, or which class I should use to stop the adaption to resolution.
This line (in AndroidManifest.xml) will lock the activity in portrait mode:
<activity android:name="MyActivity"
android:screenOrientation="portrait" />
There are things that you can do to make your layouts work well in different orientations and resolutions, such as using dips instead of pixels to measure your views.
When you have time, consider making layout files for landscape mode. Create a "layout-land" directory within your res directory and drop he landscape layout files there, using the exact same file names for their portrait counterparts.