Question

OK guys, I am done with it. I have been googling for last 2 days but I can't find the exact solution. Everyone is talking about configChanges and all those cliche things which do not seem to work in my case .

I have a login screen which consists of 2 EditTexts. Now this login screen has different layout for both Portrait and Landscape orientation . So I had to create one login.xml in layout folder and another login.xml in layout-land folder. And to support orientation changes I overrid onConfigurationChanged() method in LoginActivity class. In this method I call setContentView(R.layout.login) method so that appropriate login.xml is set as layout fro every orientation.

After all this I defined following in my manifest file as well:

android:configChanges="orientation|keyboardHidden"

But still I am facing the famous old problem. If there is any text in the Edittext and the device is rotated, that text is lost. I don't want to lose that text. Is it possible or not? I have read that we can do it using onSaveInstanceState(Bundle savedInstanceState) method and I have even tried that too but it din't work for me. Please help. Thanks in advance.

Was it helpful?

Solution

Use the put methods to store values in onSaveInstanceState:

protected void onSaveInstanceState(Bundle extra) {
  super.onSaveInstanceState(extra);
  extra.putString("text", "your text here");
}

And restore the values in onCreate:

public void onCreate(Bundle extra) {
  if (extra != null) {
    String value = extra.getString("text");
  }
}

EDIT(What actually worked):

try to delete android:configChanges="orientation|keyboardHidden" from manifest.

Good luck!

OTHER TIPS

First remove all onConfigurationChanged and configChanges=orientation stuff you did - this solution is for the weak. Then do the following:

  1. Override onRetainNonConfigurationInstance() so that it returns the texts that you need to save on device rotation. You may need to create a simple Object that contains these values - for example:

    public class TextObject {
        public String loginText;
        public String passwordText;
    }
    
  2. In onCreate, after initializing your views, try getting the saved object from rotation via getLastNonConfigurationInstance(). This will return null if it's the first time you're going through onCreate, so you need to do a null check. Example:

    TextObject mySavedTextObject = (TextObject) getLastNonConfigurationInstance();
    if(mySavedTextObject!=null) {
      myLoginEditText.setText(mySavedTextObject.loginText);
      myPasswordEditText.setText(mySavedTextObject.passwordText);
    }
    

On https://github.com/jcraane/AndroidBundleState you find a very simple library handling the state logic for you. All you have to do is annotate you fields.

@BundleState("state_name") private String name; The library will restore the values in the fields for you after the rotationChange.

Simply set this for your login text and password text

textView.setSaveEnabled(false);

This may be unconventional or overkill, but I have found stashing data in bundles in the Application class most universally successful and intuitive for Fragments and Activities.

In your Application class add:

static class Bundles {
    static Bundle USER_BUNDLE = null;
}

Then in your Fragment or Activity add:

private String username = "";

@Override
public void onSaveInstanceState(@NonNull Bundle extra) {
    super.onSaveInstanceState(extra);
    EditText txtUsername = v.findViewById(R.id.user_name);
    String username = txtUsername==null ? "" : txtUsername.getText().toString();
    MyApplication.Bundles.USER_BUNDLE = new Bundle();
    MyApplication.Bundles.USER_BUNDLE.putString("User.username", username);     
}

@Override
public void onCreate(Bundle extra) {
    super.onCreate(extra);
    if (MyApplication.Bundles.USER_BUNDLE != null) {
        username = MyApplication.Bundles.USER_BUNDLE.getString("User.username", "");
    }
}

and then wherever you set up the view components add something like:

EditText txtUsername = v.findViewById(R.id.user_name);
if (txtUsername!=null) txtUsername.setText(username);

It's easy to add multiple values of different types, and if you use fragments you can even share data across them.

At the point (time) in your code where the orientation is about to change, implement this:

this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

But this has to be placed before the screen is changing orientation e.g. while returning from device camera to your app, it often happens that the app returns and changes the orientation again without any reason.

And don`t forget to mark me =)

Good luck.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top