I am a beginner android developer trying to make an android application. My app has a viewpager with 4 fragments. Now whenever I move from main activity (viewpager activity) to another activity and back, the main activity starts again and viewpager displays first fragment instead of the fragment which was in display by user earlier. I have provided my code below. Please help so that I can fix this issue of viewpager unnecessarily rolling back to first fragment.
public class MainActivity extends AppCompatActivity {
private static final int RC_SIGN_IN = 123;
private FirebaseAuth mFirebaseAuth;
private FirebaseAuth.AuthStateListener mAuthStateListener;
public String ADMIN_CHANNEL_ID = "ADMIN";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
final PbFragmentPagerAdapter adapter = new PbFragmentPagerAdapter(getSupportFragmentManager());
final TabLayout tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
mFirebaseAuth = FirebaseAuth.getInstance();
mAuthStateListener = new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if(user!=null){
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
viewPager.setOffscreenPageLimit(4);
adapter.fetchFragmentByPosition(viewPager, viewPager.getCurrentItem());
}
else{startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(Arrays.asList(
new AuthUI.IdpConfig.EmailBuilder().build(),
new AuthUI.IdpConfig.GoogleBuilder().build()
))
.setLogo(R.drawable.ic_fui_icon_round)
.build(),
RC_SIGN_IN);
}
}
};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create the NotificationChannel
CharSequence name = getString(R.string.notifications_admin_channel_name);
String description = getString(R.string.notifications_admin_channel_description);
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel(ADMIN_CHANNEL_ID, name, importance);
mChannel.setDescription(description);
mChannel.enableLights(true);
mChannel.setLightColor(R.color.colorPrimaryDark);
mChannel.enableVibration(true);
NotificationManager notificationManager = (NotificationManager) getSystemService(
NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(mChannel);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode== RC_SIGN_IN){
if(resultCode==RESULT_OK){
Toast.makeText(MainActivity.this, "Signed In Successfully!",Toast.LENGTH_SHORT).show();
}
else if (resultCode==RESULT_CANCELED){
finish();
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.sign_out_menu:
AuthUI.getInstance().signOut(this);
return true;
case R.id.share_menu:
shareApp();
return true;
case R.id.terms_menu:
openTermsActivity();
return true;
case R.id.privacy_menu:
openPrivacyActivity();
return true;
case R.id.about_menu:
openAboutActivity();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void openAboutActivity() {
Intent intent = new Intent(this, AboutActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
public void openTermsActivity() {
Intent intent = new Intent(this, TermsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
public void openPrivacyActivity() {
Intent intent = new Intent(this, PrivacyActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
public void shareApp() {
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_TEXT,
"Hi, I would like to recommend the xyz app to you..);
shareIntent.setType("text/plain");
startActivity(shareIntent);
}
@Override
protected void onPause() {
super.onPause();
mFirebaseAuth.removeAuthStateListener(mAuthStateListener);
}
@Override
protected void onResume() {
super.onResume();
mFirebaseAuth.addAuthStateListener(mAuthStateListener);
}
public class PbFragmentPagerAdapter extends SmartFragmentStatePagerAdapter {
final int PAGE_COUNT = 4;
private String tabTitles[] = new String[] { "Open Trades", "Past Trades", "Books", "Broker" };
public PbFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new OpenTradesFragment();
case 1:
return new PastTradesFragment();
case 2:
return new BooksFragment();
case 3:
return new BrokersFragment();
default:
return null;
}
}
@Override
public int getCount() {
return PAGE_COUNT;
}
@Override
public CharSequence getPageTitle(int position) {
return tabTitles[position];
}
}
}
// below code is for pager adapter
public abstract class SmartFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
// Sparse array to keep track of registered fragments in memory
private SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
public SmartFragmentStatePagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
// Register the fragment when the item is instantiated
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
// Unregister when the item is inactive
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
// Returns the fragment for the position (if instantiated)
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
public Fragment fetchFragmentByPosition(ViewGroup pagerInstance, int position) {
Fragment existingInstance = registeredFragments.get(position);
if (existingInstance != null) {
return existingInstance;
} else {
return (Fragment)instantiateItem(pagerInstance, position);
}
}
}
sharing XML file below:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:orientation="vertical"
android:id="@+id/main_activity_layout"
tools:context="in.permabull.permabull.MainActivity">
<android.support.design.widget.TabLayout
android:id="@+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabSelectedTextColor="@color/colorPrimaryDark"
app:tabTextColor="@color/colorGrey"
app:tabPadding="8dp"
app:tabMode="scrollable">
</android.support.design.widget.TabLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/colorLightGrey"/>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1">
</android.support.v4.view.ViewPager>
</LinearLayout>
As expected it was a simple problem.. solved it (using onPageSelected) as follows:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
tabPosition=position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
where tabPosition is a global int variable that helps to store the fragment(tab) number on which the viewpager is when back/home button is pressed.