I have a problem, in my Activity I have a NavigationDrawer, I use to call 3 fragment.
I have implemented the onSaveInstanceState/onRestoreInstanceState for the Fragment active, all the data are saved correctly, but when I rotate the device, the savedInstanceState (inside onCreate) is not null and the NavigationDrawer not call the Fragment.
now I have broken my head to think a solution....
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dualpane);
if(savedInstanceState == null)
instantiateFragments(null);//init
// Handle Toolbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
if (null != toolbar) {
setSupportActionBar(toolbar);
//set the back arrow in the toolbar
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
//Create the AccountHeader
headerResult = new AccountHeaderBuilder()
.withActivity(this)
.withTranslucentStatusBar(false)
.withSavedInstance(savedInstanceState)
.build();
Fragment_1 = new PrimaryDrawerItem()
.withName("Fragment 1")
.withIdentifier(1);
Fragment_2 = new PrimaryDrawerItem()
.withName("Fragment 2")
.withIdentifier(2);
Fragment_3 = new PrimaryDrawerItem()
.withName("Fragment 3")
.withIdentifier(3);
builder = new DrawerBuilder()
.withActivity(this)
.withToolbar(toolbar)
.withTranslucentStatusBar(false)
.withAccountHeader(headerResult) //set the AccountHeader we created earlier for the header
.addDrawerItems(
Fragment_1,
Fragment_2,
Fragment_3
) // add the items we want to use with our Drawer
// .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
// #Override
// public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
// // do something with the clicked item :D
// if (drawerItem != null && drawerItem instanceof Nameable) {
// String name = ((Nameable) drawerItem).getName().getText(CustomListActivity.this);
// getSupportActionBar().setTitle(name);
// FragmentManager mFragmentManager = getSupportFragmentManager();
// FragmentTransaction transaction = mFragmentManager.beginTransaction();
// Log.d(TAG, "onCreate: savedInstanceState = " + (savedInstanceState == null ? "NULL" : "Not NULL"));
// if (savedInstanceState == null) {
// switch (position) {
// case 1:
// transaction.replace(R.id.fragment_container, Fragment1.newInstance(), FRAGMENT_TAG1).commit();
// break;
// case 2:
// transaction.replace(R.id.fragment_container, Fragment2.newInstance(), FRAGMENT_TAG2).commit();
// break;
// case 3:
// transaction.replace(R.id.fragment_container, Fragment3.newInstance("Terzo"), FRAGMENT_TAG3).commit();
// break;
// }
// }else{
// instantiateFragments(savedInstanceState);
// }
// /* FragmentManager mFragmentManager = getSupportFragmentManager();
// Fragment fragment = mFragmentManager.findFragmentById(R.id.fragment_container);
// fragment1 = (Fragment1) mFragmentManager.findFragmentByTag(FRAGMENT_TAG1);
// fragment2 = (Fragment2) mFragmentManager.findFragmentByTag(FRAGMENT_TAG2);
// fragment3 = (Fragment3) mFragmentManager.findFragmentByTag(FRAGMENT_TAG3);
// if (savedInstanceState == null) {
//
// // List<Fragment> lista = mFragmentManager.getFragments();
// if (fragment == null) {
// mFragmentManager.beginTransaction().add(R.id.fragment_container, Fragment3.newInstance("Terzo"), FRAGMENT_TAG3).commit();
// mFragmentManager.beginTransaction().add(R.id.fragment_container, Fragment2.newInstance(), FRAGMENT_TAG2).commit();
// mFragmentManager.beginTransaction().add(R.id.fragment_container, Fragment1.newInstance(), FRAGMENT_TAG1).commit();
//
// } else {
// //mFragmentManager.beginTransaction().remove(fragment).commit();
// mFragmentManager.beginTransaction().detach(fragment).commit();
//
// switch (position) {
// case 1:
// mFragmentManager.beginTransaction().attach(fragment1).commit();
// break;
// case 2:
// mFragmentManager.beginTransaction().attach(fragment2).commit();
// break;
// case 3:
// //bSavePage = new Bundle();
// //bSavePage.putString("section_name", "Quarto");
// //fragment3.setArguments(bSavePage);
// Bundle args = new Bundle();
// args.putString("someString", "Quarto");
// // Put any other arguments
// fragment3.setArguments(args);
// Fragment.instantiate(getApplicationContext(), Fragment3.class.getName(), args);
// mFragmentManager.beginTransaction().attach(fragment3).commit();
// break;
// }
// }
// } else {
// // probabilmente e' accaduta una rotazione
// mFragmentManager.beginTransaction().detach(fragment).commit();
// switch (position) {
// case 1:
// mFragmentManager.beginTransaction().attach(fragment1).commit();
// break;
// case 2:
// mFragmentManager.beginTransaction().attach(fragment2).commit();
// break;
// case 3:
// Bundle args = new Bundle();
// args.putString("someString", "Quarto");
// // Put any other arguments
// fragment3.setArguments(args);
// Fragment.instantiate(getApplicationContext(), Fragment3.class.getName(), args);
// mFragmentManager.beginTransaction().attach(fragment3).commit();
// break;
// }
// }*/
// getSupportActionBar().setTitle(name);
// }
// return false;
// }
// }
//
// )
.withOnDrawerListener(new Drawer.OnDrawerListener() {
#Override
public void onDrawerOpened(View drawerView) {
KeyboardUtil.hideKeyboard(CustomListActivity.this);
}
#Override
public void onDrawerClosed(View drawerView) {
}
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
}
}
)
.withFireOnInitialOnClick(true)
.withSavedInstance(savedInstanceState);
result = builder.build();
#Override
protected void onSaveInstanceState(Bundle outState) {
//add the values which need to be saved from the drawer to the bundle
outState = result.saveInstanceState(outState);
//add the values which need to be saved from the accountHeader to the bundle
outState = headerResult.saveInstanceState(outState);
super.onSaveInstanceState(outState);
Log.d(TAG, "onSaveInstanceState");
FragmentManager mFragmentManager = getSupportFragmentManager();
mMyFragment = mFragmentManager.findFragmentById(R.id.fragment_container);
mFragmentManager.putFragment(outState, "SaveFrag", mMyFragment);
outState.putString("TAG", mMyFragment.getTag());
}
#Override
protected void onRestoreInstanceState(Bundle inState) {
super.onRestoreInstanceState(inState);
Log.d(TAG, "onRestoreInstanceState");
instantiateFragments(inState);
}
private void instantiateFragments(Bundle inState) {
FragmentManager mFragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = mFragmentManager.beginTransaction();
if (inState != null) {
mMyFragment = (Fragment) mFragmentManager.getFragment(inState, "SaveFrag");
transaction.replace(R.id.fragment_container, mMyFragment, inState.getString("TAG"));
} /*else {
// inizializzazione
transaction.add(R.id.fragment_container, Fragment1.newInstance(), FRAGMENT_TAG1);
transaction.commit();
}*/
}
EDIT**
I have implemented onPostCreate in my Activity and moved the code withOnDrawerItemClickListener inside and now works!
#Override
protected void onPostCreate( final Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
Log.d(TAG, "onPostCreate");
builder.withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
#Override
public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
if (drawerItem != null && drawerItem instanceof Nameable) {
String name = ((Nameable) drawerItem).getName().getText(CustomListActivity.this);
getSupportActionBar().setTitle(name);
FragmentManager mFragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = mFragmentManager.beginTransaction();
Log.d(TAG, "onCreate: savedInstanceState = " + (savedInstanceState == null ? "NULL" : "Not NULL"));
//if (savedInstanceState == null) {
switch (position) {
case 1:
transaction.replace(R.id.fragment_container, Fragment1.newInstance(), FRAGMENT_TAG1).commit();
break;
case 2:
transaction.replace(R.id.fragment_container, Fragment2.newInstance(), FRAGMENT_TAG2).commit();
break;
case 3:
transaction.replace(R.id.fragment_container, Fragment3.newInstance("Terzo"), FRAGMENT_TAG3).commit();
break;
}
//}else{
//instantiateFragments(savedInstanceState);
//}
getSupportActionBar().setTitle(name);
}
return false;
}
});
}
Related
I'm using BottomBar menu's in my android application. And there are 5 menus in the BottomBar. This is the main activity
public class MainActivity extends BaseActivity {
private static final String TAG = "MainActivity";
private static final String COMMAND_RESET_PASSWORD = "reset-password";
private static final String COMMAND_REFERRAL = "referral";
private static final int HOME = 0;
private static final int MAP = 1;
private static final int DEAL = 2;
private static final int NOTIFICATION = 3;
private static final int SETTINGS = 4;
private BottomBar mBottomBar;
private int mCurrentTab = HOME;
private BottomBarBadge mNotificationBadge;
private boolean mActive;
#Override
protected void onCreate(Bundle savedInstanceState) {
mActive = true;
super.onCreate(savedInstanceState);
initBottomBar(savedInstanceState);
Intent intent = getIntent();
handleIntent(intent);
}
private void initBottomBar(Bundle savedInstanceState) {
mBottomBar = BottomBar.attach(this, savedInstanceState);
mBottomBar.useFixedMode();
mBottomBar.noTabletGoodness();
mBottomBar.setItemsFromMenu(R.menu.bottombar_menu, new OnMenuTabClickListener() {
#Override
public void onMenuTabSelected(#IdRes int menuItemId) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
switch (menuItemId) {
case R.id.bottomBarHome:
showStoreList();
break;
case R.id.bottomBarMap:
showMap();
break;
case R.id.bottomBarDeal:
showDeals();
break;
case R.id.bottomBarSettings:
showSettings();
break;
case R.id.bottomBarNotification:
if (mNotificationBadge != null) {
mNotificationBadge.hide();
Sample.getApp().clearBadge();
}
showNotifications();
break;
}
}
#Override
public void onMenuTabReSelected(#IdRes int menuItemId) {
switch (menuItemId) {
case R.id.bottomBarHome:
if (mCurrentTab != HOME)
showStoreList();
break;
case R.id.bottomBarMap:
if (mCurrentTab != MAP)
showMap();
break;
case R.id.bottomBarDeal:
if (mCurrentTab != DEAL) {
showDeals();
}
break;
case R.id.bottomBarNotification:
if(mCurrentTab != NOTIFICATION) {
if (mNotificationBadge != null) {
mNotificationBadge.hide();
mNotificationBadge.setDealItemCount(0);
Sample.getApp().clearBadge();
}
showNotifications();
}
break;
case R.id.bottomBarSettings:
if (mCurrentTab != SETTINGS)
showSettings();
break;
}
}
});
mNotificationBadge = mBottomBar.makeBadgeForTabAt(3, R.color.sample_badge_color, Sample.getApp().getBadgeCount());
}
public void hideBottomBar() {
if (mBottomBar != null) mBottomBar.hide();
}
public void showBottomBar() {
if (mBottomBar != null) mBottomBar.show();
}
#Override
protected void onResume() {
super.onResume();
handleCommands();
if (mNotificationBadge != null) {
mNotificationBadge.setDealItemCount(Sample.getApp().getBadgeCount());
}
}
public void showPointPopUp() {
PointDialogFragment fragment = new PointDialogFragment();
fragment.setShowsDialog(true);
fragment.show(getSupportFragmentManager(),TAG);
}
private void showStoreList() {
mCurrentTab = HOME;
Fragment fragment = Fragment.instantiate(this, StoreListFragment.class.getName());
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, fragment)
.commitAllowingStateLoss();
}
private void showMap() {
String storeId = Sample.getApp().getMallId();
Store store = mStoreCache.getMall(storeId);
if (store != null && store.isMapAvailable()) {
Bundle args = new Bundle();
args.putString(Sample.EXTRA_STORE_ID, Sample.getApp().getMallId());
args.putBoolean(Sample.EXTRA_COMMAND, true);
Fragment fragment = Fragment.instantiate(this, SampleMapFragment.class.getName(), args);
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, fragment)
.commitAllowingStateLoss();
} else {
Fragment fragment = Fragment.instantiate(this, StoreMapFragment.class.getName());
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, fragment)
.commitAllowingStateLoss();
}
mCurrentTab = MAP;
}
private void showDeals() {
mCurrentTab = DEAL;
String storeId = Sample.getApp().getMallId();
Bundle args = new Bundle();
if (storeId != null)
args.putString(Sample.EXTRA_STORE_ID, storeId);
Fragment fragment = Fragment.instantiate(this, DealsFragment.class.getName(), args);
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, fragment)
.commitAllowingStateLoss();
}
private void showNotifications(){
mCurrentTab = NOTIFICATION;
Fragment fragment = Fragment.instantiate(this, NotificationFragment.class.getName());
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, fragment)
.commitAllowingStateLoss();
}
private void showSettings() {
mCurrentTab = SETTINGS;
Fragment fragment = Fragment.instantiate(this, ProfileFragment.class.getName());
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, fragment)
.commitAllowingStateLoss();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected int getLayoutResource() {
return R.layout.activity_content_frame;
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
Log.d(TAG, "inside onNewIntent");
if (mActive) {
handleIntent(getIntent());
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mBottomBar.onSaveInstanceState(outState);
}
#Override
protected void onDestroy() {
mActive = false;
super.onDestroy();
}
#Override
protected void onStart() {
super.onStart();
Branch branch = Branch.getInstance();
if (BuildConfig.DEBUG) {
branch.setDebug();
}
Log.d(TAG, "inside branch no error");
branch.initSession((referringParams, error) -> {
if (error == null) {
try {
Log.d(TAG, "parsed data from referringParams");
if (referringParams.has("data")) {
String link = referringParams.getJSONObject("data").getString("link");
if(link != null && !link.isEmpty()){
Uri uri = Uri.parse(link);
if(uri.getScheme().equals("sample")){
List<String> pathSegments = uri.getPathSegments();
String command = "";
String argument = null;
if (!pathSegments.isEmpty() && pathSegments.size() == 1) {
command = uri.getHost();
argument = pathSegments.get(0);
}
if(COMMAND_REFERRAL.equals(command) && argument != null){
Sample.getApp().currentUser().setReferralCode(argument);
}else {
Intent activityIntent = new Intent(MainActivity.this, LinkHandlerActivity.class);
activityIntent.setData(uri);
startActivity(activityIntent);
}
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, this.getIntent().getData(), this);
}
public void showSignUpInPage() {/*line 319 */
Bundle args = new Bundle();
args.putString(Sample.TYPE, Sample.SIGN_UP);
Fragment fragment =
Fragment.instantiate(this, SignUpInFragmentMain.class.getName(),args);
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, fragment)
.addToBackStack(null)
.commit();/***This is the 319th line***/
}
public void forgotPassword(){
Fragment fragment =
Fragment.instantiate(this, ForgotPasswordFragment.class.getName());
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, fragment)
.addToBackStack(null)
.commit();
}
private void handleCommands() {
if (!mActive || Sample.getApp().getNotificationCommand() == null) {
return;
}
switch (Sample.getApp().getNotificationCommand()) {
case Sample.COMMAND_DEAL:
showStoreDetail(Sample.getApp().getStoreId());
break;
case Sample.COMMAND_MALL_DEAL:
showMallDetail(Sample.getApp().getStoreId());
break;
case Sample.COMMAND_REGISTER:
showSignUpInPage();
break;
case Sample.COMMAND_DEFAULT:
break;
case Sample.COMMAND_MAP:
mBottomBar.selectTabAtPosition(1, true);
break;
}
Sample.getApp().setNotificationCommand(null);
}
private void handleIntent(Intent intent) {
if (!mActive) {
return;
}
Uri uri = intent.getData();
if (uri != null) {
Fragment fragment;
List<String> pathSegments = uri.getPathSegments();
String command;
String argument;
if (pathSegments.isEmpty()) {
return;
}
if (pathSegments.size() == 1) {
command = uri.getHost();
argument = pathSegments.get(0);
} else {
command = pathSegments.get(1);
argument = pathSegments.size() > 2 ? pathSegments.get(2) : null;
Log.d(TAG,pathSegments.toString());
}
Bundle args = new Bundle();
switch (command) {
case COMMAND_RESET_PASSWORD:
String uid = pathSegments.size() > 2 ? pathSegments.get(2) : null;
String token = pathSegments.size() > 3 ? pathSegments.get(3) : null;
args.putString(Sample.EXTRA_PASSWORD_TOKEN, token);
args.putString(Sample.EXTRA_PASSWORD_UID, uid);
Fragment resetPasswordFragment =
Fragment.instantiate(this, ResetPasswordFragment.class.getName(), args);
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, resetPasswordFragment)
.addToBackStack(null)
.commit();
break;
case COMMAND_REFERRAL:
if(argument != null)
Sample.getApp().currentUser().setReferralCode(argument);
break;
}
}
}
private void showStoreDetail(String storeId) {
Sample.getApp().setStoreId(null);
Bundle args = new Bundle();
args.putString(Sample.EXTRA_STORE_ID, storeId);
Fragment fragment = Fragment.instantiate(this, StoreDetailFragment.class.getName(), args);
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, fragment)
.addToBackStack(null)
.commit();
}
private void showMallDetail(String storeId) {
Sample.getApp().setStoreId(null);
Bundle args = new Bundle();
args.putString(Sample.EXTRA_STORE_ID, storeId);
Fragment fragment = Fragment.instantiate(this, MallDetailFragment.class.getName(), args);
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, fragment)
.addToBackStack(null)
.commit();
}
}
when switching between tabs(Bottombar menu's) results in app crash in some devices. But I couldn't reproduce the exception.
This is the stacktrace
Non-fatal Exception: java.lang.RuntimeException: Unable to resume activity {com.beco.ibeco/com.beco.ibeco.app.MainActivity}: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3000)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3031)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5268)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:902)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:697)
Caused by java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1842)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1860)
at android.support.v4.app.FragmentManagerImpl.popBackStack(FragmentManager.java:781)
at com.beco.ibeco.app.MainActivity$1.onMenuTabSelected(MainActivity.java:74)
at com.beco.ibeco.app.views.bottombar.BottomBar.notifyMenuListener(BottomBar.java:1239)
at com.beco.ibeco.app.views.bottombar.BottomBar.updateSelectedTab(BottomBar.java:1199)
at com.beco.ibeco.app.views.bottombar.BottomBar.selectTabAtPosition(BottomBar.java:437)
at com.beco.ibeco.app.MainActivity.handleCommands(MainActivity.java:347)
at com.beco.ibeco.app.MainActivity.onResume(MainActivity.java:154)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1257)
at android.app.Activity.performResume(Activity.java:6119)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2989)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3031)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5268)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:902)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:697)
Can anyone help me.!
Quick solution is to use .commitAllowingStateLoss(); instead of .commit(); for all FragmentTransactions you are doing for current activity.
There is a bug related to it : https://issuetracker.google.com/issues/36932872
To save the instance and add something to your outState Bundle you can use the following:
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("WORKAROUND_FOR_BUG_KEY","WORKAROUND_FOR_BUG_VALUE");
super.onSaveInstanceState(outState);
}
Also try to add this line if it doesn't work:
transaction.commitAllowingStateLoss();
I have faced this problem
I use .commitAllowingStateLoss(); instead of .commit(); for those FragmentTransactions which fragment state has loss.
In another class you can use .commit();
Im using BottomNavigation Bar Library of (roughike)
Please check SnapShot attached as shown there gallery is currently select i want to de select it. and dnt want to show any selected item when i want.
please help.
SnapShot
mBottomBar = BottomBar.attach(this, savedInstanceState);
mBottomBar.useDarkTheme();
mBottomBar.setItemsFromMenu(R.menu.bottom_tab, new OnMenuTabClickListener() {
#Override
public void onMenuTabSelected(#IdRes int menuItemId) {
if (menuItemId == R.id.HomeTab) {
displayView(0);
}
if (menuItemId == R.id.ProfileTab) {
displayView(1);
}
if (menuItemId == R.id.GalleryTab) {
displayView(2);
}
if (menuItemId == R.id.FriendsTab) {
displayView(3);
}
if (menuItemId == R.id.SettingTab) {
displayView(4);
}
}
#Override
public void onMenuTabReSelected(#IdRes int menuItemId) {
if (menuItemId == R.id.HomeTab) {
displayView(0);
}
if (menuItemId == R.id.ProfileTab) {
displayView(1);
}
if (menuItemId == R.id.GalleryTab) {
displayView(2);
}
if (menuItemId == R.id.FriendsTab) {
displayView(3);
}
if (menuItemId == R.id.SettingTab) {
displayView(4);
}
}
});
public void displayView(int position) {
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 0:
fragment = new MainWall();
break;
case 1:
fragment = new Profile();
break;
case 2:
fragment = new Gallery();
break;
case 3:
fragment = new Friends();
break;
case 4:
fragment = new Settings();
break;
case 5:
fragment = new Messages();
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment).commit();
// update selected item and title, then close the drawer
} else {
// error in creating fragment
Log.e("MainActivity", "Error in creating fragment");
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Necessary to restore the BottomBar's state, otherwise we would
// lose the current tab on orientation change.
mBottomBar.onSaveInstanceState(outState);
}
I have an application with two fragments which will not switch back to the original from the method I am using. I have a feeling this is not the way to carry out this. Where am I going wrong? My code is below.
// region GlobalVars
boolean viewLib;
// endregion
// region Init
void Init () {
viewLib = false;
}
// endregion
// region onCreate
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_music);
Init();
// Set Initial Library Fragment
if (findViewById(R.id.fragment_container) != null) {
if (savedInstanceState != null) {
return;
}
PlayerFragment firstFragment = new PlayerFragment();
firstFragment.setArguments(getIntent().getExtras());
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();
}
}
// endregion
// region SwitchView
void SwitchView () {
if (viewLib = false) {
Toast.makeText(getApplicationContext(), "viewLib", Toast.LENGTH_SHORT).show();
Library();
viewLib = true;
} else {
Toast.makeText(getApplicationContext(), "!viewLib", Toast.LENGTH_SHORT).show();
Player();
viewLib = false;
}
}
//region Library
void Library() {
LibraryFragment newFragment = new LibraryFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
transaction.commit();
}
// endregion
//region Player
void Player() {
PlayerFragment newFragment = new PlayerFragment();
//Bundle args = new Bundle();
//args.putInt(LibraryFragment.ARG_POSITION, position);
//newFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
transaction.commit();
}
// endregion
// endregion
// region Menu
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_music, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_library:
SwitchView();
return true;
case R.id.action_settings:
return true;
default:
return super.onOptionsItemSelected(item);
}
}
// endregion
Fixed My problem. I did this:
void SwitchView() {
if (!viewLib) {
Toast.makeText(getApplicationContext(), "viewLib", Toast.LENGTH_SHORT).show();
Library();
viewLib = true;
} else {
Toast.makeText(getApplicationContext(), "!viewLib", Toast.LENGTH_SHORT).show();
Player();
viewLib = false;
}
}
Seems to work fine now after fixing the mistake in the boolean test. Now all I have to do is override onBackPressed to stop the constant views
Hee Guys,
I'm currently working with fragments and I'm trying to manage it so that when you click twice on the same menu item it won't put 2 of the same fragments on top of eachother. However it still does. Could anyone tell me what I'm doing wrong?
/*
* Method to check which action is behind the selected Menu item. Then call ShowFragment()
* With the correct fragment parameter used with this Menu action value.
*/
public void getAction(int position, Cursor cursor) {
// TODO Auto-generated method stub
mCursor = cursor;
cursor.moveToPosition(position);
String action = cursor.getString(cursor.getColumnIndex(AppMenu.ACTION));
if (action != null) {
if (action.equalsIgnoreCase("home")) {
trans = manager.beginTransaction();
BaseFragment newFragment = new HomeFragment();
if (manager.findFragmentByTag(newFragment.getTag()) != null) {
mCursor.moveToPosition(position);
// Set the current fragment
mCurrentFragment = newFragment;
Bundle bundle = new Bundle();
int fragId = mCursor.getInt(mCursor.getColumnIndex(AppMenu._ID));
Log.i(TAG, fragId + " ");
bundle.putInt("fragmentID", fragId);
newFragment.setArguments(bundle);
trans.replace(R.id.fragmentContainer, newFragment).addToBackStack(
newFragment.tag());
trans.commit();
} else {
trans.show(newFragment);
}
} else if (action.equalsIgnoreCase("event")) {
showFragment(new EventsFragment(), position);
} else if (action.equalsIgnoreCase("location")) {
showFragment(new LocationsFragment(), position);
} else if (action.equalsIgnoreCase("news")) {
showFragment(new NewsFragment(), position);
} else if (action.equalsIgnoreCase("bars")) {
showFragment(new BarsFragment(), position);
} else if (action.equalsIgnoreCase("currency")) {
showFragment(new CurrencyFragment(), position);
} else if (action.equalsIgnoreCase("map")) {
showFragment(new MapFragment(), position);
}
} else {
Log.i(TAG, "You've got a nullpointerexception on getAction().");
}
}
/*
* Method that's called when changing from fragment through Menu or HomeMenu.
*/
public void showFragment(BaseFragment newFragment, int position) {
trans = manager.beginTransaction();
if (manager.findFragmentByTag(newFragment.tag()) == null) {
mCursor.moveToPosition(position);
// Set the current fragment
mCurrentFragment = newFragment;
// Go on and set the bundle values and pass it on the fragment.
Bundle bundle = new Bundle();
int fragId = mCursor.getInt(mCursor.getColumnIndex(AppMenu._ID));
Log.i(TAG, fragId + " ");
bundle.putInt("fragmentID", fragId);
newFragment.setArguments(bundle);
trans.replace(R.id.fragmentContainer, newFragment).addToBackStack(
newFragment.tag());
trans.commit();
} else {
trans.show(newFragment);
}
}
And here are 2 callbacks for when something changes or when back pressed.
/*
* Interface method called whenever a new fragment is created.
*/
#Override
public void onNewFragment(BaseFragment newFragment) {
// TODO Auto-generated method stub
FragmentManager fm = getSupportFragmentManager();
Class<? extends Fragment> newFragmentClass = newFragment.getClass();
if (newFragmentClass == EventsFragment.class
|| newFragmentClass == LocationsFragment.class
|| newFragmentClass == MapFragment.class
|| newFragmentClass == NewsFragment.class
|| newFragmentClass == CurrencyFragment.class
|| newFragmentClass == BarsFragment.class) {
for (Fragment fragment : fm.getFragments()) {
if (fragment != null && ((Object) fragment).getClass() == newFragmentClass) {
while (((Object) mCurrentFragment).getClass() != newFragmentClass) {
popFragment();
}
popFragment();
break;
}
}
}
}
/*
* Interface method called when you navigate back from a fragment.
* Checks which fragment is active, calls upon this fragments back function to clear any data,
* then pops the first fragment on the backstack.
*/
#Override
public void onBackNavigated() {
// TODO Auto-generated method stub
if ((mCurrentFragment instanceof HomeFragment)
&& !((HomeFragment) mCurrentFragment)
.isStackEmpty()) {
System.exit(0);
// break;
}
if ((mCurrentFragment instanceof LocationsFragment)
&& !((LocationsFragment) mCurrentFragment)
.isStackEmpty()) {
((LocationsFragment) mCurrentFragment).goBack();
// return;
}
if ((mCurrentFragment instanceof EventsFragment)
&& !((EventsFragment) mCurrentFragment)
.isStackEmpty()) {
((EventsFragment) mCurrentFragment).goBack();
// return;
}
if ((mCurrentFragment instanceof MapFragment)
&& !((MapFragment) mCurrentFragment).isStackEmpty()) {
((MapFragment) mCurrentFragment).goBack();
// break;
}
if ((mCurrentFragment instanceof BarsFragment)
&& !((BarsFragment) mCurrentFragment).isStackEmpty()) {
((BarsFragment) mCurrentFragment).goBack();
// break;
}
if ((mCurrentFragment instanceof CurrencyFragment)
&& !((CurrencyFragment) mCurrentFragment).isStackEmpty()) {
((CurrencyFragment) mCurrentFragment).goBack();
// break;
}
popFragment();
}
/*
* Pops the first fragment in the backstack. Then sets this as the new current fragment.
* If no fragment is in the backstack then finish() is called. Which will destroy the only fragment.
* Which in this case exits the application.
*/
public void popFragment() {
if (manager.getBackStackEntryCount() > 1) {
manager.popBackStack();
manager.executePendingTransactions();
ArrayList<Fragment> reversedFragments = new ArrayList<Fragment>(
manager.getFragments());
Collections.reverse(reversedFragments);
for (Fragment fragment : reversedFragments)
if (fragment != null) {
mCurrentFragment = (BaseFragment) fragment;
break;
}
} else {
finish();
}
}
**NOTE : ** The tag() functions calls a final String from the fragment itself with the same hardcoded tag everytime. So every fragment of the same class has the same tag. (Which should prevent double fragments, but it still doesn't)
Solution:
The tag() was returning null al the time. (Don't know why) So I changed the showFragment(fragment, tag, position) and hardcoded the tag in the mainactivity. Then used :
trans.replace(R.id.fragmentContainer, newFragment, tag);
//instead of
trans.replace(R.id.fragmentContainer, newFragment).addToStackBack(tag);
Don't forget to still add it to the backstack! Or else your back navigation won't work.
Just add an extra line: trans.addToBackStack(tag);
You can set the tag while adding/replacing the Fragment,
So you need to mention it as :
trans.replace(R.id.fragmentContainer, newFragment,tag);
Pass the tag value to the method according to the Fragment
showFragment(new EventsFragment(),tag, position);
Hope it will help you ツ
I'm having issues with fragment replacing implementing a navigation drawer.
The problem is layout overlapping, but it happens only if I let the application on the background for a long time (I asume after the activity goes to Stop).
This is the code I'm using for changing fragments. I'm not doing anything in onStop method
(Should I be doing something?)
#Override
public void onNavigationDrawerItemSelected(int position) {
if(lastPosition == position){
return;
}
FragmentTransaction transaction = fragmentManager.beginTransaction();
Fragment lastFragment = fragmentManager.findFragmentByTag( lastTag );
Fragment fragment;
if ( lastFragment != null ) {
transaction.hide( lastFragment );
}
switch (position) {
case 0:
lastTag = "miPerfil";
lastPosition = 0;
fragment = fragmentManager.findFragmentByTag("miPerfil");
if(fragment != null) {
transaction.remove(fragment);
}
transaction.add(R.id.container, MiPerfilFragment.newInstance(position + 1),"miPerfil");
break;
case 1:
lastTag = "misReportes";
lastPosition = 1;
fragment = fragmentManager.findFragmentByTag("misReportes");
if(fragment != null) {
transaction.remove(fragment);
}
transaction.add(R.id.container, MisReportesFragment.newInstance(position + 1),"misReportes");
break;
case 2:
lastTag = "mapFragment";
lastPosition = 2;
fragment = fragmentManager.findFragmentByTag("mapFragment");
if(fragment != null) {
transaction.show(fragment);
}else{
transaction.add(R.id.container, MapFragment.newInstance(position + 1),"mapFragment");
}
break;
case 3:
moveTaskToBack(true);
return;
}
transaction.addToBackStack( lastTag ).commit();
}
Thanks.
there is two solution that you can try to overcome from your problem of overlapping fragment.
try (1) set a background color to your fragment in xml file.
if it does not work,
try (2) fixing this by writing your own code to remove any existing fragments before committing a new one.
for example:
fragmentManager = getFragmentManager();
ft = fragmentManager.beginTransaction();
mbFragment = new SettingsManageBooksFragment();
ft.replace(R.id.setting_detail_container2, mbFragment).commit();
mImgFragmentTitle.setImageResource(R.drawable.manage_my_books);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.imageButtonSettingsManageBooks:
if (mPurchaseHistory == true) {
ft.remove(phFragment);
Log.d(TAG, "REMOVING PURCHASE HISTORY FRAG");
} else if (mAudio == true) {
ft.remove(aFragment);
Log.d(TAG, "REMOVING AUDIO FRAG");
} else if (mRestore == true) {
ft.remove(rFragment);
Log.d(TAG, "REMOVING RESTORE FRAG");
} else if (mCopyright == true) {
ft.remove(cFragment);
Log.d(TAG, "REMOVING COPYRIGHT FRAG");
} else if (mAbout == true) {
ft.remove(abFragment);
Log.d(TAG, "REMOVING ABOUT FRAG");
}
ft = fragmentManager.beginTransaction();
mbFragment = new SettingsManageBooksFragment();
ft.replace(R.id.setting_detail_container2, mbFragment).commit();
mImgFragmentTitle.setImageResource(R.drawable.manage_my_books);
mManageBooks = true;
mPurchaseHistory = false;
mAudio = false;
mRestore = false;
mCopyright = false;
mAbout = false;
break;
hope it will helps....
if you use first solution You may also come up with problems where the fragment behind your new fragment is still clickable. If this happens then just make the parent view of the new fragment clickable..