3

Here is the code of MainActivity which I have written. I am loading the list of fragment in the first screen. When the user taps on any of the list items, the planet name will be shown to the user in the detail fragment which I have defined in a separate class.

I am adding the transaction of "Fragment Planet List" -> "Fragment Planet Detail" to back stack. So what I expect is when I press the back button from the fragment of planet detail, it should load planet list in the phone. But it is not happening this way.

import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.FrameLayout;

import com.meditab.fragments.fragment.FragmentPlanetDetail;
import com.meditab.fragments.fragment.FragmentPlanetList;

import java.util.ArrayList;
import java.util.List;


public class MainActivity extends ActionBarActivity implements Callback {

    private FrameLayout frmPlanetList;
    private FrameLayout frmPlanetDetail;
    private boolean isPhone;


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

        frmPlanetList = (FrameLayout) findViewById(R.id.frmPlanetList);
        frmPlanetDetail = (FrameLayout) findViewById(R.id.frmPlanetDetail);

        if (null != frmPlanetDetail) {
            isPhone = false;
        } else {
            isPhone = true;
        }

        FragmentManager fragmentManager = getFragmentManager();

        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

        fragmentTransaction.replace(R.id.frmPlanetList, new FragmentPlanetList());

        fragmentTransaction.commit();

    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.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.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onListItemClicked(int intPosition) {

        FragmentManager fragmentManager = getFragmentManager();

        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

        List<String> lstPlanetArray = getPlanetArray();
        String strPlanetName = lstPlanetArray.get(intPosition);

        FragmentPlanetDetail fragmentPlanetDetail = FragmentPlanetDetail.newInstance(strPlanetName);
        if (isPhone) {
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.replace(R.id.frmPlanetList, fragmentPlanetDetail);
        } else {
            fragmentTransaction.replace(R.id.frmPlanetDetail, fragmentPlanetDetail);
        }

        fragmentTransaction.commit();

    }

    private List<String> getPlanetArray() {
        List<String> lstPlanets = new ArrayList<>(10);
        lstPlanets.add("Mercury");
        lstPlanets.add("Venus");
        lstPlanets.add("Earth");
        lstPlanets.add("Mars");
        lstPlanets.add("Jupiter");
        lstPlanets.add("Saturn");
        lstPlanets.add("Uranus");
        lstPlanets.add("Neptune");
        lstPlanets.add("Saturn");

        return lstPlanets;
    }

}

However if I override the backPress method and pop the back stack programatically, it works just fine.

@Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() != 0) {
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
}

Do I need to override the onBackPressed() method this way if I want to achieve this behavour? It is not documented that you need to override this method in this link.Android Back Press Fragment Documentation

Fragment Planet Detail Class

import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.meditab.fragments.R;

/**
 * Created by BHARGAV on 25-Dec-14.
 */
public class FragmentPlanetDetail extends Fragment {

    private String strPlanetName;

    public FragmentPlanetDetail() {

    }

    public static FragmentPlanetDetail newInstance(String strPlanetName) {
        FragmentPlanetDetail fragmentPlanetDetail = new FragmentPlanetDetail();

        Bundle bundle = new Bundle();
        bundle.putString("Planet_Name", strPlanetName);
        fragmentPlanetDetail.setArguments(bundle);
        return fragmentPlanetDetail;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Bundle bundle = getArguments();
        if (null != bundle) {
            strPlanetName = bundle.getString("Planet_Name");
        }
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.planet_name, container, false);

        TextView txtPlanetName = (TextView) rootView.findViewById(R.id.txtPlanetName);
        txtPlanetName.setText(strPlanetName);

        return rootView;
    }
}

Fragment Planet List Class:

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.meditab.fragments.Callback;
import com.meditab.fragments.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by BHARGAV on 25-Dec-14.
 */
public class FragmentPlanetList extends Fragment {

    private ListView listView;
    private ArrayAdapter<String> stringArrayAdapter;

    private Callback callback;


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final View rootView = inflater.inflate(R.layout.listview, container, false);

        listView = (ListView) rootView.findViewById(R.id.listView);
        stringArrayAdapter = new ArrayAdapter<>(getActivity(),
                android.R.layout.simple_list_item_1, getPlanetArray());
        listView.setAdapter(stringArrayAdapter);

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                callback.onListItemClicked(position);
            }
        });
        return rootView;
    }



    @Override
    public void onAttach(Activity activity) {

        super.onAttach(activity);

        callback = (Callback) activity;
    }

    private List<String> getPlanetArray() {
        List<String> lstPlanets = new ArrayList<>(5);
        lstPlanets.add("Mercury");
        lstPlanets.add("Venus");
        lstPlanets.add("Earth");
        lstPlanets.add("Mars");
        lstPlanets.add("Jupiter");
        lstPlanets.add("Saturn");
        lstPlanets.add("Uranus");
        lstPlanets.add("Neptune");
        lstPlanets.add("Saturn");

        return lstPlanets;
    }

}

Callback Interface:

/**
 * Created by BHARGAV on 26-Dec-14.
 */
public interface Callback {

    public void onListItemClicked(int intPosition);
}

Thanks. Please let me know if any additional detail or code is needed.

Bhargav Jhaveri
  • 2,123
  • 1
  • 18
  • 23

5 Answers5

6

Ok. So the reason why it is not working is the conflict of ActionBarActivty and Activity class differences. And the differnce between getSupportFragmentManager() and getFragmentManager() methods of FragmentTransaction.

ActionBarActivity:

I was using ActionBarActivity which is android.support.v7.app.ActionBarActivity. This means I was using v7 compat library

FragmentManager: Fragment Manager were not from the compat library. It was directly

import android.app.FragmentManager;
import android.app.FragmentTransaction;

as you can see in the MainActivity class.

Fragment: android.app.Fragment; is the class which is imported in the separate fragment classes.

So once I changed from ActionBarActivity to Activity class, things were working fine. The same holds true when I changed the FragmentManager,FragmentTransaction and Fragment classes to support library classes.

So after any of the modification, things started working normally. Thanks.

Bhargav Jhaveri
  • 2,123
  • 1
  • 18
  • 23
0

Of course you don't need to override the onBackPressed() method. It's just a hack.

Your this condition is messing it up.

if (isPhone) {
        fragmentTransaction.addToBackStack(null);

why don't you use this statement without condition once to see if it works. You can keep rest as it is. Just move this statement outside of the if condition.

Rohit5k2
  • 17,948
  • 8
  • 45
  • 57
  • Thanks for the answer. I am targeting the devices ICS and above. Also removing this from the if condition did not work. – Bhargav Jhaveri Dec 26 '14 at 16:13
  • I don't think Android version has anything to do with it. Did you try putting the statement outside of if statement? – Rohit5k2 Dec 26 '14 at 16:14
  • Yeah. FragmentPlanetDetail fragmentPlanetDetail = FragmentPlanetDetail.newInstance(strPlanetName); fragmentTransaction.addToBackStack(null); if (isPhone) { fragmentTransaction.replace(R.id.frmPlanetList, fragmentPlanetDetail); } else { fragmentTransaction.replace(R.id.frmPlanetDetail, fragmentPlanetDetail); } fragmentTransaction.commit(); – Bhargav Jhaveri Dec 26 '14 at 16:15
  • Nope. It did not. Exiting from the application. – Bhargav Jhaveri Dec 26 '14 at 16:19
  • This is weird but now overriding the back button is the solution. I never had to do that. – Rohit5k2 Dec 26 '14 at 16:24
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/67725/discussion-between-bhargav-jhaveri-and-rohit5k2). – Bhargav Jhaveri Dec 26 '14 at 16:24
0

Wierd, but I think

addToBackStack(null)

is the problem

Try replcing it with

addToBackStack("planetDetail");
Hirak Chhatbar
  • 3,159
  • 1
  • 27
  • 36
0

You are using actionbar activity which extends fragment activity. Now, to have perfect behaviour, you need support fragments to work with actionbar activity.

Here you are using actionbar activity with normal fragments (not support v4 fragments) and that's what is causing the issue. So to have perfect behaviour, change your fragments to support fragments and it should work fine.

Let me know if that doesn't work.

0

Well I was having the same problem with you. What worked for me and I think its the solution for you too is to change the :

1.fragment with the fragment from the support library :

import android.support.v4.app.Fragment;

and

  1. getFragmentManager() with the getSupportFragmentManager() :
mt0s
  • 5,781
  • 10
  • 42
  • 53