I'm trying to get the view created in onCreateView () (Fragment) to modify components through findviewbyId but always returns null
eg
this is onCreateView in my fragment
public View onCreateView(final LayoutInflater inflater,
final ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.myLayout, container, false);
return view;
}
and from my activity call fragment and add eg.
FragmentTransaction ft = getFragmentManager().beginTransaction();
Fragment newFragment = new myFragment();
ft.replace(main_container.getId(), newFragment).commit();
/*and i need modify the text button with setText() of View create in my fragment
eg*/
View myViewFragment = newFragment.getView();
Button b = (Button) myViewFragment.findViewById(R.id.mybuttoninfragment);
b.setText("Hello World");
but always returns null, how do I fix this?? Thanks
This is because ft.replace(main_container.getId(), newFragment).commit(); just request an initiation of the fragment transaction, but it will only actually be done (and thus onCreateView() be invoked) the next time the main thread have spare CPU cycles.
So, you'll have to wait calling
View myViewFragment = newFragment.getView();
etc to at a later time (in an onClick() method for example)
Related
Is it possible to get the attach complete of a fragment in the hosting activity? I am new to Android.
Here is my code to add a fragment:
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
DecorationFragment fragment = new DecorationFragment();
ft.add(R.id.fragmentContainer,fragment,"decoration_fragment");
ft.commit();
I have 2 objects in the Fragment. I want to handle their click event in the Activity.
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_decoration, container, false);
mChangeTextColorButton = (Button) rootView.findViewById(R.id.changeTextColorButton);
mColorPallette = (LinearLayout)rootView.findViewById(R.id.color_pallette_linearView);
return rootView;
}
How to achieve this?
Not sure exactly what you're asking, but perhaps this is what you're looking for:
https://developer.android.com/reference/android/support/v4/app/FragmentActivity.html#onAttachFragment(android.support.v4.app.Fragment)
void onAttachFragment (Fragment fragment)
Called when a fragment is attached to the activity.
This is called after the attached fragment's onAttach and before the attached fragment's onCreate if the fragment has not yet had a previous call to onCreate.
Here's the problem
I have a Fragment class DisplayFragment and I already have one show in the content frame, then I do
DisplayFragment a = DisplayFragment.newInstance();
getSupportFragmentManager().beginTransaction()
.replace(R.id.contentFrame, DisplayFragment)
.commit();
Then I want to get the view of fragment a using View v = a.getView();, but it return a null view.
Can anyone tell me why? Cause I have to change some view setting of the new Fragment.
onCreateView() in DisplayFragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_display, container, false);
//Some TextView setup
Button button = (Button) view.fineViewById(R.id.button);
return view; }
You need to use delay or put your View v = a.getView(); in loop which will watch first that your fragment is successfully attached, created and added in your activity or not. For this you can check with this isAdded() and isInLayout() if both return true then only call getView()
Now why this, as you add/replace fragment with commit with will fragment will class will be execute first it'll be start Fragment life cycle that is onAttach(), onCreate(), onCreateView() and so on. Now you will getting null from getView() just because your view is not created still. Fragment Life Cycle. If you doubt regarding this let me know.
I assume that you call View v = a.getView(); right after commit?
Because getView method only return not null value after onCreateView returned.
In your case, after called commit(), it take time to complete all the lifecyle callback of DisplayFragment a (from onCreate -> onCreatedView,..).
So that, right after commit(), the getView method still return null.
Declare DisplayFragment a; as Class Reference. Because after commit you want to just access View v = a.getView(); it unavailable due to fragment Life Cycle. You can get after execute block of code.
Make sure you have to mentioned OnCreateView() Method on class DisplayFragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (container == null) {
// We have different layouts, and in one of them this
// fragment's containing frame doesn't exist. The fragment
// may still be created from its saved state, but there is
// no reason to try to create its view hierarchy because it
// won't be displayed. Note this is not needed -- we could
// just run the code below, where we would create and return
// the view hierarchy; it would just never be used.
return null;
}
Log.i("Right", "onCreateView()");
return inflater.inflate(R.layout.right, container, false);
}
I had same problem as like you.
As the transaction of fragment did not takes place immediately. Thats why sometime the findViewById() does not work properly. But we can execute the pending transaction by using executePendingTransactions() method. I have used following code in my project to execute the pedingTransactions.
Fragment f = (Fragment)(FragmentClass.class).newInstance();
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.your_fragment_container_name,f).commit();
fm.executePendingTransactions(); //Notice the FragmentManager Class object
I am working on App where i am attaching 5 fragments on an activity. Everything is working great but when i put my app in background from any fragment and after some time when my app resumes it crashes. I get reference of my Activty as null. here is my code
This is code in Activty from where i am attaching fragment
FragmentManager fragmentManager = getSupportFragmentManager();
searchFragment = SearchFragment.newInstance(MainBaseActivity.this);
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.frameLayoutMain, searchFragment, "SearchFragment");
fragmentTransaction.commit();
And this is my Fragment class
public static SearchFragment newInstance(MainBaseActivity mainBaseActivity) {
fragment = new SearchFragment();
fragment.mainBaseActivity = mainBaseActivity;
fragment.inflater = (LayoutInflater) mainBaseActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
fragment.myApplication = ((MyApplication) mainBaseActivity.getApplicationContext());
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.search_fragment, container, false);
preferences = mainBaseActivity.getSharedPreferences(Constant.CHAI_APP, Context.MODE_PRIVATE); // here i get null pointer
editor = preferences.edit();
return view;
}
Fragments can be killed and recreated by the system at various times. You cannot trust the kind of initialization you do in your newInstance() - when the fragment is recreated, the fields won't be initialized.
Remove these initializations:
fragment.mainBaseActivity = mainBaseActivity;
fragment.inflater = (LayoutInflater) mainBaseActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
fragment.myApplication = ((MyApplication) mainBaseActivity.getApplicationContext());
and use getActivity() in your fragment when you need to access your hosting activity or the Application.
For inflater, one is already passed in as an argument to onCreateView(). No need to fetch it yourself.
(To pass params to a fragment that persist over fragment recreation, use setArguments().)
Fragment has the getActivity() method to retrieve the activity to which it is attached. Use it in place of mainBaseActivity
I set the text on the textview located on the fragment, it returns a NullPointerException. It works when the fragments are added statically but it crashes when i'm using dynamically added fragments.
this is the function that is called when I want to set the text on the fragment.
#Override
public void countrySelected(String wordIn) {
word = wordIn;
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
display.setCountryText(wordIn);
}else{
display = new DisplayFragment();
//display.setCountryText(wordIn);
fragmentTransaction.addToBackStack(list.getTag());
fragmentTransaction.replace(R.id.fragment_place,display,"disp");
fragmentTransaction.commit();
display.setCountryText(wordIn);
}
}
this is the fragment.
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.right,container, false);
txt = (TextView) view.findViewById(R.id.txtView);
Log.d("LOOOOADED", "Loaded");
return view;
}
public void setCountryText(String word){
txt.setText(word);
}
When I set the text on the statically added fragments, it works just fine. But when I set the text on the dynamically added fragment, it doesn't log "LOOOOADED", which means it never reached the onCreateView() method.
You are calling the method display.setCountryText(wordIn); too soon before the fragment is attached to activity.
Look at framgent lifecycle. You need to wait till the fragment is attached to the activity and then call display.setCountryText(wordIn).
Let say the target application is built from 3 fragments which are all in the same activity public class MainActivity extends android.support.v4.app.FragmentActivity implements ActionBar.TabListener. Starting fragment is public class ButtonSectionFragment extends Fragment where there is a Button:
public class ButtonSectionFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.btn, container, false);
Button mybutton = (Button) rootView.findViewById(R.id.mybutton);
mybutton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
????????????????????
}
});
}
There are ?? in the onClick method, I will get to that. And there is another fragment like this:
public static class TextSectionFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.tv, container, false);
TextView textv = (TextView) rootView.findViewById(R.id.texty);
}
Both of the fragments are using different layouts so this is why rootView is being used right in front of findViewById.
The outcome I would like to achieve is: by Button from 1st fragment click set the TextView from 2nd fragment to Hello. What should I put in the ??? part to make it all work?
You need to use interface as callback to the activity then set the textview in fragment.
Two framgents should never communicate directly.
http://developer.android.com/training/basics/fragments/communicating.html.
Framgent1 -->Activity -->Fragment2.
You can comunicate value from fragment2 to activity first then from activity to fragment2. Then set text in fragment2
You just have to use getActivity().findViewById() instead of getView().findViewById()
final TextView tv = (TextView) getActivity().findViewById(R.id.texty);
if (tv != null)
tv.setText("Hello");
Fragments are just branches inside the common layout tree of activity. All fragment views of a common activity can be accessed through Activity.findViewByXXX(). The only complication is that fragments can be dynamically added, removed, replaced, etc. So you to be sure that the needed fragment is already inflated into the layout hierarchy. You can make initialization of the UI in onViewCreated() of the other fragment. That guarantees you the layout has been loaded already.
Fragment frag1 = new ButtonSectionFragment ();
Fragment frag2 = new TextSectionFragment();
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(layout, frag1);
ft.add(layout, frag2);
ft.commit();
View frag1RootView = frag1.getView();
View frag2RootView = frag2.getView();
Button btn = (Button)frag1RootView.findViewById(id);
TextView tv = (TextView)frag2RootView.findViewById(id);
untested but... I think that would do it...
EDIT: You should get the root views onActivityCreated(); or it'll throw you a null...
In continuation to Raghunandan's answer, you could check similar implementation in the link.
update TextView in fragment A when clicking button in fragment B
Do not forget to get a reference of the textview of the TextSectionFragment into the MainActivity.