Basically all i have is tablayout with each tab containing a webview. From the settings menu I enable the user to add or remove tabs. when this is done I need to call pageradapter.notifydatasetchanged(); however doing this all the webview starts to refresh . My question is, Is there a way to avoid this ? I just want the tab to be added or deleted without affecting other tabs.
case "Yahoo":
if (!fragmentList.contains(fragYahoo)) {
if (tabYahoo == null) {
tabYahoo = tabLayout.newTab().setText("Yahoo").setTag("Yahoo");
}
tabLayout.addTab(tabYahoo);
fragYahoo = NewsFragment.newInstance("http://www.Yahoo.com/");
fragmentList.add(fragYahoo);
navigationView.getMenu().findItem(R.id.Yahoo).setVisible(true);
}
break;
case "stackoverflow":
if (!fragmentList.contains(fragstackoverflow)) {
if (tabstackoverflow == null) {
tabstackoverflow = tabLayout.newTab().setText("stackoverflow").setTag("stackoverflow");
}
tabLayout.addTab(tabstackoverflow);
fragstackoverflow = NewsFragment.newInstance("http://www.stackoverflow.com/");
fragmentList.add(fragstackoverflow);
navigationView.getMenu().findItem(R.id.stackoverflow).setVisible(true);
}
pagerAdapter.notifyDataSetChanged();
pageradapter initialization
public List<Fragment> fragmentList = new ArrayList<>();
mViewPager = (ViewPager) findViewById(R.id.pager);
pagerAdapter = new TabPagerAdapter(getSupportFragmentManager(), fragmentList);
mViewPager.setAdapter(pagerAdapter);
mViewPager.setOffscreenPageLimit(pagerAdapter.getCount()-1);
I did not test, but you can use TabLayout#setupWithViewPager(viewPager, false);.
The second parameter is autoRefresh:
* #param autoRefresh whether this layout should refresh its contents if the given ViewPager's
* content changes
Navigation drawer contains 4 items and each item contains 4 actionbar tabs ,while switching between menu items means if i click on menu item 2 then number of actionbar items changing to 8 and if i click on menu item3 then number of actionbar tabs changing to 12 ,how o stop this repeation of tabs.here is my code
public class TopicsFragment extends Fragment {
public TopicsFragment() {
}
// Declare Tab Variable
ActionBar.Tab AllTopics, NewContent, StaffPicks, Popular, Recommended;
Fragment fragmentTab1 = new FragmentTab1();
Fragment fragmentTab2 = new FragmentTab2();
Fragment fragmentTab3 = new FragmentTab3();
Fragment fragmentTab4 = new FragmentTab2();
Fragment fragmentTab5 = new FragmentTab1();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup tabs,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_topics, tabs, false);
ActionBar actionBar = ((ActionBarActivity) getActivity())
.getSupportActionBar();
// Create Actionbar Tabs
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Set Tab Icon and Titles
AllTopics = actionBar.newTab().setIcon(R.drawable.tab1);
NewContent = actionBar.newTab().setIcon(R.drawable.tab1);
StaffPicks = actionBar.newTab().setIcon(R.drawable.tab1);
Popular = actionBar.newTab().setIcon(R.drawable.tab1);
Recommended = actionBar.newTab().setIcon(R.drawable.tab1);
// Set Tab Listeners
AllTopics.setTabListener(new TabListener(fragmentTab1));
NewContent.setTabListener(new TabListener(fragmentTab2));
StaffPicks.setTabListener(new TabListener(fragmentTab3));
Popular.setTabListener(new TabListener(fragmentTab2));
Recommended.setTabListener(new TabListener(fragmentTab2));
// Add tabs to actionbar
actionBar.addTab(AllTopics);
actionBar.addTab(NewContent);
actionBar.addTab(StaffPicks);
actionBar.addTab(Popular);
actionBar.addTab(Recommended);
return rootView;
}
}
That problem is that you are adding tabs constantly when you go back in your TopicsFragment which will call onCreateView again and executing the adding of tabs to the actionbar thus adding another set of tabs to the current tabs.
solution:
you need to check first if the number of tabs is zero in your actionbar.
sample:
actionBar.removeAllTabs();
if(actionBar.getTabCount() == 0)
{
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Set Tab Icon and Titles
AllTopics = actionBar.newTab().setIcon(R.drawable.tab1);
NewContent = actionBar.newTab().setIcon(R.drawable.tab1);
StaffPicks = actionBar.newTab().setIcon(R.drawable.tab1);
Popular = actionBar.newTab().setIcon(R.drawable.tab1);
Recommended = actionBar.newTab().setIcon(R.drawable.tab1);
// Set Tab Listeners
AllTopics.setTabListener(new TabListener(fragmentTab1));
NewContent.setTabListener(new TabListener(fragmentTab2));
StaffPicks.setTabListener(new TabListener(fragmentTab3));
Popular.setTabListener(new TabListener(fragmentTab2));
Recommended.setTabListener(new TabListener(fragmentTab2));
// Add tabs to actionbar
actionBar.addTab(AllTopics);
actionBar.addTab(NewContent);
actionBar.addTab(StaffPicks);
actionBar.addTab(Popular);
actionBar.addTab(Recommended);
}
I have a tabbed Android app. When I switch away from a tab, I am seeing OnDestroy called for the corresponding fragment. When I come back to that tab, I am then seeing OnCreate called for THE SAME FRAGMENT OBJECT. It is definitely the same object, not another instance of the same class. If I switch away to another tab, OnDestroy is called again, followed by a third call to OnCreate if I return to that tab, and so on.
Android docs appear to state that this should not happen.
Does this indicate an architectural problem with my app? If it's relevant, I am using Mono, and I am setting RetainInstance to true in OnActivityCreated.
EDIT: code below is from the activity that wraps all the tabs.
protected override void OnCreate(Bundle bundle) {
base.OnCreate(bundle);
MainContext mainContext = MainContext;
TabContext tabContext = mainContext.TabContext;
// Tab is a custom model object; not related to Android tabs.
List<Tab> tabs = tabContext.Tabs;
foreach (Tab tab in tabs) {
string displayString = tab.DisplayString;
string withUnderscores = displayString.Replace(' ', '_');
Type fragmentType = Type.GetType(Assembly.GetExecutingAssembly().GetName().Name + "." + withUnderscores + "Fragment");
this.AddTab(tab, (Fragment) Activator.CreateInstance(fragmentType));
}
ActionBar bar = this.ActionBar;
bar.NavigationMode = ActionBarNavigationMode.Tabs;
bar.SetDisplayShowTitleEnabled(false);
bar.SetDisplayShowHomeEnabled(false);
SetContentView(Resource.Layout.MainTabActivityLayout);
if (bundle != null) {
int index = bundle.GetInt("index");
ActionBar.SetSelectedNavigationItem(index);
}
}
private void AddTab(Tab tab, Fragment fragment) {
ActionBar bar = this.ActionBar;
Android.App.ActionBar.Tab droidTab = bar.NewTab();
droidTab.SetTag(tab.ToString());
// omitting code that sets icon and display text.
droidTab.TabSelected += (sender, e) => {
e.FragmentTransaction.Replace(Resource.Id.fragmentContainer, fragment, tab.ToString());
};
this.ActionBar.AddTab(droidTab);
}
It is calling the onDestroy because you are replacing the fragment each time you change the tab
e.FragmentTransaction.Replace(Resource.Id.fragmentContainer, fragment, tab.ToString());
As you could see that you are only using one layout(Resource.Id.fragmentContainer) for replacing the fragment therefore it is reusing it after you change tab and releasing the memory of the replaced fragment thus calling the onDestroy.
I am using Actionbarsherlock for tab layout. In some conditions I want to set the tab at index 4 as the default tab. I mean the tab should stay at 5th position but it should be the default one. Is there any way to do that?
My class definition looks like this:
public class CalendarActivity extends SherlockFragmentActivity implements ActionBar.TabListener
and the onCreate method looks like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab tabMonthly = bar.newTab();
tabMonthly.setText("Monthly").setTabListener(this);
bar.addTab(tabMonthly);
ActionBar.Tab tabWeekly = bar.newTab();
tabWeekly.setText("Weekly").setTabListener(this);
bar.addTab(tabWeekly);
ActionBar.Tab tabDaily = bar.newTab();
tabDaily.setText("Day").setTabListener(this);
bar.addTab(tabDaily);
ActionBar.Tab tabList = bar.newTab();
tabList.setText("List").setTabListener(this);
bar.addTab(tabList);
ActionBar.Tab addEvent = bar.newTab();
addEvent.setText("Unread").setTabListener(this);
bar.addTab(addEvent);
//String callerActivity = getIntent().getStringExtra("activityCaller");
//if( callerActivity!= null && callerActivity.equalsIgnoreCase("notification") ){
//bar.setSelectedNavigationItem(4);
//}
}
I tried the code commented at the end of onCreate() method above. But the problem with this code is that it first loads the tab at index zero and then suddenly goes to tab at index4.
I have noticed that when using
actionBar.setSelectedNavigationItem(x)
in the onCreate() method of my Activity, the tab item at position 0 is always selected first and then the tab item at position x is loaded. This means that (since I'm using Fragments) 2 Fragments are loaded. One of them being unnecessary...
Here's my code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Determine which bundle to use; either the saved instance or a bundle
// that has been passed in through an intent.
Bundle bundle = getIntent().getExtras();
if (bundle == null) {
bundle = savedInstanceState;
}
// Initialize members with bundle or default values.
int position;
if (bundle != null) {
position = bundle.getInt("selected_tab");
} else {
position = 0;
}
// Set the tabs.
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
Tab tab = actionBar
.newTab()
.setText("Tab 1")
.setTabListener(
new TabListener<RendersGridFragment>(this, "1",
RendersGridFragment.class));
actionBar.addTab(tab);
tab = actionBar
.newTab()
.setText("Tab 2")
.setTabListener(
new TabListener<RendersGridFragment>(this, "2",
RendersGridFragment.class));
actionBar.addTab(tab);
tab = actionBar
.newTab()
.setText("Tab 3")
.setTabListener(
new TabListener<RendersGridFragment>(this, "3",
RendersGridFragment.class));
actionBar.addTab(tab);
actionBar.setSelectedNavigationItem(position);
}
It seems that the tab at position 0 is selected initially by default. But, as you can see, I'm passing bundles to make sure the last selected tab is still selected when the activity onCreate() method is run again.
For example,
if the last selected tab is at position 2, the onCreate() runs and the tab at position is 0 is loaded, then the tab at position 2 is loaded.
How can I make sure the ActionBar doesn't select tab at position 0 first when using actionBar.setSelectedNavigationItem(position).
Use the other addTab calls to override this behaviour. You'll need to add the tab you want to be selected first (in your case, the tab at position 2). Relevant Javadoc
actionBar.addTab(tab2);
actionBar.addTab(tab0, 0, false);
actionBar.addTab(tab1, 1, false);
For any others looking to do this you can also set the tab to selected by setting the position and then set true or false to indicate which tab should be selected
actionBar.addTab(tab1, 0, false);
actionBar.addTab(tab2, 1, true);
actionBar.addTab(tab3, 2, false);
Here are the docs on this approach: http://developer.android.com/reference/android/app/ActionBar.html#addTab(android.app.ActionBar.Tab, int, boolean)
you can use below statment in activtiy onStart method:
protected void onStart() {
super.onStart();
actionBar.selectTab(mainTab);
}
which mainTab variable here is of type Tab.
this way you need to define tabs as class-wide variables like this:
Tab mainTab, tab2,tab3;
#Override
protected void onCreate(Bundle savedInstanceState) {
//add tabs to action bar
....
}
If you have 3 tabs (i.e. tab 0, tab 1, tab 2) and want tab 1 to be preselected. Do this:
for (int i = 0; i < mFragmentPagerAdapter.getCount(); i++) {
boolean preselected = (i == 1);
actionBar.addTab(actionBar.newTab().setText(
mFragmentPagerAdapter.getPageTitle(i)).setTabListener(this), preselected);
}
You will be using:
public abstract void addTab (ActionBar.Tab tab, boolean setSelected)
as per this API specification.
bkurzius' answer helped me to fix a problem I was having with the same issue.
What I did was:
private final String TAB_SELECTED = "tab_selected"
...
private int mTabSelected;
...
mTabSelected = savedInstanceState.getInt(TAB_SELECTED);
...
final ActionBar actionbar = getActionBar();
...
actionbar.addTab(tab1, mTabSelected == 0);
actionbar.addTab(tab2, mTabSelected == 1);
actionbar.addTab(tab3, mTabSelected == 2);
...
outState.putInt(TAB_SELECTED, getActionBar().getSelectedNavigationIndex());
This way, the setSelected parameter is true only if mTabSelected is equal to the tab's index.
Percy Vega's reply seems to be the best working solution.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
boolean preselected = (i == ErrorDetails.tab_id);
actionBar.addTab(
actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this),preselected);
}