Dynamically Changing the Fragments Inside a Fragment Tab Host

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:

  1. Init the third tab with FragmentContainer.class and provide C.class as an fragment arguments. (argument key is PARAM_CONTENT_FRAGMENT)

  2. onCreateView()
    Just create a FrameLayout with id @+id/fragment_content, this is where we place child fragment.

  3. onResume()
    Place child fragment into FrameLayout if not exists.

  4. 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 :

  1. AlertFragment.java
  2. 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:

  1. AlertContainerFragment.java extends BaseContainerFragment.java
  2. 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



Leave a reply



Submit