diff --git a/res/layout/fdroid.xml b/res/layout/fdroid.xml
index dd8766859..5f84b230b 100644
--- a/res/layout/fdroid.xml
+++ b/res/layout/fdroid.xml
@@ -1,23 +1,15 @@
-
+ android:orientation="vertical">
-
-
-
+ android:layout_height="fill_parent">
-
\ No newline at end of file
+
+
+
diff --git a/src/org/fdroid/fdroid/FDroid.java b/src/org/fdroid/fdroid/FDroid.java
index 9e7f8f583..4af2bf571 100644
--- a/src/org/fdroid/fdroid/FDroid.java
+++ b/src/org/fdroid/fdroid/FDroid.java
@@ -29,14 +29,11 @@ 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.view.*;
import android.widget.*;
import org.fdroid.fdroid.DB.App;
-import org.fdroid.fdroid.R;
-import android.R.drawable;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.Intent;
@@ -49,15 +46,11 @@ import android.os.Handler;
import android.os.ResultReceiver;
import android.preference.PreferenceManager;
import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.TabHost.TabSpec;
-import org.fdroid.fdroid.views.AppListFragmentStatePageAdapter;
+import org.fdroid.fdroid.views.AppListFragmentPageAdapter;
+import org.fdroid.fdroid.views.AppListView;
public class FDroid extends FragmentActivity implements OnItemClickListener,
OnItemSelectedListener {
@@ -97,6 +90,9 @@ public class FDroid extends FragmentActivity implements OnItemClickListener,
private ViewPager viewPager;
+ // Used by pre 3.0 devices which don't have an ActionBar...
+ private TabHost tabHost;
+
// The following getters
// (availableAdapter/installedAdapter/canUpdateAdapter/categoriesAdapter)
// are used by the APpListViewFactory to construct views that can be used
@@ -123,14 +119,15 @@ public class FDroid extends FragmentActivity implements OnItemClickListener,
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
setContentView(R.layout.fdroid);
// 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);
+ categories = new ArrayAdapter(this,
+ android.R.layout.simple_spinner_item, new Vector());
+ categories
+ .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
createViews();
createTabs();
@@ -141,9 +138,9 @@ public class FDroid extends FragmentActivity implements OnItemClickListener,
call.putExtra("uri", i.getStringExtra("uri"));
startActivityForResult(call, REQUEST_MANAGEREPOS);
} else if (i.hasExtra(EXTRA_TAB_UPDATE)) {
- boolean updateTab = i.getBooleanExtra(EXTRA_TAB_UPDATE, false);
- if (updateTab) {
- tabHost.setCurrentTab(2);
+ boolean showUpdateTab = i.getBooleanExtra(EXTRA_TAB_UPDATE, false);
+ if (showUpdateTab) {
+ selectTab(2);
}
}
@@ -284,7 +281,12 @@ public class FDroid extends FragmentActivity implements OnItemClickListener,
private void createViews() {
viewPager = (ViewPager)findViewById(R.id.main_pager);
- viewPager.setAdapter(new AppListFragmentStatePageAdapter(this));
+ viewPager.setAdapter(new AppListFragmentPageAdapter(this));
+ viewPager.setOnPageChangeListener( new ViewPager.SimpleOnPageChangeListener() {
+ public void onPageSelected(int position) {
+ selectTab(position);
+ }
+ });
}
private void createTabs() {
@@ -295,6 +297,14 @@ public class FDroid extends FragmentActivity implements OnItemClickListener,
}
}
+ private void selectTab(int index) {
+ if (Build.VERSION.SDK_INT >= 11) {
+ getActionBar().setSelectedNavigationItem(index);
+ } else {
+ tabHost.setCurrentTab(index);
+ }
+ }
+
private void updateTabText(int index) {
CharSequence text = viewPager.getAdapter().getPageTitle(index);
if ( Build.VERSION.SDK_INT >= 11) {
@@ -328,17 +338,70 @@ public class FDroid extends FragmentActivity implements OnItemClickListener,
}
}));
}
-
- pager.setOnPageChangeListener( new ViewPager.SimpleOnPageChangeListener() {
- public void onPageSelected(int position) {
- actionBar.setSelectedNavigationItem(position);
- }
- });
}
+ /**
+ * There is a bit of boiler-plate code required to get a TabWidget showing,
+ * which includes creating a TabHost, populating it with the TabWidget,
+ * and giving it a FrameLayout as a child. This will make the tabs have
+ * dummy empty contents and then hook them up to our ViewPager.
+ */
private void createOldTabs() {
+ tabHost = new TabHost(this);
+ tabHost.setLayoutParams(new TabHost.LayoutParams(
+ TabHost.LayoutParams.MATCH_PARENT, TabHost.LayoutParams.WRAP_CONTENT));
+
TabWidget tabWidget = new TabWidget(this);
- tabWidget.
+ tabWidget.setId(android.R.id.tabs);
+ tabHost.setLayoutParams(new TabHost.LayoutParams(
+ TabWidget.LayoutParams.MATCH_PARENT, TabWidget.LayoutParams.WRAP_CONTENT));
+
+ FrameLayout layout = new FrameLayout(this);
+ layout.setId(android.R.id.tabcontent);
+ layout.setLayoutParams(new TabWidget.LayoutParams(0, 0));
+
+ tabHost.addView(tabWidget);
+ tabHost.addView(layout);
+ tabHost.setup();
+
+ TabHost.TabContentFactory factory = new TabHost.TabContentFactory() {
+ @Override
+ public View createTabContent(String tag) {
+ return new View(FDroid.this);
+ }
+ };
+
+ TabSpec availableTabSpec = tabHost.newTabSpec("available")
+ .setIndicator(
+ getString(R.string.tab_noninstalled),
+ getResources().getDrawable(android.R.drawable.ic_input_add))
+ .setContent(factory);
+
+ TabSpec installedTabSpec = tabHost.newTabSpec("installed")
+ .setIndicator(
+ getString(R.string.tab_installed),
+ getResources().getDrawable(android.R.drawable.star_off))
+ .setContent(factory);
+
+ TabSpec canUpdateTabSpec = tabHost.newTabSpec("canUpdate")
+ .setIndicator(
+ getString(R.string.tab_updates),
+ getResources().getDrawable(android.R.drawable.star_on))
+ .setContent(factory);
+
+ tabHost.addTab(availableTabSpec);
+ tabHost.addTab(installedTabSpec);
+ tabHost.addTab(canUpdateTabSpec);
+
+ LinearLayout contentView = (LinearLayout)findViewById(R.id.fdroid_layout);
+ contentView.addView(tabHost, 0);
+
+ tabHost.setOnTabChangedListener( new TabHost.OnTabChangeListener() {
+ @Override
+ public void onTabChanged(String tabId) {
+ viewPager.setCurrentItem(tabHost.getCurrentTab());
+ }
+ });
}
// Populate the lists.
@@ -530,17 +593,13 @@ public class FDroid extends FragmentActivity implements OnItemClickListener,
public void onItemClick(AdapterView> arg0, View arg1, final int arg2,
long arg3) {
- ViewPager pager = (ViewPager)findViewById(R.id.main_pager);
+ Fragment fragment = ((AppListFragmentPageAdapter)viewPager.getAdapter()).getItem(viewPager.getCurrentItem());
- final DB.App app;
- String curtab = tabHost.getCurrentTabTag();
- if (curtab.equalsIgnoreCase(TAB_Installed)) {
- app = (DB.App) apps_in.getItem(arg2);
- } else if (curtab.equalsIgnoreCase(TAB_Updates)) {
- app = (DB.App) apps_up.getItem(arg2);
- } else {
- app = (DB.App) apps_av.getItem(arg2);
- }
+ // The fragment.getView() returns a wrapper object which has the
+ // actual view we're interested in inside:
+ // http://stackoverflow.com/a/13684505
+ AppListView view = ((AppListView)((ViewGroup)fragment.getView()).getChildAt(0));
+ final DB.App app = (DB.App)view.getAppList().getAdapter().getItem(arg2);
Intent intent = new Intent(this, AppDetails.class);
intent.putExtra("appid", app.id);
diff --git a/src/org/fdroid/fdroid/views/AppListFragmentStatePageAdapter.java b/src/org/fdroid/fdroid/views/AppListFragmentPageAdapter.java
similarity index 81%
rename from src/org/fdroid/fdroid/views/AppListFragmentStatePageAdapter.java
rename to src/org/fdroid/fdroid/views/AppListFragmentPageAdapter.java
index 0c74692f6..b26e1f891 100644
--- a/src/org/fdroid/fdroid/views/AppListFragmentStatePageAdapter.java
+++ b/src/org/fdroid/fdroid/views/AppListFragmentPageAdapter.java
@@ -2,19 +2,23 @@ package org.fdroid.fdroid.views;
import android.os.Bundle;
import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentStatePagerAdapter;
+import android.support.v4.app.FragmentPagerAdapter;
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 {
+/**
+ * Used by the FDroid activity in conjunction with its ViewPager to support
+ * swiping of tabs for both old devices (< 3.0) and new devices.
+ */
+public class AppListFragmentPageAdapter extends FragmentPagerAdapter {
private FDroid parent;
private Fragment[] fragments = new Fragment[3];
- public AppListFragmentStatePageAdapter(FDroid parent) {
+ public AppListFragmentPageAdapter(FDroid parent) {
super(parent.getSupportFragmentManager());
this.parent = parent;
@@ -57,7 +61,7 @@ public class AppListFragmentStatePageAdapter extends FragmentStatePagerAdapter {
return parent.getString(R.string.tab_installed);
case 2:
String updates = parent.getString(R.string.tab_updates);
- updates += " (" + parent.getCanUpdateAdapter() + ")";
+ updates += " (" + parent.getCanUpdateAdapter().getCount() + ")";
return updates;
default:
return "";
diff --git a/src/org/fdroid/fdroid/views/AppListView.java b/src/org/fdroid/fdroid/views/AppListView.java
new file mode 100644
index 000000000..c1b1f9272
--- /dev/null
+++ b/src/org/fdroid/fdroid/views/AppListView.java
@@ -0,0 +1,32 @@
+package org.fdroid.fdroid.views;
+
+import android.content.Context;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+
+/**
+ * There are three main app-lists in the UI:
+ * - Available
+ * - Installed
+ * - Apps which can be updated
+ * This class provides a View which knows about these app lists, but can have
+ * different contents (e.g. a drop down list of categories). It allows us to
+ * get a reference to the selected item in the FDroid Activity, without having
+ * to know which list we are actually looking at.
+ */
+public class AppListView extends LinearLayout {
+
+ private ListView appList;
+
+ public AppListView(Context context) {
+ super(context);
+ }
+
+ public void setAppList(ListView appList) {
+ this.appList = appList;
+ }
+
+ public ListView getAppList() {
+ return appList;
+ }
+}
diff --git a/src/org/fdroid/fdroid/views/AppListViewFactory.java b/src/org/fdroid/fdroid/views/AppListViewFactory.java
index 62d538ff1..927641c88 100644
--- a/src/org/fdroid/fdroid/views/AppListViewFactory.java
+++ b/src/org/fdroid/fdroid/views/AppListViewFactory.java
@@ -2,7 +2,6 @@ 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;
@@ -10,6 +9,10 @@ import org.fdroid.fdroid.AppListAdapter;
import org.fdroid.fdroid.FDroid;
import org.fdroid.fdroid.R;
+/**
+ * Provides functionality to create the three lists of applications
+ * required for the FDroid activity.
+ */
public class AppListViewFactory {
private FDroid parent;
@@ -18,32 +21,52 @@ public class AppListViewFactory {
this.parent = parent;
}
- public View createAvailableView() {
- ListView list = createAppListView(parent.getAvailableAdapter());
- LinearLayout view = new LinearLayout(parent);
+ public AppListView createAvailableView() {
+ AppListView view = new AppListView(parent);
view.setOrientation(LinearLayout.VERTICAL);
- Spinner cats = new Spinner(parent);
+ Spinner spinner = 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));
+ spinner.setId(R.id.categorySpinner);
+ spinner.setAdapter(parent.getCategoriesAdapter());
+ spinner.setOnItemSelectedListener(parent);
+
+ view.addView(
+ spinner,
+ new ViewGroup.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT));
+
+ ListView list = createAppListView(parent.getAvailableAdapter());
+ view.setAppList(list);
+ view.addView(
+ list,
+ new ViewGroup.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.MATCH_PARENT));
+
return view;
}
- public View createInstalledView() {
- return createAppListView(parent.getInstalledAdapter());
+ public AppListView createInstalledView() {
+ return createPlainAppList(parent.getInstalledAdapter());
}
- public View createCanUpdateView() {
- return createAppListView(parent.getCanUpdateAdapter());
+ public AppListView createCanUpdateView() {
+ return createPlainAppList(parent.getCanUpdateAdapter());
+ }
+
+ protected AppListView createPlainAppList(AppListAdapter adapter) {
+ AppListView view = new AppListView(parent);
+ ListView list = createAppListView(adapter);
+ view.addView(
+ list,
+ new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+ view.setAppList(list);
+ return view;
}
protected ListView createAppListView(AppListAdapter adapter) {