I create an activity contain tabhost with 3 tabs, also define
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize">
in the manifest for changed orientation, it helps me to remain on the same tab on landscape mode. But when I create a new xml file for the landscape mode and I put it into res/layout-land.My problem is when I entered into 2nd or 3rd tab and changed to landscape mode it calls the xml in layout- land but tab host switches to 1st tab.Kindly help me on this.
thank you.
It's better to override #onSaveInstance to save the position of the current tab.
And in onCreate method you can check for the position and set the tab according to the position
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the current position of the tab
savedInstanceState.putInt(CURRENT_TAB, getTabHost().getCurrentTab());
super.onSaveInstanceState(savedInstanceState);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Check for the tabPosition Value
if (savedInstanceState != null) {
// Restore tab position from saved state and set to TaBHost
mCurrentTab= savedInstanceState.getInt(CURRENT_TAB);
}
//initialize the tabHost and tab
tabHost.setCurrentTab(mCurrentTab);
Related
I have read a lot of things about the data save instance and restore but Unable to implement in my case. What is my case in application .
I am using the Activity (MainActivity) and calling the fragment in it let say ParentFragment
ParentFragment Calls the ChildFragment in it though ParentFragment has its own views such as TextViews which takes First name, Last name and age and below this part I am programatically calling the ChildFragment
So in this way I have 2 fragments in the MainActivity, which is being shown to the user at a time on the screen
**What I want **
I want when User has change the orientation the layout should also change but I also want that the text fields should maintain there data in them .
I want to save some more fragment variables and their data also on configuration changes and retrieve them after the new layout is set after screen orientation changed.
**Problems and Confusions **
I have no idea If i set the Fragment.setRetainInstance(true) then would my fragment still be able to receive the onConfiguration Change call back?
When I rotate my device, the fragment gets re-initialize and also my activity has the Asynctask and that runs again , i want my activity to hold the same data . How can I achieve that?
Please help me and give me some hint.
If you want to change layout on orientation change then,you should not handle configuration change by retaining the activity(by setting android:configChanges="orientation" value for corresponding activity defined in manifest) or by using setRetainInstance() in fragment.
For saving the fragment state on configuration change use
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(FIRST_NAME_VALUE_KEY, firstNameTextView.getText());
outState.putInt(LAST_NAME_VALUE_KEY, lastNameTextView.getText());
super.onSaveInstanceState(outState);
}
and for writing back state to the views in fragment use
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.my_fragment, container, false);
if (savedInstanceState != null) {
String firstName = savedInstanceState.getInt(FIRST_NAME_VALUE_KEY);
String lastName = savedInstanceState.getInt(LAST_NAME_VALUE_KEY);
firstNameTextView.setText(firstName);
lastNameTextView.setText(lastName);
}
return view;
}
You will receive onConfigurationChanged() callback by retaining activity.it is not related to Fragment.setRetainInstance(true).
To avoid running asynctask again,We can store data and retain it using following callbacks inside the activity.
#Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
// Save custom values into the bundle
savedInstanceState.putInt(SOME_VALUE, someIntValue);
savedInstanceState.putString(SOME_OTHER_VALUE, someStringValue);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
in onCreate(Bundle savedInstanceState) call back you can check for savedInstanceSate , based on that you can call u asynctask or retain values as below
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
asyncTask.execute();
} else {
someIntValue = savedInstanceState.getInt(SOME_VALUE);
someStringValue = savedInstanceState.getString(SOME_OTHER_VALUE);
}
}
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()
I am new to fragments and have a lot of problems understanding and working with them. I will try to describe my problem step by step:
I start with a list
after selecting an item i start an activity with a dynamic url in a webview
If portrait, only the webview is showed, if landscape the list is presented next to it
In landscape when i select another item, it is showd in the webview (check the code)
Problem: When i turn back now to portrait the first selected item is showd instead of the last one.
How can i update the activity so it will keep the last opened url after orientation change?
if (fragment==null || ! fragment.isInLayout()) {
Intent intent = new Intent(this.getActivity(), DetailViewActivity.class);
intent.putExtra("link", urlforwebview);
startActivity(intent);
} else {
DetailView detailFragment =
(DetailView)
getFragmentManager().findFragmentById(R.id.detailfragment);
detailFragment.changeWebviewURL(urlforwebview);
}
FIX:
Added this to my detailfragment:
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("currentUrl", url);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
// Restore last state for checked position.
url = savedInstanceState.getString("currentUrl", "");
changeWebviewURL(url);
}
}
Have a look at : onSaveInstanceState.
http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)
This answer here can help you: android fragment- How to save states of views in a fragment when another fragment is pushed on top of it
In my application i have a FragmentPager. Now each Fragment has a next button with which i navigate to the next fragment. Via the next button i know that the user is navigation away from the view. But how do i know if the user has clicked on the tabs. Will the
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(KEY_CONTENT, mContent);
}
function be called when a user presses a different tab ? Can i save the state and restore it on the
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if ((savedInstanceState != null)
&& savedInstanceState.containsKey(KEY_CONTENT)) {
mContent = savedInstanceState.getString(KEY_CONTENT);
}
}
will this work ? What other way can i know that the user has clicked on the different tab ?
Kind Regards
First of all, are you using ActionBarSherlock for you actionbar/tabs? I recommend that you do since you'll get a cross-version way of working with the actionbar.
In any case, you should add a listener to each tab before adding it to the actionbar. With the listener implemented you know when a tab has been selected, reselected and unselected
I'm not sure about when the onSaveInstanceState is called (try it using the debugger!), but with the listener implemented you'll get a fool-proof way of knowing what goes on with your tabs.
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
}
}