I have one fragment in which I am setting tabhost widget with three tabs each have fragment.
When ever first time I come to this fragment first tab not loading first child fragment but after click on another tab and return on first tab then it is loading first child fragment.
Also I have little confusion that what will be the third parameter in tabhost.setup() method.It should be the layout of parent fragment which handles tabs or the layout of first child fragment.
Here is my code for parent fragment
public class MyStoreFragment extends Fragment implements TabHost.OnTabChangeListener {
private FragmentTabHost mTabHost;
View rootView;
public MyStoreFragment() {
// Empty constructor required for fragment subclasses
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// rootView = inflater.inflate(R.layout.fragment_my_store,container, false);
// mTabHost = (FragmentTabHost)rootView.findViewById(android.R.id.tabhost);
mTabHost = new FragmentTabHost(getActivity());
// mTabHost.setup(getActivity(), getChildFragmentManager(), android.R.id.tabcontent);
mTabHost.setup(getActivity(), getChildFragmentManager(),R.layout.fragment_my_store);
mTabHost.addTab(mTabHost.newTabSpec("new").setIndicator("NEW"), NewBookFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("trending").setIndicator("TRENDING"),FragmentTab.class, null);
mTabHost.addTab(mTabHost.newTabSpec("explore").setIndicator("EXPLORE"),FragmentTab.class, null);
mTabHost.setCurrentTab(0);
mTabHost.setOnTabChangedListener(this);
mTabHost.getTabWidget().getChildAt(0).setBackgroundColor(Color.WHITE);
mTabHost.getTabWidget().getChildAt(1).setBackgroundColor(Color.parseColor("#FCF4E7"));
mTabHost.getTabWidget().getChildAt(2).setBackgroundColor(Color.parseColor("#FCF4E7"));
mTabHost.getTabWidget().getChildAt(0)
.setBackgroundColor(Color.parseColor("#DF4426"));
TextView tv1 = (TextView) mTabHost.getTabWidget().getChildAt(0).findViewById(android.R.id.title);
tv1.setTextColor(Color.parseColor("#F6CFC2"));
TextView tv2 = (TextView) mTabHost.getTabWidget().getChildAt(1).findViewById(android.R.id.title);
tv2.setTextColor(Color.parseColor("#E03C20"));
TextView tv3 = (TextView) mTabHost.getTabWidget().getChildAt(2).findViewById(android.R.id.title);
tv3.setTextColor(Color.parseColor("#E03C20"));
// TODO To set height and width properly of tab widget
ViewGroup.LayoutParams params = mTabHost.getTabWidget().getChildAt(0).getLayoutParams();
// params.width = 128;
params.height = 50;
mTabHost.getTabWidget().getChildAt(0).setLayoutParams(params );
mTabHost.getTabWidget().getChildAt(1).setLayoutParams(params );
mTabHost.getTabWidget().getChildAt(2).setLayoutParams(params );
// for (int i = 0; i < mTabHost.getTabWidget().getChildCount(); i++) {
// TextView tv = (TextView) mTabHost.getTabWidget().getChildAt(i).findViewById(android.R.id.title);
// tv.setTextColor(Color.parseColor("#DA4426"));
// }
return mTabHost;
}
Related
I'm trying to create tabs based on an array returned by the database. However, I'm getting the following error.
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setVisibility(int)' on a null object reference
The code that I'm using is below, the array subAreas has already 3 values.
public class ExtintorFragment extends Fragment {
private LinearLayout ll;
private TabHost tabs;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ll = (LinearLayout) inflater.inflate(R.layout.fragment_criterios, container, false);
setHasOptionsMenu(true);
tabs = (TabHost) ll.findViewById(R.id.tabHost);
tabs.setup();
String[] subAreas;
EquipamentosSubAreaDbAdapter mDb = new EquipamentosSubAreaDbAdapter(getContext());
mDb.open();
subAreas = mDb.getSubareasEquipamento("Extintores");
mDb.close();
for (int i = 0; i < subAreas.length; i++) {
TabHost.TabSpec spec = tabs.newTabSpec(subAreas[i]);
spec.setIndicator(subAreas[i]);
spec.setContent(new TabHost.TabContentFactory() {
#Override
public View createTabContent(String tag) {
return null;
}
});
tabs.addTab(spec);
}
return ll;
}
#Override
public void onActivityCreated (Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
}
}
Also, could you give me tips to create a listView as TabContent.
Thank you
You can't inflate the view while there are no tabs in said view. It will attempt to set the first tab as what should be shown in the fragment and since you haven't added any tabs to the view, it results in a null pointer.
Try the following code inside onCreateView. Of course, you'll have to parameterize addTab to the values you want.
mTabHost = new FragmentTabHost(getActivity());
mTabHost.setup(getActivity(), getChildFragmentManager(), android.R.id.tabcontent);
mTabHost.addTab(
mTabHost.newTabSpec("Tab 1").setIndicator("Tab 1")
, DefaultContentFragment.class
, null);
mTabHost.addTab(
mTabHost.newTabSpec("Tab 2").setIndicator("Tab 2")
, DefaultContentFragment.class
, null);
mTabHost.addTab(
mTabHost.newTabSpec("Tab 3").setIndicator("Tab 3")
, DefaultContentFragment.class
, null);
return mTabHost;
I want to create a custom tabhost, which contains an icon also. For the purpose I need to use a method. This method works fine, but the tab indicator is disappeared from the tab.
The code for the tab indicator is:
private View getTabIndicator(Context context, String title, int icon) {
View view = LayoutInflater.from(context).inflate(R.layout.tab_layout, null);
ImageView iv = (ImageView) view.findViewById(R.id.imageView);
iv.setImageResource(icon);
TextView tv = (TextView) view.findViewById(R.id.textView);
tv.setText(title);
return view;
}
Main Activity is :
public class MainActivity extends AppCompatActivity {
private FragmentTabHost mTabHost;
Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Setting up a toolbar for the navigation purpose.
toolbar = (Toolbar)findViewById(R.id.app_bar);
toolbar.setTitle(" Call History Control");
toolbar.setLogo(R.mipmap.ic_launcher);
setSupportActionBar(toolbar);
// The fragments management is done here
// mTabHost = (FragmentTabHost)findViewById(android.R.id.tabhost);
// mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
//
// mTabHost.addTab(
// mTabHost.newTabSpec("home").setIndicator(" HOME"),
// Home.class, null);
// mTabHost.addTab(mTabHost.newTabSpec("settings").setIndicator(" SETTINGS"),
// Settings.class, null);
//
// mTabHost.addTab(mTabHost.newTabSpec("about").setIndicator(" ABOUT"),
// About.class, null);
mTabHost.addTab(
mTabHost.newTabSpec("home").setIndicator(getTabIndicator(getApplicationContext(),"HOME",R.drawable.ic_home)),
Home.class, null);
mTabHost.addTab(mTabHost.newTabSpec("settings").setIndicator(getTabIndicator(getApplicationContext(),"SETTINGS",R.drawable.ic_settings)),
Settings.class, null);
mTabHost.addTab(mTabHost.newTabSpec("about").setIndicator(getTabIndicator(getApplicationContext(),"ABOUT",R.drawable.ic_account)),
About.class, null);
}
The screeen shot is:
I need some help in setting the background colour using code for my current fragment. The fragment is created on selecting a particular tab.
Below is my main activity code
public class TabActionBarActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the text and background colour
setTheme(R.style.MyTheme);
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
String label6 = getResources().getString(R.string.label6);
tab = actionBar.newTab();
tab.setText(label6);
TabListener<Tab6Fragment> tl6 = new TabListener<Tab6Fragment>(this,
label6, Tab6Fragment.class);
tab.setTabListener(tl6);
actionBar.addTab(tab);
String label7 = getResources().getString(R.string.label7);
tab = actionBar.newTab();
tab.setText(label7);
TabListener<Tab7Fragment> tl7 = new TabListener<Tab7Fragment>(this,
label7, Tab7Fragment.class);
tab.setTabListener(tl7);
actionBar.addTab(tab);
}
Now the code for the Tab7Fragment class looks like this
public class Tab7Fragment extends Fragment {
TextView tv1;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ScrollView sv = new ScrollView(this.getActivity());
LinearLayout ll = new LinearLayout(this.getActivity());
ll.setOrientation(LinearLayout.VERTICAL);
sv.addView(ll);
TextView tv = new TextView(this.getActivity());
tv.setText("Dynamic layouts ftw!");
ll.addView(tv);
EditText et = new EditText(this.getActivity());
et.setText("weeeeeeeeeee~!");
ll.addView(et);
Button b = new Button(this.getActivity());
b.setText("I don't do anything, but I was added dynamically. :)");
ll.addView(b);
for(int i = 0; i < 20; i++) {
CheckBox cb = new CheckBox(this.getActivity());
cb.setText("I'm dynamic!");
ll.addView(cb);
}
return this.getView();
}
}
Now how can i set the view for this fragment?
this.getActivity().setContentView(sv);
I know the above method is incorrect. But i need to set the content view with the scrollview layout. and another question is how do i set the background colour for this view?(using setBackgroundColor()?
Try this code in your onCreateView():
View view = inflater.inflate(R.layout.your_fragment_layout, container, false);
Then dont forget to return the view that you just inflated to the android runtime.
Remove return this.getView(); and add return view;
To set background color :
sv.setBackgroundColor(getRessources().getColors(R.color.yourcolor));
To inflate layout into a fragment, you need to return a View from onCreateView :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.your layout, container, false);
}
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);
Is it possible to update the TabWidget icons/indicators? If so, how, when you are creating TabContent through intents?
Edits below with answer thanks to #Bart
Generic code:
MainActivity:
public class TestActivity extends TabActivity {
public int i;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//TabHost mTabHost = (TabHost) findViewById(android.R.id.tabhost);
TabHost mTabHost = getTabHost();
mTabHost.addTab(mTabHost.newTabSpec("tab1").setContent(
new Intent(this, OneActivity.class)).setIndicator("One"));
mTabHost.addTab(mTabHost.newTabSpec("tab2").setContent(
new Intent(this, TwoActivity.class)).setIndicator("Two"));
changeTitle(0, 20);
}
public void changeTitle(int cnt, int i){
View v = getTabWidget().getChildAt(cnt);
TextView tv = (TextView) v.findViewById(android.R.id.title);
tv.setText("One ("+i+")");
}
}
OneActivity (ChildActivity):
public class OneActivity extends Activity {
TextView tv;
Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.one);
tv = (TextView) findViewById(R.id.tv);
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int i = Integer.parseInt((String) tv.getText());
i++;
tv.setText(""+i);
TestActivity parent = OneActivity.this.getParent();
parent.changeTitle(0,i);
}
});
}
}
I'd like to show the number in the Tab's title
It is possible but it is a bit of tricky:
ViewGroup vg = (ViewGroup) getTabHost().getTabWidget().getChildAt(0);
TextView tv = (TextView) vg.getChildAt(1);
You should pay attention to indices while calling getChildAt(). The best way is always to debug and check.
Since 1.6 TabWidget has a method getChildTabViewAt thanks to which you could skip the first line and write:
ViewGroup vg = (ViewGroup) getTabHost().getTabWidget().getChildTabViewAt(0);
I attach also source code of Android SDK to show how TabWidget icons are built:
View tabIndicator = inflater.inflate(R.layout.tab_indicator,
mTabWidget, // tab widget is the parent
false); // no inflate params
final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
tv.setText(mLabel);
final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.icon);
iconView.setImageDrawable(mIcon);
As you can see, it contains a TextView and ImageView.
Try get the imageView like this
ImageView v = (ImageView)tabActivity.getTabHost().getTabWidget().getChildTabViewAt(i).findViewById(android.R.id.icon);
v.setImageDrawable(getResources().getDrawable(R.drawable.newIcon));
Given a arrays for titles and icons
for (int i = 0; i < numTabs; i++ ) {
TabSpec spec = host.newTabSpec(String.valueOf(i)); //sets tab index
Drawable icon = res.getDrawable(icons[i]); //sets the icon
// set tab text and icon
spec.setIndicator(titles[i], icon); //sets the title
host.addTab(spec);
}