Dynamically changing the fragments inside a fragment tab host?
Basic concept- We can achieve this by creating a container. Each tab will be assigned with a specific container. Now when we need a new fragment then we will replace same using this container.
Kindly follow undermentioned code step by step to have better understanding.
Step-1: Create Tabs for your app. Say "Home.java". It will contain code for creating tabs using fragment.
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
import android.widget.TextView;
import app.drugs.talksooner.container.GoContainerFragment;
import app.drugs.talksooner.container.LearnContainerFragment;
import app.drugs.talksooner.container.MoreContainerFragment;
import app.drugs.talksooner.container.TalkContainerFragment;
import app.drugs.talksooner.container.WatchContainerFragment;
import app.drugs.talksooner.utils.BaseContainerFragment;
public class Home extends FragmentActivity {
private static final String TAB_1_TAG = "tab_1";
private static final String TAB_2_TAG = "tab_2";
private static final String TAB_3_TAG = "tab_3";
private static final String TAB_4_TAG = "tab_4";
private static final String TAB_5_TAG = "tab_5";
private FragmentTabHost mTabHost;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home);
initView();
}
private void initView() {
mTabHost = (FragmentTabHost)findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
// mTabHost.addTab(mTabHost.newTabSpec(TAB_1_TAG).setIndicator("Talk", getResources().getDrawable(R.drawable.ic_launcher)), TalkContainerFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec(TAB_1_TAG).setIndicator("Talk"), TalkContainerFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec(TAB_2_TAG).setIndicator("Learn"), LearnContainerFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec(TAB_3_TAG).setIndicator("Go"), GoContainerFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec(TAB_4_TAG).setIndicator("Watch"), WatchContainerFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec(TAB_5_TAG).setIndicator("More"), MoreContainerFragment.class, null);
/* Increase tab height programatically
* tabs.getTabWidget().getChildAt(1).getLayoutParams().height = 150;
*/
for (int i = 0; i < mTabHost.getTabWidget().getChildCount(); i++) {
final TextView tv = (TextView) mTabHost.getTabWidget().getChildAt(i).findViewById(android.R.id.title);
if (tv == null)
continue;
else
tv.setTextSize(10);
}
}
@Override
public void onBackPressed() {
boolean isPopFragment = false;
String currentTabTag = mTabHost.getCurrentTabTag();
if (currentTabTag.equals(TAB_1_TAG)) {
isPopFragment = ((BaseContainerFragment)getSupportFragmentManager().findFragmentByTag(TAB_1_TAG)).popFragment();
} else if (currentTabTag.equals(TAB_2_TAG)) {
isPopFragment = ((BaseContainerFragment)getSupportFragmentManager().findFragmentByTag(TAB_2_TAG)).popFragment();
} else if (currentTabTag.equals(TAB_3_TAG)) {
isPopFragment = ((BaseContainerFragment)getSupportFragmentManager().findFragmentByTag(TAB_3_TAG)).popFragment();
} else if (currentTabTag.equals(TAB_4_TAG)) {
isPopFragment = ((BaseContainerFragment)getSupportFragmentManager().findFragmentByTag(TAB_4_TAG)).popFragment();
} else if (currentTabTag.equals(TAB_5_TAG)) {
isPopFragment = ((BaseContainerFragment)getSupportFragmentManager().findFragmentByTag(TAB_5_TAG)).popFragment();
}
if (!isPopFragment) {
finish();
}
}
}
Your home.xml file
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="@+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" />
<android.support.v4.app.FragmentTabHost
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="0dip"
android:layout_height="0dip"
android:layout_weight="0" />
</android.support.v4.app.FragmentTabHost>
</LinearLayout>
Step-2: Define Base container fragment which will be helpful for backtracking and replacment of fragments "check out replaceFragement() ". Our class "BaseContainerFragment.java"
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import app.drugs.talksooner.R;
public class BaseContainerFragment extends Fragment {
public void replaceFragment(Fragment fragment, boolean addToBackStack) {
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
if (addToBackStack) {
transaction.addToBackStack(null);
}
transaction.replace(R.id.container_framelayout, fragment);
transaction.commit();
getChildFragmentManager().executePendingTransactions();
}
public boolean popFragment() {
Log.e("test", "pop fragment: " + getChildFragmentManager().getBackStackEntryCount());
boolean isPop = false;
if (getChildFragmentManager().getBackStackEntryCount() > 0) {
isPop = true;
getChildFragmentManager().popBackStack();
}
return isPop;
}
}
Step3: Now here I am considering for one fragment only hoping that rest can be handled by you in same fashion. Defining container Fragment class. Each tab will have specific container. Say TalkContainerFragment.java for first tab
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import app.drugs.talksooner.R;
import app.drugs.talksooner.Talk;
import app.drugs.talksooner.utils.BaseContainerFragment;
public class TalkContainerFragment extends BaseContainerFragment {
private boolean mIsViewInited;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.e("test", "tab 1 oncreateview");
return inflater.inflate(R.layout.container_fragment, null);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.e("test", "tab 1 container on activity created");
if (!mIsViewInited) {
mIsViewInited = true;
initView();
}
}
private void initView() {
Log.e("test", "tab 1 init view");
replaceFragment(new Talk(), false);
}
}
It's xml file. "container_fragment.xml" this xml container contains frameLayout. we will use this id to replace different Fragments.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container_framelayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
Your main class. "Talk.java"
public class Talk extends Fragment {
/** Define global variables over here */
//private ProgressDialog pDialog;
StaticApiList sal;
TalkModelAll tma;
JSONObject myJasonObject = null;
private ListView lv;
private ArrayList<TalkModelAll> m_ArrayList = null;
//ArrayList<String> stringArrayList = new ArrayList<String>();
TalkArrayAdapter taa;
Set<String> uniqueValues = new HashSet<String>();
TextView rowTextView = null;
boolean vivek = false;
int postid;
String title;
String thumsrc;
String largeimg;
String excert;
String description;
String cat;
String myUrl;
String jsonString;
int mCurCheckPosition;
String check_state = null;
String ccc;
LinearLayout myLinearLayout;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.talk, container, false);
Button btn = (Button) rootView.findViewById(R.id.your_btn_id);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//Here TalkDetail is name of class that needs to open
TalkDetail fragment = new TalkDetail();
// if U need to pass some data
Bundle bundle = new Bundle();
bundle.putString("title", m_ArrayList.get(arg2).title);
bundle.putString("largeimg", m_ArrayList.get(arg2).largeimg);
bundle.putString("excert", m_ArrayList.get(arg2).excert);
bundle.putString("description", m_ArrayList.get(arg2).description);
bundle.putString("cat", m_ArrayList.get(arg2).cat);
//bundle.putInt("postid", m_ArrayList.get(arg2).postid);
fragment.setArguments(bundle);
((BaseContainerFragment)getParentFragment()).replaceFragment(fragment, true);
}
});
return rootView;
}
}
That's it. You are good to go. The whole magic lies in calling R.id. instead of R.layout.
Cheers!
android, dynamically change a fragment inside a tab
Create a class acts like an fragment container.
for example:
public class FragmentContainer extends SherlockFragment implements OnBackStackChangedListener {
public static final String PARAM_CONTENT_FRAGMENT = "param_content_fragment";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.frag_container, null);
}
public void replaceContent(Class<? extends Fragment> clz, Bundle args) {
FragmentTransaction tx = getChildFragmentManager().beginTransaction();
tx.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
// save
Fragment curFrag = getChildFragmentManager().findFragmentById(R.id.fragment_content);
tx.addToBackStack(curFrag.getClass().getSimpleName());
// change
try {
Fragment newFragment = clz.newInstance();
newFragment.setArguments(args);
tx.replace(R.id.fragment_content, newFragment, clz.getClass().getSimpleName());
tx.commit();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void onResume() {
super.onResume();
Fragment f = getChildFragmentManager().findFragmentById(R.id.fragment_content);
if (f == null) {
Class<? extends Fragment> claz = (Class<? extends Fragment>) getArguments().getSerializable(
PARAM_CONTENT_FRAGMENT);
FragmentTransaction tx = getChildFragmentManager().beginTransaction();
try {
f = claz.newInstance();
f.setTargetFragment(this, 0);
tx.add(R.id.fragment_content, f);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
Several key point here:
Init the third tab with FragmentContainer.class and provide C.class as an fragment arguments. (argument key is PARAM_CONTENT_FRAGMENT)
onCreateView()
Just create a FrameLayout with id @+id/fragment_content, this is where we place child fragment.onResume()
Place child fragment into FrameLayout if not exists.replaceContent()
Call this method When Fragment-C wants to change it-self to Fragment-D.
In Frament-C, for example:
((FragmentContainer)getParentFragment() ).replaceContent( D.class, null );
android : using Tab view with dynamic fragment
You are trying to cast a TabHost to FragmentTabHost
try this
<android.support.v4.app.FragmentTabHost
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:orientation="horizontal" />
<FrameLayout
android:id="@+id/tabFrameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
</android.support.v4.app.FragmentTabHost >
Replace one fragment to another fragment in the TabHost
Check out my post. This contains all you need with basic.
Dynamically changing the fragments inside a fragment tab host?
fragment Repeat in tabhost when changing the tab
Hi I have fixed you point see below solution. Ideally your have to create one extra BaseContainerFragment. It has the framelayout. In next create the container fragment for each of your four static fragment. let's say I have two fragment with it related container fragment. see below code.
Original Fragment :
- AlertFragment.java
- ChatFragment.java
BaseContainerFragment.java
public class BaseContainerFragment extends Fragment {
public BaseContainerFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void replaceFragment(Fragment fragment, boolean addToBackStack) {
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
if (addToBackStack) {
transaction.addToBackStack(null);
}
transaction.replace(R.id.container_framelayout, fragment);
transaction.commit();
getChildFragmentManager().executePendingTransactions();
}
public boolean popFragment() {
boolean isPop = false;
if (getChildFragmentManager().getBackStackEntryCount() > 0) {
isPop = true;
getChildFragmentManager().popBackStack();
}
return isPop;
}
}
Container Fragment which extends the above BaseContainerFragment:
- AlertContainerFragment.java extends BaseContainerFragment.java
- ChatContainerFragment.java extends BaseContainerFragment.java
Now In your FragmentActivity you have to add ContainerFragment of each fragment inside FragmentTabHost.see the below code.
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
import android.view.Menu;
import android.view.MenuItem;
public class TestSukhwantTabHost extends FragmentActivity {
private FragmentTabHost mTabHost;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_sukhwant_tab_host);
mTabHost = (FragmentTabHost) findViewById(R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.tabFrameLayout);
mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator(null, getResources().getDrawable(R.drawable.ic_launcher)),AlertContainerFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("tab2").setIndicator(null, getResources().getDrawable(R.drawable.ic_launcher)),ChatContainerFragment.class, null);
mTabHost.getTabWidget().setStripEnabled(false);
mTabHost.setCurrentTab(0);
}
}
Now I post the Container Fragment code, this container fragment actually load our original Fragment. To load the fragment inside the fragment we used the container fragment method to replace the new fragment.
fragment_base_container.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container_framelayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
AlertContainerFragment.java
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class AlertContainerFragment extends BaseContainerFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_base_container, container, false);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initView();
}
private void initView() {
replaceFragment(new AlertFragment(), false);
}
}
ChatContainerFragment.java
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class ChatContainerFragment extends BaseContainerFragment {
public ChatContainerFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_base_container, container, false);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initView();
}
private void initView() {
replaceFragment(new ChatFragment(), false);
}
}
Original Fragment :
Below is AlertFragment.java
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
public class AlertFragment extends Fragment {
private Button framgnet1_button;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View mView = inflater.inflate(R.layout.fragment_alert, container, false);
framgnet1_button = (Button) mView.findViewById(R.id.framgnet1_button);
framgnet1_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
((BaseContainerFragment)getParentFragment()).replaceFragment(new DynamicAlertFramgnet(), false);
}
});
return mView;
}
}
ChatFragment.java
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
public class ChatFragment extends Fragment {
private Button button_chart_fragment;
public ChatFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View mView = inflater.inflate(R.layout.fragment_chat, container, false);
button_chart_fragment = (Button)mView.findViewById(R.id.button_chart_fragment);
button_chart_fragment.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
((BaseContainerFragment)getParentFragment()).replaceFragment(new DynamicChartFramgnet(), false);
}
});
return mView;
}
}
In above code what i had implemented, each original fragment has button when you click on it, it will load the new fragment.
Let me know if you have any question & pleas give your suggestion.
Thank you
Dynamically change visibility of fragment
This was one issue of a much larger problem I was facing with animating a nested fragment with ObjectAnimator
and then toggling its visibility.
To anyone trying to toggle the visibility of the fragment, it seems you can only change the affect change on the ViewGroup
included in the arguments for fragmentTransaction.add(R.id.fragment_container, fragment1);
. In this case it would've been fragment_container
. As this is the rootView, changing this was sufficient as I wanted the entire card to disappear.
Also worth noting this was supposed to be a child fragment. Consequently, using getFragmentManager
was incorrect. I avoided getChildFragmentManager
because I was receiving a series of errors that were becoming increasingly complex. After changing the ViewGroup
that I was adding my child fragment (changed it to a FrameLayout
within the parent Fragment
), this was quickly resolved.
Related Topics
Which Is the Best Way to Add a Button
How to Resize a Custom View Programmatically
The Completest Cocos2D-X Tutorial & Guide List
How to Set Custom Header in Volley Request
How Did Google Manage to Do This? Slide Actionbar in Android Application
How to Check Current Running Applications in Android
Android: Customize Application's Menu (E.G Background Color)
How to Launch Activity Only Once When App Is Opened for First Time
Unable Instantiate Android.Gms.Maps.Mapfragment
Android Activity Over Default Lock Screen
How to Set a Gradient Background in a Material Button from Material Components
How Does One Use Glide to Download an Image into a Bitmap
Sync Data Between Android App and Webserver
Com.Google.Android.Gms:Play-Services-Measurement-Base Is Being Requested by Various Other Libraries
Difference Between Android.App.Fragment and Android.Support.V4.App.Fragment