Fragment not retaining EditText value after screen rotation [duplicate] - android

This question already has answers here:
How to retain EditText data on orientation change?
(12 answers)
Closed 5 years ago.
I have already posted this question once and even tried all possible solutions. So please, if are going to downvote, at least provide the correct answer because I have tried out many solutions and nothing is working out.
In my app, I have an EditText inside the fragment which on orientation change, looses its value.One more thing, I am using different layouts for different orientations. Is there any way to retain the fragment data? I am again mentioning "Fragment data".Please find my Fragment code below for further reference.
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putString("fname",etxt_firstname.getText().toString());
outState.putString("lname",etxt_lastname.getText().toString());
super.onSaveInstanceState(outState);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// retain this fragment
setRetainInstance(true);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(savedInstanceState!= null)
{
etxt_firstname.setText(savedInstanceState.getString("fname"));
etxt_lastname.setText(savedInstanceState.getString("lname"));
}
}
Inside OnCreateView():
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
shrp_sharedpreferences = myContext.getSharedPreferences("shrp", Context.MODE_PRIVATE);
View view = null;
if(!isTablet(myContext))
{
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
{
view = inflater.inflate(R.layout.fragment_home_landscape, container, false);
}
else
{
view = inflater.inflate(R.layout.fragment_home, container, false);
}
}
else
{
view = inflater.inflate(R.layout.fragment_home, container, false);
}

Even though the fragment itself is retained, its view is destroyed when device is rotated in onDestroyView() (You should also clear any references to views there to prevent leaking old orientation).
Trying to restore text in onActivityCreated() does nothing because you're referencing views from old orientation, and they aren't used anymore.
When fragment is reattached (in Activity created for new orientation), new View is created in onCreateView() - this is where you can use savedInstanceState or any fragment fields to restore views to previous state:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// (...) your layout inflation and view binding logic...
if(savedInstanceState != null){
etxt_firstname.setText(savedInstanceState.getString("fname"));
etxt_lastname.setText(savedInstanceState.getString("lname"));
}
// return view you inflated
}

Related

Android get view of fragment in activity [duplicate]

This question already has answers here:
findViewById in Fragment
(37 answers)
Closed 2 years ago.
I have an activity, let's call it A, and it launches a fragment like so:
remoteFragment = new RemoteFragment();
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.frameLayout_remote_activity, remoteFragment)
.commit();
my remoteFragment looks something like this:
public Button okBtn;
public RemoteFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_remote, container, false);
okBtn= view.findViewById(R.id.okBtn);
return view;
}
public RemoteLayoutView getOkBtn() {
return okBtn;
}
and in my activity I am trying to get it like so:
Button okBtnMessageNotWorking = remoteFragment.getOkBtn();
but okBtnMessageNotWorking is always null.
my question is how can I get the view objects from the fragment inside my activity?
Here, you are trying to find the view from layoutOnTopScrollview. Instead you should find the okBtn from inflated view. Please change code as below:
#Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_remote, container, false);
okBtn= view.findViewById(R.id.okBtn);
return view;
}
Also, make sure that you are calling this method once the fragment is created.

When Fragment.onCreateView is complete and how to receive this event from the Activity? [duplicate]

This question already has answers here:
NullPointerException accessing views in onCreate()
(13 answers)
Closed 8 years ago.
EDIT
Changed title.
SDK Guide document says, Activity.onCreate complete after Fragment.onCreateView and Fragment.onAcvityCreated.
But If I try findViewById for a view of the fragment it returns null.
How can I access contents of the fragment?
I'm very new to Android UI dev.
Below is a sample code generated by Eclipse IDE.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
// this is null
View rootView = findViewById(R.id.txtView);
}
}
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
}
First of all, I want to access inner contents of the 'fragment_main'.
Can I do this with findViewById?
I found that calling findViewById for a view of the fragment at onCreate call is not working.
How do I know when the Fragment views are ready at the Activity level?
I read How to implement OnFragmentInteractionListener
Am I needed to manually implement a event listener for this?
I think short answer is 'impossible' or 'not works like that'.
If one want to manage inner contents of fragments just delete fragments and move all the contents to the activity layout.
But If I try findViewById for a view of the fragment it returns null.
You can not just access the view of the fragment in your activity's oncreate or where ever, you can call view of the fragment in your activity.
I found that calling findViewById for a view of the fragment at onCreate call is not working.
That is because the view is not inflated yet in your fragment thus returning null.
Have a look at the fragment life cycle:
(source: xamarin.com)
As you can see onCreate is before onCreateView which you inflate your view for the fragment's layout.
solution:
you call findViewByIdit in your fragment's onActivityCreated.
sample:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
TextView sample = (TextView) getView().findViewById(your_id);
}

Save simple variable in Android Fragment

this is my issue, when I create a fragment in android for example let's Say:
GastosSectionFragment gastosFragment = new GastosSectionFragment();
Fragment.gastosFragment.darUserID(userKey);
I send a simple Integer to that activity, no problem. For example lets say I send the number 1. It will be stored in attribute inside that class, because I create the fragment.
Everything will work fine, I receive the number. But when I rotate the phone, the variable "userKEY will be lost, it will converted to cero" I can't save that number when I rotate horizontally my phone, how can I save the data of that variable.
Here I put the code of how I recieve the "userKey" inside the Fragment,
public long darUserID(long userKey) {
// TODO Auto-generated method stub
return user_id = userKey;
}
And the attribute with the onCreate method.
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_section_gastos,
container, false);
idStatico = darUserID(user_id);
And I can't save that little number. this is not a FragmentActivity, this class is just a FRAGMENT. First time fine, rotate screen lost the number that I previously recieve. Fragment doesn't have OnSaveBundleInstances.
Fragment can save user_id in bundle in onSaveInstanceState method and restore after orientation change in onCreateView method. Check this fragment guide, especially in example is shown saving fragment state.
Activity code stays the same (I just changed method name) and your fragment should look like this:
class GastosSectionFragment extends Fragment {
private static final String BUNDLE_USER_ID = "BUNDLE_USER_ID";
private long user_id;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_section_gastos, container, false);
if (savedInstanceState != null)
user_id = savedInstanceState.getLong(BUNDLE_USER_ID);
// now is your user_id restored after orientation change,
// so you can do some stuff with it
return rootView;
}
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putLong(BUNDLE_USER_ID, user_id);
}
public long setUserID(long userKey) {
this.user_id = userKey;
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
add method override, and you variable saving state
After KOSO answer, this is how I solve the problem, hope it helps someone else.
When I create the Fragment for first time everything work well, send the userKey, everything is fine.
GastosSectionFragment gastosFragment = new GastosSectionFragment();
Fragment.gastosFragment.darUserID(userKey);
Now in order to fix that, a fragment when the phone is rotated, for example to horizontal it will call the override method OnCreateView(). Everytime when you rotate the phone this method will be called.
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.fragment_section_gastos,
container, false);
//This is not null when we rotate the screen, first we save the Bundle SavedInstance
//After do that we put a integer, in this case the userKey
//then we recover the user key, and everything will work fine.
if (savedInstanceState != null)
{
this.savedInstanceState = savedInstanceState;
savedInstanceState.putInt("userKey", (int) idStatico);
idStatico = savedInstanceState.getInt("userKey");
}
//this will be null for the first time, only the first time this will bse used.
if (savedInstanceState == null)
{
idStatico = darUserID(user_id);
}
//Do the rest of the work
}

Stop fragment from being recreated after resume?

I am using several fragments to be dynamically added into activity. Everything works fine, when I press back-button, the fragments go to backstack. And when I resume it, it appears. But everytime on Resume, it is recreating the fragment and call onCreateView. I know it is a normal behavior of the fragment lifecycle.
This is my onCreateView:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(
R.layout.competitive_programming_exercise, container, false);
return rootView;
}
I want to stop those fragments from recreating. I tried with onSavedInstanstate but nothing is working. How can I accomplish that?
In the Activity's onCreateView set the savedInstanceState to null before calling the super method. You could also remove only the keys "android:viewHierarchyState" and "android:fragments" from the savedInstanceState bundle. Here is code for the simple solution, nulling the state:
#Override
public void onCreate(Bundle savedInstanceState)
{
savedInstanceState = null;
super.onCreate(savedInstanceState);
...
}
Iam using 5 fragments and working for me good as I was facing the same issue before..
public class MyFragmentView1 extends Fragment {
View v;
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
if (v == null)
v = inflater.inflate(R.layout.my_fragment_view_layout,
container, false
);
return v;
}
}
I put the view variable inside class and inflating it as new only if the view instance is null or otherwise use the one created before
You can't stop the fragment from being recreated, unfortunately. The best you can do is to remove the fragment in a transaction, after it has been restored but before it gets displayed.
If you know you are going to remove the fragment immediately you can reduce the performance hit of restoring the fragment by simplifying methods such as onCreateView() to return a dummy view, rather than inflating the whole view hierarchy again.
Unfortunately the tricky part is finding the best place to commit this transaction. According to this article there are not many safe places. Perhaps you can try inside FragmentActivity.onResumeFragments() or possibly Fragment.onResume().

Access Fragment View from Activity's onCreate

I am in the process of making my first app for Android, and I have a Fragment that gets added to my Activity in the Activity's onCreate() method. The problem I am facing is that I am unable to find any of the views contained within the Fragment from the Activity's onCreate() method.
Other threads have suggested that this is because the Fragment has not yet been inflated, so findViewById() will return null for any views contained within the Fragment.
Here is what I mean:
Activity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("activity onCreate");
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
return;
}
initialiseUI(); // Fragment added to Activity
System.out.println("end of activity onCreate");
}
Fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
System.out.println("fragment onCreateView");
return inflater.inflate(R.layout.event_log, container, false);
}
This prints the results:
activity onCreate
end of activity onCreate
fragment onCreateView
Because of this order, any attempt to access the views of the Fragment in the Activity's onCreate() method (using findViewById()) produces a NullPointerException, as the Fragment's onCreateView() only gets called AFTER the end of the Activity's onCreate().
Using the FragmentManger's executePendingTransactions() after adding the Fragment doesn't help.
Basically, I have been forced to put the problem code in the Activity's onStart() method instead of onCreate(), as onStart() happens AFTER the Fragment's onCreateView().
Does anyone what the standard practice here is, or how I can make my Fragment-View-accessing code work within the Activity's onCreate() method?
Update your views in onCreateView().
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.event_log, container, false);
TextView tv = (TextView) view.findViewById(R.id.text);
tv.setText("hello world");
return view;
}
Or if your changes depend on Activity your Fragment is attached to, use onActivityCreated().
#Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
TextView tv = (TextView) getView().findViewById(R.id.text);
tv.setText(getActivity.getSomeText());
}

Categories

Resources