FragmentManager with FragmentTabHost - android

I have an Activity that has a ViewPager with four Fragments. One of those Fragments must have two tabs inside of it so I tried FragmentTabHost.
private FragmentTabHost fragmentTabHost;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_zbritjet, container, false);
fragmentTabHost = (FragmentTabHost) view.findViewById(android.R.id.tabhost);
fragmentTabHost.setup(view.getContext(), getFragmentManager(), android.R.id.tabcontent);
fragmentTabHost.addTab(fragmentTabHost.newTabSpec("tab_ofertat").setIndicator("Ofertat"), OfertatItems.class, null);
fragmentTabHost.addTab(fragmentTabHost.newTabSpec("tab_bizneset").setIndicator("Bizneset"), BiznesetItems.class, null);
return view;
}
The problem is that android is throwing
java.lang.IllegalStateException: FragmentManager is already executing transactions
Stack trace:
android.support.v4.app.FragmentManagerImpl.ensureExecReady(FragmentManager.java:1946)
android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1992)
android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:762)
android.support.v4.app.FragmentTabHost.onAttachedToWindow(FragmentTabHost.java:289)

Try getChildFragmentManager() instead of getFragmentManager().
From the docs:
Return a private FragmentManager for placing and managing Fragments inside of this Fragment.

Related

Viewpager returning null in fragment

I have a fragment that holds a viewpager and tablayout. I can access the tablayout from the fragment but when I try to do the same for the view pager it always returns null
//this is a method on the pagefragment
public override void OnActivityCreated(Bundle savedInstanceState)
{
base.OnActivityCreated(savedInstanceState);
tabs = this.View.FindViewById<TabLayout>(Resource.Id.mytab);
vp = (ViewPager) Activity.FindViewById(Resource.Id.myviewpage);
SetUpViewPager(vp);
tabs.SetupWithViewPager(vp);
}
vp alway returns null so the app crashes when it get to SetUpViewPager(vp) but the the tabs is accessible
I have a fragment that holds a viewpager and tablayout.
Problem is that you are hosting your ViewPager in a fragment, but you're trying to find it in the Activity. In the Fragment, you can code like this:
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var view = inflater.Inflate(Resource.Layout.fragment1, container, false);
var tabs = view.FindViewById<TableLayout>(Resource.Id.mytab);
var vp1 = (ViewPager)view.FindViewById(Resource.Id.myviewpage);
return view;
}

Android FragmentTabHost how to get a reference to fragment in tab

I have a Fragment which implements FragmentTabHost and creates a couple of tabs each of which has a Fragment. I am trying to get a reference to one of these Fragments, but am drawing a blank as to how.
public class TabFragment extends Fragment {
private FragmentTabHost mTabHost;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mTabHost = new FragmentTabHost(getActivity());
mTabHost.setup(getActivity(), getChildFragmentManager(), R.id.container);
addTab("study","Study",StudyFragment.class);
addTab("tab2","Tab 2",Tab2Fragment.class);
return mTabHost;
}
private <T extends Fragment> void addTab(String sTag, String sTitle, Class<T> c) {
View tabView = createTabView(getActivity(),sTitle);
mTabHost.addTab(mTabHost.newTabSpec(sTag).setIndicator(tabView),
c, null);
}
public StudyFragment getStudyFragment() {
// not working as fragment has not been tagged
return getChildFragmentManager().findFragmentByTag("study");
}
So the question is how do I either tag the study fragment or return a reference to it when it is created?
I've seen a couple of solutions which suggest overriding onAttachFragment, but that is for FragmentActivity not Fragment
To get a fragment, you can set an id to your fragment, then use this:
FragmentManager manager = getSupportFragmentManager();
MyFragment myFragment = (MyFragment)manager.findFragmentById(R.id.MyFragment);
Ok so you have to add tabs using TabHost.TabSpec like that:
tabHost = (FragmentTabHost)mainView.findViewById(android.R.id.tabhost);
tabHost.setup(this, getSupportFragmentManager(), android.R.id.tabcontent);
TabHost.TabSpec tabOne = tabHost.newTabSpec("One").setContent(R.id.fragOne);
TabHost.TabSpec tabTwo = tabHost.newTabSpec("Two").setContent(R.id.fragTwo);
tabHost.addTab(tabOne, TabOne.class, savedInstanceState);
tabHost.addTab(tabTwo, TabTwo.class, savedInstanceState);
In this code R.id.fragOne and R.id.fragTwo refers to two FrameLayout defined in the activity layout.
If you dont have xml layout you can define programmatically a new FrameLayout with an id for each tab.

In Tab bar to go an other fragment in the same tab?

I am using FragmentAcitvity in my Tab Bar .
I am able to load a new fragment on tab changed.
But i have a problem Because i have many activties in one tab.
for example i have 2 tabs :
Tab1 , Tab2. and i have in
Tab1 : activityA-->activityB---ActivityC
and
Tab2: activityF
how i can achieve this.
my code is here.
Main Class
public class MainActivity extends FragmentActivity {
private FragmentTabHost mTabHost;
Context context=this;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
mTabHost.setup(context, getSupportFragmentManager(), android.R.id.tabcontent);
mTabHost.addTab(
mTabHost.newTabSpec("Records").setIndicator("")), ActiovityA.class, null);
mTabHost.addTab(
mTabHost.newTabSpec("tab2").setIndicator("tab2"),acitvityf.class, null);
mTabHost.setCurrentTab(0);
}
}
my acitvityA is here
public class acitvityA extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.acitvitya_xml, container, false);
return v;
}
}
myactivityB is
public class acitvityb extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.acitvityb_xml, container, false);
return v;
}
}
how i can solve this ?what is missing here.
You might have to do a little bit of homework yourself, but i could give you a hint that could help you.
You have the tabs set well. What you could do is, When the transition from Activity1 to 2 takes place, hide the last fragment from the stack, and then show the Activity 2 fragment in tab one (here you will push the fragment into the stack and show it). Maintain a stack of the fragments you are using, and compare an instance of which fragment has been pushed or popped from the stack to bring back the correct fragment.
Its a combination of fragment transactions add, hide, and stack push and pop.
Stack is needed for back press events.
Hope that helps.

How does the container get passed to a fragment?

I'm attempting to understand someone else's code. They are using fragments (which I'm rather hazy on).
I know that a fragment starts up with onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState .. but I can't fathom where the "container" was set up.
where should I look?
container is handled by the Android framework, it typically refers to View passed by id in methods like FragmentTransaction's add(int containerViewId, Fragment fragment) or replace(int containerViewId, Fragment fragment).
For example, this is from the Developer's Guide:
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
v = inflater.inflate(R.layout.news_list, container, false);
return v;
}
The layout news_list is for this fragment.

Set new layout in fragment

I'm trying to change the layout of a fragment during runtime under a particular condition.
The initial layout in inflated within the onCreateView():
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.cancel_video, null);
}
Then sometime later within the fragment code I would like to replace the initial layout with some other layout.
I've tried a few things so far; this is the latest that I have:
private void Something(){
if(checkLicenseStatus(licenseStatus, statusMessage)){
View vv = View.inflate(getActivity(), R.layout.play_video, null);
//more code
}
}
How can I accomplish this?
You cannot replace the fragment's layout once it is inflated. If you need conditional layouts, then you either have to redesign your layout and break it down into even smaller elemens like Fragments. Alternatively you can group all the layout elements into sub containers (like LinearLayout), then wrap them all in RelativeLayout, position them so they overlay each other and then toggle the visibility of these LinearLayouts with setVisibility() when and as needed.
Yes, I have done this in following way. When I need to set a new layout(xml), the following code snippet should be executed.
private View mainView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup containerObject, Bundle savedInstanceState){
super.onCreateView(inflater, containerObject, savedInstanceState);
mainView = inflater.inflate(R.layout.mylayout, null);
return mainView;
}
private void setViewLayout(int id){
LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mainView = inflater.inflate(id, null);
ViewGroup rootView = (ViewGroup) getView();
rootView.removeAllViews();
rootView.addView(mainView);
}
Whenever I need to change the layout I just call the following method
setViewLayout(R.id.new_layout);
Use a FragmentTransaction through the FragmentManger
FragmentManager fm = getFragmentManager();
if (fm != null) {
// Perform the FragmentTransaction to load in the list tab content.
// Using FragmentTransaction#replace will destroy any Fragments
// currently inside R.id.fragment_content and add the new Fragment
// in its place.
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fragment_content, new YourFragment());
ft.commit();
}
The code for the class YourFragment is just a LayoutInflater so that it returns a view
public class YourFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.your_fragment, container, false);
return view;
}
}
I will change whole layout. You can change only a specific portion of your layout.
Add a root FrameLayout in your_layout.xml, it contains nothing.
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fl_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Set your content in the java code.
ViewGroup flContent = findViewById(R.id.fl_content);
private void setLayout(int layoutId) {
flContent.removeAllViews();
View view = getLayoutInflater().inflate(layoutId, flContent, false);
flContent.addView(view);
}
You can change layoutId free at some point.
If you have some listeners, you must set again.

Categories

Resources