9

I have project with navigation drawer with fragment, with 5 menu, the problem is when i go to menu 4 and the i press the back button the app closed, but i need the app back to first menu which is all the menu in fragment.

This is code for Main Activity (Navigation Drawer)

public class MainActivity extends AppCompatActivity{
DrawerLayout mDrawerLayout;
NavigationView mNavigationView;
FragmentManager mFragmentManager;
FragmentTransaction mFragmentTransaction;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    /**
     *Setup the DrawerLayout and NavigationView
     */

    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
    mNavigationView = (NavigationView) findViewById(R.id.shitstuff) ;

    /**
     * Lets inflate the very first fragment
     * Here , we are inflating the TabFragment as the first Fragment
     */

    mFragmentManager = getSupportFragmentManager();
    mFragmentTransaction = mFragmentManager.beginTransaction();
    mFragmentTransaction.replace(R.id.containerView,new Recommendation()).commit();
    /**
     * Setup click events on the Navigation View Items.
     */

    mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(MenuItem menuItem) {
            mDrawerLayout.closeDrawers();



            if (menuItem.getItemId() == R.id.nav_item_lux_level_recomen) {
                FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
                fragmentTransaction.replace(R.id.containerView,new Recommendation()).commit();

            }

            if (menuItem.getItemId() == R.id.nav_item_room_index_calc) {
                FragmentTransaction xfragmentTransaction = mFragmentManager.beginTransaction();
                xfragmentTransaction.replace(R.id.containerView,new RoomIndex()).commit();
            }

            if (menuItem.getItemId() == R.id.nav_item_utilization_factor_calc) {
                FragmentTransaction xfragmentTransaction = mFragmentManager.beginTransaction();
                xfragmentTransaction.replace(R.id.containerView,new UtilizationFactorCalculator()).commit();
            }

            if (menuItem.getItemId() == R.id.nav_item_conversions) {
                FragmentTransaction xfragmentTransaction = mFragmentManager.beginTransaction();
                xfragmentTransaction.replace(R.id.containerView,new Conversion()).commit();
            }
            if (menuItem.getItemId() == R.id.nav_item_lux) {
                FragmentTransaction xfragmentTransaction = mFragmentManager.beginTransaction();
                xfragmentTransaction.replace(R.id.containerView,new LuxSensor()).commit();
            }


            return false;
        }

    });

    /**
     * Setup Drawer Toggle of the Toolbar
     */

    android.support.v7.widget.Toolbar toolbar = (android.support.v7.widget.Toolbar) findViewById(R.id.toolbar);
    ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this,mDrawerLayout, toolbar,R.string.app_name,
            R.string.app_name);

    mDrawerLayout.setDrawerListener(mDrawerToggle);

    mDrawerToggle.syncState();




}

This one of the Menu (Fragment)

public class LuxSensor extends Fragment {
TextView textLIGHT_available, textLIGHT_reading;
FragmentManager mFragmentManager;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View x =  inflater.inflate(R.layout.lux_sensor,null);
    textLIGHT_reading
            = (TextView)x.findViewById(R.id.LIGHT_reading);

    SensorManager mySensorManager = (SensorManager)getActivity().getSystemService(Context.SENSOR_SERVICE);

    Sensor LightSensor = mySensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
    if(LightSensor != null){
        mySensorManager.registerListener(
                LightSensorListener,
                LightSensor,
                SensorManager.SENSOR_DELAY_NORMAL);

    }else{
        textLIGHT_available.setText("Sensor.TYPE_LIGHT NOT Available");
    }
    FragmentManager fm = getFragmentManager();

    return x;
}





private final SensorEventListener LightSensorListener
        = new SensorEventListener(){

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if(event.sensor.getType() == Sensor.TYPE_LIGHT){
            textLIGHT_reading.setText(event.values[0]+" LUX");
        }
    }

};

}

I have tried solution in internet but it still closed

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Josh Parinussa
  • 633
  • 2
  • 11
  • 28

7 Answers7

13

In fragment you should use something like this:

  @Override
    //Pressed return button - returns to the results menu
    public void onResume() {
        super.onResume();
        getView().setFocusableInTouchMode(true);
        getView().requestFocus();
        getView().setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {

                if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){

                 //your code

                   return true;
                }
                return false;
            }
        });
    }
Catarina Ferreira
  • 1,824
  • 5
  • 17
  • 26
12

onCreateView of fragment add this

Java

requireActivity().getOnBackPressedDispatcher().addCallback(activity, new OnBackPressedCallback(true) {
    @Override
    public void handleOnBackPressed() {
        // in here you can do logic when backPress is clicked
    }
});

Kotlin

requireActivity().onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
    override fun handleOnBackPressed() {
        // in here you can do logic when backPress is clicked
    }
})
  • this code goes in loop – D_K Aug 19 '22 at 10:39
  • Yes this method is clearly the best way since onBackPressed is deprecated. But this callback handle the event. What if I just want to be aware of the event and not handle it ? – Marine Droit Oct 19 '22 at 14:23
6

In main activity you need to override the following function

@Override
public void onBackPressed()
{
     // code here to check what fragment you are on and handle that accordingly
     super.onBackPressed();  // this exits the app.
}

Documentation is available here: https://developer.android.com/reference/android/app/Activity.html#onBackPressed()

Menachem Hornbacher
  • 2,080
  • 2
  • 24
  • 36
  • 1
    For ***"code .. to check what fragment you are on"*** - see `getActiveFragment()` here: https://stackoverflow.com/a/15543580/2162226 – Gene Bo Aug 09 '17 at 04:40
4

In your MainActivity

@Override
public void onBackPressed()
{
    FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
    fragmentTransaction.replace(R.id.containerView,new Recommendation()).commit();
}
jorgeavilae
  • 208
  • 1
  • 9
3

use this (in kotlin)

activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
    // in here you can do logic when backPress is clicked
}

})

i think this is the most elegant way to do it

Abhilash Das
  • 1,388
  • 1
  • 16
  • 22
0

You can key press listener in android using setOnKeyListener(). And then, if you want to handle the back press, override the onKey method :

@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
    if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
         // do your thing
    }

}
Yash
  • 5,225
  • 4
  • 32
  • 65
  • 2
    The back button doesn't send a key event, it calls into onBackPressed instead. – Gabe Sechan Mar 17 '17 at 14:01
  • @GabeSechan: IMO, it works. I've tested this in Dialog Fragment, so it should work in fragment also. – Yash Mar 17 '17 at 14:08
  • 2
    It doesn't work. It hasn't worked since 2010. The back and home buttons are not capturable via onKeyPressed. If you found a place where it does, its either a bug or a weird version of the OS from an OEM. – Gabe Sechan Mar 17 '17 at 14:10
  • okay, I didn't know if it's 'supposed' to work or not. But I just tested in my dialog fragment. It indeed works. My device is : gennymotion emulator, running android 6. – Yash Mar 17 '17 at 18:11
  • 1
    I checked again, it works in `DialogFragment` but not in `Fragment`. Any explanation? – Yash Mar 21 '17 at 05:22
0

Now the onBackPressed method is deprecated and we need to use this way (much simpler !):

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
          if(shouldInterceptBackPress()){
            // in here you can do logic when backPress is clicked
          }else{
            isEnabled = false
            activity?.onBackPressed()
          }
        }
    })
}

You can found full explanation here With this example it shows how to do when you are not sure that you need to consume the back press event

Marine Droit
  • 101
  • 8