Android: ActionBar, TabListener und Unterstützung.v4.Fragment

Baue ich ein app mit MainActivity erstreckt FragmentActivity und hat eine ActionBar mit drei Registerkarten. Auf jeder Registerkarte möchte ich anfügen einer ParentFragment was sollte die Kontrolle über die streichen zu internen Seiten. Das Ergebnis sollte sein, drücken Sie die Laschen der Benutzer sollte sich ändern, von den verschiedenen Instanzen der ParentFragment und streichen, sollte er sich unter der TextViewFragments in jedem ParentFragment.

Jetzt kann ich perfekt schalten Sie zwischen den drei Registerkarten, aber das problem ist, dass die ParentFragment ist nicht richtig dargestellt, es scheint, es ist noch nicht angelegt, weil ich kann nicht einmal sehen, die onCreate(), onCreateView() und onViewCreated() Funktionen im LogCat anzeigen.

Ich denke, das problem liegt in der benutzerdefinierten TabListener-Klasse und Ihre Funktionen, aber ich kann nicht wirklich verstehen, was das problem ist. Ich habe versucht, die Suche auf vielen Seiten habe und ich sah in eine Menge Beispiele, aber keiner von Ihnen war in Bezug auf die gleiche situation.

Was ich vermisse oder was mache ich hier falsch?

Dies ist meine MainActivity:

    import java.util.Random;
    import android.app.ActionBar;
    import android.app.ActionBar.Tab;
    import android.graphics.drawable.Drawable;
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentActivity;
    import android.support.v4.app.FragmentTransaction;
    import android.support.v4.view.ViewPager;
    import android.view.Gravity;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    import android.widget.Toast;
    import com.viewpagerindicator.PageIndicator;

public class MainActivity extends FragmentActivity {

    MyAdapter mAdapter;
    ViewPager mPager;
    PageIndicator mIndicator;    
    private View mCustomView; 
    private static final Random RANDOM = new Random();

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

        //Set up the action bar.
        ActionBar.LayoutParams params = new ActionBar.LayoutParams(
                ActionBar.LayoutParams.MATCH_PARENT,
                ActionBar.LayoutParams.MATCH_PARENT, Gravity.CENTER);
        final ActionBar actionBar = getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        actionBar.setDisplayShowTitleEnabled(false);
        actionBar.setDisplayUseLogoEnabled(false);
        actionBar.setDisplayShowHomeEnabled(false);


            actionBar.addTab(actionBar
                    .newTab()
                    .setIcon(getIcon(0, true))
                    .setTabListener(
                            new TabListener<ParentFragment>(this, "home",
                                    ParentFragment.class)));

            actionBar.addTab(actionBar
                    .newTab()
                    .setIcon(getIcon(1, false))
                    .setTabListener(
                            new TabListener<ParentFragment>(this, "apps",
                                    ParentFragment.class)));

            actionBar.addTab(actionBar
                    .newTab()
                    .setIcon(getIcon(2, false))
                    .setTabListener(
                            new TabListener<ParentFragment>(this, "settings",
                                    ParentFragment.class)));

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

    }


    public static class TabListener<T extends Fragment> implements
            ActionBar.TabListener {

        private Fragment mFragment;
        private final FragmentActivity mActivity;
        private final String mTag;
        private final Class<T> mClass;
        private final Bundle mArgs;
        private FragmentTransaction fft;
            public static final String TAG = TabListener.class.getSimpleName();

        public TabListener(FragmentActivity activity, String tag, Class<T> clz) {

            this(activity, tag, clz, null);
        }

        public TabListener(FragmentActivity activity, String tag, Class<T> clz,
                Bundle args) {

            mActivity = activity;
            mTag = tag;
            mClass = clz;
            mArgs = args;

            mFragment = mActivity.getSupportFragmentManager()
                    .findFragmentByTag(mTag);
            if (mFragment != null && !mFragment.isDetached()) {

                fft = mActivity.getSupportFragmentManager().beginTransaction();
                fft.detach(mFragment);
                fft.commit();
            }
        }

        public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {

            System.out.println(TAG + (" - ") + " -> mTag "
                    + mTag + " selected!");
            fft = mActivity.getSupportFragmentManager().beginTransaction();

            if (mFragment == null) {
                mFragment = Fragment.instantiate(mActivity, mClass.getName());

                fft.add(android.R.id.content, mFragment, mTag);

            } else {
                System.out.println(TAG + (" - ") + " -> Fragment con mTag = " + mTag
                        + " trovato con tag!");
                fft.attach(mFragment);
                fft.commit();
            }
        }

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

        }

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

            mFragment = mActivity.getSupportFragmentManager()
                    .findFragmentByTag(mTag);
            System.out.println(TAG + (" - ") + " -> mTag "
                    + mTag + " unselected!");

            if (mFragment != null && !mFragment.isDetached()) {
                fft = mActivity.getSupportFragmentManager().beginTransaction();
                fft.detach(mFragment);
                fft.commit();
            }
        }

    }

    public Drawable getIcon(int tabPosition, boolean selected) {

        switch (tabPosition) {
        case 0:
            return getResources().getDrawable(R.drawable.actionbar_home);

        case 1:
            return getResources().getDrawable(R.drawable.actionbar_apps);

        case 2:
            return getResources().getDrawable(R.drawable.actionbar_settings);

        }
        return null;
    }

}

Und das ist mein ParentFragment die exteds jetzt das android.Unterstützung.v4.app.Fragment-Klasse:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.viewpagerindicator.IconPageIndicator;
import com.viewpagerindicator.PageIndicator;

public class ParentFragment extends Fragment {

    public static final String TAG = ParentFragment.class.getSimpleName();

    MyAdapter fragmentAdapter;
    ViewPager mPager;
    PageIndicator mIndicator;



    public static ParentFragment newInstance() {
 System.out.println(TAG + " - newInstance()");
    System.out.println(TAG + " - " + methodName());
        ParentFragment fragment = new ParentFragment();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
System.out.println(TAG + " - onCreate()");
        System.out.println(TAG + " - " + methodName());

        super.onCreate(savedInstanceState);
        setRetainInstance(true);

    }

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

System.out.println(TAG + " - onCreateView()");
        System.out.println(TAG + " - " + methodName());
        fragmentAdapter = new MyAdapter(getFragmentManager());

        View view = inflater.inflate(R.layout.simple_icons, container, false);
        mPager = (ViewPager) view.findViewById(R.id.pager);
        mPager.setAdapter(fragmentAdapter);

        return view;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        System.out.println(TAG + " - onViewCreated()" );
        System.out.println(TAG + " - " + methodName());
        super.onViewCreated(view, savedInstanceState);

        mIndicator = (IconPageIndicator) getActivity().findViewById(R.id.indicator);
        mIndicator.setViewPager(mPager);          
    }
}

Dies ist die Klasse MyAdapter:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import com.viewpagerindicator.IconPagerAdapter;

public class MyAdapter extends PagerAdapter  {

    FragmentManager myFragmentMgr;
    private FragmentTransaction mCurTransaction;

    protected static final String[] CONTENT = new String[] { "This", "Is", "A", "Test", };
    protected static final int[] ICONS = new int[] {
            R.drawable.icon_page_indicator,
            R.drawable.icon_page_indicator,
            R.drawable.icon_page_indicator,
            R.drawable.perm_group_calendar,
            R.drawable.perm_group_camera,
            R.drawable.perm_group_device_alarms,
            R.drawable.perm_group_location
    };

    private int mCount = CONTENT.length;

    public MyAdapter(FragmentManager fm) {
        super();
        myFragmentMgr = fm;
    }

    @Override
    public int getCount() {

        return 3;
    }

    @Override
    public Object instantiateItem(ViewGroup viewGroup, int position) {

        ParentFragment fragment = ParentFragment.newInstance(); 
        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup viewGroup, int position, Object obj) {

        if (mCurTransaction == null) {
            mCurTransaction = myFragmentMgr.beginTransaction();
        }
        mCurTransaction.detach((Fragment)obj);
    }   

    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        return false;
    }

    public Fragment getItem(int position) {
        Bundle args = new Bundle();
        args.putInt(TextViewFragment.POSITION_KEY, position);
        return TextViewFragment.newInstance(args);
    }

    @Override
    public CharSequence getPageTitle(int position) {

        return "Fragment # " + position;
    }

    public int getIconResId(int index) {

        return ICONS[index % ICONS.length];
    }

     public void setCount(int count) {
            if (count > 0 && count <= 10) {
                mCount = count;
                notifyDataSetChanged();
            }
        } 
}

und die letzten die TextViewFragment Klasse:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

public class TextViewFragment extends Fragment {

    public static final String POSITION_KEY = "POSITION";
    public static final String TITLE_KEY = "TITLE";

    public static TextViewFragment newInstance(Bundle args) {
        TextViewFragment fragment = new TextViewFragment();
        fragment.setArguments(args);
        return fragment;
    }

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_test, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        TextView textview = (TextView) view.findViewById(R.id.textViewPosition);
        final int position;
        if (getArguments() != null) {
            position = getArguments().getInt(POSITION_KEY);
            textview.setText(Integer.toString(position));
        } else {
            position = 0;
            textview.setText("Child Fragment");
        }

        textview.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                Toast.makeText(v.getContext(), "Clicked Position: " + position,
                        Toast.LENGTH_LONG).show();
            }
        });
    }    
}

----- EDIT: LÖSUNG -----

Ich kann nicht die Antwort auf meine eigene Frage durch "niedrige reputation" aber ich Teile trotzdem die Lösung, um zu helfen, jemand anderes, und hoffentlich wieder einige Stimmen.

Ich endlich einen Weg gefunden, um Dinge, die für mich arbeiten, ich hoffe, dass dies hilfreich sein könnte für andere mit dem gleichen problem.
Wie ich vermutet hatte, war das problem in TabListener. Mein problem wurde gelöst zu ändern, dass Artikel mit diesem code:

   public static class TabListener<T extends Fragment> implements
            ActionBar.TabListener {
    private Fragment mFragment;
    private final FragmentActivity mActivity;
    private final String mTag;
    private final Class<T> mClass;
    private final Bundle mArgs;
    private FragmentTransaction fft;

    public TabListener(FragmentActivity activity, String tag, Class<T> clz) {

        this(activity, tag, clz, null);
    }

    public TabListener(FragmentActivity activity, String tag, Class<T> clz,
            Bundle args) {

        mActivity = activity;
        mTag = tag;
        mClass = clz;
        mArgs = args;

        System.out.println(TAG + " - " + methodName() + " - Constructor of TabListener -> mTag = "
                + mTag);
        //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.getSupportFragmentManager()
                .findFragmentByTag(mTag);
        if (mFragment != null && !mFragment.isDetached()) {

            fft = mActivity.getSupportFragmentManager().beginTransaction();
            fft.detach(mFragment);
            fft.commit();
            mActivity.getSupportFragmentManager()
                    .executePendingTransactions();
        }
    }

    public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {

        Fragment tmp = mActivity.getSupportFragmentManager()
                .findFragmentByTag(mTag);

        fft = mActivity.getSupportFragmentManager().beginTransaction();

        if (mFragment == null) {

            System.out.println(TAG + " - " + methodName() + " - add mFragment " + mTag);
            //If not, instantiate and add it to the activity
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            fft.add(android.R.id.content, mFragment, mTag);
            fft.commit();
            mActivity.getSupportFragmentManager()
                    .executePendingTransactions();
        } else {
            System.out.println(TAG + " - " + methodName() + " - attach mFragment " + mTag);
            //If it exists, simply attach it in order to show it
            fft.attach(mFragment);
            fft.commit();
            mActivity.getSupportFragmentManager()
                    .executePendingTransactions();
        }
    }

    @Override
    public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) {
        System.out.println(TAG + " - " + methodName() + " - mFragment " + mTag);

    }

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

        mFragment = mActivity.getSupportFragmentManager()
                .findFragmentByTag(mTag);

        if (mFragment != null && !mFragment.isDetached()) {
            System.out.println(TAG + " - " + methodName() + " - detach mFragment " + mTag);
            fft = mActivity.getSupportFragmentManager().beginTransaction();
            fft.detach(mFragment);
            fft.commit();
            mActivity.getSupportFragmentManager()
                    .executePendingTransactions();
        }
    }



    public static final String TAG = TabListener.class.getSimpleName();
    private static final int CLIENT_CODE_STACK_INDEX;

    static {
        //Finds out the index of "this code" in the returned stack trace -
        //funny but it differs in JDK 1.5 and 1.6
        int i = 0;
        for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
            i++;
            if (ste.getClassName().equals(TabListener.class.getName())) {
                break;
            }
        }
        CLIENT_CODE_STACK_INDEX = i;
    }

    public static String methodName() {

        if (Thread.currentThread().getStackTrace().length < CLIENT_CODE_STACK_INDEX)
            return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX]
                    .getMethodName() + "()";
        else
            return new String(
                    "methodName() - stackTrace index is out of bound");
    }
}

Der grundlegende Unterschied war die Zugabe nach jedem commit() der folgenden Zeile:

mActivity.getSupportFragmentManager().executePendingTransactions();

Dieses problem wurde wirklich schlecht dokumentiert und vermutlich passiert das nur in bestimmten Bedingungen, aber ich hoffe, dass diese Lösung spart einige Zeit, um jemand anderes, das die gleichen Probleme!

  • In meinem Fall hinzufügen executePendingTransanctions geworfen eine Rekursion Fehler . Jedenfalls habe ich deinen code ohne Anruf und es funktionierte.
InformationsquelleAutor Andre | 2013-06-03
Schreibe einen Kommentar