As a lot of people have been doing so far, I'm implementing the FragmentTabsPager into my app, which is using ActionBarSherlock 4.0. However, I'm lost.
Fragments, and all of Google's little ideas, plans and methods surrounding it, are confusing me. If anyone could take a look at my code and walk me through this, providing help in making it work, I would thank them a thousand times :D.
I have another project with a sort-of beginning for a ViewPager, but the Tabs just mix better, especially with them being in the ActionBar on landscape and tablets.
My code is all zipped up and ready to go over here:
http://dl.dropbox.com/u/21807195/Antonius%20College%202.zip
Thanks in advance!
I will show you my code that has a ViewPager, TabListener, and system of Fragments linked to each tab. It implements ABS, but as of yet, still crashes on Gingerbread and lower (works beautifully on ICS, though):
import java.util.ArrayList;
import library.DatabaseHandler;
import org.json.JSONObject;
import com.actionbarsherlock.R;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.View.OnClickListener;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
public class Polling extends SherlockFragmentActivity {
private ViewPager mViewPager;
private TabsAdapter mTabsAdapter;
private final static String TAG = "21st Polling:";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewPager = new ViewPager(this);
mViewPager.setId(R.id.pager);
setContentView(mViewPager);
ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayShowTitleEnabled(false);
bar.setDisplayShowHomeEnabled(false);
mTabsAdapter = new TabsAdapter(this, mViewPager);
mTabsAdapter.addTab(bar.newTab().setText(R.string.login),
LoginFragment.class, null);
mTabsAdapter.addTab(bar.newTab().setText(R.string.economics),
EconFragment.class, null);
mTabsAdapter.addTab(bar.newTab().setText(R.string.elections),
ElectionsFragment.class, null);
mTabsAdapter.addTab(bar.newTab().setText(R.string.politics),
PoliticsFragment.class, null);
mTabsAdapter.addTab(bar.newTab().setText(R.string.science),
ScienceFragment.class, null);
mTabsAdapter.addTab(bar.newTab().setText(R.string.finance),
FinanceFragment.class, null);
mTabsAdapter.addTab(bar.newTab().setText(R.string.religion),
ReligionFragment.class, null);
mTabsAdapter.addTab(bar.newTab().setText(R.string.military),
MilitaryFragment.class, null);
mTabsAdapter.addTab(bar.newTab().setText(R.string.international),
InternationalFragment.class, null);
Log.v(TAG, (String)bar.getTabAt(0).getText());
}
public static class TabsAdapter extends FragmentPagerAdapter
implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}
public TabsAdapter(SherlockFragmentActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = activity.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
public int getCount() {
return mTabs.size();
}
public SherlockFragment getItem(int position) {
TabInfo info = mTabs.get(position);
return (SherlockFragment)Fragment.instantiate(mContext, info.clss.getName(), info.args);
}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
public void onPageSelected(int position) {
mActionBar.setSelectedNavigationItem(position);
}
public void onPageScrollStateChanged(int state) {
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
mViewPager.setCurrentItem(tab.getPosition());
//Log.v(TAG, "clicked");
Object tag = tab.getTag();
for (int i=0; i<mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
}
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) {}
}
And here is what one fragment looks like:
package com.davekelley.polling;
import com.actionbarsherlock.R;
import com.actionbarsherlock.app.SherlockFragment;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class MilitaryFragment extends SherlockFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.militaryfragment, container, false);
}
}
My last note would that my code still has one other issue: individual fragments do not always reload their interface after the user press back (which results in removing the entire app from the screen, regardless which tab/fragment they are on, because I have no backStack). So that's what I'm working through now. I think once I have that sorted, I'll try to figure out why I still don't have Gingerbread execution functioning properly. Either way, I hope looking through this code helps you out.
Here is a fragment with some onClickListeners:
import com.actionbarsherlock.R;
import com.actionbarsherlock.app.SherlockFragment;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
public class LoginFragment extends SherlockFragment {
Button loginButton;
Button registerButton;
Polling activity;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.loginfragment, container, false);
return v;
}
public void onResume() {
super.onResume();
Log.d("Econ", "onresume");
loginButton = (Button) getActivity().findViewById(R.id.loginButton);
loginButton.setOnClickListener(loginListener);
registerButton = (Button) getActivity().findViewById(R.id.registerButton);
registerButton.setOnClickListener(registerListener);
}
public OnClickListener loginListener = new OnClickListener() {
@Override
public void onClick(View v) {
if(loginButton.getText().toString() == "Log Out") {
activity.loginReport(2);
loginButton.setText(R.string.login);
//Remove user from dB sqllite when I know how
}
else {
Log.v("LoginF", "onclick");
ProgressDialog progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Logging in...");
LoginTask loginTask = new LoginTask((Polling) getActivity(), progressDialog);
loginTask.execute();
}
}
};
public OnClickListener registerListener = new OnClickListener() {
@Override
public void onClick(View v) {
Log.v("Register", "onclick");
ProgressDialog progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Registering new user...");
RegisterTask registerTask = new RegisterTask((Polling) getActivity(), progressDialog);
registerTask.execute();
}
};
public void onAttach(Activity activity) {
super.onAttach(activity);
this.activity = (Polling) activity;
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
public void onStart() {
super.onStart();
Log.d("Econ", "onstart");
}
public void onPause() {
super.onPause();Log.d("Econ", "onpause");
}
public void onStop() {
super.onStop();
Log.d("Econ", "onstop");
}
public void onDestroyView() {
super.onDestroyView();
Log.d("Econ", "ondestroyview");
}
public void onDestroy() {
super.onDestroy();
Log.d("Econ", "ondestroy");
}
public void onDetach() {
super.onDetach();
Log.d("Econ", "ondetach");
}
}
The loginTask objects that you see are actually classes that extend ASyncTask - they handle connecting to my server and registering/logging in.
I thought it would be helpful to add in one bit more of code. This is another one of my fragments, like LoginFragment, but it inflates a UI a little differently. Eventually, what you see in the while loop below, will head into an ASyncTask to acquire each question from the server, rather than the dummy string array you see:
public class EconFragment extends SherlockFragment {
private TableLayout questionContainer;
int pos = 0;
private String[] titles = {"The first title ", "hallo1","hallo2", "hallo3",
"hallo4", "hallo5","hallo6", "hallo7","hallo8", "hallo9"};
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.v("Econ", "onCreateView");
View v = inflater.inflate(R.layout.econfragment, container, false);
questionContainer = (TableLayout) v.findViewById(R.id.questionContainer);
//bs
int leftMargin=5;
int topMargin=5;
int rightMargin=5;
int bottomMargin=5;
while (pos < 10) {
View question = inflater.inflate(R.layout.question, null);
question.setId(pos);
TextView title = (TextView) question.findViewById(R.id.questionTextView);
title.setText(titles[pos]);
Button charts = (Button) question.findViewById(R.id.chartsButton);
charts.setId(pos);
charts.setOnClickListener(chartsListener);
TableRow tr = (TableRow) question;
TableLayout.LayoutParams trParams = new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT);
trParams.setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
tr.setLayoutParams(trParams);
Log.v("econ", "while loop");
questionContainer.addView(tr);
pos++;
}
pos = 0;
return v;
}
I have ported the FragmentTabsPager
Activity and associated Fragments from "Support4Demos" (Android Support library sample) to use ActionBarSherlock and true ActionBar Tabs. The sample includes an Activity that uses both a ViewPager and Tabs to switch between Fragments. The Fragments contain three kinds of ListViews. I've tested it from ICS down to Eclair (2.1). You can browse or download the code at http://code.google.com/p/sherlock-demo/.