I have a navigation drawer and i use selector to get the highligghted item of the list
<item
android:state_activated="true"
android:drawable="#color/pressed_color"/>
<item
android:drawable="#color/default_color" />
The problem is that i Override the backpressed to change my fragment to my main element like this:
#Override
public void onBackPressed()
{
onNavigationDrawerItemSelected(0);
onSectionAttached(1);
restoreActionBar();
now when i press back it changes the fragment but the highlighted item stays where I clicked last time.How can I achive to change the highlights postion too? with somethig like change the texts state somehow from code,but i create the navigation drawer elements with an adapter ...(i use the Android Studio sample )
#Override
public void onNavigationDrawerItemSelected(final int position) {
// update the main content by replacing fragments
final FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, KedvencekFragment.newInstance(position + 1))
// .addToBackStack(null)
.commit();
if(position==0)
{
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
fragmentManager.beginTransaction()
.replace(R.id.container, KedvencekFragment.newInstance(position + 1))
// .addToBackStack(null)
.commit();
}
}, 250);
}
and ` public void onSectionAttached(int number) {
switch (number) {
case 1:
mTitle = getString(R.string.title_section1);
break;
case 2:
mTitle = getString(R.string.title_section2);
break;
case 3:
mTitle = getString(R.string.title_section3);
break;
case 4:
mTitle = getString(R.string.title_section4);
break;
case 5:
// mTitle = getString(R.string.title_section5);
break;
case 6:
mTitle = getString(R.string.title_section6);
break;
}
}`
EDIT:
You can access you NavigationDrawerFragment in your activity, you just need to make your selectItem(int position) method of the NavigationDrawerFragment public, like this:
...
publicvoid selectItem(int position) {
mCurrentSelectedPosition = position;
if (mDrawerListView != null) {
mDrawerListView.setItemChecked(position, true);
}
if (mDrawerLayout != null) {
mDrawerLayout.closeDrawer(mFragmentContainerView);
}
if (mCallbacks != null) {
mCallbacks.onNavigationDrawerItemSelected(position);
}
}
...
And then in your onNavigationDrawerItemSelected method:
#Override
public void onNavigationDrawerItemSelected(final int position) {
// update the main content by replacing fragments
final FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, KedvencekFragment.newInstance(position + 1))
// .addToBackStack(null)
.commit();
if(position==0)
{
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
fragmentManager.beginTransaction()
.replace(R.id.container, KedvencekFragment.newInstance(position + 1))
// .addToBackStack(null)
.commit();
}
}, 250);
}
navigationDrawerFragment.selectItem(position);
}
i found it!!! had to change the selectItem() to public then call it in the onBackPressed like this!
#Override
public void onBackPressed()
{
if(mTitle!=getString(R.string.title_section1)) {
onNavigationDrawerItemSelected(0);
onSectionAttached(1);
mNavigationDrawerFragment.selectItem(0);
restoreActionBar();
}
else{
super.onBackPressed();
}
}
Related
I am using bottom navigation drawer to switch between fragments, the problem is that every time I switch back to a fragment it gets recreated.
How can I save the state of fragment and resume it when switched back to it?
bottomNavigationBar.setTabSelectedListener(new BottomNavigationBar.OnTabSelectedListener(){
#Override
public void onTabSelected(int position) {
if (position==0){
loadFragment(new Daily());
}
if (position==1){
loadFragment(new Trending());
}
if (position==2){
loadFragment(new Random());
}
}
#Override
public void onTabUnselected(int position) {
}
#Override
public void onTabReselected(int position) {
}
});
private void loadFragment(Fragment fragment) {
// load fragment
FragmentTransaction transaction =
getSupportFragmentManager().beginTransaction();
transaction.attach( fragment);
transaction.addToBackStack(null);
transaction.commit();
}
The issue is that you are always creating a new Fragment on any onTabSelected. So in order to fix it, you need to work with your FragmentManager.
Possible solution: use the add and show/hide methods.
Example:
private static final String DAILY_TAG = BuildConfig.APPLICATION_ID + ".DAILY_TAG";
private static final String TRENDING_TAG = BuildConfig.APPLICATION_ID + ".TRENDING_TAG";
private static final String RANDOM_TAG = BuildConfig.APPLICATION_ID + ".RANDOM_TAG";
public void onTabSelected(int position) {
FragmentManager fragmentManager = getSupportFragmentManager();
if (position == 0) {
hideFragment(TRENDING_TAG)
hideFragment(RANDOM_TAG)
Fragment fragment = fragmentManager.findFragmentByTag(DAILY_TAG);
FragmentTransaction transaction = fragmentManager.beginTransaction()
if (fragment != null) {
transaction.show(fragment)
} else {
transaction.add(content.id, new Daily(), DAILY_TAG)
}
transaction.commitNow()
} else if (position == 1) {
hideFragment(DAILY_TAG)
hideFragment(RANDOM_TAG)
Fragment fragment = fragmentManager.findFragmentByTag(TRENDING_TAG);
FragmentTransaction transaction = fragmentManager.beginTransaction()
if (fragment != null) {
transaction.show(fragment)
} else {
transaction.add(content.id, new Trending(), TRENDING_TAG)
}
transaction.commitNow()
} else {
hideFragment(TRENDING_TAG)
hideFragment(DAILY_TAG)
Fragment fragment = fragmentManager.findFragmentByTag(RANDOM_TAG);
FragmentTransaction transaction = fragmentManager.beginTransaction()
if (fragment != null) {
transaction.show(fragment)
} else {
transaction.add(content.id, new Random(), RANDOM_TAG)
}
transaction.commitNow()
}
fragments.put(position, fragment);
loadFragment(fragment);
}
private void hideFragment(String tag) {
FragmentManager fragmentManager = getSupportFragmentManager()
Fragment currentFragment = fragmentManager.findFragmentByTag(tag)
if (currentFragment != null) {
fragmentManager.beginTransaction().hide(currentFragment).commitNow()
}
}
PS - The code can be optimized.
I have problem with implement fragment and bottom bar on my apps..
I wan to switch fragment according initialize bottom bar..
this my code
private Fragment frag_summary = new SummaryFragment();
private Fragment frag_my_proposal = new MyProposalFragment();
private Fragment frag_proposal = new ProposalFragment();
private Fragment frag_friends = new FriendsFragment();
bottomNavigation.setOnTabSelectListener(new OnTabSelectListener() {
#Override
public void onTabSelected(#IdRes int tabId) {
setSelectedFragment(tabId);
}
});
public void setSelectedFragment(int id) {
switch (id) {
case R.id.menu_home:
setFragment(id, frag_summary);
break;
case R.id.menu_my_proposals:
setFragment(id, new MyProposalFragment());
break;
case R.id.menu_proposal:
setFragment(id, new ProposalFragment());
break;
case R.id.menu_friends:
setFragment(id, new FriendsFragment());
break;
case R.id.menu_more:
/* drawer.openDrawer(GravityCompat.START);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
drawer.openDrawer(GravityCompat.START);
}*/
break;
default:
setFragment(id, frag_summary);
break;
}
}
private void setFragment(int id, Fragment fragments) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
String fragmentTag = String.valueOf(id);
if (frag_summary.isAdded()) {
fragmentTransaction.hide(frag_summary);
}
if (frag_my_proposal.isAdded()) {
fragmentTransaction.hide(frag_my_proposal);
}
if (frag_proposal.isAdded()) {
fragmentTransaction.hide(frag_proposal);
}
if (frag_friends.isAdded()) {
fragmentTransaction.hide(frag_friends);
}
if (fragments.isAdded()) {
fragmentTransaction.show(fragments);
} else {
fragmentTransaction.add(R.id.content_frame, fragments, fragmentTag);
}
fragmentTransaction.commitAllowingStateLoss();
}
The Issue is : When I selected from Fragment frag_summary to Fragment frag_friends, Fragment frag_summary and other fragment sometimes still showed.. like other activity ex: from Fragment frag_friends to Fragment frag_proposal .
sho how to fix it ?
sorry for my english
Repalce the code in setFragment with -
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragments, fragmentTag);
fragmentTransaction.commitAllowingStateLoss();
Basically you are replacing the current visivble fragment.
Edit : Change the code as below -
public void setSelectedFragment(int id) {
switch (id) {
case R.id.menu_home:
setFragment(id, frag_summary);
break;
case R.id.menu_my_proposals:
setFragment(id, /*send the class instance you created for this fragment */);
break;
case R.id.menu_proposal:
setFragment(id, /*send the class instance you created for this fragment */);
break;
case R.id.menu_friends:
setFragment(id, /*send the class instance you created for this fragment */);
break;
case R.id.menu_more:
/* drawer.openDrawer(GravityCompat.START);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
drawer.openDrawer(GravityCompat.START);
}*/
break;
default:
setFragment(id, frag_summary);
break;
}
}
I receive IllegalStateException : Fragment already added when changing screen orientation. I have one Activity and three fragments
CODE:
private Fragment mFragment;
...
#Override
protected void onCreate(Bundle savedInstanceState) {
initViews();
setBackStackBehavior();
mFragment = getSupportFragmentManager().findFragmentByTag(Constants.FIND_FRAGMENT_BY_TAG);
if (mFragment == null) {
mFragment = new SectionFragment();
}
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, mFragment, Constants.FIND_FRAGMENT_BY_TAG).commit();
private void setBackStackBehavior() {
getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
#Override
public void onBackStackChanged() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getSupportFragmentManager().popBackStack();
getSupportFragmentManager().executePendingTransactions();
}
});
} else {
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
mDrawerToggle.syncState();
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mDrawerLayout.openDrawer(GravityCompat.START);
}
});
}
}
});
}
Also I can move to the First Fragment :
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.section_selection:
mFragment = new SectionFragment();
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left,
R.anim.enter_from_left, R.anim.exit_to_right)
.replace(R.id.container, mFragment, Constants.FIND_FRAGMENT_BY_TAG)
.commit();
return true;
case R.id.exit:
finish();
default:
return super.onOptionsItemSelected(item);
}
}
I tried to create ArrayList<Fragment> mAdded and add here Fragment after transaction and then,when all fragments was added :
if(mAdded.contains(mFragment.getClass())){
getSupportFragmentManager().beginTransaction()
.show( mFragment).commit();
}
It did not help. Tried to remove Fragment in onPause(), but it did not solve my problem too. I tried to use commitAllowingStateLoss () instead commit()
How to fix this bug?
In oncreate check whether saved instance state is null if not don't replace the fragment.Also you can check whether your fragment is already added and available by using find fragment by id.
if(savedInstanceState == null){
getSupportFragmentManager().beginTransaction()
.replace(R.id.container,
mFragment,Constants.FIND_FRAGMENT_BY_TAG).commit();
}
or
if(((Fragment) getSupportFragmentManager().findFragmentByTag(Constants.FIND_FRAGMENT_BY_TAG)) == null){
getSupportFragmentManager().beginTransaction()
.replace(R.id.container,
mFragment,Constants.FIND_FRAGMENT_BY_TAG).commit();
}
When I am pressing back button getting the fragment as empty. Not getting the previous fragment poped back. Tried many solutions but didn't work. What is the solution for this ? I have no idea how to solve this.
private void displayView(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = mHomeFragmentInstance;
break;
case 1:
fragment = mOrderFragmentInstance;
break;
case 2:
fragment = mOrdersheetFragmentInstance;
break;
case 3:
fragment = mMyorderwidgetFragmentInstance;
break;
case 4:
Intent intent=new Intent(this,LoginActivity.class);
startActivity(intent);
clearValues();
finish();
return;
default:
fragment = mHomeFragmentInstance;
break;
}
if (fragment != null) {
replaceFragment(fragment, position);
}
}
/**
* When using the ActionBarDrawerToggle, you must call it during
* onPostCreate() and onConfigurationChanged()...
*/
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
public void replaceFragment(Fragment fragment){
if (fragment != null) {
Fragment currentFragment = this.getSupportFragmentManager().findFragmentById(R.id.frame_container);
if(null != currentFragment ){
if(currentFragment.equals(fragment)){
return;
}else{
getSupportFragmentManager().beginTransaction().remove(currentFragment).commit();
}
}
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.frame_container, fragment);
ft.addToBackStack(null);
ft.commit();
} else {
// error in creating fragment
Log.e("MainActivity", "Error in creating fragment");
}
}
public void replaceFragment(Fragment fragment, int position){
adapter.selectItem(position);
Log.i("TAG", "replaceFragment:"+fragment.getClass().getName()+":"+position);
replaceFragment(fragment);
Log.i("TAG", "Add"+fragment.getClass().getName()+"backStackFragment");
if(fragment.equals(mHomeFragmentInstance)){
Log.i("TAG", "clear backStackFragment");
backStackFragment.clear();
backStackFragment.add(mHomeFragmentInstance);
}
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
setTitle(navMenuTitles[position]);
mDrawerLayout.closeDrawer(drawerContainer);
}
#Override
public void setTitle(CharSequence title) {
mTitle = title;
//getActionBar().setTitle(Html.fromHtml("<font color='#983A1B'>" + title + "</font>"));
View view = getActionBar().getCustomView();
//((TextView)view.findViewById(R.id.title)).setText(Html.fromHtml("<font color='#983A1B'>" + title + "</font>"));
((TextView)view.findViewById(R.id.title)).setText(Html.fromHtml("<font color='"+ ApplicationInfo.getPlfColor(this)+"'>" + title + "</font>"));
}
#Override
public void onBackPressed() {
FragmentManager fm = getSupportFragmentManager();
if(fm.getBackStackEntryCount() > 1) {
fm.popBackStack();
}else {
//super.onBackPressed();
finish();
}
}
}
Just add addToBackStack while you are transitioning between your fragments like below:
fragmentManager.beginTransaction().replace(R.id.content_frame,fragment).addToBackStack("tag").commit();
if you write addToBackStack(null) , it will handle it by itself but if you give a tag , you should handle it manually.
I'm using NavigationDrawer with some fragments, the problem is when I'm in a fragment and hit the back button, it makes the app close, then I have to open it again, put my username and password all over again to use the app, how can I prevent that from happen?
public class NavigationMain extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
}
public void setFragmentList(int posicao) {
Fragment fragment = null;
switch (posicao) {
case 0:
fragment = new MainFragment();
break;
case 1:
fragment = new MensagensFragment();
break;
case 2:
fragment = new EscolasFragment();
break;
case 3:
fragment = new AutorizadasFragment();
break;
case 4:
fragment = new CadastroFragment();
break;
default:
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
navigationAdapter.resetarCheck();
navigationAdapter.setChecked(posicao, true);
layoutDrawer.closeDrawer(linearDrawer);
} else {
// error in creating fragment
Log.e("MainActivity", "Error in creating fragment");
}
}
}
#Override
public void onBackPressed() {
int count = getFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
//additional code
} else {
getFragmentManager().popBackStack();
}
}
I think you missed to add the fragment transaction in your back stack. Try the following:
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).addToBackStack(null).commit();