0

I have tabs, in one tab there is a ListFragment with an onListItemClick. When you click one item another ListFragment is displayed so this works fine. The same onListItemClick as the one for the first ListFragment is implemented to the second ListFragment.

EDIT: this is how i tried to change the 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;
private final Bundle mArgs;


public CustomTabListener(Activity activity, String tag, Class<T> clz) {
    this(activity, tag, clz, null);
}

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


    // Check to see if we already have a fragment for this tab, probably
    // from a previously saved state.  If so, deactivate it, because our
    // initial state is that a tab isn't shown.
    mFragment = mActivity.getFragmentManager().findFragmentById(android.R.id.content);
    if (mFragment != null && !mFragment.isDetached()) {
        FragmentTransaction ft = mActivity.getFragmentManager().beginTransaction();
        ft.hide(mFragment);
        ft.commit();
    }
}

@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(), mArgs);
        ft.add(android.R.id.content, mFragment, mTag);
    }else{
        ft.show(mFragment);
    }
}

@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
mActivity.getFragmentManager().findFragmentByTag(mTag);

    if(mFragment!=null){
        ft.hide(mFragment);
        }
    }
}

Now the app crashes if I click on an item in the first list. LogCat says:

04-24 16:00:37.161: E/AndroidRuntime(9421): FATAL EXCEPTION: main
04-24 16:00:37.161: E/AndroidRuntime(9421): java.lang.ClassCastException: com.example.easysave.InfoFragment cannot be cast to android.app.ListFragment
04-24 16:00:37.161: E/AndroidRuntime(9421):     at com.example.easysave.KategorierFragment.onListItemClick(KategorierFragment.java:66)
04-24 16:00:37.161: E/AndroidRuntime(9421):     at android.app.ListFragment$2.onItemClick(ListFragment.java:160)
04-24 16:00:37.161: E/AndroidRuntime(9421):     at android.widget.AdapterView.performItemClick(AdapterView.java:298)
04-24 16:00:37.161: E/AndroidRuntime(9421):     at android.widget.AbsListView.performItemClick(AbsListView.java:1100)
04-24 16:00:37.161: E/AndroidRuntime(9421):     at android.widget.AbsListView$PerformClick.run(AbsListView.java:2749)
04-24 16:00:37.161: E/AndroidRuntime(9421):     at android.widget.AbsListView$1.run(AbsListView.java:3423)
04-24 16:00:37.161: E/AndroidRuntime(9421):     at android.os.Handler.handleCallback(Handler.java:725)
04-24 16:00:37.161: E/AndroidRuntime(9421):     at android.os.Handler.dispatchMessage(Handler.java:92)
04-24 16:00:37.161: E/AndroidRuntime(9421):     at android.os.Looper.loop(Looper.java:137)
04-24 16:00:37.161: E/AndroidRuntime(9421):     at android.app.ActivityThread.main(ActivityThread.java:5041)
04-24 16:00:37.161: E/AndroidRuntime(9421):     at java.lang.reflect.Method.invokeNative(Native Method)
04-24 16:00:37.161: E/AndroidRuntime(9421):     at java.lang.reflect.Method.invoke(Method.java:511)
04-24 16:00:37.161: E/AndroidRuntime(9421):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
04-24 16:00:37.161: E/AndroidRuntime(9421):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
04-24 16:00:37.161: E/AndroidRuntime(9421):     at dalvik.system.NativeStart.main(Native Method)

I have two problems:

  1. When I have clicked one item in the first ListFragment being displayed and then click another tab, the list doesn't hide.

  2. (Solved) When I have clicked one item in the first ListFragment being displayed and then click on the other ListFragment the app crashes.

What I would like to have when second ListFragment is clicked is a fragment with simple text in it, not a list.

Am I doing this the wrong way? Anyone who knows?

Problem 2 solved by:

comment the setContentView in main

change all the ListFragment current = (ListFragment) fm.findFragmentByTag(getTag()); and ft.add(R.id.Frame, mFragment); to Listfragment current = (ListFragment) fm.findFragmentById(android.R.id.content); and ft.add(android.R.id.content, mFragment);

and finally changing to this in PlaneraFragment:

public class PlaneraFragment extends Fragment{

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

    /** Inflating the layout country_details_fragment_layout to the view object v */
    View v = inflater.inflate(R.layout.planera_fragment, null);

    /** Getting the textview object of the layout to set the details */
    TextView tv = (TextView) v.findViewById(R.id.text_planera);

    /** Getting the clicked item's position and setting corresponding details in the textview of the detailed fragment */
    tv.setText("Hej ");

    return v;
    }

}

My code:

Main

package com.example.easysave;  

import android.os.Bundle;
import android.app.ActionBar;
import android.app.Activity;
import android.app.ActionBar.Tab;

public class MainActivity extends Activity {

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

    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);
    }
}

KategorierFragment

package com.example.easysave;

import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.ListFragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class KategorierFragment extends ListFragment {

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


@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.findFragmentByTag(getTag());

    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);
    } 
}

MatFragment

package com.example.easysave;

import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.ListFragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MatFragment extends ListFragment{

String mat[] = {"Planera", "Storkok"};

@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);
}

@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 MatFragment();
    switch(position){
    case 0:
        mFragment = new PlaneraFragment();
        break;
    case 1:
        mFragment = new StorkokFragment();
        break;
    }

    FragmentManager fm = getFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ListFragment current = (ListFragment) fm.findFragmentByTag(getTag());
    if(current == null)
    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);
    }    
}

CustonTabListener

package com.example.easysave;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.ActionBar.Tab;
import android.app.ActionBar.TabListener;

public class CustomTabListener<T extends Fragment> implements TabListener {

//deklarerar variabler mm
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(R.id.Frame, mFragment, mTag);
    }else{
        ft.attach(mFragment);
    }
}

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

    if(mFragment!=null)
        ft.detach(mFragment);
    }
}

PlaneraFragment

package com.example.easysave;

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

public class PlaneraFragment extends Fragment{

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    View view = inflater.inflate(R.layout.planera_fragment, container, false);

    TextView text = (TextView) getActivity().findViewById(R.id.text_planera);
    text.setText("Hello there!");

    return view;
    }

}

planera_fragment

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<TextView
    android:textIsSelectable="false"
    android:id="@+id/text_planera"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"/>

</LinearLayout>
  • Is error in every code you posted, or it could be simplified for us? – Marek Sebera Apr 24 '13 at 12:09
  • and btw. http://stackoverflow.com/questions/7274231/listfragment-onlistitemclick-not-being-called – Marek Sebera Apr 24 '13 at 12:11
  • I fixed the second problem. There is no error, i'll try explain the first problem again. I am on the "Kategorier"-Tab, clicking on one item in the list makes another list to be shown and the last to be hidden. But if I then click another tab, the list from the "Kategorier"-Tab doesn't hide. It shows two fragments on top of eachother. I looked at this: http://stackoverflow.com/questions/10502786/switching-fragments-within-tab and tried to change my tablistener as this person did but with no success. – user2307292 Apr 24 '13 at 12:42

1 Answers1

0

You need to figure out how you should handle your tabs. You're attaching and detaching in your TabListener, but showing and hiding when clicking through your ListView.

You either detach all your current fragments and then attach the new one, or change your tab listeners to .show() and .hide() instead.

EDIT: According to the last comment in this answer, there's a good example of keeping your tab history while switching between tabs.

The following implementation of TabListener is simple but will not keep your back stack intact. When switching to another tab, you're not selecting one to hide. This just glazes over it and detach the whole thing.

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
     mFragment = Fragment.instantiate(mActivity, mClass.getName());
     ft.replace(android.R.id.content, mFragment, mTag);
}

@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    if (mFragment != null)
        ft.detach(mFragment);
    }
}
Community
  • 1
  • 1
jwong
  • 76
  • 3
  • So I changed my TabListenter, but now the app crashes if I press an item in the first list. I'll add the CustomTabListener in the text so you can see what I've done. – user2307292 Apr 24 '13 at 16:05
  • They are almost at the top of the page. – user2307292 Apr 24 '13 at 16:18
  • Read your logcat. Casting is causing an exception to occur. Step through your app in Debug mode to try and resolve your errors first. – jwong Apr 24 '13 at 16:22
  • It seems like if I click a tab and then click "Kategorier"-Tab and when clicking on an item it crashe1s. – user2307292 Apr 24 '13 at 16:22
  • Refer to your logcat again. You are trying to access an InfoFragment and casting it as a ListFragment. Try googling some of these exceptions or use your IDE's Debug Perspective and understand what is causing these crashes. – jwong Apr 24 '13 at 16:40
  • Run it in debugmode. It pointed at the line: ListFragment current = (ListFragment) fm.findFragmentById(android.R.id.content); in KategorierFragment. When my program comes to this line it tries to find the ListFragment that we want to hide. My InfoFragment is just extended by Fragment and not ListFragment, can this be the error? tried change the pointed out row to Fragment and not ListFragment, this doesn't crash the app but some fragments are still overlapping eachother. I haven't used debuggingmode before so I'm not sure what to make of this. – user2307292 Apr 24 '13 at 17:21
  • Congrats! It seems that you've figured out Debug mode. It'll come in handy. And you are correct, that was what caused your crash. Also, since you're traversing between fragments, you're going to have to edit your TabListener to handle all the traversal. I'll edit my original answer. – jwong Apr 24 '13 at 22:09
  • Thanks! It still isn't working correctly. If I click on an item in the second listfragment and come to the fragment with textviews, then click on another tab, the fragment with the textviews are still visible as well as the fragment of the clicked tab. If I then click on another tab, only that tabs fragment is visible. My textviews and such widgets are now added programmatically and not in my .xml. It works well if I begin by clicking on my InfoFragment, which also has textviews added the same way, and then clicking on another tab. Any idea what can be wrong here? – user2307292 Apr 25 '13 at 12:45
  • I tested printing out the mFragmentin onTabUnselected. When i'm only clicking on the tabs, it prints out the last visited tab, correctly. But if i go into the lists i don't get a mFragment printed. Anyone that knows why the mFragments I set in the listFragments isn't noticed in the onTabUnSelected? – user2307292 Apr 26 '13 at 13:04