diff --git a/.gitignore b/.gitignore
index 43a5ae231..a5e3b6aea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,6 @@ gen/*
proguard.cfg
proguard-project.txt
*~
+.idea
+*.iml
+out
diff --git a/libs/android-support-v4.jar b/libs/android-support-v4.jar
new file mode 100644
index 000000000..65ebaf8dc
Binary files /dev/null and b/libs/android-support-v4.jar differ
diff --git a/res/layout/fdroid.xml b/res/layout/fdroid.xml
index 508ec029b..dd8766859 100644
--- a/res/layout/fdroid.xml
+++ b/res/layout/fdroid.xml
@@ -1,22 +1,23 @@
-
+ android:orientation="vertical">-->
-
+
-
+
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/src/org/fdroid/fdroid/FDroid.java b/src/org/fdroid/fdroid/FDroid.java
index 1460b1bd8..9e7f8f583 100644
--- a/src/org/fdroid/fdroid/FDroid.java
+++ b/src/org/fdroid/fdroid/FDroid.java
@@ -25,13 +25,18 @@ import java.util.Comparator;
import java.util.Date;
import java.util.Vector;
+import android.app.*;
+import android.os.Build;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentStatePagerAdapter;
+import android.support.v4.view.PagerTitleStrip;
+import android.support.v4.view.ViewPager;
+import android.widget.*;
import org.fdroid.fdroid.DB.App;
import org.fdroid.fdroid.R;
import android.R.drawable;
-import android.app.AlertDialog;
-import android.app.ProgressDialog;
-import android.app.TabActivity;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.Intent;
@@ -49,19 +54,12 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.Spinner;
-import android.widget.TabHost;
-import android.widget.TextView;
-import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.TabHost.TabSpec;
+import org.fdroid.fdroid.views.AppListFragmentStatePageAdapter;
-public class FDroid extends TabActivity implements OnItemClickListener,
+public class FDroid extends FragmentActivity implements OnItemClickListener,
OnItemSelectedListener {
private static final int REQUEST_APPDETAILS = 0;
@@ -87,38 +85,54 @@ public class FDroid extends TabActivity implements OnItemClickListener,
// Category list
private ArrayAdapter categories;
+
private String currentCategory = null;
private ProgressDialog pd;
- // Tags for the tabs
- private static final String TAB_Installed = "I";
- private static final String TAB_Available = "A";
- private static final String TAB_Updates = "U";
-
- private TabHost tabHost;
- private TabSpec ts;
- private TabSpec ts1;
- private TabSpec tsUp;
-
private boolean triedEmptyUpdate;
// List of apps.
private Vector apps = null;
+ private ViewPager viewPager;
+
+ // The following getters
+ // (availableAdapter/installedAdapter/canUpdateAdapter/categoriesAdapter)
+ // are used by the APpListViewFactory to construct views that can be used
+ // either by Android 3.0+ devices with ActionBars, or earlier devices
+ // with old fashioned tabs.
+
+ public AppListAdapter getAvailableAdapter() {
+ return apps_av;
+ }
+
+ public AppListAdapter getInstalledAdapter() {
+ return apps_in;
+ }
+
+ public AppListAdapter getCanUpdateAdapter() {
+ return apps_up;
+ }
+
+ public ArrayAdapter getCategoriesAdapter() {
+ return categories;
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
setContentView(R.layout.fdroid);
- categories = new ArrayAdapter(this,
- android.R.layout.simple_spinner_item, new Vector());
- categories
- .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ // Needs to be created before createViews(), because that will use the
+ // getCategoriesAdapter() accessor which expects this object...
+ categories = new ArrayAdapter(
+ this, android.R.layout.simple_spinner_item, new Vector());
+ categories.setDropDownViewResource(
+ android.R.layout.simple_spinner_dropdown_item);
- tabHost = getTabHost();
+ createViews();
createTabs();
Intent i = getIntent();
@@ -268,71 +282,63 @@ public class FDroid extends TabActivity implements OnItemClickListener,
}
}
+ private void createViews() {
+ viewPager = (ViewPager)findViewById(R.id.main_pager);
+ viewPager.setAdapter(new AppListFragmentStatePageAdapter(this));
+ }
+
private void createTabs() {
- tabHost.clearAllTabs();
+ if (Build.VERSION.SDK_INT >= 11) {
+ createActionBarTabs();
+ } else {
+ createOldTabs();
+ }
+ }
- // TabContentFactory that can generate the appropriate list for each
- // tab...
- TabHost.TabContentFactory tf = new TabHost.TabContentFactory() {
- @Override
- public View createTabContent(String tag) {
+ private void updateTabText(int index) {
+ CharSequence text = viewPager.getAdapter().getPageTitle(index);
+ if ( Build.VERSION.SDK_INT >= 11) {
+ getActionBar().getTabAt(index).setText(text);
+ } else {
- AppListAdapter ad;
- if (tag.equals(TAB_Installed))
- ad = apps_in;
- else if (tag.equals(TAB_Updates))
- ad = apps_up;
- else
- ad = apps_av;
+ }
+ }
- ListView lst = new ListView(FDroid.this);
- lst.setFastScrollEnabled(true);
- lst.setOnItemClickListener(FDroid.this);
- lst.setAdapter(ad);
+ private void createActionBarTabs() {
+ final ActionBar actionBar = getActionBar();
+ final ViewPager pager = viewPager;
+ actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
+ for (int i = 0; i < viewPager.getAdapter().getCount(); i ++) {
+ CharSequence label = viewPager.getAdapter().getPageTitle(i);
+ actionBar.addTab(
+ actionBar.newTab()
+ .setText(label)
+ .setTabListener(new ActionBar.TabListener() {
+ public void onTabSelected(ActionBar.Tab tab,
+ FragmentTransaction ft) {
+ pager.setCurrentItem(tab.getPosition());
+ }
- if (!tag.equals(TAB_Available))
- return lst;
+ @Override
+ public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
+ }
- LinearLayout v = new LinearLayout(FDroid.this);
- v.setOrientation(LinearLayout.VERTICAL);
- Spinner cats = new Spinner(FDroid.this);
- // Giving it an ID lets the default save/restore state
- // functionality do its stuff.
- cats.setId(R.id.categorySpinner);
- cats.setAdapter(categories);
- cats.setOnItemSelectedListener(FDroid.this);
- v.addView(cats, new LayoutParams(
- LinearLayout.LayoutParams.FILL_PARENT,
- LinearLayout.LayoutParams.WRAP_CONTENT));
- v.addView(lst, new LayoutParams(
- LinearLayout.LayoutParams.FILL_PARENT,
- LinearLayout.LayoutParams.FILL_PARENT));
- return v;
+ @Override
+ public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
+ }
+ }));
+ }
+
+ pager.setOnPageChangeListener( new ViewPager.SimpleOnPageChangeListener() {
+ public void onPageSelected(int position) {
+ actionBar.setSelectedNavigationItem(position);
}
- };
-
- // Create the tab of installed apps...
- ts = tabHost.newTabSpec(TAB_Installed);
- ts.setIndicator(getString(R.string.tab_installed), getResources()
- .getDrawable(drawable.star_off));
- ts.setContent(tf);
-
- // Create the tab of apps with updates...
- tsUp = tabHost.newTabSpec(TAB_Updates);
- tsUp.setIndicator(getString(R.string.tab_updates), getResources()
- .getDrawable(drawable.star_on));
- tsUp.setContent(tf);
-
- // Create the tab of available apps...
- ts1 = tabHost.newTabSpec(TAB_Available);
- ts1.setIndicator(getString(R.string.tab_noninstalled), getResources()
- .getDrawable(drawable.ic_input_add));
- ts1.setContent(tf);
-
- tabHost.addTab(ts1);
- tabHost.addTab(ts);
- tabHost.addTab(tsUp);
+ });
+ }
+ private void createOldTabs() {
+ TabWidget tabWidget = new TabWidget(this);
+ tabWidget.
}
// Populate the lists.
@@ -457,12 +463,7 @@ public class FDroid extends TabActivity implements OnItemClickListener,
for (DB.App app : availapps)
apps_av.addItem(app);
- // Update the count on the 'Updates' tab to show the number available.
- // This is quite unpleasant, but seems to be the only way to do it.
- TextView uptext = (TextView) tabHost.getTabWidget().getChildAt(2)
- .findViewById(android.R.id.title);
- uptext.setText(getString(R.string.tab_updates) + " ("
- + Integer.toString(apps_up.getCount()) + ")");
+ updateTabText(2);
// Tell the lists that the data behind the adapter has changed, so
// they can refresh...
@@ -529,6 +530,8 @@ public class FDroid extends TabActivity implements OnItemClickListener,
public void onItemClick(AdapterView> arg0, View arg1, final int arg2,
long arg3) {
+ ViewPager pager = (ViewPager)findViewById(R.id.main_pager);
+
final DB.App app;
String curtab = tabHost.getCurrentTabTag();
if (curtab.equalsIgnoreCase(TAB_Installed)) {
diff --git a/src/org/fdroid/fdroid/views/AppListFragmentStatePageAdapter.java b/src/org/fdroid/fdroid/views/AppListFragmentStatePageAdapter.java
new file mode 100644
index 000000000..0c74692f6
--- /dev/null
+++ b/src/org/fdroid/fdroid/views/AppListFragmentStatePageAdapter.java
@@ -0,0 +1,67 @@
+package org.fdroid.fdroid.views;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentStatePagerAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import org.fdroid.fdroid.FDroid;
+import org.fdroid.fdroid.R;
+
+public class AppListFragmentStatePageAdapter extends FragmentStatePagerAdapter {
+
+ private FDroid parent;
+ private Fragment[] fragments = new Fragment[3];
+
+ public AppListFragmentStatePageAdapter(FDroid parent) {
+
+ super(parent.getSupportFragmentManager());
+ this.parent = parent;
+ final AppListViewFactory viewFactory = new AppListViewFactory(parent);
+
+ fragments[0] = new Fragment() {
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ return viewFactory.createAvailableView();
+ }
+ };
+
+ fragments[1] = new Fragment() {
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ return viewFactory.createInstalledView();
+ }
+ };
+
+ fragments[2] = new Fragment() {
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ return viewFactory.createCanUpdateView();
+ }
+ };
+ }
+
+ @Override
+ public Fragment getItem(int i) {
+ return fragments[i];
+ }
+
+ @Override
+ public int getCount() {
+ return fragments.length;
+ }
+
+ public String getPageTitle(int i) {
+ switch(i) {
+ case 0:
+ return parent.getString(R.string.tab_noninstalled);
+ case 1:
+ return parent.getString(R.string.tab_installed);
+ case 2:
+ String updates = parent.getString(R.string.tab_updates);
+ updates += " (" + parent.getCanUpdateAdapter() + ")";
+ return updates;
+ default:
+ return "";
+ }
+ }
+
+}
diff --git a/src/org/fdroid/fdroid/views/AppListViewFactory.java b/src/org/fdroid/fdroid/views/AppListViewFactory.java
new file mode 100644
index 000000000..62d538ff1
--- /dev/null
+++ b/src/org/fdroid/fdroid/views/AppListViewFactory.java
@@ -0,0 +1,57 @@
+package org.fdroid.fdroid.views;
+
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.Spinner;
+import org.fdroid.fdroid.AppListAdapter;
+import org.fdroid.fdroid.FDroid;
+import org.fdroid.fdroid.R;
+
+public class AppListViewFactory {
+
+ private FDroid parent;
+
+ public AppListViewFactory(FDroid parent) {
+ this.parent = parent;
+ }
+
+ public View createAvailableView() {
+ ListView list = createAppListView(parent.getAvailableAdapter());
+ LinearLayout view = new LinearLayout(parent);
+ view.setOrientation(LinearLayout.VERTICAL);
+ Spinner cats = new Spinner(parent);
+
+ // Giving it an ID lets the default save/restore state
+ // functionality do its stuff.
+ cats.setId(R.id.categorySpinner);
+ cats.setAdapter(parent.getCategoriesAdapter());
+ cats.setOnItemSelectedListener(parent);
+ view.addView(cats, new ViewGroup.LayoutParams(
+ LinearLayout.LayoutParams.FILL_PARENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT));
+ view.addView(list, new ViewGroup.LayoutParams(
+ LinearLayout.LayoutParams.FILL_PARENT,
+ LinearLayout.LayoutParams.FILL_PARENT));
+ return view;
+ }
+
+ public View createInstalledView() {
+ return createAppListView(parent.getInstalledAdapter());
+ }
+
+ public View createCanUpdateView() {
+ return createAppListView(parent.getCanUpdateAdapter());
+ }
+
+ protected ListView createAppListView(AppListAdapter adapter) {
+ ListView list = new ListView(parent);
+ list.setFastScrollEnabled(true);
+ list.setOnItemClickListener(parent);
+ list.setAdapter(adapter);
+ return list;
+ }
+
+}