Handling back button in Android Navigation Component

前端 未结 23 1261
遥遥无期
遥遥无期 2020-11-29 18:20

I\'d like to know how properly handle system back button action using Navigation Controller. In my app I have two fragments (for ex. fragment1 and fragment2) and I have an a

相关标签:
23条回答
  • 2020-11-29 19:05

    Just add these lines

         override fun onBackPressed() {
                if(navController.popBackStack().not()) {
                //Last fragment: Do your operation here 
                finish()
       } 
    

    navController.popBackStack() will just pop your fragment if this is not your last fragment

    0 讨论(0)
  • 2020-11-29 19:05

    And if you want the same behavior also for the toolbar back button just add this in your activity:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == android.R.id.home) {
            getOnBackPressedDispatcher().onBackPressed();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
    
    0 讨论(0)
  • 2020-11-29 19:06

    Newest Update - April 25th, 2019

    New release androidx.activity ver. 1.0.0-alpha07 brings some changes

    More explanations in android official guide: Provide custom back navigation

    Example:

    public class MyFragment extends Fragment {
    
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            // This callback will only be called when MyFragment is at least Started.
            OnBackPressedCallback callback = new OnBackPressedCallback(true /* enabled by default */) {
                @Override
                public void handleOnBackPressed() {
                    // Handle the back button event
                }
            };
            requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
    
            // The callback can be enabled or disabled here or in handleOnBackPressed()
        }
        ...
    }
    

    Old Updates

    UPD: April 3rd, 2019

    Now its simplified. More info here

    Example:

    requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), this);
    
    @Override
    public boolean handleOnBackPressed() {
        //Do your job here
        //use next line if you just need navigate up
        //NavHostFragment.findNavController(this).navigateUp(); 
        //Log.e(getClass().getSimpleName(), "handleOnBackPressed");
        return true;
        }
    

    Deprecated (since Version 1.0.0-alpha06 April 3rd, 2019) :

    Since this, it can be implemented just using JetPack implementation OnBackPressedCallback in your fragment and add it to activity: getActivity().addOnBackPressedCallback(getViewLifecycleOwner(),this);

    Your fragment should looks like this:

    public MyFragment extends Fragment implements OnBackPressedCallback {
    
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            
            getActivity().addOnBackPressedCallback(getViewLifecycleOwner(),this);
    }
        
        @Override
        public boolean handleOnBackPressed() {
            //Do your job here
            //use next line if you just need navigate up
            //NavHostFragment.findNavController(this).navigateUp(); 
            //Log.e(getClass().getSimpleName(), "handleOnBackPressed");
            return true;
        }
    
        @Override
        public void onDestroyView() {
            super.onDestroyView();
            getActivity().removeOnBackPressedCallback(this);
        }
    }
    

    UPD: Your activity should extends AppCompatActivityor FragmentActivity and in Gradle file:

     implementation 'androidx.appcompat:appcompat:{lastVersion}'
    
    0 讨论(0)
  • 2020-11-29 19:09

    A little late to the party, but with the latest release of Navigation Component 1.0.0-alpha09, now we have an AppBarConfiguration.OnNavigateUpListener.

    Refer to these links for more information: https://developer.android.com/reference/androidx/navigation/ui/AppBarConfiguration.OnNavigateUpListener https://developer.android.com/jetpack/docs/release-notes

    0 讨论(0)
  • 2020-11-29 19:10

    If you are using BaseFragment for your app then you can add onBackPressedDispatcher to your base fragment.

    //Make a BaseFragment for all your fragments
    abstract class BaseFragment : Fragment() {
    
    private lateinit var callback: OnBackPressedCallback
    
    /**
     * SetBackButtonDispatcher in OnCreate
     */
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setBackButtonDispatcher()
    }
    
    /**
     * Adding BackButtonDispatcher callback to activity
     */
    private fun setBackButtonDispatcher() {
        callback = object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                onBackPressed()
            }
        }
        requireActivity().onBackPressedDispatcher.addCallback(this, callback)
    }
    
    /**
     * Override this method into your fragment to handleBackButton
     */
      open fun onBackPressed() {
      }
    
    }
    

    Override onBackPressed() in your fragment by extending basefragment

    //How to use this into your fragment
    class MyFragment() : BaseFragment(){
    
    private lateinit var mView: View
    
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        mView = inflater.inflate(R.layout.fragment_my, container, false)
        return mView.rootView
    }
    
    override fun onBackPressed() {
        //Write your code here on back pressed.
    }
    

    }

    0 讨论(0)
  • 2020-11-29 19:11

    If you use Navigation Component follow the codes below in your onCreateView() method (in this example I want just to close my app by this fragment)

     OnBackPressedCallback backPressedCallback = new OnBackPressedCallback(true) {
            @Override
            public void handleOnBackPressed() {
                new AlertDialog.Builder(Objects.requireNonNull(getActivity()))
                        .setIcon(R.drawable.icon_01)
                        .setTitle(getResources().getString(R.string.close_app_title))
                        .setMessage(getResources().getString(R.string.close_app_message))
                        .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                getActivity().finish();
                            }
                        })
                        .setNegativeButton(R.string.no, null)
                        .show();
            }
        };
        requireActivity().getOnBackPressedDispatcher().addCallback(this, backPressedCallback);
    
    0 讨论(0)
提交回复
热议问题