My EditText is in my fragment named : EquationsCalculFragment.java
I want to recover the value in my fragment named : EquationsResultat.java
I have two NullPointerException with no apparent reasons (see the comments directly in the code).
NB : For the error in the EquationsResultsFragment, I tried to cast with String.valueOf(), with Float.parseFloat(), with the two combined... but no one worked.
EquationsCalculFragment.java
public class EquationsCalculFragment extends Fragment {
private ViewPager viewPager;
private EditText champ_a;
private EditText champ_b;
private String a;
private String b;
public float getA_equa_2nd() {
return Float.parseFloat(a);
}
public float getB_equa_2nd() {
return Float.parseFloat(b);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_equations_calcul, container, false);
viewPager = (ViewPager) getActivity().findViewById(R.id.viewpager);
champ_a = (EditText) view.findViewById(R.id.equa_2nd_a);
champ_b = (EditText) view.findViewById(R.id.equa_2nd_b);
Button button = (Button) view.findViewById(R.id.btn_equations_resultats);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
b = champ_b.getText().toString();
a = champ_a.getText().toString();
EquationsResultatFragment eqResFr = new EquationsResultatFragment();
eqResFr.getResultat(getA_equa_2nd(), getB_equa_2nd()); //NullPointerException happens here
//at com.example.slabre.applitest.EquationsCalculFragment$1.onClick(EquationsCalculFragment.java:60)
viewPager.setCurrentItem(1, true);
}
});
return view;
}
}
EquationsResultat.java
public class EquationsResultatFragment extends Fragment {
private TextView results;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_equations_resultat, container, false);
results = (TextView) view.findViewById(R.id.equa_2nd_resultat);
return view;
}
public void getResultat(float a, float b) {
results.setText(String.valueOf((a*a)+(2*a*b)+(b*b))); // NullPointerException happens here
// at com.example.slabre.applitest.EquationsResultatFragment.getResultat(EquationsResultatFragment.java:29)
}
}
Hope you can help me, I think this is not a big problem.
Parent Activity : TabFragment.java (yes my app si working with a TabLayout and ViewPager)
public class TabFragment extends Fragment {
public static TabLayout tabLayout;
public static ViewPager viewPager;
public static int int_items = 3 ;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/**
*Inflate tab_layout and setup Views.
*/
View x = inflater.inflate(R.layout.tab_layout,null);
tabLayout = (TabLayout) x.findViewById(R.id.tabs);
viewPager = (ViewPager) x.findViewById(R.id.viewpager);
/**
*Set an Apater for the View Pager
*/
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);
}
/**
* Return fragment with respect to Position .
*/
#Override
public Fragment getItem(int position)
{
switch (position){
case 0 : return new EquationsCalculFragment();
case 1 : return new EquationsResultatFragment();
case 2 : return new EquationsInfosFragment();
}
return null;
}
#Override
public int getCount() {
return int_items;
}
/**
* This method returns the title of the tab according to the position.
*/
#Override
public CharSequence getPageTitle(int position) {
switch (position){
case 0 :
return "Calcul";
case 1 :
return "Résultats";
case 2 :
return "Infos";
}
return null;
}
}
}
First of all, you cannot directly communicate between different fragments. You need to go through your container activity for it.
Declare a listener interface through which your fragment will communicate with your container activity. Attach that listener to your EquationsCalculFragment. Your container activity should implement that listener.
Now when you EquationsCalculFragment wants to communicate with EquationsResultatFragment you notify your container activity using that listener. In the container activity, when you get the listener callback, grab your EquationsResultatFragment fragment instance using findFragmentById(int id) or findFragmentByTag(String tag) and check if it is already added to your container activity. If it is, then call any public method of EquationsResultatFragment fragment, using that grabbed EquationsResultatFragment fragment instance.
Check out this link for more details and sample code.
EquationsResultat's getResultat is called when you click on the EquationsCalculFragment's button, and should set EquationsResultat's TextView (results) text. Problem is, results is set on EquationsResultat's onCreateView, and it seems this method has no been called yet, and therefore results is still null.
Post your activitie's code, it will be easier to help you knowing when you are attaching the fragments, etc.
Try this!!
public void getResultat(float a, float b) {
results.setText(((a * a) + (2 * a * b) + (b * b))+"");
}
Related
I have an Weather adapter to show the weather, the activity is split into two screens, one half a listview (different adapter), the other is tablayout with another tablayout inside to scroll through all the different pages of weather that are available
After turning off the wifi to make sure i don't receive anything and then turning on the wifi to receive the weather i get the update method called for the adapter and the list is updated, new fragments created, onViewCreated is called but the fragments display as blank and as only 1 (can't cycle through them if there are multiple).
Here is the Weather ViewPagerAdapter
public class WeatherViewPagerAdapter extends FragmentStatePagerAdapter {
private List<Fragment> fragments;
public WeatherViewPagerAdapter(FragmentManager fm) {
super(fm);
fragments = new LinkedList<>();
if (Storage.getInstance().getWeatherModels().size() == 0){
// Displays page but with "no weather available" message
fragments.add(WeatherFragment.newInstance(null));
}else{
for (CurrentWeatherModel model : Storage.getInstance().getWeatherModels()){
fragments.add(WeatherFragment.newInstance(model));
}
}
}
public void rediscoverWeather(){
fragments.clear();
if (Storage.getInstance().getWeatherModels().size() == 0){
fragments.add(WeatherFragment.newInstance(null));
}else{
for (CurrentWeatherModel model : Storage.getInstance().getWeatherModels()){
fragments.add(WeatherFragment.newInstance(model));
}
}
}
#Override
public int getItemPosition(#NonNull Object object) {
return POSITION_NONE;
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public Parcelable saveState() {
return null;
}
}
And this is the fragment that is in the Tablayout on the side that displays the weather
public class WeatherViewPagerFragment extends Fragment {
private WeatherViewPagerAdapter adapter;
private ViewPager viewpager;
private TabLayout tabLayout;
public static WeatherViewPagerFragment newInstance(){
return new WeatherViewPagerFragment();
}
#Override
public UniqueInfo getUniqueInfo() {
return null;
}
#Override
public void update() {
adapter.rediscoverWeather();
setPage(0);
adapter.notifyDataSetChanged();
}
public void setPage(int pageNumber){
if (pageNumber >=0 && pageNumber < adapter.getCount()){
viewpager.setCurrentItem(pageNumber, true);
}
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.weather_view_pager, container, false);
}
private void createAdapter(){
adapter = new WeatherViewPagerAdapter(getChildFragmentManager());
viewpager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewpager);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewpager = view.findViewById(R.id.viewpager);
tabLayout = view.findViewById(R.id.sliding_tabs);
createAdapter();
}
}
The update() for WeatherViewPagerFragment gets called when its meant to, which updates the Adapter, re-doing the fragments and calling onCreateView and onViewCreated, but what i see is just a blank fragment, any suggestions why this would be happening? i figured it could be a focus issue but i haven't had any luck as of yet with fixing it
Sorry for my english. I have one activity and in this activity in FragmentPagerAdapter exist 5 fragments. All fragments use one object model for inforation(product name, product image ...).
My activity get data from data base. And then it data send to all fragments. My example Activity:
#BindView(R.id.tabs_sep_prod) TabLayout tabs_sep_prod;
#BindView(R.id.viewpager_sep_prod) ViewPager viewpager_sep_prod;
PrepBaseProdFragment prepBaseProdFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sep_product);
ButterKnife.bind(this);
prepBaseProdFragment = new PrepBaseProdFragment();
// there i have another fragments
// ...
setupViewPager(viewpager_sep_prod);
tabs_sep_prod.setupWithViewPager(viewpager_sep_prod);
}
private void setupViewPager(ViewPager viewPager) {
SepProductActivity.ViewPagerAdapter adapter = new SepProductActivity.ViewPagerAdapter(
adapter.addFrag(prepBaseProdFragment, getString(R.string.sep_prep_base));
// there i have another addFrag
// ...
viewPager.setOffscreenPageLimit(5);
viewPager.setAdapter(adapter);
}
#Override
public void onResume() {
super.onResume();
// this i call method from presenter, it return data in method setData
if(idCat != null && idProd != null)
sepProductPresenter.getSepProd(idCat, idProd);
}
#Override
public void setData(SepProductModel sepProductModel) {
// there i send data to fragment
prepBaseProdFragment.setDataInf(sepProductModel);
// ...
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
my fragment
public class PrepBaseProdFragment extends BaseFragment {
#BindView(R.id.text) TextView text;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_about_prod_prepare_base, parent, false);
ButterKnife.bind(this, view);
Log.e("PrepBaseProdFragment", "PrepBaseProdFragment");
return view;
}
public void setDataInf(SepProductModel sepProductModel) {
text.setText(sepProductModel.getPROPERTY_PR_SUBSTRPREP_UA_VALUE().getTEXT());
}
}
My question: when i send data from activity to fragment, my view do not have time to initialize. In fragment line text.setText(sepProductModel.getPROPERTY_PR_SUBSTRPREP_UA_VALUE().getTEXT()); error
java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.widget.TextView.setText(java.lang.CharSequence)' on a null
object reference
Please, help me solve my problem. I spend many times for this
You can check if the text view is null save the data in a variable inside the fragment and in onCreateView use the data variable if it is filled and set the textview text.
Something like this:
// Inside the Fragment body
private SepProductModel sepProductModel;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_about_prod_prepare_base, parent, false);
ButterKnife.bind(this, view);
Log.e("PrepBaseProdFragment", "PrepBaseProdFragment");
if(this.sepProductModel != null)
text.setText(this.sepProductModel.getPROPERTY_PR_SUBSTRPREP_UA_VALUE().getTEXT());
return view;
}
public void setDataInf(SepProductModel sepProductModel) {
if(text != null){
// use text
}
else this.sepProductModel=sepProductModel;
}
I can advise you to wait for your data and then show fragments to adapter, moreover all of them use the same model. While you dont have data, you can show progress bar.
When you have needed model, you can create instances of your fragments and set bundle arguments for them. You can use method like this:
public static MyFragment newInstance(MyModel model){
MyFragment fragment = new MyFragment();
Bundle args = new Bundle();
args.putSerializable(KEY, model);//or args.putParcelable(KEY, model);
fragment.setArguments(args);
return fragment;
}
Notice: your model need to implement Serializable or Parcelable to be putted in bundle. You may read about difference here.
Then in your set data method, when you already have your model you can setup your adapter and set it to view pager, but with this approach:
adapter.addFrag(MyFragment.newInstance(model), getString(R.string.sep_prep_base));
It have to help you, ask me if you have some questions.
I have googled everything during a day about the subject and nothing seems to work around for my project. I have added a viewpager to my main activity. There is two fragments attached to it thanks to a page adapter. I initialized everything on the OnCreate method from my main activity. The view pager work well. The problem is when I want to access from my MainActivity the textviews included in my fragments. I created a Set method in each fragment which modify the textviews accordingly to the arguments. So in order to call this method from my MainActivity I have to instantiate the fragments on my MainActivity and the problem is that this line of code return null and the fragments can not be instantiated. Here is the code used for testing this purpose.
Main Activity
public class MainActivity extends AppCompatActivity{
private SecondActivitySwipeAdapter adapterViewPager;
private FirstFragmentSwipe fragment1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v(TAG, "onCreate");
setContentView(R.layout.main_activity_test);
ViewPager vpPager = (ViewPager) findViewById(R.id.viewpager);
adapterViewPager = new SecondActivitySwipeAdapter(getSupportFragmentManager());
vpPager.setAdapter(adapterViewPager);
fragment1 = (FirstFragmentSwipe) adapterViewPager.getRegisteredFragment(vpPager.getCurrentItem());
fragment1.setTextViews(1,2,3,4,5);
}
...
}
SecondActivitySwipeAdapter
public class SecondActivitySwipeAdapter extends FragmentStatePagerAdapter {
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
private static int NUM_ITEMS = 2;
private FragmentManager mFragmentManager;
public SecondActivitySwipeAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
mFragmentManager = fragmentManager;
}
// Returns total number of pages
#Override
public int getCount() {
return NUM_ITEMS;
}
// Returns the fragment to display for that page
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return FirstFragmentSwipe.newInstance();
case 1:
return SecondFragmentSwipe.newInstance();
default:
return null;
}
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
}
FirstFragmentSwipe
public class FirstFragmentSwipe extends Fragment {
private TextView avg1;
private TextView avg2;
private TextView avg3;
private TextView avg4;
private TextView avg5;
public static FirstFragmentSwipe newInstance(){
return new FirstFragmentSwipe();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.swipelayout1, container, false);
avg1 = view.findViewById(R.id.pwrAvgNmbview1);
avg2 = view.findViewById(R.id.pwrAvgNmbview2);
avg3 = view.findViewById(R.id.pwrAvgNmbview3);
avg4 = view.findViewById(R.id.pwrAvgNmbview4);
avg5 = view.findViewById(R.id.pwrAvgNmbview5);
return view;
}
public void setTextViews(int avg1, int avg2, int avg3, int avg4, int avg5){
this.avg1.setText(Integer.toString(avg1));
this.avg2.setText(Integer.toString(avg2));
this.avg3.setText(Integer.toString(avg3));
this.avg4.setText(Integer.toString(avg4));
this.avg5.setText(Integer.toString(avg5));
}
}
The second fragment is basically the same as fragment for the moment. I am using some ideas found by googling. The last line of the onCreate method make the app crash. Thanks for you precious help.
So the problem here is that registeredFragments doesn't have the fragments instantiated yet.
First you can check if fragment1 is null to prevent crashes.
Furthermore you'd rather put initialization methods in getItem() of adapter or in onViewCreated() of the fragment and do some updates in later lifecycle methods if needed.
I am trying to call a Fragment's public Method from its Parent View and I followed this, this and these questions on Stack. However the method I need is not avilable when I try to call it from the Parent view.
Here's my code:
Fragment:
public class FirstTabView extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_first_tab_view, container, false);
return rootView;
}
//The method I need to call
public void PostStuff(String caption){
}
}
Parent View: (Which contains the Main View Pager)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_view);
pager = (ViewPager) findViewById(R.id.mainpager);
mAdapter = new HomePagerAdapter(getSupportFragmentManager());
pager.setAdapter(mAdapter);
pager.setOffscreenPageLimit(4);
//Getting the Fragment's Tag. o is the Pager's Fragment index. i.e.: The first fragment
String fragment_tag = "android:switcher:" + pager.getId() + ":" + 0;
FirstTabView fragment = (FirstTabView) getSupportFragmentManager().findFragmentByTag(fragment_tag);
fragment. <This is where I need to call the method and pass the parameter> ();
//The method however doesn't appear when I try to reference it
}
Am I calling the Fragment's method correctly from my Parent View? What am I doing wrong?
EDIT
This is the adapter that I used to push the Fragments:
public class HomePagerAdapter extends FragmentPagerAdapter {
public HomePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new FirstTabView();
case 1:
return new SecondTabView();
case 2:
return new ThirdTabView();
case 3:
return new FourthTabView();
case 4:
return new FifthTabView();
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 5;
}
}
You can save a reference of the FirstTabView to your MainActivity, then call the method of the fragment.
FirstTabView
public class FirstTabView extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_first_tab_view, container, false);
return rootView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
//set this fragment to your MainActivity
MainActivity mainActivity = (MainActivity)getActivity();
mainActivity.setFirstTabView(this);
}
//The method I need to call
public void PostStuff(String caption){
}
}
MainActivity
private FirstTabView firstTabView;
#Override
public void onCreate(Bundle bundle) {
........
if(firstTabView != null) {
firstTabView.PostStuff("Hello World");
}
}
public void setFirstTabView(FirstTabView firstTabView){
this.firstTabView = firstTabView
}
Hello kind (android) programmers,
The situation is as follows:
I have an activity that uses a NavigationDrawer that allows to load 3 fragments. Inside one of those fragments I have a ViewStatePagerAdapter, which on it's turn hosts 3 fragments. In one of those fragments I load a bunch of databasedata using a cursorloader. These values are editable to a new value, but should not be persisted to DB until a certain button is clicked.
All this works fine, but the problem is that when I now rotate the screen, all the changed data is gone. I tried using onSaveInstance in the inner fragment itself, but I think the problem lies higher, as I already noticed than when I rotate the screen, the viewpager jumps back to the first tab.
What would be the correct way (/correct location: activity, certain fragment,...) to:
Make sure the viewpager remains on the right tab
Remembers the data that changed in the inner fragment
The fragment that contains the viewpager currently has following onCreateView :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_home, null);
tabLayout = (TabLayout) v.findViewById(R.id.fragment_tabs);
viewPager = (ViewPager) v.findViewById(R.id.fragment_viewpager);
viewPager.setOffscreenPageLimit(3);
viewPager.setAdapter(new MyAdapter(getChildFragmentManager()));
tabLayout.setupWithViewPager(viewPager);
return v;
}
and an inner class for the FragmentStatePagerAdapter
class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
/**
* Return fragment with respect to Position .
*/
#Override
public Fragment getItem(int position)
{
switch (position){
case 0 : return PersonFragment.newInstance();
case 1 : return FriendsFragment.newInstance();
case 2 : return EventsFragment.newInstance();
}
return null;
}
#Override
public int getCount() {
return int_items;
}
/**
* This method returns the title of the tab according to the position.
*/
#Override
public CharSequence getPageTitle(int position) {
switch (position){
case 0 :
return "ME";
case 1 :
return "FOLLOWING";
case 2 :
return "EVENTS";
}
return null;
}
}
nothing special happening for the rest in here. (Which maybe should?)
The fragment inside of the viewpager has following onCreate/onCreateView
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_person, container, false);
this.viewHolder = new ViewHolder(rootView);
if (savedInstanceState != null) {
CharSequence savedPersonName = savedInstanceState.getCharSequence("personName");
if (savedPersonName != null) {
Log.v("PersonFragment", savedPersonName.toString());
this.viewHolder.personnameView.setText(savedPersonName);
}
}
return rootView;
}
Thanks in advance.
You probably know this already but this is the kind of thing I would do to address your second issue
private TextView tvTitle;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.mylayout, container, false);
tvTitle = (TextView) rootView.findViewById(R.id.mytitle);
if (savedInstanceState != null) {
CharSequence csTitle = savedInstanceState.getCharSequence("myTitle");
if (csTitle != null) tvTitle.setText(csTitle);
}
}
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putCharSequence("myTitle", tvTitle.getText());
}