I have the following FragmentActivity:
public class TabsActivity extends FragmentActivity {
private FragmentTabHost mTabHost;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tabs);
mTabHost = (FragmentTabHost)findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
mTabHost.addTab(mTabHost.newTabSpec("Home").setIndicator("Home", getResources().getDrawable(R.drawable.hometab)),HomeTab.class, null);
mTabHost.addTab(mTabHost.newTabSpec("Explore").setIndicator("Explore", getResources().getDrawable(R.drawable.exploretab)),ExploreTab.class, null);
mTabHost.addTab(mTabHost.newTabSpec("Info").setIndicator("Info", getResources().getDrawable(R.drawable.infotab)),InfoTab.class, null);
mTabHost.addTab(mTabHost.newTabSpec("Social").setIndicator("Social", getResources().getDrawable(R.drawable.socialtab)),SocialTab.class, null);
mTabHost.addTab(mTabHost.newTabSpec("Contact").setIndicator("Contact", getResources().getDrawable(R.drawable.contacttab)),ContactTab.class, null);
TabWidget tabWidget = mTabHost.getTabWidget();
tabWidget.setStripEnabled(false);
for(int i=0; i < tabWidget.getChildCount(); i++){
tabWidget.getChildAt(i).setBackgroundResource(R.drawable.tab_bg);
TextView tv = (TextView)tabWidget.getChildAt(i).findViewById(android.R.id.title);
tv.setTextColor(this.getResources().getColor(R.color.white));
}
mTabHost.setOnTabChangedListener(new OnTabChangeListener() {
#Override
public void onTabChanged(String tabId) {
Log.d("PAUL",tabId);
if(tabId=="Home"){
finish();
}
TabWidget tw = mTabHost.getTabWidget();
for(int i=0; i < tw.getChildCount(); i++){
TextView tabText = (TextView)tw.getChildAt(i).findViewById(android.R.id.title);
if(tabText.getText()==tabId){
tabText.setTextColor(TabsActivity.this.getResources().getColor(R.color.tcmgreen));
} else {
tabText.setTextColor(TabsActivity.this.getResources().getColor(R.color.white));
}
}
}
});
Intent intent = getIntent();
String tag = intent.getStringExtra("tab");
Log.d("DEBUG",tag);
mTabHost.setCurrentTabByTag(tag);
}
}
When the user taps the 'Explore' tab I get the following error: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. Here is my ExploreTab class:
public class ExploreTab extends Fragment {
private ArrayList<Level> levels;
private TCMSQLiteHelper sqliteHelper;
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
sqliteHelper = new TCMSQLiteHelper(this.getActivity());
levels = sqliteHelper.getAllLevels();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("DEBUG","Explore Created");
View v = inflater.inflate(R.layout.explorelist, container);
return v;
}
}
This doesn't make any sense to me because I don't see where there could be a problem of a view already being loaded. What am I missing here?
In onCreateView(), you should be passing in a third parameter, false. This third parameter specifies whether the layout should attached itself to the ViewGroup container.
From the Fragments documentation:
In this case, this is false because the system is already inserting the inflated layout into the container—passing true would create a redundant view group in the final layout.
Thus your code should be:
View v = inflater.inflate(R.layout.explorelist, container, false);
Related
I am using tab host with fragment, the following is the code of the main activity
public class HomeActivity extends Activity{
private FragmentTabHost mTabHost;
private ArrayList<CustomTabIndicator> mCustomTabIndicator;
private ArrayList<BaseFragment> mTabFragments;
private class CustomTabIndicator {
private int mIdResId;
private int mTitleResId;
private int mIconResId;
public CustomTabIndicator(int idResId, int titleResId, int iconResId) {
this.mIdResId = idResId;
this.mTitleResId = titleResId;
this.mIconResId = iconResId;
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_screen);
mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
initializeTabIndicatorsAndFragments();
addTabIndicatorsToTabHost();
}
private void initializeTabIndicatorsAndFragments() {
mCustomTabIndicator = new ArrayList<HomeActivity.CustomTabIndicator>();
mCustomTabIndicator.add(new CustomTabIndicator(R.string.tab_dashboard,
R.string.tab_dashboard, R.drawable.tab_dashboard));
mCustomTabIndicator.add(new CustomTabIndicator(R.string.tab_feed,
R.string.tab_feed, R.drawable.tab_feed));
mCustomTabIndicator.add(new CustomTabIndicator(R.string.tab_lists,
R.string.tab_lists, R.drawable.tab_lists));
mCustomTabIndicator.add(new CustomTabIndicator(R.string.tab_me,
R.string.tab_me, R.drawable.tab_me));
mTabFragments = new ArrayList<BaseFragment>();
mTabFragments.add(new DashboardFragment());
mTabFragments.add(new FeedFragment());
mTabFragments.add(new ListsFragment());
mTabFragments.add(new MeFragment());
}
private void addTabIndicatorsToTabHost() {
for (int i = 0; i < mCustomTabIndicator.size(); i++) {
mTabHost.addTab(
mTabHost.newTabSpec(
getString(mCustomTabIndicator.get(i).mIdResId))
.setIndicator(
createTabView(
this,
mCustomTabIndicator.get(i).mTitleResId,
mCustomTabIndicator.get(i).mIconResId)),
mTabFragments.get(i).getClass(), null);
}
}
#SuppressLint("InflateParams")
private View createTabView(final Context context, final int textStringId,
final int imageResId) {
View view = LayoutInflater.from(context).inflate(
R.layout.fragment_tab_header_image_text_layout, null);
ImageView tabIV = (ImageView) view.findViewById(R.id.tab_icon);
tabIV.setImageResource(imageResId);
//TextView titleTV = (TextView) view.findViewById(R.id.tab_title);
//titleTV.setText(textStringId);
return view;
}
}
This is the code of one of the fragements
public class MeFragment extends BaseFragment {
private View mFragementView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.i("AMIRA", "MeFragment - onCreateView");
mFragementView = inflater.inflate(R.layout.fragment_me_screen,container, false);
initializeUIComponents();
initializeUIComponentsData();
initializeUIComponentsTheme();
initializeUIComponentsAction();
return mFragementView;
}
}
The problem now that onCreateView called every time I change the tab, and take long time to render and draw the content of fragment.
So I have tried the following code
public class MeFragment extends BaseFragment {
private View mFragementView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (mFragementView != null) {
return mFragementView;
} else {
Log.i("AMIRA", "MeFragment - onCreateView");
mFragementView = inflater.inflate(R.layout.fragment_me_screen,container, false);
initializeUIComponents();
initializeUIComponentsData();
initializeUIComponentsTheme();
initializeUIComponentsAction();
return mFragementView;
}
}
}
and i got the following exception
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
so can anyone help here ?
First, about the java.lang.IllegalStateException,
You haven't initialized mFragmentView.
Say something like:
mFragmentView = (View)getActivity().findViewById(R.id.mFragmentView);
or:
mFragmentView = (View)getActivity().findFragmentById(R.id.mFragmentView);
Second about the Fragment changing every time you change the tab.
Try this:
add setRetainInstance(true); to the Fragments onAttach() or onCreateView().
Open for correction, as always!
Regards,
Edward Quixote.
What I have:
I have a fragment
I am using SherlockActionBar library
I have a FragmentTabHost in Fragment
What i want to know: I want to detect onClick event each tab and perform some action based on it
Fragment1.java:
public class Fragment1 extends SherlockFragment{
private FragmentTabHost mTabHost;
//Mandatory Constructor
public Fragment1() {
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment1,container, false);
mTabHost = (FragmentTabHost)rootView.findViewById(android.R.id.tabhost);
mTabHost.setup(getActivity(), getChildFragmentManager(), R.id.realtabcontent);
mTabHost.addTab(mTabHost.newTabSpec("fragmentb").setIndicator("Rating"),
RatingAscending.class, null);
mTabHost.addTab(mTabHost.newTabSpec("fragmentc").setIndicator("Price"),
PriceAscending.class, null);
mTabHost.addTab(mTabHost.newTabSpec("fragmentd").setIndicator("Distance"),
DistanceAscending.class, null);
return rootView;
}
}
I'm assuming what you want to do is detect when a specific tab has been clicked in your FragmentTabHost. This can be accomplished quite simply by adding a setOnTabChangedListener.
Here is an example:
FragmentTabHost t = new FragmentTabHost(getActivity());
t.setOnTabChangedListener(new OnTabChangeListener() {
#Override
public void onTabChanged(String tabId) {
// TODO your actions go here
}
});
}
I'm doing a small app with FragmentTabHost and two nested fragments. I need update the data of nested fragments from the fragment that contains the FragmentTabHost but for any reason I don't have the second fragment (second tab) when I do click in its tab then I get a null pointer exception.
Here it is a test of my code:
TabsTransactionFragment.java, this is the Fragment that contain the FragmentTabHost
public class TabsTransactionFragment extends Fragment implements
OnTabChangeListener{
private static final String TAB_ONE_TAG = "ONE";
private static final String TAB_TWO_TAG = "TW0";
private FragmentTabHost mTabHost;
private ArrayList<Integer> mData;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mData = new ArrayList<Integer>();
for (int i=0; i<10; i++) {
mData.add(i);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_tabs_transations,
container, false);
mTabHost = (FragmentTabHost) view.findViewById(android.R.id.tabhost);
mTabHost.setup(getActivity(), getChildFragmentManager(),
android.R.id.tabcontent);
mTabHost.addTab(
mTabHost.newTabSpec(TAB_ONE_TAG).setIndicator(
"ODD"),
ListDataFragment.class, null);
mTabHost.addTab(
mTabHost.newTabSpec(TAB_TWO_TAG).setIndicator(
"EVEN"),
ListDataFragment.class, null);
mTabHost.setOnTabChangedListener(this);
return mTabHost;
}
#Override
public void onDestroyView() {
super.onDestroyView();
mTabHost = null;
}
private void updateDataChildFragments(String tabName) {
if (mData != null) {
ListDataFragment listOneFragment =
(ListDataFragment) getChildFragmentManager().findFragmentByTag(TAB_ONE_TAG);
ListDataFragment listTwoFragment =
(ListDataFragment) getChildFragmentManager().findFragmentByTag(TAB_TWO_TAG);
if (tabName.equalsIgnoreCase(TAB_ONE_TAG)) {
ArrayList<Integer> odds = new ArrayList<Integer>();
for (int i=0; i<mData.size(); i++) {
if (mData.get(i) % 2 != 0) {
odds.add(mData.get(i));
}
}
listOneFragment.updateData(odds);
} else {
ArrayList<Integer> even = new ArrayList<Integer>();
for (int i=0; i<mData.size(); i++) {
if (mData.get(i) % 2 != 0) {
even.add(mData.get(i));
}
}
// Fragment two is null then crash...
listTwoFragment.updateData(even);
}
}
}
#Override
public void onTabChanged(String tabName) {
updateDataChildFragments(tabName);
}
}
Each tab contains a simple ListFragment like this:
public class ListDataFragment extends ListFragment {
private ArrayAdapter<Integer> mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new ArrayAdapter<Integer>(getActivity(), android.R.layout.simple_list_item_1);
setListAdapter(mAdapter);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
return super.onCreateView(inflater, parent, savedInstanceState);
}
public void updateData(ArrayList<Integer> data) {
mAdapter.addAll(data);
mAdapter.notifyDataSetChanged();
}
}
And layout fragment_tabs_transations.xml is the structure of android.support.v4.app.FragmentTabHost with a linearLayout, TabWidget and FrameLayout.
I have tried many things and ways but I haven't got to pass data to the second fragment once I do click... I have tried to created first both fragment and add to FragmentTabHost but I didn't get neither...
I think the problem it is the second fragment it is attached to FragmentTabHost after onTagChanged and that is because I can not find it... But I don't understand this behaviour... :S.
Anybody can help me? Or know any solution to pass data to second Fragment before do click in its tab?
Many thanks!!
I am having an issue getting the view to change on a tabhost - when I select a tab the content stays blank.
From what I can tell, onCreateView is not being called on the child Fragments. onMenuCreate runs fine because the menu changes like it is supposed to.
public class PatientTabFragment extends Fragment {
private FragmentTabHost mTabHost;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mTabHost = new FragmentTabHost(getActivity());
mTabHost.setup(getActivity(), getChildFragmentManager());
mTabHost.addTab(mTabHost.newTabSpec("simple").setIndicator("Info"),
NewPatientFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("contacts").setIndicator("Notes"),
NoteListFragment.class, null);
return mTabHost;
}
#Override
public void onDestroyView() {
super.onDestroyView();
mTabHost = null;
}
}
according to the docs:
Special TabHost that allows the use of Fragment objects for its tab
content. When placing this in a view hierarchy, after inflating the
hierarchy you must call setup(Context, FragmentManager, int) to
complete the initialization of the tab host.
(emphasis mine)
So I suggest somethong like this:
public class PatientTabFragment extends Fragment {
private FragmentTabHost mTabHost;
private boolean createdTab = false;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mTabHost = new FragmentTabHost(getActivity());
mTabHost.setup(getActivity(), getChildFragmentManager());
mTabHost.addTab(mTabHost.newTabSpec("simple").setIndicator("Info"),
NewPatientFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("contacts").setIndicator("Notes"),
NoteListFragment.class, null);
return mTabHost;
}
public void onResume(){
if (!createdTab){
createdTab = true;
mTabHost.setup(getActivity(), getActivity().
getSupportedFragmentManager());
}
}
#Override
public void onDestroyView() {
super.onDestroyView();
mTabHost = null;
}
}
Now we can use TabLayout and ViewPager do those things.This is a good guide to use it.Here is my code:
viewPager=(NonSwipeableViewPager)view.findViewById(R.id.circleresdyn_viewpager);
tabLayout=(TabLayout)view.findViewById(R.id.circleresdyn_tablayout);
if (viewPager != null) {
Adapter adapter = new Adapter(((AppCompatActivity)activity).getSupportFragmentManager());
ContentFragment con=new ContentFragment();
con.setArguments(bundleForFramgnet);
MemberFragment memberFragment=new MemberFragment();
memberFragment.setArguments(bundleForFramgnet);
CirResDynTileFragment cirResDynTileFragment=new CirResDynTileFragment();
cirResDynTileFragment.setArguments(bundleForFramgnet);
adapter.addFragment(cirResDynTileFragment, "Tab1");
adapter.addFragment(con, "Tab2");
adapter.addFragment(memberFragment, "Tab3");
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(3);
tabLayout.setTabGravity(TabLayout.GRAVITY_CENTER);
tabLayout.setupWithViewPager(viewPager);
tabLayout.getTabAt(0).select();
}
Check this peace of code. It may help you:
import android.app.Fragment;
public class Change_password extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.change_password, container,false);
setTabs();
return rootView;
}
private void setTabs() {
try {
addTab("Airlines", R.drawable.tab_home, HomeActivity_bkp.class);
addTab("Advance Search", R.drawable.tab_search,
AdvanceSearchAcitivty.class);
addTab("Booking", R.drawable.tab_home, Booking.class);
addTab("Settings", R.drawable.tab_search, SettingAcitivty.class);
} catch (Exception e) {
Toast.makeText(getApplicationContext(), e.toString(),
Toast.LENGTH_LONG).show();
// TODO: handle exception
}
}
private void addTab(String labelId, int drawableId, Class<?> c) {
TabHost tabHost = getTabHost();
Intent intent = new Intent(this, c);
TabHost.TabSpec spec = tabHost.newTabSpec("tab" + labelId);
View tabIndicator = LayoutInflater.from(this).inflate(
R.layout.tab_indicator, getTabWidget(), false);
TextView title = (TextView) tabIndicator.findViewById(R.id.title);
title.setText(labelId);
ImageView icon = (ImageView) tabIndicator.findViewById(R.id.icon);
icon.setImageResource(drawableId);
spec.setIndicator(tabIndicator);
spec.setContent(intent);
tabHost.addTab(spec);
}
My FragmentActivity loops and creates numerous Fragments, each with `new TextView. After some help, I have this:
FragmentActivity.java
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
for (int j=0; j<positionsCount; j++) {
...
mTabsAdapter = new PositionFragmentAdapter(this, mViewPager);
mTabsAdapter.addTab(bar.newTab().setText("My Tab Name"), Fragment.class, args);
}
}
Fragment.java
public class Fragment extends Fragment {
private static int id = 0;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
LinearLayout mLinearLayout = new LinearLayout(getActivity());
TextView mTextView = new TextView(getActivity());
mTextView.setId(id);
id++;
mLinearLayout.addView(mTextView);
return mLinearLayout;
}
#Override
public void onStart() {
super.onStart();
Bundle args = getArguments();
id.setText(args.get("posName").toString()); // ERROR HERE: "Cannot invoke setText(String) from primitive type int"
}
}
How can I stop the error?
Edit 2:
06-11 12:54:53.843: E/AndroidRuntime(21005): java.lang.NullPointerException
06-11 12:54:53.843: E/AndroidRuntime(21005): at com.example.guide.Fragment.onStart(Fragment.java:33)
06-11 12:54:53.843: E/AndroidRuntime(21005): at android.support.v4.app.Fragment.performStart(Fragment.java:1484)
...
You're calling setText on an integer, not a TextView. Instead of this
id.setText(args.get("posName").toString());
do this:
mTextView.setText(args.get("posName").toString());
Note that you will have to make your TextView an instance variable of the Fragment, so that it'll be accessible from other methods.
public class Fragment extends Fragment {
TextView mTextView;