Currently I use ABS, ActionBar Tabs and a TabsAdapter/ViewPager to make a nice tab layout for my app. I have 5+ category tabs up top - eventually the user will be able to add new categories (I'll set this up later) as well. So, at the moment, I have a main SherlockFragmentActivity
with many SherlockFragment
category files. In onCreate for the main SFA, I build the actionBar and add all its tabs, like so:
mTabsAdapter.addTab(bar.newTab().setText(R.string.login),
LoginFragment.class, null);
mTabsAdapter.addTab(bar.newTab().setText("Geographics"),
GeoFragment.class, null);
mTabsAdapter.addTab(bar.newTab().setText(R.string.economics),
EconFragment.class, null);
mTabsAdapter.addTab(bar.newTab().setText(R.string.elections),
ElectionsFragment.class, null);
What I would like to do instead, is create a new solution, CategoryFragment
rather than using all of the specific Elections, Geo, Econ etc. Can anyone imagine a solution? Ideally, I would like to just pass a string to the tab that gets added, so that CategoryFragment can just inflate based on the string. I would like this solution because the code is very redundant in multiple classes, when all the class really does is load stuff from an SQL dB online, getting only the data for its own category.
Here is my TabsAdapter class:
public class TabsAdapter extends FragmentPagerAdapter
implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private Polling activity;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
final class TabInfo {
private final Class<?> clss;
private final Bundle args;
//private final String title;
//This string is implemented only as part of my attempt!
TabInfo(Class<?> _class, Bundle _args, String _title) {
clss = _class;
args = _args;
title = _title;
}
}
/*Constructor method that adds a TabsAdapter to each tab that is created.
* It also adds the ViewPager to each tab so that the user can swipe to change tabs.
*/
public TabsAdapter(SherlockFragmentActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
this.activity = (Polling) activity;
mActionBar = activity.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
/*This is the method I've been trying to use to solve the problem, but it's not really cutting it!*/
public void buildTabs() throws ClassNotFoundException {
String [] tabs = {"Econ", "Elections", "Geo", "Politics", "Science", "Finance", "Religion",
"Military", "International" };
final String resource = "R.string.";
mTabsAdapter.addTab(bar.newTab().setText("Login"),
LoginFragment.class, null, "Login");
for (int j = 0; j < tabs.length; j++) {
String res = resource + tabs[j];
String clas = tabs[j] + "Fragment";
String total = "com.davekelley.polling." + clas;
mTabsAdapter.addTab(bar.newTab().setText(tabs[j]),
CategoryFragment.class, null, tabs[j]);
}
}
/*A fairly simple method that sets the TabInfo for each tab so that the TabsAdapter
* knows which class the tab that is being added actually belonds to. It also updates
* the UI interface when each tab is added.
*/
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args, String title) {
TabInfo info = new TabInfo(clss, args, title);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
public int getCount() {
return mTabs.size();
}
/*A method that is used in other classes to allow each tab Fragment to
* access its inherited methods from a mother-class, in this case, SherlockFragment
*/
public int getPosition(SherlockFragment fragment) {
for (int j = 1; j < mTabs.size(); j++) {
TabInfo info = (TabInfo) mActionBar.getTabAt(j).getTag();
if (info.title.matches(mTabs.get(j).title)) {
return j;
}
}
return -1;
}
public SherlockFragment getItem(int position) {
TabInfo info = mTabs.get(position);
return (SherlockFragment)Fragment.instantiate(mContext, info.clss.getName(), info.args);
}
/*This method reads the user's selection for a new tab and sets that tab as
* the new current focus.*/
public void onPageSelected(int position) {
mActionBar.setSelectedNavigationItem(position);
selectInSpinnerIfPresent(position, true);
}
private void selectInSpinnerIfPresent(int position, boolean animate) {
try {
View actionBarView = findViewById(R.id.abs__action_bar);
if (actionBarView == null) {
int id = getResources().getIdentifier("action_bar", "id", "android");
actionBarView = findViewById(id);
}
Class<?> actionBarViewClass = actionBarView.getClass();
Field mTabScrollViewField = actionBarViewClass.getDeclaredField("mTabScrollView");
mTabScrollViewField.setAccessible(true);
Object mTabScrollView = mTabScrollViewField.get(actionBarView);
if (mTabScrollView == null) {
return;
}
Field mTabSpinnerField = mTabScrollView.getClass().getDeclaredField("mTabSpinner");
mTabSpinnerField.setAccessible(true);
Object mTabSpinner = mTabSpinnerField.get(mTabScrollView);
if (mTabSpinner == null) {
return;
}
Method setSelectionMethod = mTabSpinner.getClass().getSuperclass().getDeclaredMethod("setSelection", Integer.TYPE, Boolean.TYPE);
setSelectionMethod.invoke(mTabSpinner, position, animate);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public void onPageScrollStateChanged(int state) {}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
/* This is the method that actually draws the newest tab onto the screen when
* it is selected.*/
public void onTabSelected(Tab tab, FragmentTransaction ft) {
mViewPager.setCurrentItem(tab.getPosition());
sp = getSharedPreferences("prefs", MODE_PRIVATE);
SharedPreferences.Editor preferencesEditor = sp.edit();
preferencesEditor.putInt("lastPosition", mViewPager.getCurrentItem());
preferencesEditor.commit();
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {}
public void onTabReselected(Tab tab, FragmentTransaction ft) {}
public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) {}
public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {}
}