How to go back to a previous viewpager fragment from an activity? - android

I know there are similar questions to the one I'm asking but none of them was able to solve the issue I'm having.
I Have a bottom navigation view with five fragments that use viewpager, one of these fragments opens an activity.
Problem
When I open the activity from the fragment it works fine but the issue is the when I press back it goes back to the same fragment that opens the activity.
Solution
I want when I press back out of the activity that it goes to a previous fragment apart from the fragment that calls the activity.
For example: if the user is on HomeFragment and the user clicks the fragment that opens the activity(NewsFragment), and the user press back they Should go back to HomeFragment, not NewsFragment.
What I tried so far:
MainActivity for the BottomnNvigationView and it's On Back Press
private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.nav_library:
viewPager.setCurrentItem(0);
temp = temp.replace("-0", "") + "-0";
break;
case R.id.nav_technology:
viewPager.setCurrentItem(1);
temp = temp.replace("-1", "") + "-1";
break;
case R.id.nav_home:
viewPager.setCurrentItem(2);
temp = temp.replace("-2", "") + "-2";
break;
case R.id.nav_science:
viewPager.setCurrentItem(3);
temp = temp.replace("-3", "") + "-3";
break;
case R.id.nav_news:
viewPager.setCurrentItem(4);
temp = temp.replace("-4", "") + "-4";
Intent intent = new Intent(MainActivity.this,BrowserActivity.class);
startActivity(intent);
return true;
}
return true;
}
};
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout)findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
}
else {
String[] words = temp.split("-");
if(words.length<=2)
if (viewPager.getCurrentItem() != 2) {
temp = "";
viewPager.setCurrentItem(2);
}else
finish();
else {
temp = temp.replace("-" + words[words.length - 1], "");
int pos = viewPager.getCurrentItem();
if (viewPager.getCurrentItem() == pos)
pos = 2;
else
pos = 1;
viewPager.setCurrentItem(Integer.parseInt(words[words.length - pos]));
}
}
}
The Activity that is call from the fragment (BrowersActivity) On Back Press
#Override
public void onBackPressed() {
if (viewPager.getCurrentItem() != 0) {
viewPager.setCurrentItem(viewPager.getCurrentItem() - 1,false);
}else{
finish();
}
}
Any help would be appreciated.

Quickest solution would be to finish the first activity after starting the second one so:
case R.id.nav_news:
viewPager.setCurrentItem(4);
temp = temp.replace("-4", "") + "-4";
Intent intent = new Intent(MainActivity.this,BrowserActivity.class);
startActivity(intent);
finish()
return true;
And in the second activity in onBackPressed, restart the first activity
#Override
public void onBackPressed() {
super.onBackPressed()
startActivity(new Intent(this, FirstActivity.class))
}

Related

Double click to exit app on bottom navigation menu item

Every posts are for navigation drawer but as I am using Bottom navigation I couldn't find any solutions. searched and tried all threads.
This is my selector method for selecting the menu items
public boolean onNavigationItemSelected(#NonNull MenuItem item)
{
View v=null;
int id = item.getItemId();
switch (id){
case R.id.search:
fragment = new Search();
break;
case R.id.todo:
fragment = new ServiceTable();
break;
case R.id.info:
fragment = new Orderlist();
break;
case R.id.close:
//have to implement double click here.
break;
}
final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.main_container, fragment).commit();
return true;
}
});
if (savedInstanceState == null) {
bottomNavigation.setSelectedItemId(R.id.search);
}
}
You have to make a global boolean variable to check the double click functionality like :
boolean doubleBackToExitPressedOnce = false;
after this implement the following code in your case R.id.close
if (doubleBackToExitPressedOnce) {
finishAffinity();
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Press again to exit", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
you can write
boolean isClickedTwice = false;
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
View v = null;
int id = item.getItemId();
switch (id){
case R.id.close:
//have to implement double click here.
if (isClickedTwice) {
this.finish();
}
isClickedTwice = true;
break;
}
final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.main_container, fragment).commit();
return true;
}
});
I see you're using fragments. are you maintaining any back stack trace for this? I suggest you do and then you implement double-click to exit the app. let me know
allowedToExit is a boolean to keep track of user if he is allowed to exit or not. that we judge based on the number of stacked fragments and if user pressed two times. i used this logic in my onBackPressed method to create a two time back press exit app
//fragments remove logic
int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
// this is last item
if (backStackEntryCount == 1) {
if (allowedToExit)
finish();
else {
allowedToExit = true;
Util.showToast(BaseActivity.this,
"Press again to exit", false);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
allowedToExit = false;
}
}, 1000);
return;
}
}
// we have more than 1 fragments in back stack
if (backStackEntryCount > 1) {
Util.hideSoftKeyboard(BaseActivity.this);
onRemoveCurrentFragment();
} else
super.onBackPressed();

ViewPager - Launch Activity from setOnTabSelectedListener

I'm trying to get an activity to launch when a specific tab is selected but when I return from that activity, I want the previous to show instead of the tab I clicked. Just like when you click the plus button on Instagram.
Like this:
Default Fragment 1/Tab 1
Go to Fragment 5/Tab 5
Click tab 3, activity pops up
Go back, see Fragment 5/Tab 5
Right now, I'm storing the last visited tab index in a variable, then when Tab 3 is clicked, it just goes to the last visited tab.
tabLayout.setOnTabSelectedListener(
new TabLayout.ViewPagerOnTabSelectedListener(viewPager) {
#Override
public void onTabSelected(TabLayout.Tab tab) {
//super.onTabSelected(tab); -- Should keep this or leave it commented out?
int pos = tab.getPosition();
switch (pos) {
case 0:
viewPager.setCurrentItem(tab.getPosition(), false);
getSupportActionBar().setTitle("Home");
pre_pos = pos;
pre_title = "Home";
break;
case 1:
viewPager.setCurrentItem(tab.getPosition(), false);
getSupportActionBar().setTitle("Trending");
pre_pos = pos;
pre_title = "Trending";
break;
case 2:
viewPager.setCurrentItem(pre_pos, false);
getSupportActionBar().setTitle(pre_title);
Intent intent = new Intent(MainActivity.this, NewEvent_Activity.class);
startActivity(intent);
Toast.makeText(getApplicationContext(),
"Curr: "+ viewPager.getCurrentItem()+
" Prev: " + pre_pos +
" Clicked: " +tab.getPosition(),
Toast.LENGTH_SHORT).show();
break;
case 3:
viewPager.setCurrentItem(tab.getPosition(), false);
getSupportActionBar().setTitle("Notifications");
pre_pos = pos;
pre_title = "Notifications";
break;
case 4:
viewPager.setCurrentItem(tab.getPosition(), false);
getSupportActionBar().setTitle("Profile");
pre_pos = pos;
pre_title = "Profile";
break;
}
}
});
In ViwPager.java it calls this function when setCurrentItem() is called
void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) {
if (mAdapter == null || mAdapter.getCount() <= 0) {
setScrollingCacheEnabled(false);
return;
}
//I think my problem lies in the following line (mCurItem == item)
if (!always && mCurItem == item && mItems.size() != 0) {
setScrollingCacheEnabled(false);
return;
}
if (item < 0) {
item = 0;
} else if (item >= mAdapter.getCount()) {
item = mAdapter.getCount() - 1;
}
final int pageLimit = mOffscreenPageLimit;
if (item > (mCurItem + pageLimit) || item < (mCurItem - pageLimit)) {
// We are doing a jump by more than one page. To avoid
// glitches, we want to keep all current pages in the view
// until the scroll ends.
for (int i = 0; i < mItems.size(); i++) {
mItems.get(i).scrolling = true;
}
}
final boolean dispatchSelected = mCurItem != item;
if (mFirstLayout) {
// We don't have any idea how big we are yet and shouldn't have any pages either.
// Just set things up and let the pending layout handle things.
mCurItem = item;
if (dispatchSelected) {
dispatchOnPageSelected(item);
}
requestLayout();
} else {
populate(item);
scrollToItem(item, smoothScroll, velocity, dispatchSelected);
}
}
I think this is where my problem is but I can't edit it.
Any suggestions?
Thanks.
implement ViewPager.OnPageChangeListener on activity. set listner on viewpager
view_pager.setOnPageChangeListener(this);
in OnPageSelected() method:
#Override
public void onPageSelected(int position) {
if (position == 3) {
startActivity(new Intent(this,activity.class));
}
}
override activity onResume method and write:
#Override
public void onResume() {
super.onResume();
view_pager.setCurrentItem(0);
}
To do this You have to follow these Simple Steps
Step : 1 Override below method in all ViewPager Frgment
#Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
}
this method will be called when your fragment become visible.
step : 2 Put a condition in Fragmenr3 to start new Activity when your Fragment become visible
#Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
if(menuVisible){
Intent intent = new Intent(MainActivity.this, NewEvent_Activity.class);
startActivity(intent);
}
}
Now it will open you activity in front. but your one requirement remaining which is, if user press back from activity, you have to show second Last fragment, so as you have mention you are storing index position of Last fragment so follow below step .
Step : 3 Override onRestart() in Your ViewPager Actvity
#Override
protected void onRestart() {
super.onRestart();
view_pager.setCurrentItem(Stored last Index);
}
it will solve your problem, its working for me.

save changes of fragment when fragment is replaced

i have implemented Drawer menu in my application. i have 7 different fragments in my app. the MainActivity which holds all the fragments is drawer activity. i have overriden the onBackPressed() method in this activity. i have a fragment where i would like user to save the data he has changed. that is if user have changed something in one fragment and without saving it if user leaves fragment (By selecting another fragment from drawer menu or by pressing a back button) then i want to show the confirmation dialog to user on same fragment where the changes were made. as an example.. if user have made some change in sixth fragment and he leaves the fragment (by selecting any other fragment or back button) i want to show user a confirmation dialog on sixth fragment itself. from where according to his input he can move the selected fragment or stay in the fragment where he made some changes.
Here is the snap of a code of my DrawerActivity.
#Override
public void onBackPressed() {
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
{
super.onBackPressed();
AppConstants.SELECTED_NAVIGATION_TAB=0;
return;
}
else { Toast.makeText(getBaseContext(), "Tap back button in order to exit", Toast.LENGTH_SHORT).show(); }
mBackPressed = System.currentTimeMillis();
}
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
Fragment fragment = null;
switch (id) {
case R.id.nav_home:
AppConstants.SELECTED_NAVIGATION_TAB = 0;
fragment = new HomeFragment();
title = getResources().getString(R.string.home);
break;
case R.id.nav_progress:
AppConstants.SELECTED_NAVIGATION_TAB = 1;
fragment = new ProgressFragment();
title = getResources().getString(R.string.progress);
break;
case R.id.nav_workouts:
AppConstants.SELECTED_NAVIGATION_TAB = 2;
/* if (Utilities.getInstance().getPreferences(DrawerActivity.this, AppConstants.PREF_KEY_USER_INFO,
AppConstants.PREF_KEY_SUBSCRIPTION_STATUS, "").equals("1")){
fragment = new FragmentPremiumClasses();
title = getResources().getString(R.string.premium);
}else {*/
fragment = new WorkoutsFragment();
title = getResources().getString(R.string.workouts);
// }
break;
case R.id.nav_subscription:
AppConstants.SELECTED_NAVIGATION_TAB = 3;
if (!Utilities.getInstance().getPreferences(DrawerActivity.this, AppConstants.PREF_KEY_USER_INFO,
AppConstants.PREF_KEY_SUBSCRIPTION_STATUS, "").equals("1")){
fragment = new SubscriptionFragment();
title = getResources().getString(R.string.subscription);
} else {
fragment = new SelectSocietyFragment();
title = getResources().getString(R.string.newsubscription);
}
break;
case R.id.nav_aboutUs:
AppConstants.SELECTED_NAVIGATION_TAB = 4;
fragment = new AboutUsFragment();
title = getResources().getString(R.string.aboutus);
break;
case R.id.nav_settings:
AppConstants.SELECTED_NAVIGATION_TAB = 5;
fragment = new SettingsFragment();
title = getResources().getString(R.string.settings);
break;
case R.id.nav_logout:
drawer.closeDrawer(GravityCompat.START);
isLogoutClicked = true;
SharedPreferences.Editor editor = getSharedPreferences(AppConstants.PREF_KEY_USER_INFO,
Context.MODE_PRIVATE).edit();
editor.clear();
editor.commit();
AppConstants.SELECTED_NAVIGATION_TAB = 0;
Utilities.getInstance().finishAndStartIntent(DrawerActivity.this, MainActivity.class, 0, 0);
break;
}
if (!isLogoutClicked) {
getSupportActionBar().setTitle(title);
android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame, fragment);
fragmentTransaction.commit();
drawer.closeDrawer(GravityCompat.START);
}
return true;
}
Hope i have made the question clear, how to achieve this functionality? any help would be much appreciated :)
thanks :)
Save data in onPause() of fragment.

Navigation in Navigation Drawer

I have a Navigation Drawer which has 5 items.
If user selects an Item, I'm loading respective Fragment in FrameLayout
Now, if user pulls out the Navigation Drawer and selects the same Item as previous, I should not load the same Fragment again, so I'm saving the selected position and if previous selected position equals current selection I'm just closing the Navigation Drawer as follows:
String title = null;
invalidateOptionsMenu();
android.support.v4.app.Fragment fragment = null;
if (position == getPrevSelectedItem()) {
// Already selected fragment is being displayed
} else {
switch (position) {
case Numerics.ZERO:
fragment = new DashBoardFragment();
title = fragment.getClass().getSimpleName();
break;
case Numerics.ONE:
break;
case Numerics.TWO:
break;
case Numerics.THREE:
break;
case Numerics.FOUR:
break;
default:
break;
}
if (fragment != null) {
showFragment(fragment, title);
}
setSelectedItem(position);
}
I'm adding fragments by adding to backstack in order to provide back navigation to previous fragment as follows :
if (fragment != null) {
String backStateName = fragment.getClass().getName();
mFragmentManager = getSupportFragmentManager();
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.dashboard_container, fragment);
mFragmentTransaction.addToBackStack(backStateName);
mFragmentTransaction.commit();
}
The problem is:
If I select Item no:3 and then select Item:4, if I navigate back the previous selection is still 4, but I'm displaying Fragment with no:3. So, if I select Item no:3 again from Navigation Drawer the Fragment loads again. How to solve this ??
EDIT:
public int getPrevSelectedItem() {
return selectedItem;
}
public void setSelectedItem(int selectedItem) {
this.selectedItem = selectedItem;
}
try this
Fragment currentFragment = getActivity().getFragmentManager().findFragmentById(R.id.dashboard_container);
if(currentFragment instanceof YouFragmentName)
return
you can check the instance of loaded fragment on clicking the menu
Fragment loadedFragment= getFragmentManager().findFragmentById(R.id.fragmentLoadingSpace);
if( !(loadedFragment instanceof FragmentName1)){
// load fragment
}
I think there is no need of else statement or you can use else only for closing drawer
public int prevPosition=-1;
if (getPrevSelectedItem() != prevPosition) {
// Already selected fragment is being displayed
prevPosition =getPrevSelectedItem();
callFragment(position);
}
private void callFragment(int position) {
// TODO Auto-generated method stub
switch (position) {
case Numerics.ZERO:
fragment = new DashBoardFragment();
title = fragment.getClass().getSimpleName();
break;
case Numerics.ONE:
break;
case Numerics.TWO:
break;
case Numerics.THREE:
break;
case Numerics.FOUR:
break;
default:
break;
}
if (fragment != null) {
showFragment(fragment, title);
}
setSelectedItem(position);
}
From my comment:
The drawer does not get updated when you press back - so you need to add some code to onBackPressed() in the activity, where you update the position according to the popped BackstackEntry.
#Override
public void onBackPressed(){
String backStackEntryName = fragmentManager.getBackStackEntryAt(backCount - 2).getName();
int id = R.id.my_main_frag; //default option
if (MyMainFrag.class.getName().equals(backStackEntryName)){
id = R.id.my_main_frag;
selectedItem = 0;
} else if (MySecondFrag.class.getName().equals(backStackEntryName)){
id = R.id.my_second_frag;
selectedItem = 1;
}
...
navigation.setCheckedItem(id);
super.onBackPressed();
}

Handling back button with fragments and activity?

I have an "activity A" that launches two fragments, with the home button being part of the activity A, and when the back button is pressed from the createFragment it should go back to the activity before activity A, which it does fine with the finish() method but when I have the second fragment, followersFragment which is added ontop of createFragment and hides createFragment (because I do not want the information being lost in the create), then I hit the back button and it switches back to the create fragment but then when I hit the back button from createFragment it does not go back to activity A anymore and does nothing... no error...
This is my code on the activity that holds the fragments(not activity A):
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar actions click
switch (item.getItemId()) {
// lets user travel back to where they came from
case android.R.id.home:
if(displayShown == 1) {
displayView(2, 0);
} else {
}
return true;
private void displayView(int i, int position) {
Log.d(Constants.DEBUG, "display view called " +position);
boolean createPost = true;
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 0:
//avoid recreating createPostFragment if already created because all data will be erased
if(createPostFragment == null){
createPost = false;
Log.d(Constants.DEBUG, "fragment create DOES NOT EXIST ");
createPostFragment = new CreatePostFragment();
}
fragment = createPostFragment;
break;
case 1:
followerFragment = new FollowerFragment();
fragment = followerFragment;
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
trans = fragmentManager.beginTransaction();
//if createpostfrag already created just show
if (createPost && position == 0) {
trans.remove(followerFragment);
trans.show(createPostFragment);
trans.commit();
//hide createpostfrag so we can reuse
} else {
if(position == 1) {
Bundle extraData = new Bundle();
extraData.putInt("follow", i);
fragment.setArguments(extraData);
trans.add(R.id.frame_container, fragment, null).commit();
trans.hide(createPostFragment);
}
if(position == 0) {
trans.add(R.id.frame_container, fragment, "keepAlive").commit();
}
}
} else {
// error in creating fragment
Log.d(Constants.DEBUG, "Error in creating fragment or no fragment needed");
}
}

Categories

Resources