1

I've an addActivity hosting 5 fragments, on each fragments I've some fields to fill.
I want to get the value of those fields from the addActivity. I tried something like that :
AddActivity.java

public class AddActivity extends FragmentActivity {
    ViewPager vp;
    ProgressDialog dialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add);

        vp = (ViewPager) findViewById(R.id.pager);
        PagerAdapter pa = new FragPagerAdapter(getSupportFragmentManager());
        vp.setAdapter(pa);}

    public class getValueOfFields() {
  //here I'm trying to get the value of differents fields in the different fragments but I get 

always "editText == Null" If the editText is in The fragment 1 or 2 or 3 it will get null
     EditText editTextFromFrag1 = (EditText) findViewById(R.id.visitDateFiled); // this == null
// If the EditText is in Fragment 4 or 5 it will get the value normaly without any issue


             ...}

FragPagerAdapter.java

public class FragPagerAdapter extends FragmentPagerAdapter {
    public FragPagerAdapter(FragmentManager fm) {
        super(fm);}

    @Override
    public Fragment getItem(int index) {
        switch (index) {
            case 0:
                return new FirstFragment();
            case 1:
                return new SecondFragment();
            case 2:
                return new HousingFragment();
            case 3:
                return new FeedingFragment();
            case 4:
                return new OtherFragment();
        }

        return null;
    }

    @Override
    public int getCount() {
        return 5; }

OtherFragment.java public class OtherFragment extends Fragment { Button btn;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_other, container, false);
    btn = (Button) view.findViewById(R.id.send);
    btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
//Call the getValueOfFields (After filling the differnts fields the user click the send button) 
                ((AddActivity) getActivity()).getValueOfFields();
            }
        });
        return view;
    }
}

Updated
The problem that I get always EditText (and the others field to get ) equals to null If they are Located In the Fragment 1 or 2 or 3. Else I get The right Value

Chlebta
  • 3,090
  • 15
  • 50
  • 99
  • where do you call `getValueOfFields()` ? – nem035 Nov 06 '14 at 19:21
  • In the Last fragment I have a Send button, (After filling the different fields in the different fragments the user have send button) wich call the `getValueOfFields() void` of the parent activity – Chlebta Nov 06 '14 at 19:22
  • And who does the `EditText` `R.id.visitDateFiled` belong to? `Activity` or a specific `Fragment`? – nem035 Nov 06 '14 at 19:26
  • The XML code of EditText is in the Fragment XML file, but the `EditText editText = (EditText) findViewById(R.id.visitDateFiled);` is on the Activity – Chlebta Nov 06 '14 at 19:27

4 Answers4

1

Hello Chlebta You need to set pager.setOffscreenPageLimit(5);. When you swipe between fragments the fragment can get destroy. that is why you getting null.

Alternatively an easy solution would be that you set

pager.setOnPageChangeListener(new OnPageChangeListener() {

                @Override
                public void onPageSelected(int arg0) {
                    // Now here you get your fragment object. 
                   // To get the Fragment Object you need to store them in an ArrayList in your FragPagerAdapter class.
                  //  create a method `getMyFraggment ` which return your Fragment from Arraylist.
                 //   Now create a method in your each Fragment which return your EditText values. Here you can use HashMap to store the values.

                // Here you use switch cases to get your Fragment Object I just wrote 1 here                        
                MyFragment f =  ((FragPagerAdapter)pager.getAdapter()).getMyFraggment(arg0);

                HashMap <String, String> hashMap = f.getValuesFromFragment();
                myValues.putAll(hashMap);    // myValues is global hashmap in your Activity. 
               // Now you get All values in your Global HashMap. But remember here you can get duplicate values if user swipe a fragment more than 1 time. You should do a logic here to remove duplicate values.

                }

                @Override
                public void onPageScrolled(int arg0, float arg1, int arg2) {
                    // TODO Auto-generated method stub

                }

                @Override
                public void onPageScrollStateChanged(int arg0) {
                    // TODO Auto-generated method stub

                }
            });
Sunny
  • 14,522
  • 15
  • 84
  • 129
0

You could try to add a text changed listener to your edit text fields on each fragment and make a String field you set equal to the value of the edittext view when ever a user changes the text. Then save each instance of the fragment in your FragPagerAdapter and create a public method that will return all of the strings from each individual fragment in an array or how ever you want. Call that method from the Activity.

zafrani
  • 4,030
  • 5
  • 31
  • 39
  • It's not really helping because I have overs 30 field that. – Chlebta Nov 06 '14 at 19:30
  • I think the problem is you're making a new instance of the fragment every time so once you getItem its a new instance and not the original (filled out) one – zafrani Nov 06 '14 at 19:37
  • Add a Fragment array field to the FragmentPagerAdapter. In the constructor of the FragmentPagerAdapter give the Fragment array a new instance of each Fragment you have. Then in get item return fragmentArray[index] instead of a new fragment – zafrani Nov 06 '14 at 19:38
  • Even using array one I get the Item I've to use the new instance!! Can you make an example ? – Chlebta Nov 06 '14 at 19:45
  • I have Updated my question can you check it again please – Chlebta Nov 06 '14 at 21:35
0

You are most likely experience this issue because you are not obtaining XML elements from the proper view or the view you are attempting to get data from gets destroyed before you attempt to access it.

However, I am not sure why exactly you are experiencing this issue but I do have a work-around solution do suggest:

Each time the user enters a field, you can store it in either SharedPreferences or a static class that will serve as a storage unit.

I am not sure how all the data is being inputed by the user but you can use different listeners (such as OnClickListener) to track when the user inputs a certain data field.

Then you can store the data using one of the two approaches i just mentioned above. Here is an example of using a static storage class.

Somewhere in your application you make:

class Storage {
    public static String dateFilled;
    // ... rest of your data
}

Then once the user, to use the example you have in the question, stops entering information into the EditText for dateFilled (they focus out of it), you store this information:

editText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
    if(hasFocus){
        // user is still typing so we do nothing
    }else {
        // user finished typing and moved on so we store the data
        Storage.dateFilled = editText.getText().toString();
    }
   }
});

You could also use some sort of a Button as the trigger to store information:

myBtn.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        Storage.dateFilled = editText.getText().toString(); 
    }
}

Then you can use the stored data like:

public class getValueOfFields() {
    Toast.makeText(getApplicationContext(), Storage.dateFilled, Toast.LENGTH_LONG);
    // ...
}

If you want to use SharedPreferences instead, here is a good example.

Community
  • 1
  • 1
nem035
  • 34,790
  • 6
  • 87
  • 99
  • Using listener is not verry helpfull because I got over 30 fields that will be much of Listner to set and it will slow my app – Chlebta Nov 06 '14 at 19:43
  • If you have a specific order in which the user enters this information, you could only have 1 listener per XML element type (1 listener for all `Buttons`, 1 listener for all `EditTexts`...) and then use a `switch(order)` statement to determine what gets stored – nem035 Nov 06 '14 at 19:45
  • Unfortunally there's no order in data entering – Chlebta Nov 06 '14 at 19:49
  • What if I saveInstance when user swip between different fragments ? – Chlebta Nov 06 '14 at 20:25
  • I have updated My question can you check it again please – Chlebta Nov 06 '14 at 21:35
0

Do the following:

Create interface for communicating fragment to activity:

import android.widget.EditText;

public interface FormInterface {

    public void returnEditedEditText(EditText editText);

}

The create a base fragment that instantiates the interface and overrides method for communicating when the EditText has been modified. Make sure the Fragment also implements OnEditorActionListener :

import android.app.Activity;
import android.app.Fragment;
import android.util.Log;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;

public class FormFragment extends Fragment implements OnEditorActionListener {

    protected final String FRAGMENT_NAME = getClass().getName();

    protected FormInterface formInterface;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        //ensure activity implements interface
        try {
            formInterface = (FormInterface) activity;
        } catch (ClassCastException ex) {
            String errorString = activity.toString() + " must implement FormInterface";
            Log.e(FRAGMENT_NAME, errorString);
            throw new ClassCastException(errorString);
        }
    }

    @Override
    public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
        if(actionId == EditorInfo.IME_ACTION_DONE)
            formInterface.returnEditedEditText((EditText) view);
        return true;
    }

 }

Then in make your other fragments extend the base fragment:

YOURFRAGMENT extends FormFragment {
    //FOR EACH EDIT TEXT DO THE FOLLOWING
    EDITTEXT.setOnEditorActionListener(this);
}

Then make sure your activity implements the custom interface:

import android.app.Activity;
import android.widget.EditText;

public class FormActivity extends Activity implements FormInterface {

    @Override
    public void returnEditedEditText(EditText editText) {

        String input = editText.getEditableText().toString();

        switch(editText.getId()) {
            case R.id.editText_FirstName:
                mFirstName = input;
                break;
            ...
        }
    }
}
Droid Chris
  • 3,455
  • 28
  • 31
  • Have you read other solution ? as I sad I have over 30 fields I can't use Listener in the differents fragments. – Chlebta Nov 06 '14 at 19:54
  • So, if each EditText is edited, you will get an EditText returned to your activity. Check the passed in ID of the EditText and have the value populate a variable in your activity. If all values are there and validate, then pass on the values. – Droid Chris Nov 06 '14 at 19:58
  • Custom interfaces are the preferred way of fragments communicating to activities. – Droid Chris Nov 06 '14 at 20:01
  • Sorry but really this not helping the solution it's so complicated and many Listner to set. – Chlebta Nov 06 '14 at 20:06
  • How many fields? Try setting up a base fragment then you only have to set up the needed methods once. Do you plan on doing validation on forms? If so, would you not need to implement something similar to this? – Droid Chris Nov 06 '14 at 20:11
  • I have 37 fields divided on the different fragment 5 fragment. And how to set base fragment and do that. sorry this my seconde app on android I'm beginner – Chlebta Nov 06 '14 at 20:12
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/64430/discussion-between-chlebta-and-droid-chris). – Chlebta Nov 06 '14 at 20:13
  • I have Updated my post Can you check That Again. – Chlebta Nov 06 '14 at 21:34
  • Last comment on this. I think the submit button should really be in the activity since it has control over every fragment. Put it in the activity, then once all the fields have been populated, show the text. – Droid Chris Nov 06 '14 at 22:04
  • The Activity is Of type Pager how to putet it there and make ik visible pnly on the last fragment? – Chlebta Nov 06 '14 at 22:12
  • 1
    case 4: submitButton.setVisibility(View.Visible) return new OtherFragment(); – Droid Chris Nov 06 '14 at 22:16