0

I have one big form broken into 3 fragments. Fragments are contained into FragmentPagerAdapter, so they can be swiped as pages. As there are a lot of calls, I think it wouldn’t be practical to call a interface from the fragment to the activity on each control that is changed. Is there a way to call a method or get a property of the fragment on each page swipe?

Here's the current code:

    final List<Fragment> fragments = getFragments();
    pageAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
    ViewPager pager = (ViewPager) findViewById(R.id.viewpager);
    pager.setOffscreenPageLimit(3); //This is necessary to prevent the destruction of the last fragment, otherwise the dynamically added views get lost
    pager.setAdapter(pageAdapter);

As the offscreenlimit is increased to deal with the issue that programmatic added views as childs to a layout in one of the fragments get destroyed when the fragment is not visible, the onPause() is not applicable, otherwise it would've been rather simple to just call the interface in it.

I've though about overriding the OnPageChangeListener of the pager, however I couldn't find how to get the data I need. Here's part the code in the fragments:

The interface from the fragment to the activity is implemented to according to this answer https://stackoverflow.com/a/9977370/1927033

Interface

public interface DataPassIF {

    public void passPartForm(UForm pageFromForm);
}
DataPassIF dataPasser;

@Override
public void onAttach(Activity a){
    super.onAttach(a);
    dataPasser = (DataPassIF) a;
}

This is the fragment that if the limit is not increased, the seekbar's get destroyed.

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    final View fragment = inflater.inflate(R.layout.page3, container, false);

    LinearLayout ll = (LinearLayout) fragment.findViewById(R.id.p3_ll);
    RelativeLayout rl = (RelativeLayout) fragment.findViewById(R.id.p3_rl);

    int child = rl.getChildCount();
    for (int i = 0; i < child; i++) {
        View v = rl.getChildAt(i);
        if (v instanceof CheckBox) {
            v.setOnClickListener(onCickAdder(fragment.getContext()));
        }
    }

    return fragment;
}

private View.OnClickListener onCickAdder(final Context context) {
    return new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (((CheckBox) view).isChecked()) {
                SeekBar nsb = createSeekBar(context);
                //TODO clear up this with proper id generation
                nsb.setId(imak++);
                view.setTag(nsb.getId());
                ll.addView(nsb);
            } else {
                ll.removeView(ll.findViewById((Integer) view.getTag()));
            }

        }
    };
}

private SeekBar createSeekBar(Context context) {
    SeekBar sb = new SeekBar(context);
    sb.setMax(20);
    sb.setProgress(10);
    return sb;
}
Community
  • 1
  • 1
user1927033
  • 142
  • 14
  • If you're using a FragmentPagerAdapter and not a FragmentStatePagerAdapter I think only the view hierarchy could potentially be destroyed while the fragment isn't on the screen, not the fragment itself. http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html – Submersed Jan 04 '14 at 18:14
  • Also, what is it that you're trying to "get from the each fragment?" – Submersed Jan 04 '14 at 18:28
  • A custom POJO, that contains the user's selections while on the fragment. Each of the 3 fragments instantiates a new POJO, which I want in the end to merge into single POJO and save in the DB – user1927033 Jan 04 '14 at 19:43

1 Answers1

0

Just set an onPageChangeListener on your ViewPager object from within your Activity, then you can use the position to know which fragment the user is currently viewing. I'm not really sure what you're trying to do with this, otherwise I'd try to be more clear...

Edit: Since you've said that you'll only have 3 Fragments, why not keep references to the fragments in your activity, then use a getter method on the fragment to get the POJO?

Subo Code:

Change your interface to:

public interface DataPassIF {
     public UForm getPartForm();
}

Make all of your fragments implement this interface, with their implementation returning their instance of the UForm:

public class YourFragment implements DataPassIF {

    UForm form;

    @Override
    public UForm getPartForm(){
        return form;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState){
         super.onCreate(savedInstanceState);
         form = new Uform();
    }

    //Logic to modify Uform
    ...

}

Since you know that each one of your fragments implements this interface, you can cast each fragment stored in your List<Fragment> fragments to a DataPassIF when needed, and call the interface's methods. Depending on whether the user uses a submit button, it might be easier to send the data to the activity from within an onClick(View v); method, so that you know they're finished modifying the data before you use it.

pager = (ViewPager) findViewById(R.id.tutorial_pager);
        pager.setOnPageChangeListener(new OnPageChangeListener() {

            @Override
            public void onPageSelected(int position) {
                        DataPassIF part = (DataPassIF) fragments.get(position);
                        completeForm.merge(part);
            }

            @Override
            public void onPageScrolled(int position, float positionOffset,
                    int postitionOffsetPixels) {
                        //Might need to use this method to see if they're changing pages...
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

}

Submersed
  • 8,810
  • 2
  • 30
  • 38
  • I'm aware of that and though of implementing it, however how to get property of the fragment class? In the fragment I instantiate a variable PartialForm part3 = new PartialForm() . In it are stored the selections that the user makes while on the fragment, and then it should be passed to the activity where it would be something like FinalForm completedForm.merge(part3). – user1927033 Jan 04 '14 at 19:39
  • Does the user never interact with a submit button? – Submersed Jan 06 '14 at 15:14
  • There is a button (not decided yet whether to be on fragment3 or on the actionbar), but still how to get the partial objects from the fragments? – user1927033 Jan 06 '14 at 15:48
  • Why don't you just parse all of the data at once once the submit button is pressed? If you're using keeping references to your fragments from within your activity, each fragment's UForm data isn't going to be garbage collected before you can use it. Also, I just explained how to interface with your activity. – Submersed Jan 06 '14 at 16:11
  • An alternative solution, though, would be to keep one global "Form" object within your activity, and use ((CastToYourActivity)getActivity()).getForm(); then modify a single instance of the object that's held by your activity, and let each fragment modify the individual fields of this object that they need. It seems like this might be a bit more simple, rather than trying to manage pieces of that object from 3 different fragments. – Submersed Jan 06 '14 at 16:14