cipley
cipley

Reputation: 1112

ViewPager first two fragments are not in order

I am making an apps which utilizes the ViewPager so the user fill in the form and saves the progress while continuing to the next fragment by scrolling right.

It is still unfinished; however I stumble upon a strange behavior from the Android.

I have about 9 fragments, and it will be loaded when HomeActivity is called. The first is SiteDetailsFragment, and the second is DevicePlacementDetailsFragment, and so on.

I intent to save the user's current progress by overriding onPageSelected and make use of the fragment position to determine which one should be saved/verified. I called List<Fragment> fs = getSupportFragmentManager().getFragments(); to store the fragments' position.

However, when I tested the apps, the two of them seems to be instantiated in reversed order - DevicePlacementDetailsFragment is on the first member of fs, then followed by SiteDetailsFragment. DevicePlacementDetailsFragment is on position 0 on fs while SiteDetailsFragment on position 1, but on the screen they are in correct order.

The rest of the fragments get instatiated in order as I scrolled right.

This has caused a confusion for me as I have to determine the fragment's position and what needs to be done when onPageSelected gets called.

Below is the code. I know it's quite strange, but it's a work in progress. I also wrote a piece of code as a workaround for this issue.

import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.widget.Toast;

import com.xxx.psie_surveyandroid.R;
import com.xxx.psie_surveyandroid.adapters.ViewPagerAdapter;
import com.xxx.psie_surveyandroid.customlibs.CustomAppCompatActivity;
import com.xxx.psie_surveyandroid.fragments.CablingToIDUFragment_;
import com.xxx.psie_surveyandroid.fragments.CablingToTransmissionFragment_;
import com.xxx.psie_surveyandroid.fragments.DevicePlacementDetailFragment_;
import com.xxx.psie_surveyandroid.fragments.GroundFragment_;
import com.xxx.psie_surveyandroid.fragments.PhotoSiteSurveyFragment_;
import com.xxx.psie_surveyandroid.fragments.PowerDetailFragment_;
import com.xxx.psie_surveyandroid.fragments.RackAndRoomLayoutFragment_;
import com.xxx.psie_surveyandroid.fragments.SiteDetailFragment_;
import com.xxx.psie_surveyandroid.fragments.SpareFragment_;

import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.ViewById;

import java.util.List;

/**
 * @author Cipleyo
 * @since 5/20/2016
 */
@EActivity(R.layout.home_activity_layout)
public class HomeActivity extends CustomAppCompatActivity {
    public final static String TAG = HomeActivity.class.getSimpleName();
    @ViewById Toolbar toolbar;
    @ViewById TabLayout tabLayout;
    @ViewById ViewPager vpForms;

    private int lastPos = 0;

    @AfterViews
    void init(){
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(false);
        setupViewPager(vpForms);
        tabLayout.setupWithViewPager(vpForms);

        vpForms.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                List<Fragment> fs = getSupportFragmentManager().getFragments();
                /*
                These strange lines of codes are for fixing the misplaced first two Fragments.
                Don't ask why - I have no idea.
                 */
                Fragment tempFragment = fs.get(0);
                if (!(tempFragment instanceof SiteDetailFragment_)) {
                    fs.set(0, fs.get(1));
                    fs.set(1, tempFragment);
                }
                /* End of strange lines of codes */
                Fragment f;
                f = fs.get(lastPos);
                if (lastPos > position) {   //left
                    Log.i(TAG, "Scrolled Left, f = " + f);
                } else {                    //right
                    Log.i(TAG, "Scrolled Right, f = " + f);
                }
                if (lastPos < position) {   //swipe right
                    if (f instanceof SiteDetailFragment_) {
                        if (!((SiteDetailFragment_) f).executeSave()) {
                            vpForms.setCurrentItem(lastPos);
                            Toast.makeText(getApplicationContext(), "Please complete the required fields!",
                                    Toast.LENGTH_SHORT).show();
                        } else
                            lastPos = position;
                    } else if (f instanceof DevicePlacementDetailFragment_){
                        if (!((DevicePlacementDetailFragment_) f).executeSave()){
                            vpForms.setCurrentItem(lastPos);
                            Toast.makeText(getApplicationContext(), "Please complete the required fields!",
                                    Toast.LENGTH_SHORT).show();
                        } else
                            lastPos = position;
                    } else if (f instanceof RackAndRoomLayoutFragment_){
                        if (!((RackAndRoomLayoutFragment_) f).executeSave()){
                            vpForms.setCurrentItem(lastPos);
                            Toast.makeText(getApplicationContext(), "Please complete the required fields!",
                                    Toast.LENGTH_SHORT).show();
                        } else
                            lastPos = position;
                    }
                } else
                    lastPos = position;
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    private void setupViewPager(ViewPager viewPager){
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFragment(new SiteDetailFragment_(), "Site Details");
        adapter.addFragment(new DevicePlacementDetailFragment_(), "Device Placement Detail");
        adapter.addFragment(new RackAndRoomLayoutFragment_(), "Rack And Room Layout");
        adapter.addFragment(new PhotoSiteSurveyFragment_(), "Photo Site Survey");
        adapter.addFragment(new PowerDetailFragment_(), "Power Details");
        adapter.addFragment(new GroundFragment_(), "Ground");
        adapter.addFragment(new CablingToTransmissionFragment_(), "Cabling To Transmission");
        adapter.addFragment(new CablingToIDUFragment_(), "Cabling To IDU");
        adapter.addFragment(new SpareFragment_(), "Spare");
        viewPager.setAdapter(adapter);
    }
}

I hope I describe my problems quite well. Feel free to ask any additional info that might help. Thanks!

Upvotes: 0

Views: 99

Answers (2)

cipley
cipley

Reputation: 1112

I found the better workaround here: Is there a way to get references for all currently active fragments in an Activity?

As @Code-Apprentice pointed out, getSupportFragmentAdapter().getFragments() is not behaving like I expected. So I took the different route using Activity.onAttachFragment()

note: I am using Support Library's Fragment. If you are using Native Fragment, you should Override the onAttachFragment method.

protected List<WeakReference<Fragment>> fragmentList = new ArrayList<>();

public void onAttachFragment(Fragment fragment){
    fragmentList.add(new WeakReference<>(fragment));
}

public List<Fragment> getActiveFragments(){
    ArrayList<Fragment> ret = new ArrayList<>();
    for (WeakReference<Fragment> ref : fragmentList){
        Fragment f = ref.get();
        if (f != null){
            if (f.isVisible()){
                ret.add(f);
            }
        }
    }
    return ret;
}

Upvotes: 0

Code-Apprentice
Code-Apprentice

Reputation: 83537

According to getSupportFragmentManager().getFragments() deprecated?, FragmentManager.getFragments() is hidden in older versions of the Android API. In the latest version of the API, it appears to have been removed entirely. (I cannot see it listed in the documentation for FragmentManager or SupportFragmentManager.) You shouldn't use this method. Since the method is undocumented, its behavior is unreliable.

Upvotes: 1

Related Questions