Android turns landscape even when setOrientation is set to portrait only - android

I've set
android:configChanges="orientation"
android:screenOrientation="portrait"
On manifest and it works well... till keyboard appears. When keyboard is shown you can turn the orientation to landscape and my webview refresh the entire application making the user to log in again. I don't want (or need) a savestate, only block entire features that can refresh the app when changing orientation. I don't need or want the app to being able to turn on landscape. I'ts completely usable on portrait only and was designed to it.
It's supposed that android:configChanges="orientation" tells android that the app will take care about orientation, and android:screenOrientation="portrait" blocks the phone to enter landscape mode when running the app, but keyboard seems to override this config.
At this point i can't figure out how to achieve this workaround,
thanks
SOLVED:
I tried
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
and now it works. I found this line on the documentation but at first sight i thought that i may have to handle keyboard show/hide after setting keyboardHidden on the configChanges but it's working fine with this options, the keyboard appears when user interacts with an input field but it's not able to show in landscape or turn the app to landscape.
I've also set screenSize and screenLayout as documentation linked avobe recommends.
I'll mark this question as solved when i can. Thanks

save the state.
private static final String STATE_COUNTER = "counter";
private int mCounter;
private ArrayList<Item> mItems;
#Override
protected void onSaveInstanceState(Bundle outState) {
// Make sure to call the super method so that the states of our views are saved
super.onSaveInstanceState(outState);
// Save our own state now
outState.putInt(STATE_COUNTER, mCounter);
// Save our own state now
outState.putSerializable(STATE_ITEMS, mItems);
}
then restore the state again
private static final String STATE_COUNTER = "counter";
private TextView mCounterTextView;
private int mCounter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// If we have a saved state then we can restore it now
if (savedInstanceState != null) {
mCounter = savedInstanceState.getInt(STATE_COUNTER, 0);
}
// Display the value of the counter
mCounterTextView = (TextView) findViewById(R.id.counter_text);
mCounterTextView.setText(Integer.toString(mCounter));
...
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(STATE_COUNTER, mCounter);
}
hope you find the answer.

Related

Keeping TextView visibility (View.INVISIBLE) and Button state (setEnabled(false)) after screen rotation

I have an app with a Button to show the answer of a question asked. And a TextView with a warning text and another empty one that displays the answer when the button is clicked. When the user clicks the button, I want the warning textView to disappear and the button to be "unclickable". I managed to achieve this and everything worked as intended, but the problem occurs when I rotate the screen, nothing stays the same.
The code below is in onCreate().
Button buShowAnswer = findViewById(R.id.buShowAnswer);
TextView tvShownAnswer = findViewById(R.id.tvShownAnswer);
TextView tvWarning = findViewById(R.id.tvWarning);
buShowAnswer.setOnClickListener((View v) -> {
String answer;
if (isAnswerTrue){
answer = getString(R.string.true_answer);
}else {
answer = getString(R.string.false_answer);
}
tvWarning.setVisibility(View.INVISIBLE);
buShowAnswer.setEnabled(false);
tvShownAnswer.setText(answer);
cheatState = true;
});
It is very simple. You can go with navylover or you do the following
Open your manifest file
add android:configChanges="keyboardHidden|orientation|screenSize" to your activity like
<activity android:name=".MainActivity"
android:configChanges = "keyboard|orientation|screenSize"
//and leave the rest of the code of your activity as it is. Just add this line and you are good to go
What Happen when you rotate your screen? actually your activity configuration changes and you may say your activity is created as new again. When you rotate your screen it actually destroy your activity and recreate it and everything reset back.
But this is not a best option to use this line of code. you can use viewModal. it saves your avtivity state and when your activity destroyed and recreated then the same viewModal Linked with that activity which helps in saving configuration and saving states
Hope this is Helping
You should use onSaveInstanceState to save the state of your local variable when the screen is rotated, then use the saved value in onCreate (which is called upon rotation to create the new rotated activity).
So add this function
private boolean cheatState = false;
private static final String CHEAT_STATE = "CHEAT_STATE";
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(CHEAT_STATE, cheatState);
// call superclass to save any view hierarchy
super.onSaveInstanceState(outState);
}
and in your onCreate you can then call
if (savedInstanceState != null) {
cheatState = savedInstanceState.getBoolean(CHEAT_STATE);
if( cheatState ) {
buShowAnswer.setEnabled(false);
tvWarning.setVisibility(View.INVISIBLE);
}
}
Oncreate() callback will be triggered when screen rotates, add below line in Androidmanifest.xml to prevent recreate activity.
android:configChanges="keyboardHidden|orientation|screenSize
The detailed explantion is here
My answer is similar to Tyler's above, but it saves and restores both visibility and enabled states.
private boolean isAnswerEnabled;
private int warningTextVisibility;
private static final String STATE_ANSWER = "state_cheat";
private static final String STATE_WARNING_VISIBILITY = "state_warning_visibility"
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(STATE_ANSWER, isAnswerEnabled);
oustState.putInt(STATE_WARNING_VISIBILITY, warningTextVisibility);
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
isAnswerEnabled = savedInstanceState.getBoolean(STATE_ANSWER);
buShowAnswer.setEnabled(isAnswerEnabled);
warningTextVisibility = savedInstanceState.getInt(STATE_WARNING_VISIBILITY);
tvWarning.setVisibility(warningTextVisibility);
}
}

How to work with AsyncTask when screen rotates

I have an activity in my android app that calls an asynctask on onCreateView()
Here is my code :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_weeklyprofit);
fromDateTxt=(TextView)findViewById(R.id.fromDate);
toDateTxt = (TextView)findViewById(R.id.toDate);
GetXYPoints getXY = new GetXYPoints();
getXY.execute(fromDateTxt.getText().toString(),toDateTxt.getText().toString());
}
now my application needs to rotate, so i need to store data when rotate :
I have implemented this as below :
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString("from", fromDateTxt.getText().toString());
savedInstanceState.putString("to", toDateTxt.getText().toString());
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
SystemClock.sleep(500);
fromDateTxt.setText(savedInstanceState.getString("from"));
toDateTxt.setText(savedInstanceState.getString("to"));
GetXYPoints getXY = new GetXYPoints();
getXY.execute(fromDateTxt.getText().toString(),toDateTxt.getText().toString());
}
So i recall the asynctask again with restored data, my problem is that the activity run again when rotate and the it calls onRestoreInstanceState so how can i prevent the activity from calling the first asyncktask?
In other way what is the best solution to store data returned by an asynck task when screen is rotate?
i would suggest you to to make sure you actually need your activity to be reset on a screen rotation (the default behavior). Every time I've had issues with rotation I've added this attribute to my tag in the AndroidManifest.xml, and been just fine.
android:configChanges="keyboardHidden|orientation"
source How to handle an AsyncTask during Screen Rotation?
In your AndroidManifest.xml add following for prevent reloading activity when orientation change
android:configChanges="orientation|screenSize"
So, you'll have something like this:
<activity android:name="Activity"
android:configChanges="orientation|screenSize">
</activity>
Hope it works!

Save the Tab state during orientation change

I have 2 tabs , for example Tab1 & Tab2 which is displayed on the screen. Let the tabs be displayed on the PORTRAIT orientation.
Tab1 displays Activity1 & Tab2 displays Activity2.
Currently , the selected tab state is Tab2 . Now , I change the orientation for PORTRAIT to LANDSCAPE . On changing the orientation to LANDSCAPE mode , instead of displaying Tab2 , currently Tab1 is displayed.
Basically , I want to save the Tab state when there is orientation change.
In order to perform the objective of saving the tab state , I am writing the following code:
protected void onPause() {
super.onPause();
saveCurrentTabState(getSelectedTab());
}
private void saveCurrentTabState(int value) {
PreferenceManager.getDefaultSharedPreferences(this).edit().putInt(
"tabState", value).commit();
}
#Override
protected void onResume() {
super.onResume();
setCurrentTab(PreferenceManager.getDefaultSharedPreferences(this)
.getInt("tabState", 0));
}
I wanted to know , is my approach correct or not & whether the above code is a proper way of saving the tab state on changing the orientation.
That's not the way it should be done... instead use the:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("tabState", getSelectedTab());
}
Then, on the onCreate method:
public void onCreate(Bundle state){
// do the normal onCreate stuff here... then:
if( state != null ){
setCurrentTab(state.getInt("tabState"));
}
}
The Robby's solution will work too and involves using the onRetainNonConfigurationInstance method. I actually like and prefer that method over onSaveInstanceState since it allows you save a complex object that represents the state of the app, not only parceables inside a Bundle.
So when to use one of the other? It depends on the data you need to save/restore the state of the app. For simple things like saving the tab state, it's almost the same.
That's not the best way. You should use onRetainNonConfigurationInstance() and getLastNonConfigurationInstance() to retain the state between config changes. Those methods are specifically for saving state during config changes.
public Object onRetainNonConfigurationInstance() {
return mTabHost.getCurrentTab();
}
public void onCreate() {
...
Integer lastTab = (Integer) getLastNonConfigurationInstance();
if(lastTab != null) {
mTabHost.setCurrentTab(lastTab);
}
...
}

When I rotate the screen, my activity restart? how can I stop this? [duplicate]

In my Android application, when I rotate the device (slide out the keyboard) then my Activity is restarted (onCreate is called). Now, this is probably how it's supposed to be, but I do a lot of initial setting up in the onCreate method, so I need either:
Put all the initial setting up in another function so it's not all lost on device rotation or
Make it so onCreate is not called again and the layout just adjusts or
Limit the app to just portrait so that onCreate is not called.
Using the Application Class
Depending on what you're doing in your initialization you could consider creating a new class that extends Application and moving your initialization code into an overridden onCreate method within that class.
public class MyApplicationClass extends Application {
#Override
public void onCreate() {
super.onCreate();
// TODO Put your application initialization code here.
}
}
The onCreate in the application class is only called when the entire application is created, so the Activity restarts on orientation or keyboard visibility changes won't trigger it.
It's good practice to expose the instance of this class as a singleton and exposing the application variables you're initializing using getters and setters.
NOTE: You'll need to specify the name of your new Application class in the manifest for it to be registered and used:
<application
android:name="com.you.yourapp.MyApplicationClass"
Reacting to Configuration Changes [UPDATE: this is deprecated since API 13; see the recommended alternative]
As a further alternative, you can have your application listen for events that would cause a restart – like orientation and keyboard visibility changes – and handle them within your Activity.
Start by adding the android:configChanges node to your Activity's manifest node
<activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="#string/app_name">
or for Android 3.2 (API level 13) and newer:
<activity android:name=".MyActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="#string/app_name">
Then within the Activity override the onConfigurationChanged method and call setContentView to force the GUI layout to be re-done in the new orientation.
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.myLayout);
}
Update for Android 3.2 and higher:
Caution: Beginning with Android 3.2 (API level 13), the "screen size" also changes when the device switches between portrait and landscape orientation. Thus, if you want to prevent runtime restarts due to orientation change when developing for API level 13 or higher (as declared by the minSdkVersion and targetSdkVersion attributes), you must include the "screenSize" value in addition to the "orientation" value. That is, you must declare android:configChanges="orientation|screenSize". However, if your application targets API level 12 or lower, then your activity always handles this configuration change itself (this configuration change does not restart your activity, even when running on an Android 3.2 or higher device).
From http://web.archive.org/web/20120805085007/http://developer.android.com/guide/topics/resources/runtime-changes.html
Instead of trying to stop the onCreate() from being fired altogether, maybe try checking the Bundle savedInstanceState being passed into the event to see if it is null or not.
For instance, if I have some logic that should be run when the Activity is truly created, not on every orientation change, I only run that logic in the onCreate() only if the savedInstanceState is null.
Otherwise, I still want the layout to redraw properly for the orientation.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_list);
if(savedInstanceState == null){
setupCloudMessaging();
}
}
not sure if this is the ultimate answer, but it works for me.
what I did...
in the manifest, to the activity section, added:
android:configChanges="keyboardHidden|orientation"
in the code for the activity, implemented:
//used in onCreate() and onConfigurationChanged() to set up the UI elements
public void InitializeUI()
{
//get views from ID's
this.textViewHeaderMainMessage = (TextView) this.findViewById(R.id.TextViewHeaderMainMessage);
//etc... hook up click listeners, whatever you need from the Views
}
//Called when the activity is first created.
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
InitializeUI();
}
//this is called when the screen rotates.
// (onCreate is no longer called when screen rotates due to manifest, see: android:configChanges)
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
setContentView(R.layout.main);
InitializeUI();
}
What you describe is the default behavior. You have to detect and handle these events yourself by adding:
android:configChanges
to your manifest and then the changes that you want to handle. So for orientation, you would use:
android:configChanges="orientation"
and for the keyboard being opened or closed you would use:
android:configChanges="keyboardHidden"
If you want to handle both you can just separate them with the pipe command like:
android:configChanges="keyboardHidden|orientation"
This will trigger the onConfigurationChanged method in whatever Activity you call. If you override the method you can pass in the new values.
Hope this helps.
I just discovered this lore:
For keeping the Activity alive through an orientation change, and handling it through onConfigurationChanged, the documentation and the code sample above suggest this in the Manifest file:
<activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="#string/app_name">
which has the extra benefit that it always works.
The bonus lore is that omitting the keyboardHidden may seem logical, but it causes failures in the emulator (for Android 2.1 at least): specifying only orientation will make the emulator call both OnCreate and onConfigurationChanged sometimes, and only OnCreate other times.
I haven't seen the failure on a device, but I have heard about the emulator failing for others. So it's worth documenting.
You might also consider using the Android platform's way of persisting data across orientation changes: onRetainNonConfigurationInstance() and getLastNonConfigurationInstance().
This allows you to persist data across configuration changes, such as information you may have gotten from a server fetch or something else that's been computed in onCreate or since, while also allowing Android to re-layout your Activity using the xml file for the orientation now in use.
See here or here.
It should be noted that these methods are now deprecated (although still more flexible than handling orientation change yourself as most of the above solutions suggest) with the recommendation that everyone switch to Fragments and instead use setRetainInstance(true) on each Fragment you want to retain.
The approach is useful but is incomplete when using Fragments.
Fragments usually get recreated on configuration change. If you don't wish this to happen, use
setRetainInstance(true); in the Fragment's constructor(s)
This will cause fragments to be retained during configuration change.
http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)
I just simply added:
android:configChanges="keyboard|keyboardHidden|orientation"
in the AndroidManifest.xml file and did not add any onConfigurationChanged method in my activity.
So every time the keyboard slides out or in nothing happens! Also checkout this article about this problem.
The onCreate method is still called even when you change the orientation of android. So moving all the heavy functionality to this method is not going to help you
Put the code below inside your <activity> tag in Manifest.xml:
android:configChanges="screenLayout|screenSize|orientation"
It is very simple just do the following steps:
<activity
android:name=".Test"
android:configChanges="orientation|screenSize"
android:screenOrientation="landscape" >
</activity>
This works for me :
Note: orientation depends on your requitement
onConfigurationChanged is called when the screen rotates.
(onCreate is no longer called when the screen rotates due to manifest, see:
android:configChanges)
What part of the manifest tells it "don't call onCreate()"?
Also,
Google's docs say to avoid using android:configChanges (except as a last resort). But then the alternative methods they suggest all DO use android:configChanges.
It has been my experience that the emulator ALWAYS calls onCreate() upon rotation.
But the 1-2 devices that I run the same code on... do not.
(Not sure why there would be any difference.)
Changes to be made in the Android manifest are:
android:configChanges="keyboardHidden|orientation"
Additions to be made inside activity are:
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
Add this line to your manifest :-
android:configChanges="orientation|keyboard|keyboardHidden|screenSize|screenLayout|uiMode"
and this snippet to the activity :-
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
There are several ways to do this:
Save Activity State
You can save the activity state in onSaveInstanceState.
#Override
public void onSaveInstanceState(Bundle outState) {
/*Save your data to be restored here
Example: outState.putLong("time_state", time); , time is a long variable*/
super.onSaveInstanceState(outState);
}
and then use the bundle to restore the state.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState!= null){
/*When rotation occurs
Example : time = savedInstanceState.getLong("time_state", 0); */
} else {
//When onCreate is called for the first time
}
}
Handle orientation changes by yourself
Another alternative is to handle the orientation changes by yourself. But this is not considered a good practice.
Add this to your manifest file.
android:configChanges="keyboardHidden|orientation"
for Android 3.2 and later:
android:configChanges="keyboardHidden|orientation|screenSize"
#Override
public void onConfigurationChanged(Configuration config) {
super.onConfigurationChanged(config);
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
//Handle rotation from landscape to portrait mode here
} else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
//Handle rotation from portrait to landscape mode here
}
}
Restrict rotation
You can also confine your activity to portrait or landscape mode to avoid rotation.
Add this to the activity tag in your manifest file:
android:screenOrientation="portrait"
Or implement this programmatically in your activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
The way I have found to do this is use the onRestoreInstanceState and the onSaveInstanceState events to save something in the Bundle (even if you dont need any variables saved, just put something in there so the Bundle isn't empty). Then, on the onCreate method, check to see if the Bundle is empty, and if it is, then do the initialization, if not, then do it.
Even though it is not "the Android way" I have gotten very good results by handling orientation changes myself and simply repositioning the widgets within a view to take the altered orientation into account. This is faster than any other approach, because your views do not have to be saved and restored. It also provides a more seamless experience to the user, because the respositioned widgets are exactly the same widgets, just moved and/or resized. Not only model state, but also view state, can be preserved in this manner.
RelativeLayout can sometimes be a good choice for a view that has to reorient itself from time to time. You just provide a set of portrait layout params and a set of landscaped layout params, with different relative positioning rules on each, for each child widget. Then, in your onConfigurationChanged() method, you pass the appropriate one to a setLayoutParams() call on each child. If any child control itself needs to be internally reoriented, you just call a method on that child to perform the reorientation. That child similarly calls methods on any of its child controls that need internal reorientation, and so on.
Every time when the screen is rotated, opened activity is finished and onCreate() is called again.
1 . You can do one thing save the state of activity when the screen is rotated so that, You can recover all old stuff when the activity's onCreate() is called again.
Refer this link
2 . If you want to prevent restarting of the activity just place the following lines in your manifest.xml file.
<activity android:name=".Youractivity"
android:configChanges="orientation|screenSize"/>
you need to use the onSavedInstanceState method to store all the values to its parameter is has which is a bundle
#Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
outPersistentState.putBoolean("key",value);
}
and use
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
savedInstanceState.getBoolean("key");
}
to retrieve and set the value to view objects
it will handle the screen rotations
Note: I post this answer if someone in the future face the same problem as me. For me the following line wasn't enough:
android:configChanges="orientation"
When I rotated the screen, the method `onConfigurationChanged(Configuration new config) didn't get called.
Solution: I also had to add "screenSize" even if the problem had to do with the orientation. So in the AndroidManifest.xml - file, add this:
android:configChanges="keyboardHidden|orientation|screenSize"
Then implement the method onConfigurationChanged(Configuration newConfig)
In the activity section of the manifest, add:
android:configChanges="keyboardHidden|orientation"
Add this line in manifest : android:configChanges="orientation|screenSize"
People are saying that you should use
android:configChanges="keyboardHidden|orientation"
But the best and most professional way to handle rotation in Android is to use the Loader class. It's not a famous class(I don't know why), but it is way better than the AsyncTask. For more information, you can read the Android tutorials found in Udacity's Android courses.
Of course, as another way, you could store the values or the views with onSaveInstanceState and read them with onRestoreInstanceState. It's up to you really.
One of the best components of android architecture introduced by google will fulfill all the requirements that are ViewModel.
That is designed to store and manage UI-related data in a lifecycle way plus that will allow data to survive as the screen rotates
class MyViewModel : ViewModel() {
Please refer to this: https://developer.android.com/topic/libraries/architecture/viewmodel
After a while of trial and error, I found a solution which fits my needs in the most situations. Here is the Code:
Manifest configuration:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.pepperonas.myapplication">
<application
android:name=".App"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
MainActivity:
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MainActivity";
private Fragment mFragment;
private int mSelected = -1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate " + "");
// null check not realy needed - but just in case...
if (savedInstanceState == null) {
initUi();
// get an instance of FragmentTransaction from your Activity
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
/*IMPORTANT: Do the INITIAL(!) transaction only once!
* If we call this everytime the layout changes orientation,
* we will end with a messy, half-working UI.
* */
mFragment = FragmentOne.newInstance(mSelected = 0);
fragmentTransaction.add(R.id.frame, mFragment);
fragmentTransaction.commit();
}
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.d(TAG, "onConfigurationChanged " +
(newConfig.orientation
== Configuration.ORIENTATION_LANDSCAPE
? "landscape" : "portrait"));
initUi();
Log.i(TAG, "onConfigurationChanged - last selected: " + mSelected);
makeFragmentTransaction(mSelected);
}
/**
* Called from {#link #onCreate} and {#link #onConfigurationChanged}
*/
private void initUi() {
setContentView(R.layout.activity_main);
Log.d(TAG, "onCreate instanceState == null / reinitializing..." + "");
Button btnFragmentOne = (Button) findViewById(R.id.btn_fragment_one);
Button btnFragmentTwo = (Button) findViewById(R.id.btn_fragment_two);
btnFragmentOne.setOnClickListener(this);
btnFragmentTwo.setOnClickListener(this);
}
/**
* Not invoked (just for testing)...
*/
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(TAG, "onSaveInstanceState " + "YOU WON'T SEE ME!!!");
}
/**
* Not invoked (just for testing)...
*/
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d(TAG, "onSaveInstanceState " + "YOU WON'T SEE ME, AS WELL!!!");
}
#Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume " + "");
}
#Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause " + "");
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy " + "");
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_fragment_one:
Log.d(TAG, "onClick btn_fragment_one " + "");
makeFragmentTransaction(0);
break;
case R.id.btn_fragment_two:
Log.d(TAG, "onClick btn_fragment_two " + "");
makeFragmentTransaction(1);
break;
default:
Log.d(TAG, "onClick null - wtf?!" + "");
}
}
/**
* We replace the current Fragment with the selected one.
* Note: It's called from {#link #onConfigurationChanged} as well.
*/
private void makeFragmentTransaction(int selection) {
switch (selection) {
case 0:
mFragment = FragmentOne.newInstance(mSelected = 0);
break;
case 1:
mFragment = FragmentTwo.newInstance(mSelected = 1);
break;
}
// Create new transaction
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.frame, mFragment);
/*This would add the Fragment to the backstack...
* But right now we comment it out.*/
// transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
}
And sample Fragment:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* #author Martin Pfeffer (pepperonas)
*/
public class FragmentOne extends Fragment {
private static final String TAG = "FragmentOne";
public static Fragment newInstance(int i) {
Fragment fragment = new FragmentOne();
Bundle args = new Bundle();
args.putInt("the_id", i);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d(TAG, "onCreateView " + "");
return inflater.inflate(R.layout.fragment_one, container, false);
}
}
Can be found on github.
Use orientation listener to perform different tasks on different orientation.
#Override
public void onConfigurationChanged(Configuration myConfig)
{
super.onConfigurationChanged(myConfig);
int orient = getResources().getConfiguration().orientation;
switch(orient)
{
case Configuration.ORIENTATION_LANDSCAPE:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
case Configuration.ORIENTATION_PORTRAIT:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
default:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
}
Put this below code in your Activity in Android Manifest.
android:configChanges="orientation"
This will not restart your activity when you would change orientation.
Fix the screen orientation (landscape or portrait) in AndroidManifest.xml
android:screenOrientation="portrait" or android:screenOrientation="landscape"
for this your onResume() method is not called.
You may use the ViewModel object in your activity.
ViewModel objects are automatically retained during configuration changes so that the data they hold is immediately available to the next activity or fragment instance.
Read more:
https://developer.android.com/topic/libraries/architecture/viewmodel

Android - switching between landscape and portrait mode makes Intent lose values

I am using Intents to switch between activities in my Android app. I am putting data in the Intent for use in the next activity. When I switch the phone between landscape and portrait modes, the values passed from the intent are lost and I get a NullPointerException.
Can someone please tell me what could be wrong.
There's a lot of code to post it entirely. But if someone needs to look at specific parts of code, I can post it here.
Edit
I solved the issue of state not being saved. But another problem I faced is that none of the buttons on the screen work after the orientation has been changed. On button press, I get this warning in LogCat
02-25 23:07:49.190: WARN/WindowManager(58): No window to dispatch pointer action 0
Please help.
When you switch orientation the activity is recreated and onCreate is recalled so you have to use the bundle to save your current state and restore after an orientation change. You can see this in action if you have just an app with a TextView and you enter text and change orientation. If you bundle your state for onCreate you can curb this. This is probably also why you have a NullPointer after the orientation changes. It is annoying as all hell but something we have to live with.
This link on a series of orientation tutorials and this first one in particular should help you understand exactly what is going on and how to successfully maintain your current state.
Update: There is also a post on SO Activity restart on rotation Android that deals with almost the same thing.
Edit for follow up question:
Did you re-attach your click handlers after the orientation change?
Write this in your manifest file..in which activity you want this--
android:configChanges="orientation|keyboardHidden"
Edited: Use this one for new APIs versions--
android:configChanges="orientation|keyboardHidden|screenSize"
Definitely it will work..
Try this:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(SOME_KEY, "blah blah blah");
}
#Override
public void onCreate(Bundle savedInstanceState) {
...
somevalue = savedInstanceState.getString(SOME_KEY);
...
}
It possible to declare an attribute android:configChanges with the value of "orientation", this will prevent the activity from being restarted. Instead, the activity remains running and its onConfigurationChanged() method is called.
Declare < android:configChanges="orientation|keyboardHidden"/> in your manifest. This allows you manage the change of Orientation/Keyboard visibility by yourself. Of course, You don't need to override the callback method for manage it.
Hi I also encountered this problem.
what fixed it for me was:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putString("Username", mUsername);
savedInstanceState.putString("Password", mPassword);
savedInstanceState.putString("UserID", mUserID);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
and then in onCreate():
if (savedInstanceState == null) {
Bundle extras = getIntent().getExtras();
if(extras == null) {
mUsername = "?";
mPassword = "?";
mUserID = "?";
} else {
mUsername = extras.getString("Username");
mPassword = extras.getString("Password");
mUserID = extras.getString("UserID");
}
} else {
mUsername = (String) savedInstanceState.getSerializable("Username");
mPassword = (String) savedInstanceState.getSerializable("Password");
mUserID = (String) savedInstanceState.getSerializable("UserID");
}
then you can be sure the objects are not null.

Categories

Resources