Inside onCreateView i can instance View with the inflate, in this way:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
if(savedInstanceState == null) {
v = inflater.inflate(R.layout.fragment_my_team, container, false);
setUpRecyclerView(v);
}
return v;
}
Now, if launch a second activity when return in the first activity, in this fragment, the View is null because onCreateView it's already called.
I don't know a to instance the view.
Is there a solution of that?
Get rid of the if(savedInstanceState == null) validation and create & return your view every time onCreateView is invoked.
Related
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.
I am using fragments to design my screen.When I navigate back to another fragment (from the back stack), the onCreateView(...) method gets called each time even if the fragment has already been created.How to avoid that the method onCreateView(...) gets called each time and make sure it's called only once (when it's created the first time)?
You can cache your inflated view to the local field if your want. For example:
public class ExampleFragment extends Fragment {
private View fragmentView;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
if (fragmentView == null) {
fragmentView = inflater.inflate(R.layout.you_super_view_id, container);
}
return fragmentView;
}
}
But practically, it's ok that pager is reinflating views because it keeps only part of all fragments in memory at the time. So, I think the best idea is to let it work as it should
I am inflating a fragment from activity at runtime. So, in order to inflate the view of the fragment in the fragment class I called:
#Nullable
#Override
public View onCreateView(final LayoutInflater inflater, #Nullable final ViewGroup container, #Nullable final Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
return inflater.inflate(R.layout.confirm_fragment, container);
}
At this moment I get a crash with logs:
Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
But if I modify my method as:
#Nullable
#Override
public View onCreateView(final LayoutInflater inflater, #Nullable final ViewGroup container, #Nullable final Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
return inflater.inflate(R.layout.confirm_fragment, null);
}
where I now specify my container as null, it works. But what I didn't understand is where did I specify a parent for the view in the code which was crashing?
Read from this link that why and when you pass parent container's instance or null in attachToRoot param.
From link:
Button button = (Button) inflater.inflate(R.layout.custom_button, mLinearLayout, false);
mLinearLayout.addView(button);
By passing in false, we say that we do not want to attach our View to the root
ViewGroup just yet. We are saying that it will happen at some other
point in time. In this example, the other point in time is simply the
addView() method used immediately below inflation.
So if you inflate with:
return inflater.inflate(R.layout.confirm_fragment, container);
First it will immediately attach confirm_fragment to container. After returning the view, fragment will be tried to be added to parent again implicitly, but since it has been added already, exception will be thrown:
Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
Hope you got the point.
where did I specify a parent for the view [...] ?
You add a Fragment dynamically by writing something like this:
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(android.R.id.content, myFragment, FRAGMENT_TAG)
.addToBackStack(null)
.commit();
In add(), you specify where the Fragment should be displayed (in this case fullscreen) by passing the id of the desired container.
See also the method description in the reference developers.android.com:
containerViewId int: Optional identifier of the container this fragment is to be placed in. If 0, it will not be placed in a container.
I you don't add a Fragment to the UI (e.g. you need it for caching purposes as a retained fragment), onCreateView() will never be called.
So once onCreateView() is called, the parent for this Fragment already exists - the FragmentManager set it for you.
Try to use the following code:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.confirm_fragment, container, false);
return view;
}
You need to set attachToParent to false
Example:
inflater.inflate(R.layout.confirm_fragment, container,false);
I have a FragmentActivity which sets a main layout with 3 tabs. Each tab has it's own fragment which inflates is own layout into main layout.
For example, one of the three Fragments:
public class Fragment1 extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (container == null) {
return null;
}
return inflater.inflate(R.layout.fragment1, container, false);
}
}
When I add all the fragments and connect them with tabs everything works. When I click on tab1, layout of the Fragment1 shows, when I click on Tab2, layout of the Fragment2 shows.
The problem is that when I want to change something in that inflated layout (for example execute setText to textView in fragment1 layout), I receive a NullPointerException in that line and application stops.
This doesn't work:
TextView test = (TextView) findViewById(R.id.fragmentOneText1);
test.setText("Test text!");
How to set data to inflated layout?
You have to inflate your fragment specific layout first by using LayoutInflater and map the control in your Fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.R.layout.fragment1, container, false);
TextView text = (TextView) fragmentView.findViewById(R.id.fragmentOneText1);
mTextNoResult=(TextView)fragmentView.findViewById(R.id.text_noresult);
return fragmentView;
}
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());
}