0

I'm trying to implement a listener to a list that is in a tab, when you click a listitem I want to switch from the ListFragment that is displayed to another ListFragment.

Now, the second listfragment opens but the first one is still in the background. How do I solve this?

Anyone willing to help a newbie?

The app crashes when clicking one item in the first list and the LogCat says:

04-22 18:51:47.359: D/dalvikvm(614): Not late-enabling CheckJNI (already on)
04-22 18:51:47.840: E/Trace(614): error opening trace file: No such file or directory (2)
04-22 18:51:48.510: D/dalvikvm(614): GC_FOR_ALLOC freed 69K, 3% free 8052K/8259K, paused 34ms, total 38ms
04-22 18:51:48.520: I/dalvikvm-heap(614): Grow heap (frag case) to 8.498MB for 614416-byte allocation
04-22 18:51:48.659: D/dalvikvm(614): GC_CONCURRENT freed 1K, 3% free 8651K/8903K, paused 86ms+23ms, total 136ms
04-22 18:51:48.809: D/gralloc_goldfish(614): Emulator without GPU emulation detected.
04-22 18:51:52.110: I/Choreographer(614): Skipped 43 frames!  The application may be doing too much work on its main thread.
04-22 18:52:02.020: D/AndroidRuntime(614): Shutting down VM
04-22 18:52:02.020: W/dalvikvm(614): threadid=1: thread exiting with uncaught exception (group=0x40a13300)
04-22 18:52:02.060: E/AndroidRuntime(614): FATAL EXCEPTION: main
04-22 18:52:02.060: E/AndroidRuntime(614): java.lang.NullPointerException
04-22 18:52:02.060: E/AndroidRuntime(614):  at android.app.BackStackRecord.run(BackStackRecord.java:609)
04-22 18:52:02.060: E/AndroidRuntime(614):  at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1397)
04-22 18:52:02.060: E/AndroidRuntime(614):  at android.app.FragmentManagerImpl$1.run(FragmentManager.java:426)
04-22 18:52:02.060: E/AndroidRuntime(614):  at android.os.Handler.handleCallback(Handler.java:615)
04-22 18:52:02.060: E/AndroidRuntime(614):  at android.os.Handler.dispatchMessage(Handler.java:92)
04-22 18:52:02.060: E/AndroidRuntime(614):  at android.os.Looper.loop(Looper.java:137)
04-22 18:52:02.060: E/AndroidRuntime(614):  at android.app.ActivityThread.main(ActivityThread.java:4745)
04-22 18:52:02.060: E/AndroidRuntime(614):  at java.lang.reflect.Method.invokeNative(Native Method)
04-22 18:52:02.060: E/AndroidRuntime(614):  at java.lang.reflect.Method.invoke(Method.java:511)
04-22 18:52:02.060: E/AndroidRuntime(614):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
04-22 18:52:02.060: E/AndroidRuntime(614):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
04-22 18:52:02.060: E/AndroidRuntime(614):  at dalvik.system.NativeStart.main(Native Method)
04-22 18:52:04.049: I/Process(614): Sending signal. PID: 614 SIG: 9

Here's my code: Main:

public class MainActivity extends Activity {

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

    ActionBar actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    actionBar.setDisplayShowTitleEnabled(true);

    Tab tab = actionBar.newTab().setText("Kategorier")
        .setTabListener(new CustomTabListener<KategorierFragment>(this, "kategorier", KategorierFragment.class));
    actionBar.addTab(tab);

    tab = actionBar.newTab().setText("Profil")
        .setTabListener(new CustomTabListener<ProfilFragment>(this, "profil", ProfilFragment.class));
    actionBar.addTab(tab);

    tab = actionBar.newTab().setText("Info")
        .setTabListener(new CustomTabListener<InfoFragment>(this, "info", InfoFragment.class));
    actionBar.addTab(tab);
    }
}

CustomTabListener

public class CustomTabListener<T extends Fragment> implements TabListener {

private Fragment mFragment;
private final Activity mActivity;
private final String mTag;
private final Class<T> mClass;

public CustomTabListener(Activity activity, String tag, Class<T> clz){
    mActivity = activity;
    mTag = tag;
    mClass = clz;
}

@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {

}

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {

    if(mFragment==null){
        mFragment = Fragment.instantiate(mActivity, mClass.getName());
        ft.add(android.R.id.content, mFragment, mTag);
    }else{
        ft.attach(mFragment);
    }
}

@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    if(mFragment!=null)
        ft.detach(mFragment);
    }
}

The listfragment that is shown under the first tab:

public class KategorierFragment extends ListFragment {

String kategorier[] = new String[]{
         "Mat","El","Resor","Aktiviteter","Övrigt"};

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

    ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity().getBaseContext(), android.R.layout.simple_selectable_list_item, kategorier);
    setListAdapter(adapter);
    return super.onCreateView(inflater, container, savedInstanceState);
}

    @Override
public void onListItemClick(ListView l, View v, int position, long id) {
    // TODO Auto-generated method stub
    super.onListItemClick(l, v, position, id);

    Fragment mFragment = new KategorierFragment();
    switch(position){
    case 0:
        mFragment = new MatFragment();
        break;
    case 1:
        mFragment = new ElFragment();
        break;
    case 2:
        mFragment = new ResorFragment();
        break;
    case 3:
        mFragment = new AktiviteterFragment();
        break;
    case 4:
        mFragment = new AnnatFragment();
        break;

    }

    FragmentManager fm = getFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ListFragment current = (ListFragment) fm.findFragmentById(R.id.Frame);
    ft.add(R.id.Frame, mFragment);
    ft.addToBackStack(null);
    ft.hide(current);
    ft.commit();
    }
}


@Override
public void onStart() {
    super.onStart();
    getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    }
} 

The first listfragment that i want to switch to:

public class MatFragment extends ListFragment{

String mat[] = {"Tips1", "Tips2", "Tips3", "Tips4", "Tips5", "Tips6", "Tips7"};


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // TODO Auto-generated method stub

     ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity().getBaseContext(), android.R.layout.simple_selectable_list_item, mat);
     setListAdapter(adapter);

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

1 Answers1

0

To get around your list getting superimposed, you need to hide your previous fragment before committing your transaction.

ListFragment current = (ListFragment) fm.findFragmentById(android.R.id.content);
ft.hide(current);

If you would like to navigate back to the last fragment using "Back", you would use

ft.add(android.R.id.content, mFragment);
ft.addToBackStack(null);
ft.hide(current);
ft.commit();
jwong
  • 76
  • 3
  • Okey, I tried it but i'm not sure if i'm doing it right cause the app crashes. I'll update the question with the code and lagcat info. Thanks for helping :) – user2307292 Apr 22 '13 at 17:03
  • Delete the first ft.hide(current). Sorry, didn't mean to confuse you with the two code snippets. They were meant to be separate examples. – jwong Apr 22 '13 at 17:44
  • Oh, sorry, I should have seen that. But the app still fails if I remove that line. – user2307292 Apr 22 '13 at 17:56
  • was this just a copy-paste error or do you have two of the following in your code? @Override public void onListItemClick(ListView l, View v, int position, long id) { // TODO Auto-generated method stub super.onListItemClick(l, v, position, id); – jwong Apr 22 '13 at 18:02
  • Regardless, try taking out ft.addToBackStack(null); – jwong Apr 22 '13 at 18:07
  • oh, copy-paste error. Now I saw that another error is displayed when i start my app on the emulator. I put the line at the top of where I write my LogCat. Still not working after i removed ft.addToBackStack(null); – user2307292 Apr 22 '13 at 18:16
  • if I do a System.out.println(current); after theListFragment current = (ListFragment) fm.findFragmentById(R.id.Frame); – user2307292 Apr 22 '13 at 20:12
  • Ok, so I created a sample project and this is what I found. When you first create a tab, the fragment is the base view. You also did not setContentView in your main activity. As such, your application cannot find your FrameLayout R.id.Frame. Change your R.id.Frame to android.R.id.content and that should fix it. I'll edit my answer to reflect this. – jwong Apr 22 '13 at 21:51
  • 1
    So now I've tried some things. The solution you give is working, as well as if I setContentView and change from findFragmentById to findFragmentByTag. Thanks for all help! – user2307292 Apr 23 '13 at 09:47
  • new problems, please see http://stackoverflow.com/questions/16177549/listfragment-and-onlistitemclick-not-working – user2307292 Apr 23 '13 at 20:54