1

I am new to Android. I would like to develop a function from fragment back to homescreen to exit application but it does not work. Currently once i pressed back button, it will prompt to exit application. How to back to main activity to exit application from onKeyDown?

 public class MainActivity extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener, FragmentFlickrGridImage.OnFragmentInteractionListener
     {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    if (savedInstanceState == null) {
        Fragment fragment = null;
        Class fragmentClass = null;
        fragment = new MyFragment("0");
        try {
            fragment = (Fragment) fragmentClass.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction().replace(R.id.flContent, fragment).commit();
    }


    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setItemIconTintList(null);
    navigationView.setNavigationItemSelectedListener(this);
}

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {
        super.onBackPressed();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.share) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();
    Fragment fragment = null;
    Class fragmentClass = null;
    String title="";

    if (id == R.id.one) {
        fragment = new MyFragment("1");
        title="One";
    } else if (id == R.id.two) {
        fragment = new MyFragment("2");
        title ="two";
    } else if (id == R.id.three) {
        fragment = new MyFragment("3");
        title="three";
    }

    try {
        fragment = (Fragment) fragmentClass.newInstance();
    } catch (Exception e) {
        e.printStackTrace();
    }
    FragmentManager fragmentManager = getSupportFragmentManager();
    fragmentManager.beginTransaction().replace(R.id.flContent, fragment).commit();
    getSupportActionBar().setTitle(title);
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}

@Override
public void onFragmentInteraction(Uri uri) {

}
// confirm when user click back key
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode != KeyEvent.KEYCODE_BACK)  return super.onKeyDown(keyCode, event);

    DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {

        public void onClick(DialogInterface dialog, int which) {
            switch (which){
                case DialogInterface.BUTTON_POSITIVE:
                    //Yes button clicked
                    finish();
                    break;

                case DialogInterface.BUTTON_NEGATIVE:
                    //No button clicked
                    break;
            }
        }
    };

    AlertDialog.Builder builder = new AlertDialog.Builder(this)
            .setMessage("Are you sure?")
            .setPositiveButton("Yes", dialogClickListener)
            .setNegativeButton("No", dialogClickListener)
            .setCancelable(false)
            .setTitle("Exit");
    builder.show();

    return super.onKeyDown(keyCode, event);
} 

Below is the error code which i got when implement addtobackstack

Application is not responding: AppWindowToken{bcc0a65 token=Token{1a7f775c ActivityRecord{3ccf31cf u0 com.google.android.googlequicksearchbox/com.google.android.launcher.GEL t310}}}.  It has been 5010.0ms since event, 5010.0ms since wait started.  
Reason: Waiting because no window has focus but there is a focused application that may eventually add a window when it finishes starting up. 
michelletbs
  • 809
  • 2
  • 9
  • 19
  • By following solution given by http://stackoverflow.com/questions/32944798/switch-between-fragments-with-onnavigationitemselected-in-new-navigation-drawer works well for me :) – michelletbs Jan 27 '16 at 02:09

3 Answers3

0

While Replacing Fragment add fragmentManager.addToBackStack(null);

    FragmentManager fragmentManager = getSupportFragmentManager(); 
    fragmentManager.beginTransaction().replace(R.id.flContent, fragment);
    fragmentManager.addToBackStack(null);
    fragmentManager.commit();

By calling addToBackStack(), the replace transaction is saved to the back stack so the user can reverse the transaction and bring back the previous fragment by pressing the Back button.

And in your Main Activity / Home Activity overide the onBackPressed()

    public boolean onKeyDown(int keyCode, KeyEvent event) {
      if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
     // Add your Dialogue or whatever to alert 
       moveTaskToBack(true);
      }
      return super.onKeyDown(keyCode, event);
     }

     @Override
     public void onBackPressed() {

      super.onBackPressed();
      onKeyDown(KeyEvent.KEYCODE_BACK, null);
     }
Pavan Bilagi
  • 1,618
  • 1
  • 18
  • 23
  • i have tested in emulator but failed. here is the error code:"Cancelling event due to no window focus." It is problem with emulator ? – michelletbs Jan 26 '16 at 06:41
  • I have tested in real devices. it will exit directly from the fragment. But what i want was from the fragment, go back to the home screen then only exit...hmm... – michelletbs Jan 26 '16 at 08:34
0

Below is my solution

Define a variable named backstact_count to save the number of replaced fragments.

You need to add the current fragment to backstack when you replace it by another one

public void replaceFragment(Fragment fragment, boolean isAddToBackStack) {
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.replace(R.id.flContent, fragment);
    if (isAddToBackStack) {
        transaction.addToBackStack(fragment.getClass().toString());
        backstack_count ++;
    }
    transaction.commit();
}

then override onBackPressed()

@Override
    public void onBackPressed() {
if (backstack_count > 0) {
            FragmentManager manager = getSupportFragmentManager();
            manager.popBackStack();
            backstack_count--;
        } else {
           super.onBackPressed();
        }
    }

finally, edit replaced fragment in your onCreate() as below:

replaceFragment(fragment, true);
ThaiPD
  • 3,503
  • 3
  • 30
  • 48
  • i have added this line of code in onCreate fragmentManager.beginTransaction().replace(R.id.flContent, fragment).commit(); would like to ask i should replace this line of code with replaceFragment(fragment,true)? – michelletbs Jan 26 '16 at 07:34
  • yes, you should. All you need is call replaceFragment(fragment, true); So your code will be : try { fragment = (Fragment) fragmentClass.newInstance(); } catch (Exception e) { e.printStackTrace(); } replaceFragment(fragment, true); – ThaiPD Jan 26 '16 at 07:37
  • I have tried in emulator, the application was not responding with error msg: "Cancelling event due to no window focus". Do you know what does this error mean? – michelletbs Jan 26 '16 at 07:43
  • try to remove all of your implementation of onKeyDown. I mean delete them. – ThaiPD Jan 26 '16 at 07:51
  • I have tried in real Devices, it doesnt return to the homescreen to exit. it will exit once i pressed back button twice – michelletbs Jan 26 '16 at 08:30
  • ah, your problem is your only have one fragment. So you have nothing to display when you pressed. try to create a main_fragment represents for the main screen of the activity, set it as the first fragment and then add your custom fragment as in above – ThaiPD Jan 26 '16 at 08:58
  • i want to ask one more question. I actually want to start one of the fragment as the main screen of the activity. can i set it as the first fragment? – michelletbs Jan 26 '16 at 09:14
  • of course you can. Please remember that DO NOT add fragment to backstack if you want to set it as the first fragment – ThaiPD Jan 26 '16 at 10:15
  • hi @Phan Dinh Thai, this link works well for me ->http://stackoverflow.com/questions/32944798/switch-between-fragments-with-onnavigationitemselected-in-new-navigation-drawer – michelletbs Jan 27 '16 at 02:08
0

Try calling moveTaskToBack(true) in your onBackPressed method. Wrap the logic to check if the fragment is that which you want to exit from around this method.Take a look at my answer on this question:

Switch between Fragments with onNavigationItemSelected in new Navigation Drawer Activity template (Android Studio 1.4 onward)

Community
  • 1
  • 1
Ojonugwa Jude Ochalifu
  • 26,627
  • 26
  • 120
  • 132