Screen orientation landscape change activity - android

I'm making an app that change the colors depending of the color you select this change the background, but when I make the screen orientation to landscape this automatically change the color to the predefined and if I'm not wrong this happen because it's being destroy after I change the orientation... so I would like to know where and how I can solve that problem.

Android gives you a chance to save state before changing the layout
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mColor = savedInstanceState.getString(COLOR_VALUE);
}
#Override //this method is called before android trashes and recreates your activity
protected void onSaveInstanceState (Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(COLOR_VALUE, mColor);
}
If your UI is expensive to recreate then look into retained fragments instead

Related

Saving state in Android not working

I have an activity that contains a fragment in it. The fragment has a progress bar and a text view, along with some other stuff. The progress bar and the text view both are visible sometimes, invisible at other times depending on some application logic.
What I'm trying to do is save the current state of both these views when the screen is rotated. Here is the relevant code in my fragment -
#Override
public void onSaveInstanceState(Bundle outState) {
// pbTranscribe is my progress bar
if (pbTranscribe != null) {
Log.d(TAG, "saving pb visibility");
boolean visibility = (pbTranscribe.getVisibility() == ProgressBar.VISIBLE);
outState.putBoolean("pbVisible", visibility);
}
}
#Override
public void onViewStateRestored(Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
if (savedInstanceState != null) {
Log.d(TAG, "bundle available !!");
boolean pbVisible = savedInstanceState.getBoolean("pbVisible", false);
Log.d(TAG, "is visible? " + pbVisible);
if (pbVisible) {
pbTranscribe.setVisibility(ProgressBar.VISIBLE);
}
}
}
The above code doesn't seem to be working for some reason. If I rotate my screen when the progress bar is visible, logcat prints all the above messages ("saving pb visibility", "bundle available !!", "is visible? true"). I know for a fact that my application logic doesn't set the visibility to invisible during this time.
Even though the value obtained from the bundle is true, the progress bar doesnt become visible, i.e. pbTranscribe.setVisibility(ProgressBar.VISIBLE); is apparently not doing its job.
Where am I going wrong ? How do I successfully maintain the progress bar state ?
I have also tried to restore the state in onCreateView() and onActivityCreated(), same results. Also, I have tried saving the text view state in a similar fashion, but that also gives the same results. Saving the text view state with android:freezesText="true" also did not do the trick.
EDIT: This is how I add the fragment to the activity, in the activity's onCreate() method -
#Override
protected void onCreate(Bundle savedInstanceState) {
...
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragments_frame, new WatsonFragment())
.commit();
...
}
When screen rotated, Activity will call onCreate and create another WatsonFragment, modify you code to this
if(savedInstanceState==null){
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragments_frame, new WatsonFragment())
.commit();
}

Page position on a ViewPager when change from portrait to landscape

I have a problem when I change from portrait to landscape orientation when programing a gallery. The page position in the method PageAdapter.instantiateItem(View container, int position) turns 0 when change the screen orientation. I want to store the current page position to keep in this page when the orientation changes.
You will need to store the currently displayed page in your saved instance state. For how to save state, please read the documentation.
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the current item
savedInstanceState.putInt("current_item", pager.getCurrentItem());
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
After an orientation change, that state can be restored and used to set your pagers position.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mCurrentItem = savedInstanceState.getInt("current_item");
}
}
Call pager.setCurrentItem(mCurrentItem); e.g. in your onStart() or onResume() method.
For how to get and set the currently selected item read the ViewPager documentation:
getCurrentItem()
setCurrentItem()

manage screen orientation change android

I have a activity with multiples initializations ( fragments , sharedpreferences , services , ui components(search bar , buttons etc..)...) and i do not want to restart the activity when the screen orientation change
I found a easy ( and working solution ) by using android:configChanges="keyboardHidden|orientation|screenSize" but my technical manager forbade me this way because according to him it's a bad practice
What are the other ways in order to handle properly the screen orientation changes?
Thank you very much
My main activity
#AfterViews
public void afterViews() {
putSharedPrefs();
initializeFragments();
initializeComponents();
initializeSynchronizeDialog();
initDownloadDialog();
}
You can just add layout for landscape mode.
You just need to add folder layout-land in your "res" directory and define layout for what your activity looks like if it is in landscape mode.
NOTE-Keep xml file name same as the name which is in simple layout folder and which you are using in your activity. It will automatically detect your screen orientation and apply layout accordingly.
EDIT1
Now to save your text from the text view =) Lets assume your textview is named as MyTextView in your layout xml file. Your activity will need the following:
private TextView mTextView;
private static final String KEY_TEXT_VALUE = "textValue";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTextView = (TextView) findViewById(R.id.main);
if (savedInstanceState != null) {
String savedText = savedInstanceState.getString(KEY_TEXT_VALUE);
mTextView.setText(savedText);
}
#Override
protected void onSaveInstanceState (Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(KEY_TEXT_VALUE, mTextView.getText());
}
Basically, whenever Android destroys and recreates your Activity for orientation change, it calls onSaveInstanceState() before destroying and calls onCreate() after recreating. Whatever you save in the bundle in onSaveInstanceState, you can get back from the onCreate() parameter.
So you want to save the value of the text view in the onSaveInstanceState(), and read it and populate your textview in the onCreate(). If the activity is being created for the first time (not due to rotation change), the savedInstanceState will be null in onCreate(). You also probably don't need the android:freezesText="true"
You can also try saving other variables if you need to, since you'll lose all the variables you stored when the activity is destroyed and recreated.

Restoring displayed fragment on activity rotation

I have a fragment with one main fragment displayed on it. When I rotate the screen, the activity is beeing recreated. What would be the best way to store the info about currently displayed fragment for screen state restore purposes?
You can use the method onSaveInstanceState to store values in a bundle:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(MY_FIRST_KEY,valueToSave);
}
then you can restore the values in the method onRestoreInstanceState
#Override
protected void onRestoreInstanceState(Bundle inState) {
super.onRestoreInstanceState(inState);
valueToSave = inState.getString(MY_FIRST_KEY);
}
You can also set an xml attribute on TextViews and EditText called "freezeText" which saves any text that was set.

Save state of activity when orientation changes android

I have an aacplayer app and I want to save the state of my activity when orientation changes from portrait to landscape. The TextViews do not appear to be empty, I tried to freeze my textview using this:
android:freezesText="true"
my manifest:
android:configChanges="orientation"
I also tried this:
#Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
setContentView(R.layout.main2);
So when orientation changes to landscape I can see my layout-land main2.xml, that works but my textview goes out and appears empty. Streaming music works great. I can listen to it when orientation changes, but the text inside textviews are gone each time I change the orientation of my device.
What should I do to fix this so I can save the state?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
....
....
Thank you very much.
When your orientation changes, you don't have to manually change to the landscape layout file. Android does this automatically for you. When orientation changes, Android destroys your current activity and creates a new activity again, this is why you are losing the text.
There are 2 parts you need to do, assuming you want a separate layout for portrait and landscape.
Assuming you have 2 XML layout files for portrait and landscape, put your main.xml layout file in the following folders:
res/layout/main.xml <-- this will be your portrait layout
res/layout-land/main.xml <-- this will be your landscape layout
That's all you need to do, you don't have to touch the manifest file to modify android:configChanges="orientation" or override the onConfigurationChanged(). Actually, it's recommended you do not touch this for what you are trying to achieve.
Now to save your text from the text view =) Lets assume your textview is named as MyTextView in your layout xml file. Your activity will need the following:
private TextView mTextView;
private static final String KEY_TEXT_VALUE = "textValue";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTextView = (TextView) findViewById(R.id.main);
if (savedInstanceState != null) {
CharSequence savedText = savedInstanceState.getCharSequence(KEY_TEXT_VALUE);
mTextView.setText(savedText);
}
}
#Override
protected void onSaveInstanceState (Bundle outState) {
super.onSaveInstanceState(outState);
outState.putCharSequence(KEY_TEXT_VALUE, mTextView.getText());
}
Basically, whenever Android destroys and recreates your Activity for orientation change, it calls onSaveInstanceState() before destroying and calls onCreate() after recreating. Whatever you save in the bundle in onSaveInstanceState, you can get back from the onCreate() parameter.
So you want to save the value of the text view in the onSaveInstanceState(), and read it and populate your textview in the onCreate(). If the activity is being created for the first time (not due to rotation change), the savedInstanceState will be null in onCreate(). You also probably don't need the android:freezesText="true"
You can also try saving other variables if you need to, since you'll lose all the variables you stored when the activity is destroyed and recreated.
There are two ways of doing this, the first one is in the AndroidManifest.xml file. You can add this to your activity's tag
android:configChanges="keyboardHidden|orientation|screenSize|screenLayout"
Or you can override two methods that will take care of this. This method requires some more effort, but arguably is much better. onSaveInstanceState saves the state of the activity before it's killed, and onRestoreInstanceState restores that information after onStart() Refer to the official documentation for a more in depth look.
In my sample code below, I am saving 2 int values, the current selection from the spinner as well as a radio button.
#Override
public void onSaveInstanceState(#NonNull Bundle savedInstanceState) {
spinPosition = options.getSelectedItemPosition();
savedInstanceState.putInt(Constants.KEY, spinPosition);
savedInstanceState.putInt(Constants.KEY_RADIO, radioPosition);
super.onSaveInstanceState(savedInstanceState);
}
// And I am restoring those values with `getInt`, then I can pass those stored values into the spinner and radio button group to select the same values that we saved earlier.
#Override
public void onRestoreInstanceState(#NotNull Bundle savedInstanceState) {
spinPosition = savedInstanceState.getInt(Constants.KEY);
radioPosition = savedInstanceState.getInt(Constants.KEY_RADIO);
options.setSelection(spinPosition, true);
type.check(radioPosition);
super.onRestoreInstanceState(savedInstanceState);
}
static CharSequence savedText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedText != null) {
TextView mTextView = (TextView) findViewById(R.id.main);
mTextView.setText(savedText);
}
}
// Another function in activity, when you change text
public void actionButton(View view) {
// Change and save text in textView
savedText = "Change text";
mTextView.setText(savedText);
}
Its work for me.
But I think its not good code style and architecture for android.
I use in KOTLIN static var / val :
class MyFragment : Fragment()
{
//all my code
//access to static vars -> MyStaticClass.hello
}
class MyStaticClass
{
companion object {
var hello: String = "Static text"
var number_static: Int = 0
}
}

Categories

Resources