Reputation: 1112
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
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
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