0

I am at ends wit with my code. I can not get a fragment to display after it is called by another fragment (via Activity). I read the Android Developer guide and many SO's related topic on Fragment/FragmentPagerAdapter/FragmentTransactions and could not resolve my issue. This one would have been an obvious solution Is it possible to remove a fragment without replacing it by another fragment

I have an activity class that will host a fragment based on the tab selected. These fragments are dynamically created by the FragmentPagerAdapter based on user's selection of the tab. In the first tab, it creates FragmentA (ListFragment) which consists of a list of items. When a user clicks on any of the item, it should display another fragment with that item's details but to much of my dismay (and eyes burning), all it does is print out my log in logcat. Please see my code. Perhaps, I am staring at it too long and/or just don't know enough of android to see what's going on. I suspect it has to do with this line: fragTransaction.replace(R.id.curriculumParent, fragC); Now I know this would work if the 1st parameter was a fragment container in the activity's layout file was define but since it is not done statically, I don't know what to put there except for the calling FragmentB's layout file.

Thanks in advance!

MainActivity.java

public class MainActivity extends FragmentActivity implements
    FragmentB.OnColorSelectedListener {

private static final String TAG = "MainActivity";
private final Handler handler = new Handler();

private PagerSlidingTabStrip tabs;
private ViewPager pager;
private MyPagerAdapter adapter;

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

    tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
    pager = (ViewPager) findViewById(R.id.pager);

    FragmentManager fm = getSupportFragmentManager();
    adapter = new MyPagerAdapter(fm);

    pager.setAdapter(adapter);

    final int pageMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4,
            getResources().getDisplayMetrics());
    pager.setPageMargin(pageMargin);

    tabs.setViewPager(pager);
}

...
...
...

public class MyPagerAdapter extends FragmentPagerAdapter {

    private final String[] TITLES = { "FragmentB", "2ndTabFragment", "3rdTabFragment" };

    public MyPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public CharSequence getPageTitle(int position)
    {
        return TITLES[position];
    }

    @Override
    public int getCount()
    {
        return TITLES.length;
    }

    @Override
    public Fragment getItem(int position)
    {
        Fragment fragment = null;
        switch (position) {
        case 0:
            fragment = Fragment.instantiate(getBaseContext(), FragmentB.class.getName());
            break;
        case 1:
            fragment = Fragment.instantiate(getBaseContext(), SecondTabFragment.class.getName());
            break;
        case 2:
            fragment = Fragment.instantiate(getBaseContext(), ThirdTabFragment.class.getName());
            break;
        }
        return fragment;
    }
}

@Override
public void onColorLevelSelected(int position)
{
    Log.i(TAG, "Got Here!");
    FragmentC fragC = new FragmentC(); 
    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction fragTransaction = fm.beginTransaction();
    **fragTransaction.replace(R.id.curriculumParent, fragC);**
    fragTransaction.addToBackStack(null);
    fragTransaction.commit();
}

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
 >

<com.astuetz.PagerSlidingTabStrip
    android:id="@+id/tabs"
    android:layout_width="match_parent"
    android:layout_height="48dip"
    android:background="@drawable/background_tabs" />

<android.support.v4.view.ViewPager
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/tabs"
    tools:context=".MainActivity" />
</RelativeLayout>

FragmentB.java

public class FragmentB extends ListFragment{

OnColorSelectedListener mCallback;

private String[] colorLevel = new String[]{
        "Yellow",
        "Orange",
        "Green",
        "Blue",
        "pink",
        "Black"
};
private int[] colorImages = new int[]{
        R.drawable.yellow,
        R.drawable.orange,
        R.drawable.green,
        R.drawable.blue,
        R.drawable.pink,
        R.drawable.black
};

public interface OnColorSelectedListener{
    public void onItemLevelSelected(int position);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){

    List<HashMap<String, String>> colorList = new ArrayList<HashMap<String, String>>();
    for(int i = 0; i < 6; i++){
        HashMap<String, String> colorMap = new HashMap<String, String>();
        colorMap.put("lvl", colorLevel[i]);
        colorMap.put("img", Integer.toString(colorImages[i]));
        colorList.add(colorMap);
    }

    String[] from = {"img", "lvl"};

    int[] to = {R.id.colorLevelImg, R.id.colorLevelTxt};

    SimpleAdapter adapter = new SimpleAdapter(getActivity().getBaseContext(),colorList, R.layout.fragment_b ,from, to);
    setListAdapter(adapter);

    return super.onCreateView(inflater, container, savedInstanceState);
}

@Override
public void onAttach(Activity activity){
    super.onAttach(activity);

    try{
        mCallback = (OnColorSelectedListener) activity;
    }catch(ClassCastException e){
        throw new ClassCastException(activity.toString()
            + " must implement OnColorSelectedListener");
    }
}

@Override
public void onListItemClick(ListView l, View v, int pos, long id){
    Toast.makeText(getActivity(), "selected color :" + colorLevel[pos],
            Toast.LENGTH_LONG).show();
    mCallback.onColorLevelSelected(pos);

} 
}

fragment_b.xml

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    **android:id="@+id/curriculumParent"**
    ...
    ...

    android:background="#FEFDFB">

    <ImageView
        android:id="@+id/colorLevelImg"
        ...
        android:paddingBottom="10dp" />

    <LinearLayout
        ...
        android:orientation="vertical" >

        <TextView
            android:id="@+id/colorLevelTxt"
            ...
            android:textSize="25sp" />
    </LinearLayout>
 </LinearLayout>

FragmentC.java

    public class FragmentC extends Fragment{

    public static final String TAG = "Fragment C";

    public FragmentC(){}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        Log.i(TAG, "HI");
        return inflater.inflate(R.layout.fragment_c, container, false); 
    }
}

fragment_c.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFCC00" >

    <TextView
        android:id="@+id/editText1"
        ...
        android:layout_margin="16dp"
        android:text="This is the C Fragment that will replace the B Fragment" >
    </TextView>

</RelativeLayout>
Community
  • 1
  • 1
Allen
  • 181
  • 1
  • 4
  • 16
  • I don't know what is working now. Do you get the logcat message of "Got Here!"? – The Original Android Jul 27 '15 at 02:08
  • Hi...Yes, I get the logcat message, "Got Here!" then I get the message "HI" in the onCreate() of FragmentC. I even verified that FragmentC has a root by setting the last parameter in the inflate method to true. Very puzzling to me... Thanks for responding. – Allen Jul 27 '15 at 03:12
  • How is your progress? I think my posted answer points to the problem. – The Original Android Jul 29 '15 at 17:57
  • Hi. I apologize for the delay in my response. You have some valid points. My progress is stagnate. It's the SimpleAdapter that is throwing me off. I pass it in a layout file to use to display the list. I just don't see it yet as to why I need another layout file for the fragment. I would think it would make sense for me to access that layout file and replace with another fragment. Perhaps, I am not quite "getting it" and/or Google should make it a little bit more trivial for a fragment calling another fragment instead callback, adapters containing layouts. Yes, frustration is setting in. thx – Allen Aug 07 '15 at 03:00
  • It seems like I need a fragment container in my activity's layout file to use the fragment transaction's replace method correctly. However, therein lies my problem, the adapter is the one that inflates the fragments list view. I can't find anywhere in the internet or on SO for an example that I can follow somewhat to lead me to promise land. Thanks for taking the time out to respond, @The Original Android. – Allen Aug 07 '15 at 03:07

1 Answers1

1

I noticed FragmentB.java does not explicitly point to any layout file to inflate. In case you don't know,

ListFragment has a default layout that consists of a single list view

, documented @ ListFragment. So you're still fine if you only want a simple ListView, but maybe NOT. But then you have code that references another layout to FragmentB:

new SimpleAdapter(getActivity().getBaseContext(),colorList, R.layout.fragment_b...

Note: R.layout.fragment_b is the layout specified for the ArrayAdapter only! Not for the fragment. But this is normal and may be fine.

In MainActivity, onColorLevelSelected():

fragTransaction.replace(R.id.curriculumParent,...

Note:

  • I think this replaces the layout only for the adapter and not the fragment.
  • Perhaps you want to inflate a layout file containing a ListView, and use that for the fragments.
  • Your problem is basically the layout, work with that.

EDIT: Code suggestion:

SimpleAdapter adapter = new SimpleAdapter(getActivity().getBaseContext(),colorList, R.layout.fragment_x

public void onColorLevelSelected(int position)
   FragmentC fragX = new FragmentX();
   ...
   fragTransaction.replace(R.id.curriculumParent, fragX);

Notes:

  • Notice I am using an example of an arbitrary FragmentX. The Adapter and the replace() matches each other.
  • I understand this code change is somewhat considerable. Since I said it, here is a new code suggestion:

    public void onListItemClick(ListView l, View v, int pos, long id){
        Toast.makeText(getActivity(), "selected color :" + colorLevel[pos], Toast.LENGTH_LONG).show();
        SimpleAdapter adapter = new SimpleAdapter(getActivity().getBaseContext(),colorList, R.layout.fragment_b ,from, to);
        ...
        setListAdapter(adapter);
        ...
        mCallback.onColorLevelSelected(pos);   }
    

Note: This code change is made only to be simpler, my attempt. The idea is when the user click on a row in ListView, you know which layout and fragment is used. Hopefully that makes code less complicated.

The Original Android
  • 6,147
  • 3
  • 26
  • 31
  • @Allen, Please respond to my post in this thread, less confusing this way for me or others to follow. It seems either you disagree with me or we misunderstood each other, which happens. You should understand that the existing code flow is bit tricky. From MainActivity to a FragmentB, and back to MainActivity via callback. I forgot about that since it has been a while. So pls respond quicker. I will add more comments under EDIT section to be more clear as best as I can. – The Original Android Aug 07 '15 at 05:02
  • I figured out my issue. I had the replace the ViewPager. fragTransaction.replace(R.id.viewpager, fragC); However, I moved on from that design. There were so many difficulties in replacing a viewpager with a fragment. I must have searched SO and google many, many times and I just don't see anyone doing it except for [link] (http://stackoverflow.com/questions/7723964/replace-fragment-inside-a-viewpager). However, the person replying just touched a little on it. Anyhow, thanks for your responses. – Allen Aug 21 '15 at 18:10
  • @Allen, I am glad you fixed your problem, though not easy. You may upvote my post if you think it's useful (thanks). I suggest you read the SO tutorial @ http://stackoverflow.com/tour . You'll get rep points just by reading it. – The Original Android Aug 22 '15 at 00:51