I have an android project in which I had to put a checkbox and a button such that if the checkbox is checked then the button is enabled, otherwise it is not enabled. Firstly I implemented this by setting onClick attribute of the checkbox, but when the checkbox was checked and I rotated the screen the button switched to not enabled although the checkbox is still checked. So I tried to use the setOnCheckedChangeListener method of checkbox and it worked (after screen rotation the button was still enabled). Why does it happen?
When you rotate the screen, the activity is basically recreated. Some state information may be automatically preserved, but you should become more familiar with the overall activity lifecycle to understand the subtle differences.
activity lifecycle
In addition to Jerry's answer, to get around the issue quickly, you can simply make boolean member variables in your activity for each of your check boxes. These should then persist through orientation change.
Jerry is right, make sure you know about the Android Lifecycle.
Add this line of code in your activity inside your manifest file.
android:configChanges="orientation"
Related
I need my app to not reload when the orientation changes. I have a regular portrait and a seperate landscape layout that both have the same stuff on the screen. But when I check a checkbox and change layout, it's no longer checked. Or when a checkbox has the number 5 in it and then change layout it goes back to it's default number 1. How can I make it stop reloading?
You need to use a way to persist data between the two screens.
Either use savedInstanceState or ViewModel.
The checked state of a CheckBox and text in an EditText will be automatically preserved if you make sure they have the same id in both layouts. However, it only automatically preserves the things that can be changed through the UI, so if you programmatically changed the text of a CheckBox, that is not automatically preserved. Typically, that sort of thing is handled with a ViewModel and LiveData/Flow.
This behavior is controlled by the saveEnabled property of a view, which is true by default.
add this following permission for your activity in Manifest file android:configChanges="orientation|screenSize
Something like this
<activity
android:name=".YourActvity"
android:configChanges="orientation|screenSize">
First tip from Philipp Lackner explains how to use the savedStateHandle
https://www.youtube.com/watch?v=0d5ax97Mb30
The state when you change orientation, for example, gets restored, so you need to handle via viewmodel the state persistence.
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 use data of the accelerometer in my app. If the device´s angle is changed the screen orientation should change.
In order to change the orientation I have 2 layouts, one for portrait and one for landscape.
When the orientation changes a function is called that changes the layout with:
setContentView(R.layout.landscape); or setContentView(R.layout.portrait);
This works fine but I have a problem with several UI elements like buttons or ToggleButtons.
I initialize a onClickListener in the onCreate Method for them and each time the orienation gets changed I initialize a new onClickListener.
Unfortunately I can´t change the state of ToggleButtons anymore.
How can I solve this problem?
you can use /layout-land and /layout-port and the phone will automatically switch them for you on orientation change. see
http://developer.android.com/guide/practices/screens_support.html#DesigningResources
as for the toggle buttons, see onRetainNonConfigurationInstance()
http://developer.android.com/reference/android/app/Activity.html#onRetainNonConfigurationInstance%28%29
As described by Bill Gary above, why not just let the system take care of orientation changes for you? Also the standard system widgets should automatically preserve their state when you do this. See here for why and how to manage custom state, if you need to.
My app lets users change the text and visibility on some TextViews. I want to offer a button that will undo all changes and return the layout to it's original settings.
If you turn the phone from portrait to landscape, it does just that... but how do I trigger it from a button?
You could invalidate the base View or call Activity.setContentView
If you turn the phone from portrait to landscape, it does just that... but how do I trigger it from a button?
The recreate method of the Activity class seems to do just that. Quote from the docs:
Cause this Activity to be recreated with a new instance. This results in essentially the same flow as when the Activity is created due to a configuration change -- the current instance will go through its lifecycle to onDestroy() and a new instance then created after it.
An example "configuration change" mentioned above is orientation change, i.e. switching from landscape to portrait or the other way around.
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.