I'm trying to build an Android 4.0 App with the new fragments and action bar.
I'm doing well but I have a little problem now.
When I put a fragment inside a tab, and for example, a time picker in the fragment layout, in the emulator it will appear twice, one on top of the other.
Here is my code:
public class NetworksActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.networks);
// setup Action Bar for tabs
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// instantiate fragment for the tab
Fragment networksFragment = new NetworksFragment();
// add a new tab and set its title text and tab listener
actionBar.addTab(actionBar.newTab().setText("Sensors")
.setTabListener(new ActionTabListener(networksFragment)));
}}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<fragment
android:id="#+id/net_frag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:name="my.package.test.NetworksFragment" />
</FrameLayout>
public class NetworksFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.networks_fragment, container, false);
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TimePicker
android:id="#+id/timePicker1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
public class ActionTabListener implements ActionBar.TabListener {
private NetworksFragment frag;
// Called to create an instance of the listener when adding a new tab
public ActionTabListener(NetworksFragment fragment) {
frag = fragment;
}
#Override
public void onTabReselected(Tab arg0, FragmentTransaction arg1) {
// TODO Auto-generated method stub
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.add(R.id.net_frag, frag, null);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(frag);
}
}
It seems like its putting two fragments (two copies) in the same activity.
Do you know what are causing this?
Thanks in advance.
It looks like you are defining a fragment in XML, which will instantiate it when that layout is inflated (from NetworksActivity.setContentView(R.layout.networks)) then you are creating another instance of it just below that.
Unless I am missing something, that is your problem. No need to define it in XML if you are going to instantiate it manually and add it yourself in code.
I had a similar problem. The way i solved it was to remove this code from my Fragment-class:
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
CameraFragment cameraFragment = new CameraFragment();
fragmentTransaction.add(R.id.spinnerFragment, spinnerFragment);
fragmentTransaction.commit();
And left this code from my fragment-XML:
<fragment
android:id="#+id/spinnerFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
class="com.example.SpinnerFragment" />
I guess you can do it the oposite way also :)
Related
From OverlayActivity:
#Override
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG,"onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_overlay);
// Check whether the activity is using the layout version with
// the fragment_container FrameLayout. If so, we must add the first chatRootFragment
if (findViewById(R.id.video_player_fragment_container) != null) {
if (savedInstanceState != null) {
return;
}
FullScreenVideoPlayerUnderlayFragment mMessageListFragment = new FullScreenVideoPlayerUnderlayFragment();
if (mMessageListFragment != null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.video_player_fragment_container, mMessageListFragment);
transaction.commit();
} else {
Log.e("OverlayActivity", "Error in creating chatRootFragment");
}
}
// Instantiate a ViewPager and a PagerAdapter.
mPager = findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
mPager.setCurrentItem(1);
}
#Override
public void onBackPressed() {
FullScreenVideoPlayerUnderlayFragment fragment = (FullScreenVideoPlayerUnderlayFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_full_screen_video_player_underlay_id);//<= NULL
OverlayActivity.super.onBackPressed();
}
The frgment:
public class FullScreenVideoPlayerUnderlayFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_full_screen_video_player_underlay, container, false);
}
#Override
public void onDestroy() {
getActivity().setResult(getActivity().RESULT_OK, getActivity().getIntent().putExtra("USER_DATA_EXTRA", "Yo User"));
super.onDestroy();
playlistManager.invokeStop();
exitFullscreen();
}
}
fragment_full_screen_video_player_underlay.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/fragment_full_screen_video_player_underlay_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/black">
<com.devbrackets.android.exomedia.ui.widget.VideoView
android:id="#+id/video_play_activity_video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:useDefaultControls="true"/>
</RelativeLayout>
activity_overlay.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/video_player_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
fragment_full_screen_video_player_underlay_id
is the id of your RelativeLayout.
From the documentation:
findFragmentById
Finds a fragment that was identified by the given id either when inflated from XML or as the container ID when added in a transaction. This first searches through fragments that are currently added to the manager's activity; if no such fragment is found, then all fragments currently on the back stack associated with this ID are searched.
This means that either your fragment is inflated from XML - in which case you will have to use the id of your <Fragment> element if any - or to the container with the given ID that hosts the fragment.
If you added your fragment using a transaction and you need to retrieve it later then use findFragmentByTag (String tag) and add the fragment using add
add (int containerViewId, Fragment fragment, String tag)
I should use
FullScreenVideoPlayerUnderlayFragment fragment = (FullScreenVideoPlayerUnderlayFragment) getSupportFragmentManager().findFragmentById(R.id. video_player_fragment_container);
instead of
FullScreenVideoPlayerUnderlayFragment fragment = (FullScreenVideoPlayerUnderlayFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_full_screen_video_player_underlay_id);//<= NULL
Instead of finding fragment what I should do is I would add a frame layout in activity_main.xml and i made a function to load a fragment in that frame layout here's a function.
public void loadFragment(Fragment fragment, String title) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.frameLayoutId, fragment, title);
transaction.commit();
}
This worked for me very good I hope same for you...
happy coding. :)
in my app I have an ActionBarActivity (I'm using support library with AppCompat) that uses the SlidingTabLayout class from Google (taken from here). So this is the XML code of the activity's layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_series_details"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".SeriesDetailsActivity">
<com.my.package.SlidingTabLayout
android:id="#+id/series_details_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="2dp"
android:background="#color/primary_material_dark" />
<android.support.v4.view.ViewPager
android:id="#+id/series_details_pager"
android:layout_height="0dp"
android:layout_width="match_parent"
android:layout_weight="1" />
</LinearLayout>
In this activty, when user press an option in the action bar, I want to add a Fragment with a custom animation. This is the code that handle menu click:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
/* ... OTHER CASES ... */
case R.id.menu_voption:
newFragment = MyNewFragment.newInstance();
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(
R.anim.slide_up,
R.anim.slide_down
)
.add(R.id.activity_series_details, newFragment)
.commit();
editing = true;
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
Doing this, my new fragment is correctly added to the activty and replace the currente fragment but not tab layout, tha remains visible. So I've tryed to add this line before start transaction:
tabsHost.setVisibility(View.GONE);
where tabsHost is the SlidingTabLayout. With this modification, the tabs layout disappear and the new fragment is correctly shown, but only in the API Level >= 21. In my Samsung Galaxy S4 (that runs API 19) and in all other emulators with lesser API level than 21 (my target is 11+), the tabs layout disappear but new fragment is not visible. I'm pretty sure is my fault, but I can't figure why. Thanks all for attention.
Since the SlidingTabLayout is not a fragment, it cannot be managed by the FragmentManager. You would have to make it part of a fragment and add it to your Activity. This is possible with getChildFragmentManager.
Move your activity layout to a fragment:
activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_series_details"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
fragment_sliding_tab.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_series_details"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.my.package.SlidingTabLayout
android:id="#+id/series_details_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="2dp"
android:background="#color/primary_material_dark" />
<android.support.v4.view.ViewPager
android:id="#+id/series_details_pager"
android:layout_height="0dp"
android:layout_width="match_parent"
android:layout_weight="1" />
</LinearLayout>
SlidingTabFragment.java
public class SlidingTabFragment extends Fragment {
private PagerAdapter mPagerAdapter;
private ViewPager mViewPager;
public static SlidingTabFragment newInstance() {
SlidingTabFragment fragment = new SlidingTabFragment();
return fragment;
}
public SlidingTabFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mPagerAdapter = new PagerAdapter(getChildFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) view.findViewById(R.id.series_details_pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
SlidingTabLayout tabs = (SlidingTabLayout) view.findViewById(R.id.series_details_tabs);
tabs.setViewPager(mViewPager);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_sliding_tab, container, false);
}
}
Add your fragment in your Activity's onCreate:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Fragment slidingTabFragment = SlidingTabFragment.newInstance();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.activity_series_details, slidingTabFragment).commit();
}
I want to call an fragment method from my activity, describe like in this SO-question: FindByID
TestFragment testFrag = (TestFragment) getFragmentManager().getFragmentById(R.id.testfragment);
if(testFrag != null && testFrag.isAdded())
testFrag.testMethod("Test");
As seen they identify the fragment by ID which is set in the xml. As I only have a fragment container none of my fragment layouts have a ID.
So my seconds thought was using the function getFragmentByTag `like in Tags
fragmentTransaction.replace(R.id.frameTitle, casinodetailFragment, "fragmentTag");
but as I use an action bar with tabs I don't have any tags:
My activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragmentcontainer);
// ActionBar gets initiated
ActionBar actionbar = getActionBar();
actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Define Tabs
ActionBar.Tab BasicInfoTab = actionbar.newTab().setText(
R.string.tab_BaseInfo);
..
// Define Fragments
PlantBasicInfoFragment BasicInfoFragment = new PlantBasicInfoFragment();
..
// Set TabListeners
BasicInfoTab.setTabListener(new TabListener(BasicInfoFragment));
..
// Add tabs to Actionbar
actionbar.addTab(BasicInfoTab);
..
// Icon clickable
actionbar.setDisplayHomeAsUpEnabled(true);
}
and its layout:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<LinearLayout
android:orientation="horizontal"
android:id="#+id/LabeledObjectHeaderInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<!-- ... -->
</LinearLayout >
<!-- fragment container -->
<LinearLayout
android:orientation="horizontal"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</LinearLayout>
</LinearLayout>
One of my fragments:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:id="#+id/table">
<TableRow>
<!-- ... -->
</TableRow>
<!-- ... -->
</TableLayout>
and finally my tab listener
public class TabListener implements ActionBar.TabListener {
public Fragment fragment;
public TabListener(Fragment fragment) {
this.fragment = fragment;
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_container, fragment);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(fragment);
}
}
So how can I identify my current fragment?
Thanks in advance
P.S. The whole tab switching works perfectly, but now I want to build an addional feature inside the activity!
Add a tag while creating tabs.
ActionBar.Tab BasicInfoTab = actionbar.newTab().setText(R.string.tab_BaseInfo);
BasicInfoTab.setTag("tab1");
And in the listener class, retrieve the tag upon event.
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
String tabId = tab.getTag().toString();
}
This way you get the current tag. To identify the current fragment, you can keep a stack of fragments and pick the right one on tab change.
Edit
The tabId, aforementioned, identifies which tab is which. In order to set a fragment id/tag, there are many ways depending on your needs. One method is to replace your actual fragment layout with an intermediate layout.
For instance, A be the fragment you want to add to fragment container. Create another fragment class called IntermediateFragment with the following layout.
<?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="horizontal"
android:baselineAligned="false">
<fragment
android:id="#+id/fragmentId"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="classA" />
</LinearLayout>
Now assign the layout you mentioned in the post (containing table) as a new one and add it to fragment class A. Now add Intermediate fragment to container which in turn pulls fragment A. Identify fragment A by id/tag added in the layout.
Hope it makes some sense!
Finally I got my solution by changing the TabListener, so I can add the fragment with an tag and then use the findFragmentByTag() function.
So my TabListener now looks like this (only constructor and onTabSelected changed)
public TabListener(Fragment fragment, String tag) {
this.fragment = fragment;
this.fragmentTag = tag;
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_container, fragment, fragmentTag);
}
With this I only need to add a string (as tag) when adding the TabListener to my fragments and don't have to do further changes.
I would like to use one Activity which holds several fragments and navigate among the fragments. For example, in the activity, there is a list view which is a fragment, when user select one item from the list, the view will navigate to another fragment, How could this be implemented?
I know there is a nice tutorial on the developer site, but it handles the tablet screen in which two pane layout with one list fragment and one detailed fragment showing in one screen. I only want to navigate among fragments without show two fragments in one screen.
Are there tutorials can teach me how to do it?
In the nutshell the answer to your question is to notify your host activity and then have your host activity replace your current fragment container using FragmentManager.
One of the approach is to make an interface in your first fragment, have your host activity register/listen (implement) to this interface and then have your FragmentManager to replace the container content with the second fragment on listener callback.
I'm not sure about tutorial but here is my snippet:
First Fragment
public class First extends Fragment{
private static onMySignalListener listener;
//call this function from whatever you like i.e button onClickListener
public void switchWindow() {
if(listener != null){
listener.onMySignal();
}
}
public interface onMySignalListener {
//customize this to your liking
//plain without argument
void onMySignal();
//with argument
void onMySignalWithNum(int mNum);
}
public static void setOnMySignalListener(onMySignalListener listener) {
First.listener = listener;
}}
Host Activity
public class HostActivity extends FragmentActivity implements onMySignalListener{
private final String ADD_TAG_IF_NECESSARY = "mTag";
#Override
public void onCreate(Bundle ssi) {
setContentLayout(R.layout.main);
FirstFragment.setOnMySignalListener(this);
}
#Override
public void onMySignal() {
//if you're using compat library
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
//initialize your second fragment
sfragment = SecondFragment.newInstance(null);
//replace your current container being most of the time as FrameLayout
transaction.replace(R.id.container, fragment, ADD_TAG_IF_NECESSARY);
transaction.commit();
}
#Override
public void onMySignalWithNum(int mNum) {
//you can do the same like the above probably with your own customization
}}
This is only an example on how you'd implement interface, kindly tidy it up by yourself. And please be noted though that this is not effective if you have a lot of fragment wanting to notify your host activity about something. doing so will lead you to implement various listener to your host activity.
I think this will be useful for you. It is example of two fragments in one screen works independently.
MainActivity :
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
Fragment newFragment = new Test();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.add(R.id.UprLayout, newFragment);
// transaction.addToBackStack(null);
transaction.commit();
Fragment newFragment2 = new TestRight();
FragmentTransaction transaction2 = getFragmentManager().beginTransaction();
transaction2.add(R.id.dwnLayout, newFragment2);
// transaction.addToBackStack(null);
transaction2.commit();
}
}
main_activity.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center|center_horizontal"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/UprLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical" />
<LinearLayout
android:id="#+id/dwnLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical" />
</LinearLayout>
Fragment Test :
public class Test extends Fragment {
TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.test, container, false);
return view;
}
}
Fragment TestRight :
public class TestRight extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.test_right, container, false);
return view;
}
#Override
public void onStart() {
super.onStart();
Button button = (Button)getActivity().findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Fragment newFragment = new Right2nd();
FragmentTransaction transaction = getFragmentManager()
.beginTransaction();
transaction.replace(R.id.dwnLayout, newFragment);
transaction.addToBackStack("aa");
transaction.commit();
//transaction.add(R.id.frag, newFragment).commit();
}
});
}
}
test.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="test"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="50sp" />
</LinearLayout>
test_right.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test right"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="45sp" />
</LinearLayout>
Fragment Right2nd :
public class Right2nd extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View vw = inflater.inflate(R.layout.right_2nd, container, false);
return vw;
}
}
right_2nd.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Right 2nd"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="50sp" />
</LinearLayout>
I know this is quite old question but this is currently implemented in Navigation Component https://developer.android.com/guide/navigation/
Here is a very nice tutorial about it. MULTIPLE FRAGMENTS STACK IN EACH VIEWPAGER TAB
I think ChildFragment
would do the job for you. Ignore the Tab ViewPager. It's performing the same thing in multiple tabs. Hope this helps a bit.
I'm new on Android and I try to make an application on Android Honeycomb 3.0
Here is my problem: I have 2 tabs in my action bar. Tab 1 uses fragments A and B and Tab 2 uses fragments C and D. When I load the application, the tab 1 is selected and fragments A and B are displayed. Then I click on tab 2 and it also works fine. But when I go back to tab 1, the app crashes and the following error is shown:
android.view.InflateException: Binary XML file line #6: Error inflating class fragment.....
.....
Caused by:java.lang.IllegalArgumentException: Binary XML file line #6: Duplicate
id 0x7f............. tag null or parent id 0x.......
here is my code:
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ActionBar bar = getActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayShowTitleEnabled(false);
ActionBar.Tab tab1 = bar.newTab().setText("tab 1");
ActionBar.Tab tab2 = bar.newTab().setText("tab 2");
Fragment frag1 = new FragmentOne();
Fragment frag2 = new FragmentTwo();
tab1.setTabListener(new MyTabListener(frag1));
tab2.setTabListener(new MyTabListener(frag2));
bar.addTab(tab1);
bar.addTab(tab2);
}
private class MyTabListener implements ActionBar.TabListener {
private Fragment mFragment;
// Called to create an instance of the listener when adding a new tab
public MyTabListener(Fragment fragment) {
mFragment = fragment;
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.add(R.id.fragments, mFragment);
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(mFragment);
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// do nothing
}
}
Fragment 1:
public class FragmentOne extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View mainView = inflater.inflate(R.layout.fragments, container, false);
return mainView;
}
}
fragments.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="ch.comem.test.FragmentOneA"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/idFragment_one_a"
android:layout_weight="30">
</fragment>
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="ch.comem.test.FragmentOneB"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/idFragment_one_b"
android:layout_weight="70">
</fragment>
Thanks for your help.
The main issue I see is that your FragmentOne class inflates fragments.xml, which itself contains references to two further fragments FragmentOne and FragmentTwo. This is not valid as Fragments can not contain other Fragments.