I have a NavigationDrawer with an Actionbar and a Fragment. My Fragment has a ScrollView with a RelativeView I am trying to add other Views to this RelativeView. I end up with a NullExceptionPointer in the addView() method which means one of my objects is null, but I cannot figure it out - though it works if I call addView() in the Fragment class. My question is why is it the way it is. Why do I end up with a NPE. I just want to understand what I am doing wrong.
With further research it turns out that mContainer is null. But I inflate fragment_main then why is it still null?
my simplified MainActivity :
public class MainActivity extends ActionBarActivity
implements NavigationDrawerFragment.NavigationDrawerCallbacks {
private ViewGroup mContainer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.getLayoutInflater.inflate(R.layout.fragment_main);
mContainer = (ViewGroup) findViewById(R.id.main_container);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpTo(this, new Intent(this, MainActivity.class));
return true;
case R.id.action_add_item:
addItem(); **// NullPointerException**
return true;
}
return super.onOptionsItemSelected(item);
}
public void addItem() { //method responsible for NPE
LayoutInflater layoutInflater = this.getLayoutInflater();
View view = layoutInflater.inflate(R.layout.ingredient, null);
final ViewGroup newView =(ViewGroup) layoutInflater.inflate(R.layout.list_example,mContainer,false);
mContainer.addView(newView, 0);
}
public static class PlaceholderFragment extends Fragment {
private View nicView;
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
#Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_main, container, final ViewGroup mainContainer = (ViewGroup) rootView.findViewById(R.id.main_container);
final View nicView = View.inflate(getActivity(),R.layout.nicotine, null);
mainContainer.addView(nicView, 0);
return rootView;
}
Any help is appreciated, thanks
Hi shouldn't your stack trace show were the NPE occurs ?
Is it possible that the layout inflater is null?
They way i normaly set my inflater is by
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Related
I want to move some data from my Mainactivity to a Fragment...which is inside a tab fragment (which handles a SectionPagerAdapter)....which is inside a fragment in Mainactivity2.
I feel its too complicated and cant get it done.
GameEndedActivity (See wrong and correct variable...these are to be transferred)
public class GameEndedActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_ended);
int correct = getIntent().getIntExtra("correct", 0);
int wrong = getIntent().getIntExtra("wrong", 0);
}
}
TabFragment
public class TabFragment extends Fragment {
private int tabsCount;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_tab, container, false);
if(this.getContext() instanceof ChallengeOverviewActivity){
tabsCount = 2;
} else {
tabsCount = 3;
}
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this.getContext(), getFragmentManager(), tabsCount);
ViewPager viewPager = view.findViewById(R.id.view_pager);
viewPager.setAdapter(sectionsPagerAdapter);
TabLayout tabs = view.findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
return view;
}
}
ResultFragment (Transfer data here - wrong and correct variables)
public class ResultDetailsFragment extends Fragment {
private TextView tvWrong, tvCorrect;
private AnswerListener answerListener;
public interface AnswerListener {
public void correct(int i);
public void wrong(int i);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_result_details, container, false);
tvCorrect = view.findViewById(R.id.tvCorrect);
tvWrong = view.findViewById(R.id.tvWrong);
return view;
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
if (context != null) {
answerListener = (AnswerListener) context;
}
}
}
One way to do this is the add arguments to the fragment when you create an instance of it. In your activity when you create the fragment you want to attach you add some arguments to it. These arguments can then be accessed from the fragments onCreate method.
Just do this same thing again when you are in your fragment and create your second one.
Check this answer out which explains more in detail how to do it: https://stackoverflow.com/a/17436739/964887
I am learning android developing(novice).I want to add a fragment to the mainActivity with a textview and change the text. This code works perfectly:
public class Fragment1 extends Fragment {
//#Nullable
//#Override
TextView textt;
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_fragment1, container, false);
((TextView)view.findViewById(R.id.textview)).setText("some text");
return view;
}
}
But this codes invokes null pointer exception:
public class Fragment1 extends Fragment {
//#Nullable
//#Override
TextView textt;
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_fragment1, container, false);
textt = (TextView)view.findViewById(R.id.textview);
return view;
}
public void updateText() {
textt.setText("some text");
}
}
and:
public class Fragment1 extends Fragment {
//#Nullable
//#Override
View view;
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_fragment1, container, false);
return view;
}
public void updateText() {
((TextView)view.findViewById(R.id.textview)).setText("some text");
}
}
MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment1 frg1 = new Fragment1();
ft.replace(R.id.fragment_container, frg1);
ft.addToBackStack(null);
ft.commit();
frg1.updateText();
}
}
why these codes providing different outcome?
my project
frg1.updateText(); is called before the onCreateView lifecycle method of your fragment is called.. You should call the method after you set
textt = (TextView)view.findViewById(R.id.textview);
View view = inflater.inflate(R.layout.fragment_fragment1, container, false);
textt = (TextView)view.findViewById(R.id.textview);
this.updateText();//here
return view;
Check out fragment lifecycle docs regarding onCreateView
The system calls this when it's time for the fragment to draw its user interface for the first time.
This will happen when fragment is loaded not when it is created in your activity.
Here, the textview is not created when you call the updateText function.
Do such calls inside your fragment. Not on the activity which houses the fragment.
I have four Fragments(tab swipe stuff). For example I created a Toast in my Fragment #2, but this toast also comes up in my Fragment #4 when I open it.
What is missing here .
this is my fragment #2
public class A extends Fragment {
View view ;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.xxx_updates_layout, container, false);
//Custom Toast
LayoutInflater inflaterToast = getActivity().getLayoutInflater();
View layout = inflaterToast.inflate(R.layout.d_toast_d,
(ViewGroup) view.findViewById(R.id.toast_layout_root));
ImageView image = (ImageView) layout.findViewById(R.id.image);
image.setImageResource(R.drawable.ic_people);
TextView text = (TextView) layout.findViewById(R.id.text);
text.setText("Ringtone Bank");
Toast toast = new Toast(getActivity().getApplicationContext());
toast.setGravity(Gravity.BOTTOM, 0, 0);
toast.setDuration(Toast.LENGTH_SHORT);
toast.setView(layout);
toast.show();
return view;
} //onCreate
}
This is my fragment #4
public class XXXSentFragment extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.xxx_sent_layout,null);
}
}
My Fragment Pager Adapter
public class XXXTabFragment extends Fragment {
public static TabLayout tabLayout;
public static ViewPager viewPager;
public static int int_items = 4 ;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View x = inflater.inflate(R.layout.xxx_tab_layout,null);
tabLayout = (TabLayout) x.findViewById(R.id.tabs);
viewPager = (ViewPager) x.findViewById(R.id.viewpager);
viewPager.setAdapter(new MyAdapter(getChildFragmentManager()));
tabLayout.post(new Runnable() {
#Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});
return x;
}
class MyAdapter extends FragmentPagerAdapter{
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position)
{
switch (position){
case 0 : return new XXXPrimaryFragment();
case 1 : return new XXXSocialFragment();
case 2 : return new XXXUpdatesFragment();
case 3 : return new XXXFOUR();
}
return null;
}
#Override
public int getCount() {
return int_items;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position){
case 0 :
return "Primary";
case 1 :
return "Social";
case 2 :
return "Updates";
case 3 :
return "Four";
}
return null;
}
}
}
The thing is that View Page loads 3 fragments at a time (the one being shown, the one on the left and the one on the right). Hence the onCreateView for all of them get called at once which is why the toast from another fragment appears.Put a log statement in the onCreateView of all your fragments to verify this and to get a better understanding of how this works.
If your use case is to show a toast when the user swipes or selects a certain fragment (In your case XXXUpdatesFragment()), one way to go about this is to hold references to your fragments in your FragmentPagerAdapter and then implement the onPageChangeListener on the viewPager, when the page changes to 2, use the reference to call a method inside XXXUpdatesFragment() which will show a toast.
public class XXXUpdatesFragment extends Fragment {
View view ;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
view = inflater.inflate(R.layout.xxx_updates_layout, container, false);
return view;
}
public void showToast() {
//Custom Toast
LayoutInflater inflaterToast = getActivity().getLayoutInflater();
View layout = inflaterToast.inflate(R.layout.d_toast_d,
(ViewGroup) view.findViewById(R.id.toast_layout_root));
ImageView image = (ImageView) layout.findViewById(R.id.image);
image.setImageResource(R.drawable.ic_people);
TextView text = (TextView) layout.findViewById(R.id.text);
text.setText("Ringtone Bank");
Toast toast = new Toast(getActivity().getApplicationContext());
toast.setGravity(Gravity.BOTTOM, 0, 0);
toast.setDuration(Toast.LENGTH_SHORT);
toast.setView(layout);
toast.show();
}
}
I'm using ViewPager to show welcome, register, and some other screens. those screens are fragments controlled by FragmentStatePagerAdapter:
private static class TourPagerAdapter extends FragmentStatePagerAdapter {
public TourPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
WellcomeTourFragment ta = null;
switch (position) {
case 0:
ta = WellcomeTourFragment.newInstance(R.layout.welcome_fragment);
break;
case 1:
ta = WellcomeTourFragment.newInstance(R.layout.signup_fragment);
break;
first fragment (WellcomeFragment) shows some views and background image loaded from internet using picasso library:
private ImageView bkgImage;
public static WellcomeTourFragment newInstance(int layoutId){
WellcomeTourFragment pane = new WellcomeTourFragment();
Bundle args = new Bundle();
args.putInt(LAYOUT_ID, layoutId);
pane.setArguments(args);
return pane;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final ViewGroup rootView = (ViewGroup) inflater.inflate(getArguments().getInt(LAYOUT_ID, -1), container, false);
this.bkgImage = (ImageView) rootView.findViewById(R.id.imgView_Background);
return rootView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Picasso.with(getActivity())
.load(IMG_uRL)
.into(this.bkgImage);
}
My problem here is that, i am getting
java.lang.IllegalArgumentException: Target must not be null.
I am sure the ImageView does exits in my welcome_fragment layout. but really don't know what makes target to be null.
Are you sure that the correct layout is being inflated? Try debugging and looking at the rootView after it has been inflated. Is it possible you are including the wrong layout id when you call your newInstance method?
I have an activity which receive data from other activity. This data has to be showed in a TextView in a fragment inflated in the activity. So, the code is:
public class DetailActivity extends Activity {
private int idEstablecimiento;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit(); //Here the fragment is added to the activity
}
Bundle extras = getIntent().getExtras();
if (extras != null) {
idEstablecimiento = extras.getInt("idEstablecimiento");
}
TextView textView = (TextView) this.findViewById(R.id.nombreView); //Declared in fragmentDetail, which has been already inflated at this point, but still null
textView.setText(this.idEstablecimiento);
}
//...
//Non related stuff...
//...
public static class PlaceholderFragment extends Fragment {
private int idEstablecimiento;
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_detail,
container, false);
return rootView;
}
}
The problem is that the textView in the onCreate() method is null, why is this happening if the fragment has been already inflated? Shouldn't I be able to access to the IU elements once the fragment has been inflated in the onCreate() method? Or if not, what is the rigth way to do access to it?
You have to find the TextView in the Fragment.
public static class PlaceholderFragment extends Fragment {
private int idEstablecimiento;
public PlaceholderFragment() {
}
public PlaceholderFragment(int idEstablecimiento) {
this.idEstablecimiento = idEstablecimiento;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_detail,
container, false);
TextView text = rootView.findViewById(R.id.nombreView);
text.setText(idEstablecimiento);
return rootView;
}
And then you can get the text and commit it.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
Bundle extras = getIntent().getExtras();
if (extras != null) {
idEstablecimiento = extras.getInt("idEstablecimiento");
}
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment(idEstablecimiento)).commit();
}
}
Regards
Nils
If you want to get the View from a fragment layout you should use the view inside the oncreateView of the fragment and then get the textView inside the oncreate view..
example:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_detail,
container, false);
TextView textView = (TextView) rootView.this.findViewById(R.id.nombreView); //Declared in fragmentDetail, which has been already inflated at this point, but still null
textView.setText("I am here");
return rootView;
}