Fabio Lanza
Fabio Lanza

Reputation: 175

onBackPressed() and Fragments

I am trying to use onBackPressed() in my Fragment so that I can allow the user to roll back in a pile of fragments he navigated in my app.

The problem is that, when I add the method below to my Fragment, it gives me the error: Method does not override method from its superclass.

@Override
public void onBackPressed() {

    android.support.v4.app.FragmentManager fragmentManager = getFragmentManager();
    fragmentManager.popBackStack();

}

Would you know why?

Thanks!

Here goes the entire Fragment:

package it.bitrack.fabio.bitrack;

import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
//import android.app.Fragment;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.ArrayAdapter;

import java.util.ArrayList;
import java.util.Arrays;
import android.view.KeyEvent;


/**
 * A simple {@link Fragment} subclass.
 * Activities that contain this fragment must implement the
 * {@link AssetMngtView.OnFragmentInteractionListener} interface
 * to handle interaction events.
 * Use the {@link AssetMngtView#newInstance} factory method to
 * create an instance of this fragment.
 */
public class AssetMngtView extends Fragment {
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    View view;

    ListView assetMngtListView;
    ArrayAdapter<String> listAdapter;

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    private OnFragmentInteractionListener mListener;

    public AssetMngtView() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment AssetMngtView.
     */
    // TODO: Rename and change types and number of parameters
    public static AssetMngtView newInstance(String param1, String param2) {
        AssetMngtView fragment = new AssetMngtView();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onBackPressed() {

        android.support.v4.app.FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.popBackStack();

    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment

        view = inflater.inflate(R.layout.fragment_asset_mngt_view, container, false);

        assetMngtListView = (ListView) view.findViewById(R.id.assetMngtListView);
        setListView();


        return view;
    }

    public void setListView() {

        String[] options = new String[]{"Bind tag & thing", "Create new thing", "Edit existent thing", "Maintain existent thing", "View things notifications"};

        ArrayList<String> optionsList = new ArrayList<String>();
        optionsList.addAll(Arrays.asList(options));

        listAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, optionsList);

        assetMngtListView.setAdapter(listAdapter);
    }

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     * <p>
     * See the Android Training lesson <a href=
     * "http://developer.android.com/training/basics/fragments/communicating.html"
     * >Communicating with Other Fragments</a> for more information.
     */
    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
    }
}

Upvotes: 1

Views: 13569

Answers (6)

If you want to implement onBackPressed behavior in fragment, you should do this in onViewCreated of your fragment:

requireActivity().getOnBackPressedDispatcher().addCallback(new OnBackPressedCallback(true) {
    @Override
    public void handleOnBackPressed() {
        if (isHandlingBackPressInFragment()) {
            // Handle back press
        } else {
            // If you want to get default implementation of onBackPressed, use this
            this.remove();
            requireActivity().onBackPressed();
        }
    }
});

Upvotes: 10

IMNK
IMNK

Reputation: 21

If you want to go back to the previous Fragment, you can use this. The content_frame is the id of your FrameLayout. You can't use onBackPressed since the fragment can't stand alone without Activity.

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                        ft.replace(R.id.content_frame, new MainActivity());
                        ft.addToBackStack(null);
                        ft.commit();

Upvotes: 0

lelloman
lelloman

Reputation: 14173

the problem is that Fragment does not have public void onBackPressed() method.

you are getting the error because your method is annotated with @Override but it is not actually overriding any method in the superclass. the purpose of @Override is exactly this one, letting you know that you think you're overriding something but, actually, you aren't

on a side note, what you are trying to do is unnecessary. if you press the back button and you have fragments in the back stack they will be popped automatically. try this

public class FragmentsActivity extends AppCompatActivity {

    public static class FragmentA extends Fragment {
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = new TextView(getActivity());
            view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            view.setBackgroundColor(0xffff0000);    
            return view;
        }
    }

    public static class FragmentB extends Fragment {
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = new TextView(getActivity());
            view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            view.setBackgroundColor(0xff00ff00);    
            return view;
        }
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragments);

        FragmentManager fm = getSupportFragmentManager();
        fm.beginTransaction()
                .add(R.id.fragment_container, new FragmentA(), FragmentA.class.getSimpleName())
                .commit();

        // notice addToBackStack here
        fm.beginTransaction()
                .add(R.id.fragment_container, new FragmentB(), FragmentB.class.getSimpleName())
                .addToBackStack(FragmentB.class.getSimpleName())
                .commit();
    }
}

Upvotes: 4

Cochi
Cochi

Reputation: 2209

To achieve what you want, you should override the onBackPressed() of the Activity associated like that:

@Override
public void onBackPressed() {
    if (getSupportFragmentManager().getBackStackEntryCount() > 1) {
        getSupportFragmentManager().popBackStack();
    } else {
      finish();
    }
}

Hope this helps. Sorry for my english.

Upvotes: 6

Ionut J. Bejan
Ionut J. Bejan

Reputation: 754

I am sorry if I missunderstood or if I am missing something, but you get the error because onBackPressed() is not a method of the super class (Fragment class in your case)

Upvotes: -1

nick_kryloff
nick_kryloff

Reputation: 126

Use method onBackPressed() and call popBackStack() in your Activity class, not in fragment

Upvotes: 0

Related Questions