diff --git a/README.md b/README.md
index e52a4f8a..69f4a51c 100644
--- a/README.md
+++ b/README.md
@@ -60,6 +60,9 @@ Some code/libraries/resources are used in the project:
* [AndroidAnnotations](http://androidannotations.org/)
Pierre-Yves Ricau (eBusinessInformations) et al.
Apache License, Version 2.0
+* [ActionBar-PullToRefresh](https://github.com/chrisbanes/ActionBar-PullToRefresh)
+ Chris Banes
+ Apache License, Version 2.0
* [Crouton](https://github.com/keyboardsurfer/Crouton)
Code: Benjamin Weiss (Neofonie Mobile Gmbh) et al.
Idea: Cyril Mottier
diff --git a/core/project.properties b/core/project.properties
index 0ca2ebd5..054f960b 100644
--- a/core/project.properties
+++ b/core/project.properties
@@ -16,3 +16,5 @@ android.library.reference.1=../external/JakeWharton-ActionBarSherlock/library
android.library.reference.2=../external/ColorPickerPreference
android.library=true
android.library.reference.3=../external/Crouton/library
+android.library.reference.4=../external/ActionBar-PullToRefresh-actionbarsherlock
+android.library.reference.5=../external/ActionBar-PullToRefresh
diff --git a/core/res/values/changelog.xml b/core/res/values/changelog.xml
index a12c9d53..82213298 100644
--- a/core/res/values/changelog.xml
+++ b/core/res/values/changelog.xml
@@ -18,6 +18,7 @@
Transdroid 2.0.1\n
+- Support for pull to refresh\n
- First Google Play release of the lite version as Transdrone\n
- First release as auto-update (now checked only once a day)\n
\n
diff --git a/core/res/values/strings.xml b/core/res/values/strings.xml
index af4e4c31..6d9e7a67 100644
--- a/core/res/values/strings.xml
+++ b/core/res/values/strings.xml
@@ -374,7 +374,7 @@
\u00A9 Eric Kok, 2312 development
Published under GNU General Public License v3
Some code/libraries are used in the project:
- ActionBarSherlock\n \u00A0 http://actionbarsherlock.com/\n \u00A0 Jake Wharton \n \u00A0 Apache License, Version 2.0\nAndroidAnnotations\n \u00A0 http://androidannotations.org/\n \u00A0 Pierre-Yves Ricau (eBusinessInformations) et al. \n \u00A0 Apache License, Version 2.0\nCrouton\n \u00A0 https://github.com/keyboardsurfer/Crouton\n \u00A0 Code: Benjamin Weiss (Neofonie Mobile Gmbh) et al. \n \u00A0 Idea: Cyril Mottier \n \u00A0 Apache License, Version 2.0\nBase16Encoder\n \u00A0 http://openjpa.apache.org/\n \u00A0 Marc Prud\'hommeaux \n \u00A0 Apache OpenJPA\n MultipartEntity \n \u00A0 Apache Software Foundation \n \u00A0 Apache License, Version 2.0\nRssParser (learning-android)\n \u00A0 http://github.com/digitalspaghetti/learning-android\n \u00A0 Tane Piper \n \u00A0 Public Domain\nBase64\n \u00A0 http://iharder.net/base64\n \u00A0 Robert Harder \n \u00A0 Public Domain\nandroid-xmlrpc\n \u00A0 http://code.google.com/p/android-xmlrpc/\n \u00A0 pskink et al. \n \u00A0 Apache License, Version 2.0\nandroid-ColorPickerPreference\n \u00A0 https://github.com/attenzione/android-ColorPickerPreference\n \u00A0 Daniel Nilsson and Sergey Margaritov \n \u00A0 Apache License, Version 2.0\nCheckableRelativeLayout\n \u00A0 http://www.marvinlabs.com/2010/10/custom-listview-ability-check-items/\n \u00A0 Cédric Caron (MarvinLabs)\n \u00A0 Public Domain\nFunnel icon\n \u00A0 http://thenounproject.com/noun/funnel/#icon-No5608\n \u00A0 Naomi Atkinson from The Noun Project\n \u00A0 Creative Commons Attribution 3.0
+ ActionBarSherlock\n \u00A0 http://actionbarsherlock.com/\n \u00A0 Jake Wharton \n \u00A0 Apache License, Version 2.0\nAndroidAnnotations\n \u00A0 http://androidannotations.org/\n \u00A0 Pierre-Yves Ricau (eBusinessInformations) et al. \n \u00A0 Apache License, Version 2.0\nActionBar-PullToRefresh\n \u00A0 https://github.com/chrisbanes/ActionBar-PullToRefresh\n \u00A0 Chris Banes \n \u00A0 Apache License, Version 2.0\nCrouton\n \u00A0 https://github.com/keyboardsurfer/Crouton\n \u00A0 Code: Benjamin Weiss (Neofonie Mobile Gmbh) et al. \n \u00A0 Idea: Cyril Mottier \n \u00A0 Apache License, Version 2.0\nBase16Encoder\n \u00A0 http://openjpa.apache.org/\n \u00A0 Marc Prud\'hommeaux \n \u00A0 Apache OpenJPA\n MultipartEntity \n \u00A0 Apache Software Foundation \n \u00A0 Apache License, Version 2.0\nRssParser (learning-android)\n \u00A0 http://github.com/digitalspaghetti/learning-android\n \u00A0 Tane Piper \n \u00A0 Public Domain\nBase64\n \u00A0 http://iharder.net/base64\n \u00A0 Robert Harder \n \u00A0 Public Domain\nandroid-xmlrpc\n \u00A0 http://code.google.com/p/android-xmlrpc/\n \u00A0 pskink et al. \n \u00A0 Apache License, Version 2.0\nandroid-ColorPickerPreference\n \u00A0 https://github.com/attenzione/android-ColorPickerPreference\n \u00A0 Daniel Nilsson and Sergey Margaritov \n \u00A0 Apache License, Version 2.0\nCheckableRelativeLayout\n \u00A0 http://www.marvinlabs.com/2010/10/custom-listview-ability-check-items/\n \u00A0 Cédric Caron (MarvinLabs)\n \u00A0 Public Domain\nFunnel icon\n \u00A0 http://thenounproject.com/noun/funnel/#icon-No5608\n \u00A0 Naomi Atkinson from The Noun Project\n \u00A0 Creative Commons Attribution 3.0
Manage your torrents from your Android device
diff --git a/core/src/org/transdroid/core/gui/DetailsActivity.java b/core/src/org/transdroid/core/gui/DetailsActivity.java
index 0f3c816d..50a5dcde 100644
--- a/core/src/org/transdroid/core/gui/DetailsActivity.java
+++ b/core/src/org/transdroid/core/gui/DetailsActivity.java
@@ -32,6 +32,7 @@ import org.androidannotations.annotations.UiThread;
import org.transdroid.core.R;
import org.transdroid.core.app.settings.*;
import org.transdroid.core.gui.lists.LocalTorrent;
+import org.transdroid.core.gui.lists.NoProgressHeaderTransformer;
import org.transdroid.core.gui.log.Log;
import org.transdroid.core.gui.navigation.Label;
import org.transdroid.core.gui.navigation.NavigationHelper;
@@ -62,10 +63,15 @@ import org.transdroid.daemon.task.SetTrackersTask;
import org.transdroid.daemon.task.StartTask;
import org.transdroid.daemon.task.StopTask;
+import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher;
+import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher.OnRefreshListener;
+import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher.Options;
+
import android.annotation.TargetApi;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
+import android.view.View;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragmentActivity;
@@ -97,6 +103,7 @@ public class DetailsActivity extends SherlockFragmentActivity implements Torrent
@Bean
protected ApplicationSettings applicationSettings;
private IDaemonAdapter currentConnection = null;
+ private PullToRefreshAttacher pullToRefreshAttacher = null;
// Details view components
@FragmentById(resName = "torrent_details")
@@ -148,6 +155,28 @@ public class DetailsActivity extends SherlockFragmentActivity implements Torrent
TorrentsActivity_.intent(this).flags(Intent.FLAG_ACTIVITY_CLEAR_TOP).start();
}
+ /**
+ * Attaches some view (perhaps contained in a fragment) to this activity's pull to refresh support
+ * @param view The view to attach
+ */
+ @Override
+ public void addRefreshableView(View view) {
+ if (pullToRefreshAttacher == null) {
+ // Still need to initialise the PullToRefreshAttacher
+ Options options = new PullToRefreshAttacher.Options();
+ options.headerTransformer = new NoProgressHeaderTransformer();
+ pullToRefreshAttacher = PullToRefreshAttacher.get(this, options);
+ }
+ pullToRefreshAttacher.addRefreshableView(view, new OnRefreshListener() {
+ @Override
+ public void onRefreshStarted(View view) {
+ // Just refresh the full screen, now that the user has pulled to refresh
+ pullToRefreshAttacher.setRefreshComplete();
+ refreshScreen();
+ }
+ });
+ }
+
@OptionsItem(resName = "action_refresh")
public void refreshScreen() {
fragmentDetails.updateIsLoading(true, null);
@@ -330,7 +359,7 @@ public class DetailsActivity extends SherlockFragmentActivity implements Torrent
protected void onCommunicationError(DaemonTaskFailureResult result, boolean isCritical) {
Log.i(this, result.getException().toString());
String error = getString(LocalTorrent.getResourceForDaemonException(result.getException()));
- fragmentDetails.updateIsLoading(false, isCritical? error: null);
+ fragmentDetails.updateIsLoading(false, isCritical ? error : null);
Crouton.showText(this, getString(LocalTorrent.getResourceForDaemonException(result.getException())),
NavigationHelper.CROUTON_ERROR_STYLE);
}
diff --git a/core/src/org/transdroid/core/gui/DetailsFragment.java b/core/src/org/transdroid/core/gui/DetailsFragment.java
index d38c26d2..29de8d05 100644
--- a/core/src/org/transdroid/core/gui/DetailsFragment.java
+++ b/core/src/org/transdroid/core/gui/DetailsFragment.java
@@ -119,6 +119,11 @@ public class DetailsFragment extends SherlockFragment implements OnTrackersUpdat
detailsList.setAdapter(new DetailsAdapter(getActivity()));
detailsList.setMultiChoiceModeListener(onDetailsSelected);
detailsList.setFastScrollEnabled(true);
+ if (getActivity() != null && getActivity() instanceof RefreshableActivity) {
+ ((RefreshableActivity) getActivity()).addRefreshableView(detailsList);
+ }
+
+ // Restore the fragment state (on orientation changes et al.)
if (torrent != null)
updateTorrent(torrent);
if (torrentDetails != null)
diff --git a/core/src/org/transdroid/core/gui/TorrentsActivity.java b/core/src/org/transdroid/core/gui/TorrentsActivity.java
index 11499432..01cc2eee 100644
--- a/core/src/org/transdroid/core/gui/TorrentsActivity.java
+++ b/core/src/org/transdroid/core/gui/TorrentsActivity.java
@@ -46,6 +46,7 @@ import org.apache.http.impl.cookie.BasicClientCookie;
import org.transdroid.core.R;
import org.transdroid.core.app.settings.*;
import org.transdroid.core.gui.lists.LocalTorrent;
+import org.transdroid.core.gui.lists.NoProgressHeaderTransformer;
import org.transdroid.core.gui.lists.SimpleListItem;
import org.transdroid.core.gui.log.*;
import org.transdroid.core.gui.navigation.*;
@@ -92,6 +93,10 @@ import org.transdroid.daemon.task.StopTask;
import org.transdroid.daemon.util.DLog;
import org.transdroid.daemon.util.HttpHelper;
+import uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock.PullToRefreshAttacher;
+import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher.OnRefreshListener;
+import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher.Options;
+
import android.annotation.TargetApi;
import android.app.SearchManager;
import android.content.ContentResolver;
@@ -138,6 +143,7 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
@SystemService
protected SearchManager searchManager;
private MenuItem searchMenu = null;
+ private PullToRefreshAttacher pullToRefreshAttacher = null;
// Settings
@Bean
@@ -571,6 +577,28 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
startSearch(query, false, null, false);
}
+ /**
+ * Attaches some view (perhaps contained in a fragment) to this activity's pull to refresh support
+ * @param view The view to attach
+ */
+ @Override
+ public void addRefreshableView(View view) {
+ if (pullToRefreshAttacher == null) {
+ // Still need to initialise the PullToRefreshAttacher
+ Options options = new PullToRefreshAttacher.Options();
+ options.headerTransformer = new NoProgressHeaderTransformer();
+ pullToRefreshAttacher = PullToRefreshAttacher.get(this, options);
+ }
+ pullToRefreshAttacher.addRefreshableView(view, new OnRefreshListener() {
+ @Override
+ public void onRefreshStarted(View view) {
+ // Just refresh the full screen, now that the user has pulled to refresh
+ pullToRefreshAttacher.setRefreshComplete();
+ refreshScreen();
+ }
+ });
+ }
+
@OptionsItem(resName = "action_refresh")
public void refreshScreen() {
fragmentTorrents.updateIsLoading(true);
diff --git a/core/src/org/transdroid/core/gui/TorrentsFragment.java b/core/src/org/transdroid/core/gui/TorrentsFragment.java
index 5a9333a0..680b4068 100644
--- a/core/src/org/transdroid/core/gui/TorrentsFragment.java
+++ b/core/src/org/transdroid/core/gui/TorrentsFragment.java
@@ -114,6 +114,10 @@ public class TorrentsFragment extends SherlockFragment implements OnLabelPickedL
torrentsList.setFastScrollEnabled(true);
if (torrents != null)
updateTorrents(torrents, currentLabels);
+ // Allow pulls on the list view to refresh the torrents
+ if (getActivity() != null && getActivity() instanceof RefreshableActivity) {
+ ((RefreshableActivity) getActivity()).addRefreshableView(torrentsList);
+ }
nosettingsText.setText(getString(R.string.navigation_nosettings, getString(R.string.app_name)));
}
diff --git a/core/src/org/transdroid/core/gui/lists/NoProgressHeaderTransformer.java b/core/src/org/transdroid/core/gui/lists/NoProgressHeaderTransformer.java
new file mode 100644
index 00000000..a9abcee2
--- /dev/null
+++ b/core/src/org/transdroid/core/gui/lists/NoProgressHeaderTransformer.java
@@ -0,0 +1,17 @@
+package org.transdroid.core.gui.lists;
+
+import org.transdroid.core.R;
+
+import android.app.Activity;
+import android.view.View;
+import uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock.AbsDefaultHeaderTransformer;
+
+public class NoProgressHeaderTransformer extends AbsDefaultHeaderTransformer {
+
+ @Override
+ public void onViewCreated(Activity activity, View headerView) {
+ super.onViewCreated(activity, headerView);
+ setProgressBarColor(activity.getResources().getColor(R.color.green));
+ }
+
+}
diff --git a/core/src/org/transdroid/core/gui/navigation/RefreshableActivity.java b/core/src/org/transdroid/core/gui/navigation/RefreshableActivity.java
index b5df126a..37ab45af 100644
--- a/core/src/org/transdroid/core/gui/navigation/RefreshableActivity.java
+++ b/core/src/org/transdroid/core/gui/navigation/RefreshableActivity.java
@@ -16,6 +16,8 @@
*/
package org.transdroid.core.gui.navigation;
+import android.view.View;
+
/**
* Interface to be implemented by any activity that allows its content to be refreshed; fragments can ask for
* user-initiated refreshes.
@@ -25,4 +27,6 @@ public interface RefreshableActivity {
public void refreshScreen();
+ public void addRefreshableView(View view);
+
}
diff --git a/core/src/org/transdroid/core/service/AppUpdateService.java b/core/src/org/transdroid/core/service/AppUpdateService.java
index 7cdf6975..ef7a29e1 100644
--- a/core/src/org/transdroid/core/service/AppUpdateService.java
+++ b/core/src/org/transdroid/core/service/AppUpdateService.java
@@ -79,7 +79,7 @@ public class AppUpdateService extends IntentService {
Date lastChecked = systemSettings.getLastCheckedForAppUpdates();
Calendar lastDay = Calendar.getInstance();
lastDay.add(Calendar.DAY_OF_MONTH, -1);
- if (lastChecked == null || lastChecked.after(lastDay.getTime())) {
+ if (lastChecked != null && lastChecked.after(lastDay.getTime())) {
Log.d(this, "Ship the update service, as we already checked the last 24 hours (or to be exact at "
+ lastChecked.toString() + ").");
return;
diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/AndroidManifest.xml b/external/ActionBar-PullToRefresh-actionbarsherlock/AndroidManifest.xml
new file mode 100644
index 00000000..ae76ec35
--- /dev/null
+++ b/external/ActionBar-PullToRefresh-actionbarsherlock/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/build.gradle b/external/ActionBar-PullToRefresh-actionbarsherlock/build.gradle
new file mode 100644
index 00000000..2ca4be69
--- /dev/null
+++ b/external/ActionBar-PullToRefresh-actionbarsherlock/build.gradle
@@ -0,0 +1,25 @@
+apply plugin: 'android-library'
+
+dependencies {
+ compile project(':library')
+ compile "com.android.support:support-v4:[18.0,)"
+ compile ("com.actionbarsherlock:actionbarsherlock:[4.4,)@aar") {
+ // Need to specifically exclude this as it is specified in ActionBarSherlock pom
+ exclude group: 'com.google.android', module: 'support-v4'
+ }
+}
+
+android {
+ compileSdkVersion 18
+ buildToolsVersion '17.0.0'
+
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src']
+ res.srcDirs = ['res']
+ }
+ }
+}
+
+apply from: '../../maven_push.gradle'
diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/build.xml b/external/ActionBar-PullToRefresh-actionbarsherlock/build.xml
new file mode 100644
index 00000000..390ff5f3
--- /dev/null
+++ b/external/ActionBar-PullToRefresh-actionbarsherlock/build.xml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/gradle.properties b/external/ActionBar-PullToRefresh-actionbarsherlock/gradle.properties
new file mode 100644
index 00000000..3a29e9ee
--- /dev/null
+++ b/external/ActionBar-PullToRefresh-actionbarsherlock/gradle.properties
@@ -0,0 +1,3 @@
+POM_NAME=ActionBar-PullToRefresh Extras: ActionBarSherlock
+POM_ARTIFACT_ID=extra-abs
+POM_PACKAGING=aar
diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/proguard-project.txt b/external/ActionBar-PullToRefresh-actionbarsherlock/proguard-project.txt
new file mode 100644
index 00000000..f2fe1559
--- /dev/null
+++ b/external/ActionBar-PullToRefresh-actionbarsherlock/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/project.properties b/external/ActionBar-PullToRefresh-actionbarsherlock/project.properties
new file mode 100644
index 00000000..367cb5d5
--- /dev/null
+++ b/external/ActionBar-PullToRefresh-actionbarsherlock/project.properties
@@ -0,0 +1,17 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-18
+android.library=true
+android.library.reference.1=../ActionBar-PullToRefresh
+android.library.reference.2=../JakeWharton-ActionBarSherlock/library
diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/res/anim/fade_in.xml b/external/ActionBar-PullToRefresh-actionbarsherlock/res/anim/fade_in.xml
new file mode 100644
index 00000000..fd820b3a
--- /dev/null
+++ b/external/ActionBar-PullToRefresh-actionbarsherlock/res/anim/fade_in.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/res/anim/fade_out.xml b/external/ActionBar-PullToRefresh-actionbarsherlock/res/anim/fade_out.xml
new file mode 100644
index 00000000..aad49484
--- /dev/null
+++ b/external/ActionBar-PullToRefresh-actionbarsherlock/res/anim/fade_out.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/src/uk/co/senab/actionbarpulltorefresh/extras/actionbarsherlock/AbsDefaultHeaderTransformer.java b/external/ActionBar-PullToRefresh-actionbarsherlock/src/uk/co/senab/actionbarpulltorefresh/extras/actionbarsherlock/AbsDefaultHeaderTransformer.java
new file mode 100644
index 00000000..3fd83be8
--- /dev/null
+++ b/external/ActionBar-PullToRefresh-actionbarsherlock/src/uk/co/senab/actionbarpulltorefresh/extras/actionbarsherlock/AbsDefaultHeaderTransformer.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2013 Chris Banes
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+
+import uk.co.senab.actionbarpulltorefresh.library.DefaultHeaderTransformer;
+
+public class AbsDefaultHeaderTransformer extends DefaultHeaderTransformer {
+
+ private Animation mHeaderInAnimation, mHeaderOutAnimation;
+
+ @Override
+ public void onViewCreated(Activity activity, View headerView) {
+ super.onViewCreated(activity, headerView);
+
+ // Create animations for use later
+ mHeaderInAnimation = AnimationUtils.loadAnimation(activity, R.anim.fade_in);
+ mHeaderOutAnimation = AnimationUtils.loadAnimation(activity, R.anim.fade_out);
+
+ if (mHeaderOutAnimation != null || mHeaderInAnimation != null) {
+ final AnimationCallback callback = new AnimationCallback();
+ if (mHeaderOutAnimation != null) {
+ mHeaderOutAnimation.setAnimationListener(callback);
+ }
+ }
+ }
+
+ @Override
+ protected Drawable getActionBarBackground(Context context) {
+ // Super handles ICS+ anyway...
+ if (Build.VERSION.SDK_INT >= super.getMinimumApiLevel()) {
+ return super.getActionBarBackground(context);
+ }
+
+ // Get action bar style values...
+ TypedArray abStyle = obtainStyledAttrsFromThemeAttr(context, R.attr.actionBarStyle,
+ R.styleable.SherlockActionBar);
+ try {
+ return abStyle.getDrawable(R.styleable.SherlockActionBar_background);
+ } finally {
+ abStyle.recycle();
+ }
+ }
+
+ @Override
+ protected int getActionBarSize(Context context) {
+ // Super handles ICS+ anyway...
+ if (Build.VERSION.SDK_INT >= super.getMinimumApiLevel()) {
+ return super.getActionBarSize(context);
+ }
+
+ TypedArray values = context.obtainStyledAttributes(R.styleable.SherlockTheme);
+ try {
+ return values.getDimensionPixelSize(R.styleable.SherlockTheme_actionBarSize, 0);
+ } finally {
+ values.recycle();
+ }
+ }
+
+ @Override
+ protected int getActionBarTitleStyle(Context context) {
+ // Super handles ICS+ anyway...
+ if (Build.VERSION.SDK_INT >= super.getMinimumApiLevel()) {
+ return super.getActionBarTitleStyle(context);
+ }
+
+ // Get action bar style values...
+ TypedArray abStyle = obtainStyledAttrsFromThemeAttr(context, R.attr.actionBarStyle,
+ R.styleable.SherlockActionBar);
+ try {
+ return abStyle.getResourceId(R.styleable.SherlockActionBar_titleTextStyle, 0);
+ } finally {
+ abStyle.recycle();
+ }
+ }
+
+ @Override
+ public boolean showHeaderView() {
+ // Super handles ICS+ anyway...
+ if (Build.VERSION.SDK_INT >= super.getMinimumApiLevel()) {
+ return super.showHeaderView();
+ }
+
+ final View headerView = getHeaderView();
+ final boolean changeVis = headerView != null && headerView.getVisibility() != View.VISIBLE;
+ if (changeVis) {
+ // Show Header
+ if (mHeaderInAnimation != null) {
+ // AnimationListener will call HeaderViewListener
+ headerView.startAnimation(mHeaderInAnimation);
+ }
+ headerView.setVisibility(View.VISIBLE);
+ }
+ return changeVis;
+ }
+
+ @Override
+ public boolean hideHeaderView() {
+ // Super handles ICS+ anyway...
+ if (Build.VERSION.SDK_INT >= super.getMinimumApiLevel()) {
+ return super.hideHeaderView();
+ }
+
+ final View headerView = getHeaderView();
+ final boolean changeVis = headerView != null && headerView.getVisibility() != View.GONE;
+ if (changeVis) {
+ // Hide Header
+ if (mHeaderOutAnimation != null) {
+ // AnimationListener will call HeaderTransformer and
+ // HeaderViewListener
+ headerView.startAnimation(mHeaderOutAnimation);
+ } else {
+ // As we're not animating, hide the header + call the header
+ // transformer now
+ headerView.setVisibility(View.GONE);
+ onReset();
+ }
+ }
+ return changeVis;
+ }
+
+ @Override
+ public void onRefreshMinimized() {
+ // Super handles ICS+ anyway...
+ if (Build.VERSION.SDK_INT >= super.getMinimumApiLevel()) {
+ super.onRefreshMinimized();
+ return;
+ }
+
+ // Here we fade out most of the header, leaving just the progress bar
+ View contentLayout = getHeaderView().findViewById(R.id.ptr_content);
+ if (contentLayout != null) {
+ contentLayout.startAnimation(AnimationUtils
+ .loadAnimation(contentLayout.getContext(), R.anim.fade_out));
+ contentLayout.setVisibility(View.INVISIBLE);
+ }
+ }
+
+ @Override
+ protected int getMinimumApiLevel() {
+ return Build.VERSION_CODES.ECLAIR_MR1;
+ }
+
+ class AnimationCallback implements Animation.AnimationListener {
+
+ @Override
+ public void onAnimationStart(Animation animation) {
+ }
+
+ @Override
+ public void onAnimationEnd(Animation animation) {
+ if (animation == mHeaderOutAnimation) {
+ View headerView = getHeaderView();
+ if (headerView != null) {
+ headerView.setVisibility(View.GONE);
+ }
+ onReset();
+ }
+ }
+
+ @Override
+ public void onAnimationRepeat(Animation animation) {
+ }
+ }
+}
diff --git a/external/ActionBar-PullToRefresh-actionbarsherlock/src/uk/co/senab/actionbarpulltorefresh/extras/actionbarsherlock/PullToRefreshAttacher.java b/external/ActionBar-PullToRefresh-actionbarsherlock/src/uk/co/senab/actionbarpulltorefresh/extras/actionbarsherlock/PullToRefreshAttacher.java
new file mode 100644
index 00000000..aad995c5
--- /dev/null
+++ b/external/ActionBar-PullToRefresh-actionbarsherlock/src/uk/co/senab/actionbarpulltorefresh/extras/actionbarsherlock/PullToRefreshAttacher.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2013 Chris Banes
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock;
+
+import com.actionbarsherlock.app.SherlockActivity;
+import com.actionbarsherlock.app.SherlockExpandableListActivity;
+import com.actionbarsherlock.app.SherlockFragmentActivity;
+import com.actionbarsherlock.app.SherlockListActivity;
+import com.actionbarsherlock.app.SherlockPreferenceActivity;
+
+import android.app.Activity;
+import android.content.Context;
+
+public class PullToRefreshAttacher extends
+ uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher {
+
+ public static PullToRefreshAttacher get(Activity activity) {
+ return get(activity, new Options());
+ }
+
+ public static PullToRefreshAttacher get(Activity activity, Options options) {
+ return new PullToRefreshAttacher(activity, options);
+ }
+
+ protected PullToRefreshAttacher(Activity activity, Options options) {
+ super(activity, options);
+ }
+
+ @Override
+ protected EnvironmentDelegate createDefaultEnvironmentDelegate() {
+ return new AbsEnvironmentDelegate();
+ }
+
+ @Override
+ protected HeaderTransformer createDefaultHeaderTransformer() {
+ return new AbsDefaultHeaderTransformer();
+ }
+
+ public static class AbsEnvironmentDelegate extends EnvironmentDelegate {
+ /**
+ * @return Context which should be used for inflating the header layout
+ */
+ public Context getContextForInflater(Activity activity) {
+ if (activity instanceof SherlockActivity) {
+ return ((SherlockActivity) activity).getSupportActionBar().getThemedContext();
+ } else if (activity instanceof SherlockListActivity) {
+ return ((SherlockListActivity) activity).getSupportActionBar().getThemedContext();
+ } else if (activity instanceof SherlockFragmentActivity) {
+ return ((SherlockFragmentActivity) activity).getSupportActionBar()
+ .getThemedContext();
+ } else if (activity instanceof SherlockExpandableListActivity) {
+ return ((SherlockExpandableListActivity) activity).getSupportActionBar()
+ .getThemedContext();
+ } else if (activity instanceof SherlockPreferenceActivity) {
+ return ((SherlockPreferenceActivity) activity).getSupportActionBar()
+ .getThemedContext();
+ }
+ return super.getContextForInflater(activity);
+ }
+ }
+}
diff --git a/external/ActionBar-PullToRefresh/AndroidManifest.xml b/external/ActionBar-PullToRefresh/AndroidManifest.xml
new file mode 100644
index 00000000..fc808f4f
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/external/ActionBar-PullToRefresh/build.gradle b/external/ActionBar-PullToRefresh/build.gradle
new file mode 100644
index 00000000..625d8f23
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/build.gradle
@@ -0,0 +1,16 @@
+apply plugin: 'android-library'
+
+android {
+ compileSdkVersion 18
+ buildToolsVersion '17.0.0'
+
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src']
+ res.srcDirs = ['res']
+ }
+ }
+}
+
+apply from: '../maven_push.gradle'
\ No newline at end of file
diff --git a/external/ActionBar-PullToRefresh/build.xml b/external/ActionBar-PullToRefresh/build.xml
new file mode 100644
index 00000000..1b4d11f9
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/build.xml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/external/ActionBar-PullToRefresh/gradle.properties b/external/ActionBar-PullToRefresh/gradle.properties
new file mode 100644
index 00000000..7d783d1a
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/gradle.properties
@@ -0,0 +1,3 @@
+POM_NAME=ActionBar-PullToRefresh Library
+POM_ARTIFACT_ID=library
+POM_PACKAGING=aar
diff --git a/external/ActionBar-PullToRefresh/proguard-project.txt b/external/ActionBar-PullToRefresh/proguard-project.txt
new file mode 100644
index 00000000..f2fe1559
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/external/ActionBar-PullToRefresh/project.properties b/external/ActionBar-PullToRefresh/project.properties
new file mode 100644
index 00000000..1b8c5a34
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/project.properties
@@ -0,0 +1,15 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-18
+android.library=true
diff --git a/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progress_primary_holo.9.png b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progress_primary_holo.9.png
new file mode 100644
index 00000000..cc547884
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progress_primary_holo.9.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo1.png b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo1.png
new file mode 100644
index 00000000..9436297d
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo1.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo2.png b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo2.png
new file mode 100644
index 00000000..a7155975
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo2.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo3.png b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo3.png
new file mode 100644
index 00000000..d2c6e88d
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo3.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo4.png b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo4.png
new file mode 100644
index 00000000..06204753
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo4.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo5.png b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo5.png
new file mode 100644
index 00000000..8b2f09a8
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo5.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo6.png b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo6.png
new file mode 100644
index 00000000..48ba1b4d
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo6.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo7.png b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo7.png
new file mode 100644
index 00000000..34f15ce4
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo7.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo8.png b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo8.png
new file mode 100644
index 00000000..7c943e3c
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-hdpi/ptr_progressbar_indeterminate_holo8.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progress_primary_holo.9.png b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progress_primary_holo.9.png
new file mode 100644
index 00000000..0f542a32
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progress_primary_holo.9.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo1.png b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo1.png
new file mode 100644
index 00000000..c59fb19b
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo1.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo2.png b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo2.png
new file mode 100644
index 00000000..59681cb5
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo2.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo3.png b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo3.png
new file mode 100644
index 00000000..74fe49f2
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo3.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo4.png b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo4.png
new file mode 100644
index 00000000..143d63c4
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo4.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo5.png b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo5.png
new file mode 100644
index 00000000..8db70e74
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo5.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo6.png b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo6.png
new file mode 100644
index 00000000..fab55fa5
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo6.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo7.png b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo7.png
new file mode 100644
index 00000000..feec26b9
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo7.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo8.png b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo8.png
new file mode 100644
index 00000000..88432428
Binary files /dev/null and b/external/ActionBar-PullToRefresh/res/drawable-xhdpi/ptr_progressbar_indeterminate_holo8.png differ
diff --git a/external/ActionBar-PullToRefresh/res/drawable/ptr_progress_horizontal_holo_center.xml b/external/ActionBar-PullToRefresh/res/drawable/ptr_progress_horizontal_holo_center.xml
new file mode 100644
index 00000000..ed1d0c7a
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/drawable/ptr_progress_horizontal_holo_center.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+ -
+
+
+
+
\ No newline at end of file
diff --git a/external/ActionBar-PullToRefresh/res/drawable/ptr_progress_indeterminate_horizontal_holo.xml b/external/ActionBar-PullToRefresh/res/drawable/ptr_progress_indeterminate_horizontal_holo.xml
new file mode 100644
index 00000000..b55003e6
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/drawable/ptr_progress_indeterminate_horizontal_holo.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/external/ActionBar-PullToRefresh/res/layout/default_header.xml b/external/ActionBar-PullToRefresh/res/layout/default_header.xml
new file mode 100644
index 00000000..4a3619e2
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/layout/default_header.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/external/ActionBar-PullToRefresh/res/values-ar/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-ar/pull_refresh_strings.xml
new file mode 100644
index 00000000..c7de7f8c
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-ar/pull_refresh_strings.xml
@@ -0,0 +1,21 @@
+
+
+
+ اسحب للتحديث…
+ اترك للتحديث…
+ تحميل…
+
diff --git a/external/ActionBar-PullToRefresh/res/values-cs/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-cs/pull_refresh_strings.xml
new file mode 100755
index 00000000..97240bec
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-cs/pull_refresh_strings.xml
@@ -0,0 +1,21 @@
+
+
+
+ Tažením aktualizujete…
+ Uvolněním aktualizujete…
+ Načítání…
+
diff --git a/external/ActionBar-PullToRefresh/res/values-de/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-de/pull_refresh_strings.xml
new file mode 100755
index 00000000..c5ac00bc
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-de/pull_refresh_strings.xml
@@ -0,0 +1,21 @@
+
+
+
+ Ziehen zum Aktualisieren…
+ Loslassen zum Aktualisieren…
+ Laden…
+
diff --git a/external/ActionBar-PullToRefresh/res/values-es/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-es/pull_refresh_strings.xml
new file mode 100755
index 00000000..04894df2
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-es/pull_refresh_strings.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ Desliza el dedo hacia abajo para actualizar.
+ Soltar para actualizar…
+ Cargando…
+
diff --git a/external/ActionBar-PullToRefresh/res/values-fi/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-fi/pull_refresh_strings.xml
new file mode 100755
index 00000000..bc8d32a5
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-fi/pull_refresh_strings.xml
@@ -0,0 +1,21 @@
+
+
+
+ Päivitä vetämällä alas…
+ Päivitä vapauttamalla…
+ Päivitetään…
+
\ No newline at end of file
diff --git a/external/ActionBar-PullToRefresh/res/values-fr/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-fr/pull_refresh_strings.xml
new file mode 100755
index 00000000..0005f8cf
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-fr/pull_refresh_strings.xml
@@ -0,0 +1,21 @@
+
+
+
+ Tirez pour rafraîchir…
+ Relâcher pour rafraîchir…
+ Chargement…
+
diff --git a/external/ActionBar-PullToRefresh/res/values-he/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-he/pull_refresh_strings.xml
new file mode 100644
index 00000000..a6a13281
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-he/pull_refresh_strings.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ משוך לרענון…
+ שחרר לרענון…
+ טוען…
+
diff --git a/external/ActionBar-PullToRefresh/res/values-it/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-it/pull_refresh_strings.xml
new file mode 100755
index 00000000..9476c787
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-it/pull_refresh_strings.xml
@@ -0,0 +1,21 @@
+
+
+
+ Tira per aggiornare…
+ Rilascia per aggionare…
+ Caricamento…
+
diff --git a/external/ActionBar-PullToRefresh/res/values-iw/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-iw/pull_refresh_strings.xml
new file mode 100644
index 00000000..539b7aaa
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-iw/pull_refresh_strings.xml
@@ -0,0 +1,21 @@
+
+
+
+ משוך לרענון…
+ שחרר לרענון…
+ טוען…
+
diff --git a/external/ActionBar-PullToRefresh/res/values-ja/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-ja/pull_refresh_strings.xml
new file mode 100644
index 00000000..5c400234
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-ja/pull_refresh_strings.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ 画面を引っ張って…
+ 指を離して更新…
+ 読み込み中…
+
diff --git a/external/ActionBar-PullToRefresh/res/values-ko/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-ko/pull_refresh_strings.xml
new file mode 100755
index 00000000..7f642cb4
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-ko/pull_refresh_strings.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ 당겨서 새로 고침…
+ 놓아서 새로 고침…
+ 로드 중…
+
diff --git a/external/ActionBar-PullToRefresh/res/values-nl/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-nl/pull_refresh_strings.xml
new file mode 100755
index 00000000..016e7bd4
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-nl/pull_refresh_strings.xml
@@ -0,0 +1,21 @@
+
+
+
+ Sleep om te vernieuwen…
+ Loslaten om te vernieuwen…
+ Laden…
+
diff --git a/external/ActionBar-PullToRefresh/res/values-pl/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-pl/pull_refresh_strings.xml
new file mode 100755
index 00000000..be33a27e
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-pl/pull_refresh_strings.xml
@@ -0,0 +1,21 @@
+
+
+
+ Pociągnij, aby odświeżyć…
+ Puść, aby odświeżyć…
+ Wczytywanie…
+
diff --git a/external/ActionBar-PullToRefresh/res/values-pt-rBR/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-pt-rBR/pull_refresh_strings.xml
new file mode 100755
index 00000000..d12ab0c8
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-pt-rBR/pull_refresh_strings.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ Puxe para atualizar…
+ Libere para atualizar…
+ Carregando…
+
diff --git a/external/ActionBar-PullToRefresh/res/values-pt/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-pt/pull_refresh_strings.xml
new file mode 100755
index 00000000..a49e011f
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-pt/pull_refresh_strings.xml
@@ -0,0 +1,21 @@
+
+
+
+ Puxe para atualizar…
+ Liberação para atualizar…
+ A carregar…
+
diff --git a/external/ActionBar-PullToRefresh/res/values-ro/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-ro/pull_refresh_strings.xml
new file mode 100644
index 00000000..7bc25483
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-ro/pull_refresh_strings.xml
@@ -0,0 +1,21 @@
+
+
+
+ Trage pentru a reîmprospăta…
+ Eliberează pentru a reîmprospăta…
+ Încărcare…
+
diff --git a/external/ActionBar-PullToRefresh/res/values-ru/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-ru/pull_refresh_strings.xml
new file mode 100755
index 00000000..7e433f66
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-ru/pull_refresh_strings.xml
@@ -0,0 +1,21 @@
+
+
+
+ потяните
+ отпустите
+ обновление
+
diff --git a/external/ActionBar-PullToRefresh/res/values-sv/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-sv/pull_refresh_strings.xml
new file mode 100755
index 00000000..14d6def5
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-sv/pull_refresh_strings.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ Dra nedåt om du vill uppdatera
+ Släpp om du vill uppdatera
+ Uppdaterar…
+
+
diff --git a/external/ActionBar-PullToRefresh/res/values-zh/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values-zh/pull_refresh_strings.xml
new file mode 100755
index 00000000..73d787a5
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values-zh/pull_refresh_strings.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ 下拉刷新…
+ 放开以刷新…
+ 正在载入…
+
diff --git a/external/ActionBar-PullToRefresh/res/values/attrs.xml b/external/ActionBar-PullToRefresh/res/values/attrs.xml
new file mode 100644
index 00000000..83cc026d
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values/attrs.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/external/ActionBar-PullToRefresh/res/values/ids.xml b/external/ActionBar-PullToRefresh/res/values/ids.xml
new file mode 100644
index 00000000..df504085
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values/ids.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/external/ActionBar-PullToRefresh/res/values/pull_refresh_strings.xml b/external/ActionBar-PullToRefresh/res/values/pull_refresh_strings.xml
new file mode 100755
index 00000000..d5f8714c
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values/pull_refresh_strings.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ Pull to refresh…
+ Release to refresh…
+ Loading…
+
+
diff --git a/external/ActionBar-PullToRefresh/res/values/styles.xml b/external/ActionBar-PullToRefresh/res/values/styles.xml
new file mode 100644
index 00000000..35d7cbb4
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/res/values/styles.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/DefaultHeaderTransformer.java b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/DefaultHeaderTransformer.java
new file mode 100644
index 00000000..d5989de4
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/DefaultHeaderTransformer.java
@@ -0,0 +1,397 @@
+/*
+ * Copyright 2013 Chris Banes
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.co.senab.actionbarpulltorefresh.library;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import uk.co.senab.actionbarpulltorefresh.library.platform.SDK11;
+
+/**
+ * Default Header Transformer.
+ */
+public class DefaultHeaderTransformer extends PullToRefreshAttacher.HeaderTransformer {
+
+ private View mHeaderView;
+ private ViewGroup mContentLayout;
+ private TextView mHeaderTextView;
+ private ProgressBar mHeaderProgressBar;
+
+ private CharSequence mPullRefreshLabel, mRefreshingLabel, mReleaseLabel;
+
+ private boolean mUseCustomProgressColor = false;
+ private int mProgressDrawableColor;
+ private long mAnimationDuration;
+
+ private final Interpolator mInterpolator = new AccelerateInterpolator();
+
+ protected DefaultHeaderTransformer() {
+ final int min = getMinimumApiLevel();
+ if (Build.VERSION.SDK_INT < min) {
+ throw new IllegalStateException("This HeaderTransformer is designed to run on SDK "
+ + min
+ + "+. If using ActionBarSherlock or ActionBarCompat you should use the appropriate provided extra.");
+ }
+ }
+
+ @Override
+ public void onViewCreated(Activity activity, View headerView) {
+ mHeaderView = headerView;
+
+ // Get ProgressBar and TextView
+ mHeaderProgressBar = (ProgressBar) headerView.findViewById(R.id.ptr_progress);
+ mHeaderTextView = (TextView) headerView.findViewById(R.id.ptr_text);
+ mContentLayout = (ViewGroup) headerView.findViewById(R.id.ptr_content);
+
+ // Default Labels to display
+ mPullRefreshLabel = activity.getString(R.string.pull_to_refresh_pull_label);
+ mRefreshingLabel = activity.getString(R.string.pull_to_refresh_refreshing_label);
+ mReleaseLabel = activity.getString(R.string.pull_to_refresh_release_label);
+
+ mAnimationDuration = activity.getResources()
+ .getInteger(android.R.integer.config_shortAnimTime);
+
+ // Setup the View styles
+ setupViewsFromStyles(activity, headerView);
+
+ // Apply any custom ProgressBar colors
+ applyProgressBarColor();
+
+ // FIXME: I do not like this call here
+ onReset();
+ }
+
+ @Override
+ public void onConfigurationChanged(Activity activity, Configuration newConfig) {
+ setupViewsFromStyles(activity, getHeaderView());
+ }
+
+ @Override
+ public void onReset() {
+ // Reset Progress Bar
+ if (mHeaderProgressBar != null) {
+ mHeaderProgressBar.setVisibility(View.GONE);
+ mHeaderProgressBar.setProgress(0);
+ mHeaderProgressBar.setIndeterminate(false);
+ }
+
+ // Reset Text View
+ if (mHeaderTextView != null) {
+ mHeaderTextView.setVisibility(View.VISIBLE);
+ mHeaderTextView.setText(mPullRefreshLabel);
+ }
+
+ // Reset the Content Layout
+ if (mContentLayout != null) {
+ mContentLayout.setVisibility(View.VISIBLE);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ SDK11.setAlpha(mContentLayout, 1f);
+ }
+ }
+ }
+
+ @Override
+ public void onPulled(float percentagePulled) {
+ if (mHeaderProgressBar != null) {
+ mHeaderProgressBar.setVisibility(View.VISIBLE);
+ final float progress = mInterpolator.getInterpolation(percentagePulled);
+ mHeaderProgressBar.setProgress(Math.round(mHeaderProgressBar.getMax() * progress));
+ }
+ }
+
+ @Override
+ public void onRefreshStarted() {
+ if (mHeaderTextView != null) {
+ mHeaderTextView.setText(mRefreshingLabel);
+ }
+ if (mHeaderProgressBar != null) {
+ mHeaderProgressBar.setVisibility(View.VISIBLE);
+ mHeaderProgressBar.setIndeterminate(true);
+ }
+ }
+
+ @Override
+ public void onReleaseToRefresh() {
+ if (mHeaderTextView != null) {
+ mHeaderTextView.setText(mReleaseLabel);
+ }
+ if (mHeaderProgressBar != null) {
+ mHeaderProgressBar.setProgress(mHeaderProgressBar.getMax());
+ }
+ }
+
+ @Override
+ public void onRefreshMinimized() {
+ // Here we fade out most of the header, leaving just the progress bar
+ if (mContentLayout != null) {
+ ObjectAnimator.ofFloat(mContentLayout, "alpha", 1f, 0f).start();
+ }
+ }
+
+ public View getHeaderView() {
+ return mHeaderView;
+ }
+
+ @Override
+ public boolean showHeaderView() {
+ final boolean changeVis = mHeaderView.getVisibility() != View.VISIBLE;
+
+ if (changeVis) {
+ mHeaderView.setVisibility(View.VISIBLE);
+ AnimatorSet animSet = new AnimatorSet();
+ ObjectAnimator transAnim = ObjectAnimator.ofFloat(mContentLayout, "translationY",
+ -mContentLayout.getHeight(), 0f);
+ ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(mHeaderView, "alpha", 0f, 1f);
+ animSet.playTogether(transAnim, alphaAnim);
+ animSet.setDuration(mAnimationDuration);
+ animSet.start();
+ }
+
+ return changeVis;
+ }
+
+ @Override
+ public boolean hideHeaderView() {
+ final boolean changeVis = mHeaderView.getVisibility() != View.GONE;
+
+ if (changeVis) {
+ Animator animator;
+ if (mContentLayout.getAlpha() >= 0.5f) {
+ // If the content layout is showing, translate and fade out
+ animator = new AnimatorSet();
+ ObjectAnimator transAnim = ObjectAnimator.ofFloat(mContentLayout, "translationY",
+ 0f, -mContentLayout.getHeight());
+ ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(mHeaderView, "alpha", 1f, 0f);
+ ((AnimatorSet) animator).playTogether(transAnim, alphaAnim);
+ } else {
+ // If the content layout isn't showing (minimized), just fade out
+ animator = ObjectAnimator.ofFloat(mHeaderView, "alpha", 1f, 0f);
+ }
+ animator.setDuration(mAnimationDuration);
+ animator.addListener(new HideAnimationCallback());
+ animator.start();
+ }
+
+ return changeVis;
+ }
+
+ /**
+ * Set color to apply to the progress bar. Automatically enables usage of the custom color. Use
+ * {@link #setProgressBarColorEnabled(boolean)} to disable and re-enable the custom color usage.
+ *
+ * The best way to apply a color is to load the color from resources: {@code
+ * setProgressBarColor(getResources().getColor(R.color.your_color_name))}.
+ *
+ * @param color The color to use.
+ */
+ public void setProgressBarColor(int color) {
+ mProgressDrawableColor = color;
+ setProgressBarColorEnabled(true);
+ }
+
+ /**
+ * Enable or disable the use of a custom progress bar color. You can set what color to use with
+ * {@link #setProgressBarColor(int)}, which also automatically enables custom color usage.
+ */
+ public void setProgressBarColorEnabled(boolean enabled) {
+ mUseCustomProgressColor = enabled;
+ applyProgressBarColor();
+ }
+
+
+ /**
+ * Set Text to show to prompt the user is pull (or keep pulling).
+ *
+ * @param pullText - Text to display.
+ */
+ public void setPullText(CharSequence pullText) {
+ mPullRefreshLabel = pullText;
+ if (mHeaderTextView != null) {
+ mHeaderTextView.setText(mPullRefreshLabel);
+ }
+ }
+
+ /**
+ * Set Text to show to tell the user that a refresh is currently in progress.
+ *
+ * @param refreshingText - Text to display.
+ */
+ public void setRefreshingText(CharSequence refreshingText) {
+ mRefreshingLabel = refreshingText;
+ }
+
+ /**
+ * Set Text to show to tell the user has scrolled enough to refresh.
+ *
+ * @param releaseText - Text to display.
+ */
+ public void setReleaseText(CharSequence releaseText) {
+ mReleaseLabel = releaseText;
+ }
+
+ private void setupViewsFromStyles(Activity activity, View headerView) {
+ final TypedArray styleAttrs = obtainStyledAttrsFromThemeAttr(activity,
+ R.attr.ptrHeaderStyle, R.styleable.PullToRefreshHeader);
+
+ // Retrieve the Action Bar size from the app theme or the Action Bar's style
+ if (mContentLayout != null) {
+ final int height = styleAttrs
+ .getDimensionPixelSize(R.styleable.PullToRefreshHeader_ptrHeaderHeight,
+ getActionBarSize(activity));
+ mContentLayout.getLayoutParams().height = height;
+ mContentLayout.requestLayout();
+ }
+
+ // Retrieve the Action Bar background from the app theme or the Action Bar's style (see #93)
+ Drawable bg = styleAttrs.hasValue(R.styleable.PullToRefreshHeader_ptrHeaderBackground)
+ ? styleAttrs.getDrawable(R.styleable.PullToRefreshHeader_ptrHeaderBackground)
+ : getActionBarBackground(activity);
+ if (bg != null) {
+ mHeaderTextView.setBackgroundDrawable(bg);
+
+ // If we have an opaque background we can remove the background from the content layout
+ if (mContentLayout != null && bg.getOpacity() == PixelFormat.OPAQUE) {
+ mContentLayout.setBackgroundResource(0);
+ }
+ }
+
+ // Retrieve the Action Bar Title Style from the app theme or the Action Bar's style
+ Context abContext = headerView.getContext();
+ final int titleTextStyle = styleAttrs
+ .getResourceId(R.styleable.PullToRefreshHeader_ptrHeaderTitleTextAppearance,
+ getActionBarTitleStyle(abContext));
+ if (titleTextStyle != 0) {
+ mHeaderTextView.setTextAppearance(abContext, titleTextStyle);
+ }
+
+ // Retrieve the Progress Bar Color the style
+ if (styleAttrs.hasValue(R.styleable.PullToRefreshHeader_ptrProgressBarColor)) {
+ mUseCustomProgressColor = true;
+ mProgressDrawableColor = styleAttrs
+ .getColor(R.styleable.PullToRefreshHeader_ptrProgressBarColor, 0);
+ }
+
+ // Retrieve the text strings from the style (if they're set)
+ if (styleAttrs.hasValue(R.styleable.PullToRefreshHeader_ptrPullText)) {
+ mPullRefreshLabel = styleAttrs.getString(R.styleable.PullToRefreshHeader_ptrPullText);
+ }
+ if (styleAttrs.hasValue(R.styleable.PullToRefreshHeader_ptrRefreshingText)) {
+ mRefreshingLabel = styleAttrs
+ .getString(R.styleable.PullToRefreshHeader_ptrRefreshingText);
+ }
+ if (styleAttrs.hasValue(R.styleable.PullToRefreshHeader_ptrReleaseText)) {
+ mReleaseLabel = styleAttrs.getString(R.styleable.PullToRefreshHeader_ptrReleaseText);
+ }
+
+ styleAttrs.recycle();
+ }
+
+ private void applyProgressBarColor() {
+ if (mHeaderProgressBar != null) {
+ if (mUseCustomProgressColor) {
+ mHeaderProgressBar.getProgressDrawable()
+ .setColorFilter(mProgressDrawableColor, PorterDuff.Mode.SRC_ATOP);
+ mHeaderProgressBar.getIndeterminateDrawable()
+ .setColorFilter(mProgressDrawableColor, PorterDuff.Mode.SRC_ATOP);
+ } else {
+ mHeaderProgressBar.getProgressDrawable().clearColorFilter();
+ mHeaderProgressBar.getIndeterminateDrawable().clearColorFilter();
+ }
+ }
+ }
+
+ protected Drawable getActionBarBackground(Context context) {
+ int[] android_styleable_ActionBar = {android.R.attr.background};
+
+ // Now get the action bar style values...
+ TypedArray abStyle = obtainStyledAttrsFromThemeAttr(context, android.R.attr.actionBarStyle,
+ android_styleable_ActionBar);
+ try {
+ // background is the first attr in the array above so it's index is 0.
+ return abStyle.getDrawable(0);
+ } finally {
+ abStyle.recycle();
+ }
+ }
+
+ protected int getActionBarSize(Context context) {
+ int[] attrs = {android.R.attr.actionBarSize};
+ TypedArray values = context.getTheme().obtainStyledAttributes(attrs);
+ try {
+ return values.getDimensionPixelSize(0, 0);
+ } finally {
+ values.recycle();
+ }
+ }
+
+ protected int getActionBarTitleStyle(Context context) {
+ int[] android_styleable_ActionBar = {android.R.attr.titleTextStyle};
+
+ // Now get the action bar style values...
+ TypedArray abStyle = obtainStyledAttrsFromThemeAttr(context, android.R.attr.actionBarStyle,
+ android_styleable_ActionBar);
+ try {
+ // titleTextStyle is the first attr in the array above so it's index is 0.
+ return abStyle.getResourceId(0, 0);
+ } finally {
+ abStyle.recycle();
+ }
+ }
+
+ protected int getMinimumApiLevel() {
+ return Build.VERSION_CODES.ICE_CREAM_SANDWICH;
+ }
+
+ class HideAnimationCallback extends AnimatorListenerAdapter {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ View headerView = getHeaderView();
+ if (headerView != null) {
+ headerView.setVisibility(View.GONE);
+ }
+ onReset();
+ }
+ }
+
+ protected static TypedArray obtainStyledAttrsFromThemeAttr(Context context, int themeAttr,
+ int[] styleAttrs) {
+ // Need to get resource id of style pointed to from the theme attr
+ TypedValue outValue = new TypedValue();
+ context.getTheme().resolveAttribute(themeAttr, outValue, true);
+ final int styleResId = outValue.resourceId;
+
+ // Now return the values (from styleAttrs) from the style
+ return context.obtainStyledAttributes(styleResId, styleAttrs);
+ }
+}
diff --git a/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/InstanceCreationUtils.java b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/InstanceCreationUtils.java
new file mode 100644
index 00000000..77766f8a
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/InstanceCreationUtils.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2013 Chris Banes
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.co.senab.actionbarpulltorefresh.library;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.View;
+
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import uk.co.senab.actionbarpulltorefresh.library.viewdelegates.AbsListViewDelegate;
+import uk.co.senab.actionbarpulltorefresh.library.viewdelegates.ScrollYDelegate;
+import uk.co.senab.actionbarpulltorefresh.library.viewdelegates.WebViewDelegate;
+
+class InstanceCreationUtils {
+
+ private static final String LOG_TAG = "InstanceCreationUtils";
+
+ private static final Class>[] VIEW_DELEGATE_CONSTRUCTOR_SIGNATURE = new Class[]{};
+ private static final Class>[] TRANSFORMER_CONSTRUCTOR_SIGNATURE = new Class[]{};
+
+ private static final HashMap BUILT_IN_DELEGATES;
+ static {
+ BUILT_IN_DELEGATES = new HashMap();
+ BUILT_IN_DELEGATES.put(AbsListViewDelegate.SUPPORTED_VIEW_CLASS, AbsListViewDelegate.class);
+ BUILT_IN_DELEGATES.put(WebViewDelegate.SUPPORTED_VIEW_CLASS, WebViewDelegate.class);
+ }
+
+ static PullToRefreshAttacher.ViewDelegate getBuiltInViewDelegate(final View view) {
+ final Set> entries = BUILT_IN_DELEGATES.entrySet();
+ for (final Map.Entry entry : entries) {
+ if (entry.getKey().isInstance(view)) {
+ return InstanceCreationUtils.newInstance(view.getContext(),
+ entry.getValue(), VIEW_DELEGATE_CONSTRUCTOR_SIGNATURE, null);
+ }
+ }
+
+ // Default is the ScrollYDelegate
+ return InstanceCreationUtils.newInstance(view.getContext(),
+ ScrollYDelegate.class, VIEW_DELEGATE_CONSTRUCTOR_SIGNATURE, null);
+ }
+
+ static T instantiateViewDelegate(Context context, String className, Object[] arguments) {
+ try {
+ Class> clazz = context.getClassLoader().loadClass(className);
+ return newInstance(context, clazz, VIEW_DELEGATE_CONSTRUCTOR_SIGNATURE, arguments);
+ } catch (Exception e) {
+ Log.w(LOG_TAG, "Cannot instantiate class: " + className, e);
+ }
+ return null;
+ }
+
+ static T instantiateTransformer(Context context, String className, Object[] arguments) {
+ try {
+ Class> clazz = context.getClassLoader().loadClass(className);
+ return newInstance(context, clazz, TRANSFORMER_CONSTRUCTOR_SIGNATURE, arguments);
+ } catch (Exception e) {
+ Log.w(LOG_TAG, "Cannot instantiate class: " + className, e);
+ }
+ return null;
+ }
+
+ private static T newInstance(Context context, Class clazz, Class[] constructorSig,
+ Object[] arguments) {
+ try {
+ Constructor> constructor = clazz.getConstructor(constructorSig);
+ return (T) constructor.newInstance(arguments);
+ } catch (Exception e) {
+ Log.w(LOG_TAG, "Cannot instantiate class: " + clazz.getName(), e);
+ }
+ return null;
+ }
+
+}
diff --git a/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/PullToRefreshAttacher.java b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/PullToRefreshAttacher.java
new file mode 100644
index 00000000..5b344be1
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/PullToRefreshAttacher.java
@@ -0,0 +1,948 @@
+/*
+ * Copyright 2013 Chris Banes
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.co.senab.actionbarpulltorefresh.library;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Build;
+import android.os.Handler;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import java.util.Set;
+import java.util.WeakHashMap;
+
+/**
+ * FIXME
+ */
+public class PullToRefreshAttacher implements View.OnTouchListener {
+
+ /* Default configuration values */
+ private static final int DEFAULT_HEADER_LAYOUT = R.layout.default_header;
+ private static final float DEFAULT_REFRESH_SCROLL_DISTANCE = 0.5f;
+ private static final boolean DEFAULT_REFRESH_ON_UP = false;
+ private static final int DEFAULT_REFRESH_MINIMIZED_DELAY = 1 * 1000;
+ private static final boolean DEFAULT_REFRESH_MINIMIZE = true;
+
+ private static final boolean DEBUG = false;
+ private static final String LOG_TAG = "PullToRefreshAttacher";
+
+ /* Member Variables */
+
+ private final EnvironmentDelegate mEnvironmentDelegate;
+ private final HeaderTransformer mHeaderTransformer;
+
+ private final Activity mActivity;
+ private final View mHeaderView;
+ private HeaderViewListener mHeaderViewListener;
+
+ private final int mTouchSlop;
+ private final float mRefreshScrollDistance;
+
+ private int mInitialMotionY, mLastMotionY, mPullBeginY;
+ private boolean mIsBeingDragged, mIsRefreshing, mHandlingTouchEventFromDown;
+
+ private final WeakHashMap mRefreshableViews;
+
+ private boolean mEnabled = true;
+ private final boolean mRefreshOnUp;
+ private final int mRefreshMinimizeDelay;
+ private final boolean mRefreshMinimize;
+
+ private final Handler mHandler = new Handler();
+
+ /**
+ * Get a PullToRefreshAttacher for this Activity. If there is already a
+ * PullToRefreshAttacher attached to the Activity, the existing one is
+ * returned, otherwise a new instance is created. This version of the method
+ * will use default configuration options for everything.
+ *
+ * @param activity
+ * Activity to attach to.
+ * @return PullToRefresh attached to the Activity.
+ */
+ public static PullToRefreshAttacher get(Activity activity) {
+ return get(activity, new Options());
+ }
+
+ /**
+ * Get a PullToRefreshAttacher for this Activity. If there is already a
+ * PullToRefreshAttacher attached to the Activity, the existing one is
+ * returned, otherwise a new instance is created.
+ *
+ * @param activity
+ * Activity to attach to.
+ * @param options
+ * Options used when creating the PullToRefreshAttacher.
+ * @return PullToRefresh attached to the Activity.
+ */
+ public static PullToRefreshAttacher get(Activity activity, Options options) {
+ return new PullToRefreshAttacher(activity, options);
+ }
+
+ protected PullToRefreshAttacher(Activity activity, Options options) {
+ if (options == null) {
+ Log.i(LOG_TAG, "Given null options so using default options.");
+ options = new Options();
+ }
+
+ mActivity = activity;
+ mRefreshableViews = new WeakHashMap();
+
+ // Copy necessary values from options
+ mRefreshScrollDistance = options.refreshScrollDistance;
+ mRefreshOnUp = options.refreshOnUp;
+ mRefreshMinimizeDelay = options.refreshMinimizeDelay;
+ mRefreshMinimize = options.refreshMinimize;
+
+ // EnvironmentDelegate
+ mEnvironmentDelegate = options.environmentDelegate != null ? options.environmentDelegate
+ : createDefaultEnvironmentDelegate();
+
+ // Header Transformer
+ mHeaderTransformer = options.headerTransformer != null ? options.headerTransformer
+ : createDefaultHeaderTransformer();
+
+ // Get touch slop for use later
+ mTouchSlop = ViewConfiguration.get(activity).getScaledTouchSlop();
+
+ // Get Window Decor View
+ final ViewGroup decorView = (ViewGroup) activity.getWindow()
+ .getDecorView();
+
+ // Check to see if there is already a Attacher view installed
+ if (decorView.getChildCount() == 1
+ && decorView.getChildAt(0) instanceof DecorChildLayout) {
+ throw new IllegalStateException(
+ "You should only create one PullToRefreshAttacher per Activity");
+ }
+
+ // Create Header view and then add to Decor View
+ mHeaderView = LayoutInflater.from(
+ mEnvironmentDelegate.getContextForInflater(activity)).inflate(
+ options.headerLayout, decorView, false);
+ if (mHeaderView == null) {
+ throw new IllegalArgumentException(
+ "Must supply valid layout id for header.");
+ }
+ // Make Header View invisible so it still gets a layout pass
+ mHeaderView.setVisibility(View.INVISIBLE);
+
+ // Create DecorChildLayout which will move all of the system's decor
+ // view's children + the
+ // Header View to itself. See DecorChildLayout for more info.
+ DecorChildLayout decorContents = new DecorChildLayout(activity,
+ decorView, mHeaderView);
+
+ // Now add the DecorChildLayout to the decor view
+ decorView.addView(decorContents, ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT);
+
+ // Notify transformer
+ mHeaderTransformer.onViewCreated(activity, mHeaderView);
+ // TODO Remove the follow deprecated method call before v1.0
+ mHeaderTransformer.onViewCreated(mHeaderView);
+ }
+
+ /**
+ * Add a view which will be used to initiate refresh requests and a listener
+ * to be invoked when a refresh is started. This version of the method will
+ * try to find a handler for the view from the built-in view delegates.
+ *
+ * @param view
+ * View which will be used to initiate refresh requests.
+ * @param refreshListener
+ * Listener to be invoked when a refresh is started.
+ */
+ public void addRefreshableView(View view, OnRefreshListener refreshListener) {
+ addRefreshableView(view, null, refreshListener);
+ }
+
+ /**
+ * Add a view which will be used to initiate refresh requests, along with a
+ * delegate which knows how to handle the given view, and a listener to be
+ * invoked when a refresh is started.
+ *
+ * @param view
+ * View which will be used to initiate refresh requests.
+ * @param viewDelegate
+ * delegate which knows how to handle view
.
+ * @param refreshListener
+ * Listener to be invoked when a refresh is started.
+ */
+ public void addRefreshableView(View view, ViewDelegate viewDelegate,
+ OnRefreshListener refreshListener) {
+ addRefreshableView(view, viewDelegate, refreshListener, true);
+ }
+
+ /**
+ * Add a view which will be used to initiate refresh requests, along with a
+ * delegate which knows how to handle the given view, and a listener to be
+ * invoked when a refresh is started.
+ *
+ * @param view
+ * View which will be used to initiate refresh requests.
+ * @param viewDelegate
+ * delegate which knows how to handle view
.
+ * @param refreshListener
+ * Listener to be invoked when a refresh is started.
+ * @param setTouchListener
+ * Whether to set this as the
+ * {@link android.view.View.OnTouchListener}.
+ */
+ void addRefreshableView(View view, ViewDelegate viewDelegate,
+ OnRefreshListener refreshListener, final boolean setTouchListener) {
+ // Check to see if view is null
+ if (view == null) {
+ Log.i(LOG_TAG, "Refreshable View is null.");
+ return;
+ }
+
+ if (refreshListener == null) {
+ throw new IllegalArgumentException(
+ "OnRefreshListener not given. Please provide one.");
+ }
+
+ // ViewDelegate
+ if (viewDelegate == null) {
+ viewDelegate = InstanceCreationUtils.getBuiltInViewDelegate(view);
+ if (viewDelegate == null) {
+ throw new IllegalArgumentException(
+ "No view handler found. Please provide one.");
+ }
+ }
+
+ // View to detect refreshes for
+ mRefreshableViews.put(view, new ViewParams(viewDelegate, refreshListener));
+ if (setTouchListener) {
+ view.setOnTouchListener(this);
+ }
+ }
+
+ /**
+ * Remove a view which was previously used to initiate refresh requests.
+ *
+ * @param view
+ * - View which will be used to initiate refresh requests.
+ */
+ public void removeRefreshableView(View view) {
+ if (mRefreshableViews.containsKey(view)) {
+ mRefreshableViews.remove(view);
+ view.setOnTouchListener(null);
+ }
+ }
+
+ /**
+ * Clear all views which were previously used to initiate refresh requests.
+ */
+ public void clearRefreshableViews() {
+ Set views = mRefreshableViews.keySet();
+ for (View view : views) {
+ view.setOnTouchListener(null);
+ }
+ mRefreshableViews.clear();
+ }
+
+ /**
+ * This method should be called by your Activity's or Fragment's
+ * onConfigurationChanged method.
+ *
+ * @param newConfig The new configuration
+ */
+ public void onConfigurationChanged(Configuration newConfig) {
+ mHeaderTransformer.onConfigurationChanged(mActivity, newConfig);
+ }
+
+ /**
+ * Manually set this Attacher's refreshing state. The header will be
+ * displayed or hidden as requested.
+ *
+ * @param refreshing
+ * - Whether the attacher should be in a refreshing state,
+ */
+ public final void setRefreshing(boolean refreshing) {
+ setRefreshingInt(null, refreshing, false);
+ }
+
+ /**
+ * @return true if this Attacher is currently in a refreshing state.
+ */
+ public final boolean isRefreshing() {
+ return mIsRefreshing;
+ }
+
+ /**
+ * @return true if this PullToRefresh is currently enabled (defaults to
+ * true
)
+ */
+ public boolean isEnabled() {
+ return mEnabled;
+ }
+
+ /**
+ * Allows the enable/disable of this PullToRefreshAttacher. If disabled when
+ * refreshing then the UI is automatically reset.
+ *
+ * @param enabled
+ * - Whether this PullToRefreshAttacher is enabled.
+ */
+ public void setEnabled(boolean enabled) {
+ mEnabled = enabled;
+
+ if (!enabled) {
+ // If we're not enabled, reset any touch handling
+ resetTouch();
+
+ // If we're currently refreshing, reset the ptr UI
+ if (mIsRefreshing) {
+ reset(false);
+ }
+ }
+ }
+
+ /**
+ * Call this when your refresh is complete and this view should reset itself
+ * (header view will be hidden).
+ *
+ * This is the equivalent of calling setRefreshing(false)
.
+ */
+ public final void setRefreshComplete() {
+ setRefreshingInt(null, false, false);
+ }
+
+ /**
+ * Set a {@link HeaderViewListener} which is called when the visibility
+ * state of the Header View has changed.
+ *
+ * @param listener
+ */
+ public final void setHeaderViewListener(HeaderViewListener listener) {
+ mHeaderViewListener = listener;
+ }
+
+ /**
+ * @return The Header View which is displayed when the user is pulling, or
+ * we are refreshing.
+ */
+ public final View getHeaderView() {
+ return mHeaderView;
+ }
+
+ /**
+ * @return The HeaderTransformer currently used by this Attacher.
+ */
+ public HeaderTransformer getHeaderTransformer() {
+ return mHeaderTransformer;
+ }
+
+ @Override
+ public final boolean onTouch(final View view, final MotionEvent event) {
+ // Just call onTouchEvent. It now handles the proper calling of onInterceptTouchEvent
+ onTouchEvent(view, event);
+ // Always return false as we only want to observe events
+ return false;
+ }
+
+ final boolean onInterceptTouchEvent(View view, MotionEvent event) {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "onInterceptTouchEvent: " + event.toString());
+ }
+
+ // If we're not enabled or currently refreshing don't handle any touch
+ // events
+ if (!isEnabled() || isRefreshing()) {
+ return false;
+ }
+
+ final ViewParams params = mRefreshableViews.get(view);
+ if (params == null) {
+ return false;
+ }
+
+ if (DEBUG) Log.d(LOG_TAG, "onInterceptTouchEvent. Got ViewParams. " + view.toString());
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_MOVE: {
+ // We're not currently being dragged so check to see if the user has
+ // scrolled enough
+ if (!mIsBeingDragged && mInitialMotionY > 0) {
+ final int y = (int) event.getY();
+ final int yDiff = y - mInitialMotionY;
+
+ if (yDiff > mTouchSlop) {
+ mIsBeingDragged = true;
+ onPullStarted(y);
+ } else if (yDiff < -mTouchSlop) {
+ resetTouch();
+ }
+ }
+ break;
+ }
+
+ case MotionEvent.ACTION_DOWN: {
+ // If we're already refreshing, ignore
+ if (canRefresh(true, params.onRefreshListener)
+ && params.viewDelegate.isReadyForPull(view, event.getX(), event.getY())) {
+ mInitialMotionY = (int) event.getY();
+ }
+ break;
+ }
+
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP: {
+ resetTouch();
+ break;
+ }
+ }
+
+ if (DEBUG) Log.d(LOG_TAG, "onInterceptTouchEvent. Returning " + mIsBeingDragged);
+
+ return mIsBeingDragged;
+ }
+
+ final boolean onTouchEvent(View view, MotionEvent event) {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "onTouchEvent: " + event.toString());
+ }
+
+ // If we're not enabled or currently refreshing don't handle any touch
+ // events
+ if (!isEnabled()) {
+ return false;
+ }
+
+ final ViewParams params = mRefreshableViews.get(view);
+ if (params == null) {
+ Log.i(LOG_TAG, "View does not have ViewParams");
+ return false;
+ }
+
+ // Record whether our handling is started from ACTION_DOWN
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ mHandlingTouchEventFromDown = true;
+ }
+
+ // If we're being called from ACTION_DOWN then we must call through to
+ // onInterceptTouchEvent until it sets mIsBeingDragged
+ if (mHandlingTouchEventFromDown && !mIsBeingDragged) {
+ onInterceptTouchEvent(view, event);
+ return true;
+ }
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_MOVE: {
+ // If we're already refreshing ignore it
+ if (isRefreshing()) {
+ return false;
+ }
+
+ final int y = (int) event.getY();
+
+ if (mIsBeingDragged && y != mLastMotionY) {
+ final int yDx = y - mLastMotionY;
+
+ /**
+ * Check to see if the user is scrolling the right direction
+ * (down). We allow a small scroll up which is the check against
+ * negative touch slop.
+ */
+ if (yDx >= -mTouchSlop) {
+ onPull(view, y);
+ // Only record the y motion if the user has scrolled down.
+ if (yDx > 0) {
+ mLastMotionY = y;
+ }
+ } else {
+ onPullEnded();
+ resetTouch();
+ }
+ }
+ break;
+ }
+
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP: {
+ checkScrollForRefresh(view);
+ if (mIsBeingDragged) {
+ onPullEnded();
+ }
+ resetTouch();
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ void resetTouch() {
+ mIsBeingDragged = false;
+ mHandlingTouchEventFromDown = false;
+ mInitialMotionY = mLastMotionY = mPullBeginY = -1;
+ }
+
+ void onPullStarted(int y) {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "onPullStarted");
+ }
+ showHeaderView();
+ mPullBeginY = y;
+ }
+
+ void onPull(View view, int y) {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "onPull");
+ }
+
+ final float pxScrollForRefresh = getScrollNeededForRefresh(view);
+ final int scrollLength = y - mPullBeginY;
+
+ if (scrollLength < pxScrollForRefresh) {
+ mHeaderTransformer.onPulled(scrollLength / pxScrollForRefresh);
+ } else {
+ if (mRefreshOnUp) {
+ mHeaderTransformer.onReleaseToRefresh();
+ } else {
+ setRefreshingInt(view, true, true);
+ }
+ }
+ }
+
+ void onPullEnded() {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "onPullEnded");
+ }
+ if (!mIsRefreshing) {
+ reset(true);
+ }
+ }
+
+ void showHeaderView() {
+ if (mHeaderTransformer.showHeaderView()) {
+ if (mHeaderViewListener != null) {
+ mHeaderViewListener.onStateChanged(mHeaderView,
+ HeaderViewListener.STATE_VISIBLE);
+ }
+ }
+ }
+
+ void hideHeaderView() {
+ if (mHeaderTransformer.hideHeaderView()) {
+ if (mHeaderViewListener != null) {
+ mHeaderViewListener.onStateChanged(mHeaderView,
+ HeaderViewListener.STATE_HIDDEN);
+ }
+ }
+ }
+
+ protected EnvironmentDelegate createDefaultEnvironmentDelegate() {
+ return new EnvironmentDelegate();
+ }
+
+ protected HeaderTransformer createDefaultHeaderTransformer() {
+ return new DefaultHeaderTransformer();
+ }
+
+ private boolean checkScrollForRefresh(View view) {
+ if (mIsBeingDragged && mRefreshOnUp && view != null) {
+ if (mLastMotionY - mPullBeginY >= getScrollNeededForRefresh(view)) {
+ setRefreshingInt(view, true, true);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void setRefreshingInt(View view, boolean refreshing, boolean fromTouch) {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "setRefreshingInt: " + refreshing);
+ }
+ // Check to see if we need to do anything
+ if (mIsRefreshing == refreshing) {
+ return;
+ }
+
+ resetTouch();
+
+ if (refreshing && canRefresh(fromTouch, getRefreshListenerForView(view))) {
+ startRefresh(view, fromTouch);
+ } else {
+ reset(fromTouch);
+ }
+ }
+
+ private OnRefreshListener getRefreshListenerForView(View view) {
+ if (view != null) {
+ ViewParams params = mRefreshableViews.get(view);
+ if (params != null) {
+ return params.onRefreshListener;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @param fromTouch
+ * - Whether this is being invoked from a touch event
+ * @return true if we're currently in a state where a refresh can be
+ * started.
+ */
+ private boolean canRefresh(boolean fromTouch, OnRefreshListener listener) {
+ return !mIsRefreshing && (!fromTouch || listener != null);
+ }
+
+ private float getScrollNeededForRefresh(View view) {
+ return view.getHeight() * mRefreshScrollDistance;
+ }
+
+ private void reset(boolean fromTouch) {
+ // Update isRefreshing state
+ mIsRefreshing = false;
+
+ // Remove any minimize callbacks
+ if (mRefreshMinimize) {
+ mHandler.removeCallbacks(mRefreshMinimizeRunnable);
+ }
+
+ // Hide Header View
+ hideHeaderView();
+ }
+
+ private void startRefresh(View view, boolean fromTouch) {
+ // Update isRefreshing state
+ mIsRefreshing = true;
+
+ // Call OnRefreshListener if this call has originated from a touch event
+ if (fromTouch) {
+ OnRefreshListener listener = getRefreshListenerForView(view);
+ if (listener != null) {
+ listener.onRefreshStarted(view);
+ }
+ }
+
+ // Call Transformer
+ mHeaderTransformer.onRefreshStarted();
+
+ // Show Header View
+ showHeaderView();
+
+ // Post a runnable to minimize the refresh header
+ if (mRefreshMinimize) {
+ if (mRefreshMinimizeDelay > 0) {
+ mHandler.postDelayed(mRefreshMinimizeRunnable, mRefreshMinimizeDelay);
+ } else {
+ mHandler.post(mRefreshMinimizeRunnable);
+ }
+ }
+ }
+
+ /**
+ * Simple Listener to listen for any callbacks to Refresh.
+ */
+ public interface OnRefreshListener {
+ /**
+ * Called when the user has initiated a refresh by pulling.
+ *
+ * @param view
+ * - View which the user has started the refresh from.
+ */
+ public void onRefreshStarted(View view);
+ }
+
+ public interface HeaderViewListener {
+ /**
+ * The state when the header view is completely visible.
+ */
+ public static int STATE_VISIBLE = 0;
+
+ /**
+ * The state when the header view is minimized. By default this means
+ * that the progress bar is still visible, but the rest of the view is
+ * hidden, showing the Action Bar behind.
+ *
+ * This will not be called in header minimization is disabled.
+ */
+ public static int STATE_MINIMIZED = 1;
+
+ /**
+ * The state when the header view is completely hidden.
+ */
+ public static int STATE_HIDDEN = 2;
+
+ /**
+ * Called when the visibility state of the Header View has changed.
+ *
+ * @param headerView
+ * HeaderView who's state has changed.
+ * @param state
+ * The new state. One of {@link #STATE_VISIBLE},
+ * {@link #STATE_MINIMIZED} and {@link #STATE_HIDDEN}
+ */
+ public void onStateChanged(View headerView, int state);
+ }
+
+ /**
+ * HeaderTransformers are what controls and update the Header View to reflect the current state
+ * of the pull-to-refresh interaction. They are responsible for showing and hiding the header
+ * view, as well as update the state.
+ */
+ public static abstract class HeaderTransformer {
+
+ /**
+ * Called whether the header view has been inflated from the resources
+ * defined in {@link Options#headerLayout}.
+ *
+ * @param activity The {@link Activity} that the header view is attached to.
+ * @param headerView The inflated header view.
+ */
+ public void onViewCreated(Activity activity, View headerView) {}
+
+ /**
+ * @deprecated This will be removed before v1.0. Override
+ * {@link #onViewCreated(android.app.Activity, android.view.View)} instead.
+ */
+ public void onViewCreated(View headerView) {}
+
+ /**
+ * Called when the header should be reset. You should update any child
+ * views to reflect this.
+ *
+ * You should not change the visibility of the header
+ * view.
+ */
+ public void onReset() {}
+
+ /**
+ * Called the user has pulled on the scrollable view.
+ *
+ * @param percentagePulled value between 0.0f and 1.0f depending on how far the
+ * user has pulled.
+ */
+ public void onPulled(float percentagePulled) {}
+
+ /**
+ * Called when a refresh has begun. Theoretically this call is similar
+ * to that provided from {@link OnRefreshListener} but is more suitable
+ * for header view updates.
+ */
+ public void onRefreshStarted() {}
+
+ /**
+ * Called when a refresh can be initiated when the user ends the touch
+ * event. This is only called when {@link Options#refreshOnUp} is set to
+ * true.
+ */
+ public void onReleaseToRefresh() {}
+
+ /**
+ * Called when the current refresh has taken longer than the time
+ * specified in {@link Options#refreshMinimizeDelay}.
+ */
+ public void onRefreshMinimized() {}
+
+ /**
+ * Called when the Header View should be made visible, usually with an animation.
+ *
+ * @return true if the visibility has changed.
+ */
+ public abstract boolean showHeaderView();
+
+ /**
+ * Called when the Header View should be made invisible, usually with an animation.
+ *
+ * @return true if the visibility has changed.
+ */
+ public abstract boolean hideHeaderView();
+
+ /**
+ * Called when the Activity's configuration has changed.
+ *
+ * @param activity The {@link Activity} that the header view is attached to.
+ * @param newConfig New configuration.
+ *
+ * @see android.app.Activity#onConfigurationChanged(android.content.res.Configuration)
+ */
+ public void onConfigurationChanged(Activity activity, Configuration newConfig) {}
+ }
+
+ /**
+ * ViewDelegates are what are used to de-couple the Attacher from the different types of
+ * scrollable views.
+ */
+ public static abstract class ViewDelegate {
+
+ /**
+ * Allows you to provide support for View which do not have built-in
+ * support. In this method you should cast view
to it's
+ * native class, and check if it is scrolled to the top.
+ *
+ * @param view
+ * The view which has should be checked against.
+ * @param x The X co-ordinate of the touch event
+ * @param y The Y co-ordinate of the touch event
+ * @return true if view
is scrolled to the top.
+ */
+ public abstract boolean isReadyForPull(View view, float x, float y);
+ }
+
+ /**
+ * This is used to provide platform and environment specific functionality for the Attacher.
+ */
+ public static class EnvironmentDelegate {
+
+ /**
+ * @return Context which should be used for inflating the header layout
+ */
+ public Context getContextForInflater(Activity activity) {
+ if (Build.VERSION.SDK_INT >= 14) {
+ return activity.getActionBar().getThemedContext();
+ } else {
+ return activity;
+ }
+ }
+ }
+
+ /**
+ * Allows you to specify a number of configuration options when instantiating a
+ * {@link PullToRefreshAttacher}. Used with {@link #get(Activity, Options) get()}.
+ */
+ public static class Options {
+
+ /**
+ * EnvironmentDelegate instance which will be used. If null, we will
+ * create an instance of the default class.
+ */
+ public EnvironmentDelegate environmentDelegate = null;
+
+ /**
+ * The layout resource ID which should be inflated to be displayed above
+ * the Action Bar
+ */
+ public int headerLayout = DEFAULT_HEADER_LAYOUT;
+
+ /**
+ * The header transformer to be used to transfer the header view. If
+ * null, an instance of {@link DefaultHeaderTransformer} will be used.
+ */
+ public HeaderTransformer headerTransformer = null;
+
+ /**
+ * The percentage of the refreshable view that needs to be scrolled
+ * before a refresh is initiated.
+ */
+ public float refreshScrollDistance = DEFAULT_REFRESH_SCROLL_DISTANCE;
+
+ /**
+ * Whether a refresh should only be initiated when the user has finished
+ * the touch event.
+ */
+ public boolean refreshOnUp = DEFAULT_REFRESH_ON_UP;
+
+ /**
+ * The delay after a refresh is started in which the header should be
+ * 'minimized'. By default, most of the header is faded out, leaving
+ * only the progress bar signifying that a refresh is taking place.
+ */
+ public int refreshMinimizeDelay = DEFAULT_REFRESH_MINIMIZED_DELAY;
+
+ /**
+ * Enable or disable the header 'minimization', which by default means that the majority of
+ * the header is hidden, leaving only the progress bar still showing.
+ *
+ * If set to true, the header will be minimized after the delay set in
+ * {@link #refreshMinimizeDelay}. If set to false then the whole header will be displayed
+ * until the refresh is finished.
+ */
+ public boolean refreshMinimize = DEFAULT_REFRESH_MINIMIZE;
+ }
+
+ /**
+ * This class allows us to insert a layer in between the system decor view
+ * and the actual decor. (e.g. Action Bar views). This is needed so we can
+ * receive a call to fitSystemWindows(Rect) so we can adjust the header view
+ * to fit the system windows too.
+ */
+ final static class DecorChildLayout extends FrameLayout {
+ private final ViewGroup mHeaderViewWrapper;
+
+ DecorChildLayout(Context context, ViewGroup systemDecorView,
+ View headerView) {
+ super(context);
+
+ // Move all children from decor view to here
+ for (int i = 0, z = systemDecorView.getChildCount(); i < z; i++) {
+ View child = systemDecorView.getChildAt(i);
+ systemDecorView.removeView(child);
+ addView(child);
+ }
+
+ /**
+ * Wrap the Header View in a FrameLayout and add it to this view. It
+ * is wrapped so any inset changes do not affect the actual header
+ * view.
+ */
+ mHeaderViewWrapper = new FrameLayout(context);
+ mHeaderViewWrapper.addView(headerView);
+ addView(mHeaderViewWrapper, ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+
+ @Override
+ protected boolean fitSystemWindows(Rect insets) {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "fitSystemWindows: " + insets.toString());
+ }
+
+ // Adjust the Header View's padding to take the insets into account
+ mHeaderViewWrapper.setPadding(insets.left, insets.top,
+ insets.right, insets.bottom);
+
+ // Call return super so that the rest of the
+ return super.fitSystemWindows(insets);
+ }
+ }
+
+ private static final class ViewParams {
+ final OnRefreshListener onRefreshListener;
+ final ViewDelegate viewDelegate;
+
+ ViewParams(ViewDelegate _viewDelegate,
+ OnRefreshListener _onRefreshListener) {
+ onRefreshListener = _onRefreshListener;
+ viewDelegate = _viewDelegate;
+ }
+ }
+
+ private final Runnable mRefreshMinimizeRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mHeaderTransformer.onRefreshMinimized();
+
+ if (mHeaderViewListener != null) {
+ mHeaderViewListener.onStateChanged(mHeaderView,
+ HeaderViewListener.STATE_MINIMIZED);
+ }
+ }
+ };
+
+}
diff --git a/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/PullToRefreshLayout.java b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/PullToRefreshLayout.java
new file mode 100644
index 00000000..296a44f0
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/PullToRefreshLayout.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2013 Chris Banes
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.co.senab.actionbarpulltorefresh.library;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.FrameLayout;
+
+/**
+ * FIXME
+ */
+public class PullToRefreshLayout extends FrameLayout {
+
+ private static final boolean DEBUG = false;
+ private static final String LOG_TAG = "PullToRefreshLayout";
+
+ private PullToRefreshAttacher mPullToRefreshAttacher;
+ private View mCurrentTouchTarget;
+
+ public PullToRefreshLayout(Context context) {
+ this(context, null);
+ }
+
+ public PullToRefreshLayout(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public PullToRefreshLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * Set the {@link PullToRefreshAttacher} to be used with this layout. The view which is added
+ * to this layout will automatically be added as a refreshable-view in the attacher.
+ */
+ public void setPullToRefreshAttacher(PullToRefreshAttacher attacher,
+ PullToRefreshAttacher.OnRefreshListener refreshListener) {
+ View view;
+ for (int i = 0, z = getChildCount(); i < z; i++) {
+ view = getChildAt(i);
+
+ if (mPullToRefreshAttacher != null) {
+ mPullToRefreshAttacher.removeRefreshableView(view);
+ }
+
+ if (attacher != null) {
+ if (DEBUG) Log.d(LOG_TAG, "Adding View to Attacher: " + view);
+ attacher.addRefreshableView(view, null, refreshListener, false);
+ }
+ }
+
+ mPullToRefreshAttacher = attacher;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent event) {
+ if (DEBUG) Log.d(LOG_TAG, "onInterceptTouchEvent. " + event.toString());
+
+ if (mPullToRefreshAttacher != null && getChildCount() > 0) {
+ View target = getChildForTouchEvent(event);
+ if (target != null && mPullToRefreshAttacher.onInterceptTouchEvent(target, event)) {
+ mCurrentTouchTarget = target;
+ return true;
+ }
+ }
+ // Reset Current Touch Target
+ mCurrentTouchTarget = null;
+ return false;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (DEBUG) Log.d(LOG_TAG, "onTouchEvent. " + event.toString());
+
+ if (mPullToRefreshAttacher != null) {
+ // This is an edge-case. If the ViewGroup does not contain a valid touch target then
+ // Android calls onTouchEvent after onInterceptTouchEvent with ACTION_DOWN event.
+ // If that happens then we need to find the visible view and pass it to the attacher as
+ // usual.
+ if (mCurrentTouchTarget == null && event.getAction() == MotionEvent.ACTION_DOWN) {
+ mCurrentTouchTarget = getChildForTouchEvent(event);
+ }
+
+ if (mCurrentTouchTarget != null) {
+ return mPullToRefreshAttacher.onTouchEvent(mCurrentTouchTarget, event);
+ }
+ }
+ // Reset Current Touch Target
+ mCurrentTouchTarget = null;
+ return super.onTouchEvent(event);
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ if (mPullToRefreshAttacher != null) {
+ mPullToRefreshAttacher.onConfigurationChanged(newConfig);
+ }
+ }
+
+ private View getChildForTouchEvent(MotionEvent event) {
+ final float x = event.getX(), y = event.getY();
+ View child;
+ for (int z = getChildCount() - 1; z >= 0 ; z--) {
+ child = getChildAt(z);
+ if (child.isShown() && x >= child.getLeft() && x <= child.getRight()
+ && y >= child.getTop() && y <= child.getBottom()) {
+ if (DEBUG) Log.d(LOG_TAG, "Got Child for Touch Event: " + child);
+ return child;
+ }
+ }
+ return null;
+ }
+}
diff --git a/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/platform/SDK11.java b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/platform/SDK11.java
new file mode 100644
index 00000000..da55ebb6
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/platform/SDK11.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 Chris Banes
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.co.senab.actionbarpulltorefresh.library.platform;
+
+import android.view.View;
+
+public class SDK11 {
+
+ public static void setAlpha(View view, float alpha) {
+ view.setAlpha(alpha);
+ }
+
+}
diff --git a/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/AbsListViewDelegate.java b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/AbsListViewDelegate.java
new file mode 100644
index 00000000..8276e146
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/AbsListViewDelegate.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2013 Chris Banes
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.co.senab.actionbarpulltorefresh.library.viewdelegates;
+
+import android.annotation.TargetApi;
+import android.os.Build;
+import android.view.View;
+import android.widget.AbsListView;
+
+import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher;
+
+/**
+ * FIXME
+ */
+public class AbsListViewDelegate
+ extends PullToRefreshAttacher.ViewDelegate {
+
+ public static final Class SUPPORTED_VIEW_CLASS = AbsListView.class;
+
+ @Override
+ public boolean isReadyForPull(View view, final float x, final float y) {
+ boolean ready = false;
+
+ // First we check whether we're scrolled to the top
+ AbsListView absListView = (AbsListView) view;
+ if (absListView.getCount() == 0) {
+ ready = true;
+ } else if (absListView.getFirstVisiblePosition() == 0) {
+ final View firstVisibleChild = absListView.getChildAt(0);
+ ready = firstVisibleChild != null && firstVisibleChild.getTop() >= 0;
+ }
+
+ // Then we have to check whether the fas scroller is enabled, and check we're not starting
+ // the gesture from the scroller
+ if (ready && absListView.isFastScrollEnabled() && isFastScrollAlwaysVisible(absListView)) {
+ switch (getVerticalScrollbarPosition(absListView)) {
+ case View.SCROLLBAR_POSITION_RIGHT:
+ ready = x < absListView.getRight() - absListView.getVerticalScrollbarWidth();
+ break;
+ case View.SCROLLBAR_POSITION_LEFT:
+ ready = x > absListView.getVerticalScrollbarWidth();
+ break;
+ }
+ }
+
+ return ready;
+ }
+
+ int getVerticalScrollbarPosition(AbsListView absListView) {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?
+ CompatV11.getVerticalScrollbarPosition(absListView) :
+ Compat.getVerticalScrollbarPosition(absListView);
+ }
+
+ boolean isFastScrollAlwaysVisible(AbsListView absListView) {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?
+ CompatV11.isFastScrollAlwaysVisible(absListView) :
+ Compat.isFastScrollAlwaysVisible(absListView);
+ }
+
+ static class Compat {
+ static int getVerticalScrollbarPosition(AbsListView absListView) {
+ return View.SCROLLBAR_POSITION_RIGHT;
+ }
+ static boolean isFastScrollAlwaysVisible(AbsListView absListView) {
+ return false;
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ static class CompatV11 {
+ static int getVerticalScrollbarPosition(AbsListView absListView) {
+ return absListView.getVerticalScrollbarPosition();
+ }
+ static boolean isFastScrollAlwaysVisible(AbsListView absListView) {
+ return absListView.isFastScrollAlwaysVisible();
+ }
+ }
+}
diff --git a/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/ScrollYDelegate.java b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/ScrollYDelegate.java
new file mode 100644
index 00000000..a38885d0
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/ScrollYDelegate.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013 Chris Banes
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.co.senab.actionbarpulltorefresh.library.viewdelegates;
+
+import android.view.View;
+
+import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher;
+
+/**
+ * FIXME
+ */
+public class ScrollYDelegate extends PullToRefreshAttacher.ViewDelegate {
+
+ @Override
+ public boolean isReadyForPull(View view, float x, float y) {
+ return view.getScrollY() <= 0;
+ }
+}
diff --git a/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/WebViewDelegate.java b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/WebViewDelegate.java
new file mode 100644
index 00000000..80c6a83d
--- /dev/null
+++ b/external/ActionBar-PullToRefresh/src/uk/co/senab/actionbarpulltorefresh/library/viewdelegates/WebViewDelegate.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2013 Chris Banes
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.co.senab.actionbarpulltorefresh.library.viewdelegates;
+
+import android.view.View;
+import android.webkit.WebView;
+
+import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher;
+
+/**
+ * FIXME
+ */
+public class WebViewDelegate extends PullToRefreshAttacher.ViewDelegate {
+
+ public static final Class SUPPORTED_VIEW_CLASS = WebView.class;
+
+ @Override
+ public boolean isReadyForPull(View view, float x, float y) {
+ return view.getScrollY() <= 0;
+ }
+}
diff --git a/external/ColorPickerPreference/build.xml b/external/ColorPickerPreference/build.xml
index c575c550..1b4d11f9 100644
--- a/external/ColorPickerPreference/build.xml
+++ b/external/ColorPickerPreference/build.xml
@@ -1,5 +1,5 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+