9

I implemented a ActionBarSherlock with a ViewPager and a TabsAdapter. It works well but now I tried to "push" from a Framework Loaded in "Tab 1" another Fragment.

The behavior should be like:

  • I've 3 Tabs in my Application, When launching I see the first Tab where a Fragment with a Button is in it
  • Pressing the Button on the First Tab, the Fragment on the First Tab should be replaced and another Fragment should be displayed

I tried to implement this, but I've a black Fragment when Replacing.

The Code:

FragmentDemoActivity.java

public class FragmentDemoActivity extends SherlockFragmentActivity {
    CustomViewPager  mViewPager;
    TabsAdapter mTabsAdapter;

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

        ActionBar bar = getSupportActionBar();
        bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);

        mViewPager = (CustomViewPager)findViewById(R.id.pager);
        mViewPager.setSwipingEnabled(false);

        mTabsAdapter = new TabsAdapter(this, bar, mViewPager);
        mTabsAdapter.addTab(bar.newTab().setText("tab1"),
                FragmentA.class, null);
        mTabsAdapter.addTab(bar.newTab().setText("tab2"),
                FragmentB.class, null);

   setTitle(R.string.app_name);

        if (savedInstanceState != null) {
            bar.setSelectedNavigationItem(savedInstanceState.getInt("tab"));
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex());
    }

    public static class TabsAdapter extends FragmentPagerAdapter
            implements ViewPager.OnPageChangeListener, ActionBar.TabListener {
        private final Context mContext;
        private final ActionBar mBar;
        private final ViewPager mViewPager;
        private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();

        static final class TabInfo {
            private final Class<?> clss;
            private final Bundle args;

            TabInfo(Class<?> _class, Bundle _args) {
                clss = _class;
                args = _args;
            }
        }

        public TabsAdapter(FragmentActivity activity, ActionBar bar, ViewPager pager) {
            super(activity.getSupportFragmentManager());
            mContext = activity;
            mBar = bar;
            mViewPager = pager;
            mViewPager.setAdapter(this);
            mViewPager.setOnPageChangeListener(this);
        }

        public void addTab(ActionBar.Tab tab, Class<? extends Fragment> clss, Bundle args) {
            TabInfo info = new TabInfo(clss, args);
            tab.setTag(info);
            tab.setTabListener(this);
            mTabs.add(info);
            mBar.addTab(tab);
            notifyDataSetChanged();
        }

        @Override
        public int getCount() {
            return mTabs.size();
        }

        @Override
        public Fragment getItem(int position) {
            TabInfo info = mTabs.get(position);
            return Fragment.instantiate(mContext, info.clss.getName(), info.args);
        }



        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }

        @Override
        public void onPageSelected(int position) {
            mBar.setSelectedNavigationItem(position);
        }

        @Override
        public void onPageScrollStateChanged(int state) {
        }

        @Override
        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            Object tag = tab.getTag();
            for (int i=0; i<mTabs.size(); i++) {
                if (mTabs.get(i) == tag) {
                    mViewPager.setCurrentItem(i,false);
                }
            }
        }

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

        }

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

        }
    }

}

FragmentA.java

public class FragmentA extends Fragment {
    Button button;
    int num;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup group, Bundle saved)
    {
        return inflater.inflate(R.layout.frag_a, group, false);
    }

    @Override
    public void onActivityCreated (Bundle savedInstanceState)
    {
        super.onActivityCreated(savedInstanceState);
        num = 0;
        button = (Button) getActivity().findViewById(R.id.button1);
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                FragmentB f1 = new FragmentB();
                FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
                ft.replace(R.id.pager, f1,"newTag");
                ft.show(f1);
                ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
                ft.addToBackStack(null);
                ft.commit();    

            }
        });
    }
}

I'm new at Android Development, so I'd be happy if someone is able to help me. I already investigated a lot of time to search a solution but the result wasn't as I expected.

My current project: http://cl.ly/3q1f2t1O2Y3j

brokedid
  • 869
  • 2
  • 10
  • 33

1 Answers1

8

I gotcha!

Let me explain, you need to put an id on your Layout that you want to replace, my example:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/Framelay"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <TextView
        android:id="@+id/txtSearchTopic"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
        android:text="TextView" />

</FrameLayout>

So I just put mine: android:id="@+id/Framelay" Then I can use this Id to replace for the new fragment, what I mean is that all the content inside this Layout will be replaced by the new Fragment, as I called DetailFragment.

FragmentManager fragmentManager = getFragmentManager();  
FragmentTransaction fragmentTransaction = fragmentManager  
        .beginTransaction();  
DetailFragment fragment3 = new DetailFragment();  
fragmentTransaction.replace(R.id.Framelay, fragment3);  
fragmentTransaction.commit(); 
Barney
  • 2,273
  • 3
  • 20
  • 37
Marckaraujo
  • 7,002
  • 11
  • 50
  • 92
  • 1
    When using android.R.id.content instead of R.id.pager as you described above it works for the Current View, but when executing this code and then switching to another Tab, the new added Fragment Overlays the Fragment displayed in the other Tab. – brokedid Jan 17 '13 at 23:24
  • 1
    I see, you got me, thats a good question, I´ll try to find a solution. – Marckaraujo Jan 18 '13 at 00:01
  • 1
    In the Fragment what is loaded initially, I added the id to the LinearLayout Paramter. Then when Replacing the View, the View isn't replaced, I see the new View under the new View. – brokedid Jan 21 '13 at 08:30
  • I couldnt understand why this is placing the new view under the old view, tried many ways and did the same, I just got a sample project that it is working well, maybe you can understand better then me, see https://github.com/tamsler/android-flash-cards – Marckaraujo Jan 21 '13 at 15:21
  • I've investigated a little bit in my Code, but there are also other things that doesn't work like expected. For example the PageAdapter always loads one Tab bevore / after, what initiate always a URL Request. Is there a better Solution to switch between Tabs which always load Data asynchrously? – brokedid Jan 23 '13 at 12:47
  • 2
    I have a better solution, see https://www.4shared.com/rar/zOWrvmyu/ViewpagerandSherlock.html, inside of each fragment you can implement Asynctask, see if you can understand. – Marckaraujo Jan 23 '13 at 19:56