I have made a simple dice game that makes use of the setTranslationY() method to indicate if a dice should be ignored for the next dice roll. This all works fine, except that when I try to restore the state of the app after a screen rotation, my restoring method cannot seem to use setTranslationY() on the views that need it.
I have confirmed time and time again the the method IS being called for all views that should be nudged upwards a little bit, but the views stay where they are.
If it is so that the app needs to go through the process of completing onCreate(), onStart(), onRestoreInstanceState() and onResume() before being able to manipulate views then please advise on how to achieve this. I need this to happen consistently upon every device rotation.
You can retain the state of your application by informing Android you'd like to handle the logic for screen orientation yourself, rather than allowing the OS to trash and rebuild the entire Activity whenever the user tilts the screen. You can do this by adding the android:configChanges attribute to the Activity entry in your AndroidManifest.xml:
<activity android:name=".YourActivity"
android:configChanges="orientation"
android:label="#string/app_name">
This should hopefully preserve the state of your animated Views.
Related
I have an activity with 4 elements. A spinner containing a list of dates, a spinner containing a list of hours, a button and a list view. The spinner's selected items are used to form a web service URL which is called when the button is clicked and the response is shown in the list view.
The issue is if the user views the app in portrait mode, chooses a date, chooses an hour and clicks the button, the response of the web service call is shown in the list view however, if the device is rotated to landscape then the data in the list view is gone (because in order to get it there a button click is needed).
I understand that onCreate is called when the screen is rotated. I do not want to force the orientation so is there any way I can stop the list view being cleared? Note that the selected values in my spinners remain the same after rotation, it is just the response in the list view that is lost.
Simplest way to prevent activity recreation put this in you AndroidManifest
<activity android:name=".YourActivityName"
android:configChanges="orientation|keyboardHidden|screenSize">
Read this for more info - Supporting Multiple Screens
You can force activity screen orientation in AndroidManifest.xml by setting screenOrientation property:
<activity android:name=".FooActivity"
android:screenOrientation="portrait"/>
This is a half-solution. If you want to handle screen rotation, you should save and restore activity state. This is the major, royal PITA in any Android application I've seen.
The problem is, that your application logic is mixed with view code, which can be destroyed at any moment. Perfect combination, Google! It's like running a function that can disappear during execution. :)
To counter this sorry design decision you may want to move your application logic to service, which will not be destroyed when screen rotates. This 2-layer design is closer to universally accepted MVC pattern, as you separate your logic from your view. Service stays, activity attaches and detaches from service on demand, making screen rotation handling a breeze.
If you're dealing with webservices, do not try to invent your own solution for this. There is couple of nice libraries to handle this nicely, such as RoboSpice and you'll probably never come with any quick solution that is as good as those libs. Give it a try.
Also, watch this Google I/O video about developing Android REST client applications: https://www.youtube.com/watch?v=xHXn3Kg2IQE
Have your button set a static class variable, or shared preference. Then, call a method that reads that value, and does what you want. THEN, put a call to that same method, in onResume(), possibly based on a condition... I think that's what's worked for me. When you come back from configuration change or kill, onResume() should re-do whatever you had last done.
I am new to android development . I have been puzzled by this problem in recent times .
Every time orientation changes my view gets reloaded. I want to avoid this. This is happening on change from landscape to portrait and vice versa.
Put below line in your manifest in activity:
android:configChanges="orientation|screenSize"
So, your activity should look like:
<activity
android:configChanges="orientation|screenSize"
android:name=".YourActivity"/>
This way prevent destroying activity on orientation changes.
The reason why Android is reloading the view after the orientation has changed is that this view is most probably another view than the one that was displayed before the orientation change happened, e.g. with new layout, font sizes, imageviews or other resources. The Android system is able to automatically load suitable resources for different screen dimensions (e.g. height, width, density ... ) in case of an orientation change.
For this to happen, Android first calls the activity's onDestroy() method, followed by a call to its onCreate() method to enable the activity to reload resources and activity state.
If for some reason you do not want this behaviour, you can follow the above advice and add an android:configChanges attribute to your activity element. In this case Android calls the activity's onConfigurationChanged() method instead of onDestroy() and onCreate(). onConfigurationChanged() is the method to place your code to adapt to the new orientation, if necessary. If not, it can also be left empty.
For further reading, see http://developer.android.com/guide/topics/resources/runtime-changes.html
I was wondering why not use android:configChanges="keyboardHidden|orientation" in every (almost every ;)) activity?
Goods:
no need to worry about your activity been rotated
it's faster
Not so nice:
need to change your layouts if they are depending on screen size (e.g. layouts with two columns or so)
Bad:
no flexible way to have different layouts on different orientation
not so good when using fragments
But if we don't use different layouts, why not?
Quick Background
By default, when certain key configuration changes happen on Android (a common example is an orientation change), Android fully restarts the running Activity to help it adjust to such changes.
When you define android:configChanges="keyboardHidden|orientation" in your AndroidManifest, you are telling Android: "Please don't do the default reset when the keyboard is pulled out, or the phone is rotated; I want to handle this myself. Yes, I know what I'm doing"
Is this a good thing? We shall soon see...
No worries?
One of the pros you start with is that there is:
no need to worry about your activity been rotated
In many cases, people mistakenly believe that when they have an error that is being generated by an orientation change ("rotation"), they can simply fix it by putting in android:configChanges="keyboardHidden|orientation".
However, android:configChanges="keyboardHidden|orientation" is nothing more than a bandaid. In truth, there are many ways a configuration change can be triggered. For example, if the user selects a new language (i.e. the locale has changed), your activity will be restarted in the same way it does by an orientation change. If you want you can view a list of all the different types of config changes.
Edit: More importantly, though, as hackbod points out in the comments, your activity will also be restarted when your app is in the background and Android decides to free up some memory by killing it. When the user comes back to your app, Android will attempt to restart the activity in the same way it does if there was some other configuration change. If you can't handle that - the user will not be happy...
In other words, using android:configChanges="keyboardHidden|orientation" is not a solution for your "worries." The right way is to code your activities so that they are happy with any restart Android throws at them. This is a good practice that will help you down the road, so get used to it.
So when should I use it?
As you mentioned there is a distinct advantage. Overwriting the default configuration change for a rotation by handling it yourself will speed things up. However, this speed does come with a price of convenience.
To put it simply, if you use the same layout for both portrait and landscape you're in good shape by doing the overwrite. Instead of a full-blown reload of the activity, the views will simply shift around to fill the remaining space.
However, if for some reason you use a different layout when the device is in landscape, the fact that Android reloads your Activity is good because it will then load up the correct layout. [If you use the override on such an Activity, and want to do some magical re-layout at runtime... well, good luck - it's far from simple]
Quick Summary
By all means, if android:configChanges="keyboardHidden|orientation" is right for you, then use it. But PLEASE be sure to test what happens when something changes, because an orientation change is not the only way a full Activity restart can be triggered.
From my point of view: If the layout is the same in both landscape and portrait mode - you might aswell disable one of the two in your app.
The reason why I state this is that I as a user expect the app to provide me with some benefit, when I change orientation. If it doesn't matter how I hold my phone, then I don't need the choice.
Take for instance an app where you have a ListView, and upon clicking a ListItem you want to be shown a detailed view for that item. In landscape you would od this by dividing the screen in two, having the ListView on the left and the detailed view on the right. In Portrait you would have the list in one screen and then change the screen to the detailed view when a ListItem is selected. In that case orientation change makes sense as well as different layouts.
I don see why.... occasional restarts are ok in my opinion... configChanges handles most cases for me... well maybe in some types of applications this can be problem but it depends really on type of app and how you restore state when app restarts... When one of my app restarts user is logged back and last activity opens by my code and user jus loses some steps to go back where he was but not big deal.. In other some state is always persisted and some state is always restored on restart. When activity restarted it had to be that app have not been used or something... so no problem at all... In game for example this can be problem maybe or in some other type of app I don't know...
I say that when you do it this way applications just works fine under normal circumstances. And code is much more readable without ton of logic needed for saving and restoring where u just can make new bugs and have to maintain it all the time... sure if android gets out of power and kill you application window it lose the context and starts again, but this happen just in special situations and on newer devices I belive this is more and more rare...
So kill me, but I use this across applications quite successfully...
android:configChanges="locale|keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
But I understand that for some special kind of applications it may be not good way but most of apps can live with this just OK.
Yeah I think pausing will make it quicker than releasing the player. Still have the pause though.
Have now found a solution that won't pause the song.
State in the manifest that you will handle the config change for screen orientation and then use the onConfigurationChanged method to load the layout file. By doing this in logCat I can see onPause, onCreate & onResume aren't called, and therefore the song isn't paused.
update the manifest to handle the orientation.
android:configChanges="orientation|screenSize"
add this code
#Override
public void onConfigurationChanged(Configuration newConfig) {
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
setContentView(R.layout.activity_main);
}
I want to be able to change the layout when a device is re-orientated to landscape or portrait. For speed and resource purposes (plus other issues applicable to my app) I do NOT want my app to be destroyed and restarted. I have several objects which I wish to retain between orientation changes as there is no benefit from destroying and re-creating them! I simply just want to change the position of some buttons and TextViews so that they suit the current orientation. Easy right?
Well no it isn't. To achieve the above I included in the app Manifest the configChange option for orientation change. Then I've implemented the onConfigurationChanged() where I determine and apply the appropriate layout. Simple yes?
But now take the textview I have in my layout. How on earth, using this particular method of responding to orientation changes, do I put the same text in the previous textview to the new textview? No instance data is passed to onConfigurationChanged() method. Also for some of the buttons, they could be disabled or enabled... I need to know this after orienatation change.
If I let Android destroy and restart my activity it's first going to create unnecessary work. All I want is to just move a few buttons and textviews.. NOT restart the whole app. That's just ludicrous!
Can anyone help me achieve what need?
An easy way to maintain configuration-independent data is to make use of onRetainNonConfigurationInstance() and its companion method getLastNonConfigurationInstance(). Just return an object that contains all the data that you want to reuse when your activity is recreated.
In Honeycomb, or if you are using the Android compatibility package, you can just call Fragment.setRetainInstance(true) instead. See the docs.
I am using android HTC HERO 2.1 version.
The activity I write :
<activity android:name=".gogogo"
android:label="#string/app_name"
android:theme="#style/Theme.mine"
android:screenOrientation="landscape"
android:configChanges="orientation">
let my orientation change to landscape.
However, I figured out that every time I pressed "power" button and then come back to my activity, it always start at portrait.
I tried the game : TEETER , which was written not by me. Has the same problem too, any one know how to fix it??
Edit: it always start at portrait. --> I mean, if you come back from power, you have to scroll down to do everything, there is something like screen lock.
You can see that there is a "status bar" at the top of the screen and at this time, the orientation is "portrait". So after You scroll the "screen lock" a little bit down, you can see the activity (such as TEETER) is at "portrait" state. When you scroll all the way down, the activity's orientation will suddenly change to the state "landscape".
So the conclusion is : My activity is forced to orient once. And I really want to know how to fix it!
Hai Steven Shih:
Pls go through this page of developer guide.
http://developer.android.com/guide/topics/manifest/activity-element.html
and try this line
android:windowSoftInputMode="stateUnspecified|adjustPan"
Not sure if it's the same problem, but here is the problem I had :
I force the orientation as landscape in the manifest
My activity has a two surfaceviews ( a camera preview and a layer on top of it )
After pressing the power button and coming back, my views were suddenly in the wrong orientation
It seems to be the same problem as another question : Disable orientation but detect orientation
I think the problem is that once you press the power button, the lock screen forces the orientation as portrait. In the onConfigurationChanged I get an orientation change right when I press the power button, which was unexpected because I told to explicitly lock the orientation. The fact is that when another activity which comes in front forces the orientation, the other activities get notified of the orientation change, even if they asked for an explicit orientation.
Here's my workaround :
in onPause, detach the views with removeView ( my application has programmatically created views, not an xml layout )
in onResume , first check if the orientation is the one you requested ( getResources().getConfiguration().orientation ). If it's the case, reattach the views ( addContentView or whatever ).
if the orientation is not the one you expect, call setRequestedOrientation
onConfigurationChanged will be called to tell the orientation has been changed to the one you requested. At this point you can reattach the views with setContentView.
Seems a bit complicated, but that's what I had to go through in my particular case, since my views are created dynamically and directly attach to the default FrameLayout of the activity. Maybe I then missed some default behaviors because of that, but this way I could achieve the reactivity I was looking for.
Not sure whether this can be called a fix, but it's kind of a work-around.
#Override
public void onWindowFocusChanged(boolean hasFocus) {
if (hasFocus)
setContentView(mGameView);
else
setContentView(mEmptyView);
}
Where mGameView is your ordinary content and mEmptyView is just a simple View object. The activity will still be drawn in portrait for a frame or two, but it will not be visible to the user.
I've tested this with HTC Hero and Nexus S.