diff --git a/plugins/Android-PullToRefresh/LICENSE.txt b/plugins/Android-PullToRefresh/LICENSE similarity index 100% rename from plugins/Android-PullToRefresh/LICENSE.txt rename to plugins/Android-PullToRefresh/LICENSE diff --git a/plugins/Android-PullToRefresh/README.md b/plugins/Android-PullToRefresh/README.md index 92b2e9f34..1c9891884 100644 --- a/plugins/Android-PullToRefresh/README.md +++ b/plugins/Android-PullToRefresh/README.md @@ -9,7 +9,14 @@ This project aims to provide a reusable Pull to Refresh widget for Android. It w * Supports both Pulling Down from the top, and Pulling Up from the bottom (or even both). * Animated Scrolling for all devices. * Over Scroll supports for devices on Android v2.3+. - * Currently works with **ListView**, **ExpandableListView** & **GridView**, **WebView** and **ScrollView**! + * Currently works with: + * **ListView** + * **ExpandableListView** + * **GridView** + * **WebView** + * **ScrollView** + * **HorizontalScrollView** + * **ViewPager** * Integrated End of List Listener for use of detecting when the user has scrolled to the bottom. * Maven Support. * Indicators to show the user when a Pull-to-Refresh is available. diff --git a/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/AndroidManifest.xml b/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/AndroidManifest.xml index 6cc0d8d9c..6745733d6 100644 --- a/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/AndroidManifest.xml +++ b/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="2110" + android:versionName="2.1.1" > diff --git a/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/LICENSE b/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/pom.xml b/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/pom.xml index 34a9da93d..06e9a13e8 100644 --- a/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/pom.xml +++ b/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/pom.xml @@ -10,7 +10,7 @@ com.github.chrisbanes.pulltorefresh extras - 1.4.2 + 2.1.1 diff --git a/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshBaseListFragment.java b/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshBaseListFragment.java new file mode 100644 index 000000000..4350f9257 --- /dev/null +++ b/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshBaseListFragment.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright 2011, 2012 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 com.handmark.pulltorefresh.extras.listfragment; + +import android.os.Bundle; +import android.support.v4.app.ListFragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.ListView; + +import com.handmark.pulltorefresh.library.PullToRefreshBase; + +abstract class PullToRefreshBaseListFragment> extends ListFragment { + + private T mPullToRefreshListView; + + @Override + public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View layout = super.onCreateView(inflater, container, savedInstanceState); + + ListView lv = (ListView) layout.findViewById(android.R.id.list); + ViewGroup parent = (ViewGroup) lv.getParent(); + + // Remove ListView and add PullToRefreshListView in its place + int lvIndex = parent.indexOfChild(lv); + parent.removeViewAt(lvIndex); + mPullToRefreshListView = onCreatePullToRefreshListView(inflater, savedInstanceState); + parent.addView(mPullToRefreshListView, lvIndex, lv.getLayoutParams()); + + return layout; + } + + /** + * @return The {@link PullToRefreshBase} attached to this ListFragment. + */ + public final T getPullToRefreshListView() { + return mPullToRefreshListView; + } + + /** + * Returns the {@link PullToRefreshBase} which will replace the ListView + * created from ListFragment. You should override this method if you wish to + * customise the {@link PullToRefreshBase} from the default. + * + * @param inflater - LayoutInflater which can be used to inflate from XML. + * @param savedInstanceState - Bundle passed through from + * {@link ListFragment#onCreateView(LayoutInflater, ViewGroup, Bundle) + * onCreateView(...)} + * @return The {@link PullToRefreshBase} which will replace the ListView. + */ + protected abstract T onCreatePullToRefreshListView(LayoutInflater inflater, Bundle savedInstanceState); + +} \ No newline at end of file diff --git a/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshExpandableListFragment.java b/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshExpandableListFragment.java new file mode 100644 index 000000000..aca73a3e7 --- /dev/null +++ b/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshExpandableListFragment.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright 2011, 2012 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 com.handmark.pulltorefresh.extras.listfragment; + +import android.os.Bundle; +import android.support.v4.app.ListFragment; +import android.view.LayoutInflater; + +import com.handmark.pulltorefresh.library.PullToRefreshExpandableListView; + +/** + * A sample implementation of how to use {@link PullToRefreshExpandableListView} + * with {@link ListFragment}. This implementation simply replaces the ListView + * that {@code ListFragment} creates with a new + * {@code PullToRefreshExpandableListView}. This means that ListFragment still + * works 100% (e.g. setListShown(...) ). + *

+ * The new PullToRefreshListView is created in the method + * {@link #onCreatePullToRefreshListView(LayoutInflater, Bundle)}. If you wish + * to customise the {@code PullToRefreshExpandableListView} then override this + * method and return your customised instance. + * + * @author Chris Banes + * + */ +public class PullToRefreshExpandableListFragment extends PullToRefreshBaseListFragment { + + protected PullToRefreshExpandableListView onCreatePullToRefreshListView(LayoutInflater inflater, + Bundle savedInstanceState) { + return new PullToRefreshExpandableListView(getActivity()); + } + +} \ No newline at end of file diff --git a/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshListFragment.java b/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshListFragment.java index 34909f53d..e544797f9 100644 --- a/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshListFragment.java +++ b/plugins/Android-PullToRefresh/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshListFragment.java @@ -18,66 +18,25 @@ package com.handmark.pulltorefresh.extras.listfragment; import android.os.Bundle; import android.support.v4.app.ListFragment; import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ListView; + import com.handmark.pulltorefresh.library.PullToRefreshListView; /** - * A sample implementation of how to the PullToRefreshListView with - * ListFragment. This implementation simply replaces the ListView that - * ListFragment creates with a new PullToRefreshListView. This means that - * ListFragment still works 100% (e.g. setListShown(...)). - * + * A sample implementation of how to use {@link PullToRefreshListView} with + * {@link ListFragment}. This implementation simply replaces the ListView that + * {@code ListFragment} creates with a new PullToRefreshListView. This means + * that ListFragment still works 100% (e.g. setListShown(...) ). + *

* The new PullToRefreshListView is created in the method - * onCreatePullToRefreshListView(). If you wish to customise the - * PullToRefreshListView then override this method and return your customised - * instance. + * {@link #onCreatePullToRefreshListView(LayoutInflater, Bundle)}. If you wish + * to customise the {@code PullToRefreshListView} then override this method and + * return your customised instance. * * @author Chris Banes * */ -public class PullToRefreshListFragment extends ListFragment { +public class PullToRefreshListFragment extends PullToRefreshBaseListFragment { - private PullToRefreshListView mPullToRefreshListView; - - @Override - public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View layout = super.onCreateView(inflater, container, savedInstanceState); - - ListView lv = (ListView) layout.findViewById(android.R.id.list); - ViewGroup parent = (ViewGroup) lv.getParent(); - - //Remove ListView and add PullToRefreshListView in its place - int lvIndex = parent.indexOfChild(lv); - parent.removeViewAt(lvIndex); - mPullToRefreshListView = onCreatePullToRefreshListView(inflater, savedInstanceState); - parent.addView(mPullToRefreshListView, lvIndex, lv.getLayoutParams()); - - return layout; - } - - /** - * @return The {@link PullToRefreshListView} attached to this ListFragment. - */ - public final PullToRefreshListView getPullToRefreshListView() { - return mPullToRefreshListView; - } - - /** - * Returns the {@link PullToRefreshListView} which will replace the ListView - * created from ListFragment. You should override this method if you wish to - * customise the {@link PullToRefreshListView} from the default. - * - * @param inflater - * - LayoutInflater which can be used to inflate from XML. - * @param savedInstanceState - * - Bundle passed through from - * {@link ListFragment#onCreateView(LayoutInflater, ViewGroup, Bundle) - * onCreateView(...)} - * @return The {@link PullToRefreshListView} which will replace the - * ListView. - */ protected PullToRefreshListView onCreatePullToRefreshListView(LayoutInflater inflater, Bundle savedInstanceState) { return new PullToRefreshListView(getActivity()); } diff --git a/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/AndroidManifest.xml b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/AndroidManifest.xml new file mode 100644 index 000000000..eaffd6803 --- /dev/null +++ b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/ant.properties b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/ant.properties new file mode 100644 index 000000000..b0971e891 --- /dev/null +++ b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/ant.properties @@ -0,0 +1,17 @@ +# This file is used to override default values used by the Ant build system. +# +# This file must be checked into Version Control Systems, as it is +# integral to the build system of your project. + +# This file is only used by the Ant script. + +# You can use this to override default values such as +# 'source.dir' for the location of your java source folder and +# 'out.dir' for the location of your output folder. + +# You can also use it define how the release builds are signed by declaring +# the following properties: +# 'key.store' for the location of your keystore and +# 'key.alias' for the name of the key to use. +# The password will be asked during the build when you use the 'release' target. + diff --git a/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/libs/android-support-v4.jar b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/libs/android-support-v4.jar new file mode 100644 index 000000000..feaf44f80 Binary files /dev/null and b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/libs/android-support-v4.jar differ diff --git a/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/pom.xml b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/pom.xml new file mode 100644 index 000000000..46761a99c --- /dev/null +++ b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + com.github.chrisbanes.pulltorefresh + extra-viewpager + apklib + Android-PullToRefresh Extras: ViewPager + + + com.github.chrisbanes.pulltorefresh + extras + 2.1.1 + + + + + com.google.android + android + + + com.google.android + support-v4 + r7 + + + ${project.groupId} + library + apklib + ${project.version} + + + + + + + com.jayway.maven.plugins.android.generation2 + android-maven-plugin + + + org.apache.maven.plugins + maven-eclipse-plugin + + + + diff --git a/plugins/Android-PullToRefresh/library/proguard-project.txt b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/proguard-project.txt similarity index 100% rename from plugins/Android-PullToRefresh/library/proguard-project.txt rename to plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/proguard-project.txt diff --git a/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/project.properties b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/project.properties new file mode 100644 index 000000000..927fba41c --- /dev/null +++ b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/project.properties @@ -0,0 +1,16 @@ +# 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 + +android.library=true +# Project target. +target=android-16 +android.library.reference.1=../../library diff --git a/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/res/layout/need_this_for_maven.xml b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/res/layout/need_this_for_maven.xml new file mode 100644 index 000000000..f59ab8781 --- /dev/null +++ b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/res/layout/need_this_for_maven.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/res/values/ids.xml b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/res/values/ids.xml new file mode 100644 index 000000000..81cebf0eb --- /dev/null +++ b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/res/values/ids.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/src/com/handmark/pulltorefresh/extras/viewpager/PullToRefreshViewPager.java b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/src/com/handmark/pulltorefresh/extras/viewpager/PullToRefreshViewPager.java new file mode 100644 index 000000000..d5f845b32 --- /dev/null +++ b/plugins/Android-PullToRefresh/extras/PullToRefreshViewPager/src/com/handmark/pulltorefresh/extras/viewpager/PullToRefreshViewPager.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright 2011, 2012 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 com.handmark.pulltorefresh.extras.viewpager; + +import android.content.Context; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; + +import com.handmark.pulltorefresh.library.PullToRefreshBase; + +public class PullToRefreshViewPager extends PullToRefreshBase { + + public PullToRefreshViewPager(Context context) { + super(context); + } + + public PullToRefreshViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public final Orientation getPullToRefreshScrollDirection() { + return Orientation.HORIZONTAL; + } + + @Override + protected ViewPager createRefreshableView(Context context, AttributeSet attrs) { + ViewPager viewPager = new ViewPager(context, attrs); + viewPager.setId(R.id.viewpager); + return viewPager; + } + + @Override + protected boolean isReadyForPullStart() { + ViewPager refreshableView = getRefreshableView(); + + PagerAdapter adapter = refreshableView.getAdapter(); + if (null != adapter) { + return refreshableView.getCurrentItem() == 0; + } + + return false; + } + + @Override + protected boolean isReadyForPullEnd() { + ViewPager refreshableView = getRefreshableView(); + + PagerAdapter adapter = refreshableView.getAdapter(); + if (null != adapter) { + return refreshableView.getCurrentItem() == adapter.getCount() - 1; + } + + return false; + } +} diff --git a/plugins/Android-PullToRefresh/extras/pom.xml b/plugins/Android-PullToRefresh/extras/pom.xml index 483b3038f..59ac6507b 100644 --- a/plugins/Android-PullToRefresh/extras/pom.xml +++ b/plugins/Android-PullToRefresh/extras/pom.xml @@ -10,10 +10,11 @@ com.github.chrisbanes.pulltorefresh parent - 1.4.2 + 2.1.1 PullToRefreshListFragment + PullToRefreshViewPager diff --git a/plugins/Android-PullToRefresh/library/AndroidManifest.xml b/plugins/Android-PullToRefresh/library/AndroidManifest.xml index 1eb616171..c3db5673d 100644 --- a/plugins/Android-PullToRefresh/library/AndroidManifest.xml +++ b/plugins/Android-PullToRefresh/library/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="2110" + android:versionName="2.1.1" > diff --git a/plugins/Android-PullToRefresh/library/LICENSE b/plugins/Android-PullToRefresh/library/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/plugins/Android-PullToRefresh/library/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/plugins/Android-PullToRefresh/library/pom.xml b/plugins/Android-PullToRefresh/library/pom.xml index d2a628beb..381eb5375 100644 --- a/plugins/Android-PullToRefresh/library/pom.xml +++ b/plugins/Android-PullToRefresh/library/pom.xml @@ -10,7 +10,7 @@ com.github.chrisbanes.pulltorefresh parent - 1.4.2 + 2.1.1 diff --git a/plugins/Android-PullToRefresh/library/res/drawable-hdpi/default_ptr_flip.png b/plugins/Android-PullToRefresh/library/res/drawable-hdpi/default_ptr_flip.png new file mode 100644 index 000000000..0a2c0bd9b Binary files /dev/null and b/plugins/Android-PullToRefresh/library/res/drawable-hdpi/default_ptr_flip.png differ diff --git a/plugins/Android-PullToRefresh/library/res/drawable-hdpi/default_ptr_flip_bottom.png b/plugins/Android-PullToRefresh/library/res/drawable-hdpi/default_ptr_flip_bottom.png deleted file mode 100644 index 91210b878..000000000 Binary files a/plugins/Android-PullToRefresh/library/res/drawable-hdpi/default_ptr_flip_bottom.png and /dev/null differ diff --git a/plugins/Android-PullToRefresh/library/res/drawable-hdpi/default_ptr_flip_top.png b/plugins/Android-PullToRefresh/library/res/drawable-hdpi/default_ptr_flip_top.png deleted file mode 100644 index 8d92b5a9d..000000000 Binary files a/plugins/Android-PullToRefresh/library/res/drawable-hdpi/default_ptr_flip_top.png and /dev/null differ diff --git a/plugins/Android-PullToRefresh/library/res/drawable-hdpi/indicator_arrow.png b/plugins/Android-PullToRefresh/library/res/drawable-hdpi/indicator_arrow.png new file mode 100644 index 000000000..8ae797709 Binary files /dev/null and b/plugins/Android-PullToRefresh/library/res/drawable-hdpi/indicator_arrow.png differ diff --git a/plugins/Android-PullToRefresh/library/res/drawable-mdpi/default_ptr_flip.png b/plugins/Android-PullToRefresh/library/res/drawable-mdpi/default_ptr_flip.png new file mode 100644 index 000000000..be696c1c6 Binary files /dev/null and b/plugins/Android-PullToRefresh/library/res/drawable-mdpi/default_ptr_flip.png differ diff --git a/plugins/Android-PullToRefresh/library/res/drawable-mdpi/default_ptr_rotate.png b/plugins/Android-PullToRefresh/library/res/drawable-mdpi/default_ptr_rotate.png new file mode 100644 index 000000000..ceed80dbf Binary files /dev/null and b/plugins/Android-PullToRefresh/library/res/drawable-mdpi/default_ptr_rotate.png differ diff --git a/plugins/Android-PullToRefresh/library/res/drawable-mdpi/indicator_arrow.png b/plugins/Android-PullToRefresh/library/res/drawable-mdpi/indicator_arrow.png new file mode 100644 index 000000000..20fe2c126 Binary files /dev/null and b/plugins/Android-PullToRefresh/library/res/drawable-mdpi/indicator_arrow.png differ diff --git a/plugins/Android-PullToRefresh/library/res/drawable-xhdpi/arrow_down.png b/plugins/Android-PullToRefresh/library/res/drawable-xhdpi/arrow_down.png deleted file mode 100644 index 855617bcc..000000000 Binary files a/plugins/Android-PullToRefresh/library/res/drawable-xhdpi/arrow_down.png and /dev/null differ diff --git a/plugins/Android-PullToRefresh/library/res/drawable-xhdpi/arrow_up.png b/plugins/Android-PullToRefresh/library/res/drawable-xhdpi/arrow_up.png deleted file mode 100644 index eaf797934..000000000 Binary files a/plugins/Android-PullToRefresh/library/res/drawable-xhdpi/arrow_up.png and /dev/null differ diff --git a/plugins/Android-PullToRefresh/library/res/drawable-xhdpi/default_ptr_flip.png b/plugins/Android-PullToRefresh/library/res/drawable-xhdpi/default_ptr_flip.png new file mode 100644 index 000000000..3e6ddba5c Binary files /dev/null and b/plugins/Android-PullToRefresh/library/res/drawable-xhdpi/default_ptr_flip.png differ diff --git a/plugins/Android-PullToRefresh/library/res/drawable-xhdpi/indicator_arrow.png b/plugins/Android-PullToRefresh/library/res/drawable-xhdpi/indicator_arrow.png new file mode 100644 index 000000000..810ff595b Binary files /dev/null and b/plugins/Android-PullToRefresh/library/res/drawable-xhdpi/indicator_arrow.png differ diff --git a/plugins/Android-PullToRefresh/library/res/layout/pull_to_refresh_header.xml b/plugins/Android-PullToRefresh/library/res/layout/pull_to_refresh_header.xml deleted file mode 100644 index efc0d4a02..000000000 --- a/plugins/Android-PullToRefresh/library/res/layout/pull_to_refresh_header.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/Android-PullToRefresh/library/res/layout/pull_to_refresh_header_horizontal.xml b/plugins/Android-PullToRefresh/library/res/layout/pull_to_refresh_header_horizontal.xml new file mode 100644 index 000000000..f05bb0338 --- /dev/null +++ b/plugins/Android-PullToRefresh/library/res/layout/pull_to_refresh_header_horizontal.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/Android-PullToRefresh/library/res/layout/pull_to_refresh_header_vertical.xml b/plugins/Android-PullToRefresh/library/res/layout/pull_to_refresh_header_vertical.xml new file mode 100644 index 000000000..2185e2d6f --- /dev/null +++ b/plugins/Android-PullToRefresh/library/res/layout/pull_to_refresh_header_vertical.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/Android-PullToRefresh/library/res/values-ar/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-ar/pull_refresh_strings.xml new file mode 100644 index 000000000..5b0b571cc --- /dev/null +++ b/plugins/Android-PullToRefresh/library/res/values-ar/pull_refresh_strings.xml @@ -0,0 +1,6 @@ + + + اسحب للتحديث… + اترك للتحديث… + تحميل… + diff --git a/plugins/Android-PullToRefresh/library/res/values-cs/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-cs/pull_refresh_strings.xml index 9ecf5b271..a8f0acea7 100755 --- a/plugins/Android-PullToRefresh/library/res/values-cs/pull_refresh_strings.xml +++ b/plugins/Android-PullToRefresh/library/res/values-cs/pull_refresh_strings.xml @@ -1,6 +1,6 @@ - Tažením aktualizujete… - Uvolněním aktualizujete… - Načítání… + Tažením aktualizujete… + Uvolněním aktualizujete… + Načítání… diff --git a/plugins/Android-PullToRefresh/library/res/values-de/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-de/pull_refresh_strings.xml index 2f2746055..3f773deb0 100755 --- a/plugins/Android-PullToRefresh/library/res/values-de/pull_refresh_strings.xml +++ b/plugins/Android-PullToRefresh/library/res/values-de/pull_refresh_strings.xml @@ -1,6 +1,6 @@ - Ziehen zum Aktualisieren… - Loslassen zum Aktualisieren… - Laden… + Ziehen zum Aktualisieren… + Loslassen zum Aktualisieren… + Laden… diff --git a/plugins/Android-PullToRefresh/library/res/values-es/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-es/pull_refresh_strings.xml index 922427b75..6f85c1008 100755 --- a/plugins/Android-PullToRefresh/library/res/values-es/pull_refresh_strings.xml +++ b/plugins/Android-PullToRefresh/library/res/values-es/pull_refresh_strings.xml @@ -1,6 +1,6 @@ - Tire para actualizar… - Deslice para actualizar… - Cargando… + Tirar para actualizar… + Soltar para actualizar… + Cargando… diff --git a/plugins/Android-PullToRefresh/library/res/values-fr/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-fr/pull_refresh_strings.xml index 9fde6cd87..e59f07eca 100755 --- a/plugins/Android-PullToRefresh/library/res/values-fr/pull_refresh_strings.xml +++ b/plugins/Android-PullToRefresh/library/res/values-fr/pull_refresh_strings.xml @@ -1,6 +1,6 @@ - Tirez pour rafraîchir… - Relâcher pour rafraîchir… - Chargement… + Tirez pour rafraîchir… + Relâcher pour rafraîchir… + Chargement… diff --git a/plugins/Android-PullToRefresh/library/res/values-he/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-he/pull_refresh_strings.xml new file mode 100644 index 000000000..f22f7853f --- /dev/null +++ b/plugins/Android-PullToRefresh/library/res/values-he/pull_refresh_strings.xml @@ -0,0 +1,6 @@ + + + משוך לרענון… + שחרר לרענון… + טוען… + diff --git a/plugins/Android-PullToRefresh/library/res/values-it/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-it/pull_refresh_strings.xml index d8b3b7aa2..9eaa74955 100755 --- a/plugins/Android-PullToRefresh/library/res/values-it/pull_refresh_strings.xml +++ b/plugins/Android-PullToRefresh/library/res/values-it/pull_refresh_strings.xml @@ -1,6 +1,6 @@ - Tira per aggiornare… - Rilascia per aggionare… - Caricamento… + Tira per aggiornare… + Rilascia per aggionare… + Caricamento… diff --git a/plugins/Android-PullToRefresh/library/res/values-iw/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-iw/pull_refresh_strings.xml new file mode 100644 index 000000000..f22f7853f --- /dev/null +++ b/plugins/Android-PullToRefresh/library/res/values-iw/pull_refresh_strings.xml @@ -0,0 +1,6 @@ + + + משוך לרענון… + שחרר לרענון… + טוען… + diff --git a/plugins/Android-PullToRefresh/library/res/values-ja/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-ja/pull_refresh_strings.xml index 09cd05b94..124154433 100644 --- a/plugins/Android-PullToRefresh/library/res/values-ja/pull_refresh_strings.xml +++ b/plugins/Android-PullToRefresh/library/res/values-ja/pull_refresh_strings.xml @@ -1,6 +1,6 @@ - 画面を引っ張って… - 指を離すと更新… - 読み込み中… + 画面を引っ張って… + 指を離して更新… + 読み込み中… diff --git a/plugins/Android-PullToRefresh/library/res/values-ko/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-ko/pull_refresh_strings.xml index 1ba619291..15d86d4dd 100755 --- a/plugins/Android-PullToRefresh/library/res/values-ko/pull_refresh_strings.xml +++ b/plugins/Android-PullToRefresh/library/res/values-ko/pull_refresh_strings.xml @@ -1,6 +1,6 @@ - 당겨서 새로 고침… - 놓아서 새로 고침… - 로딩 중… + 당겨서 새로 고침… + 놓아서 새로 고침… + 로드 중… diff --git a/plugins/Android-PullToRefresh/library/res/values-nl/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-nl/pull_refresh_strings.xml index 8e7414784..0701c9b47 100755 --- a/plugins/Android-PullToRefresh/library/res/values-nl/pull_refresh_strings.xml +++ b/plugins/Android-PullToRefresh/library/res/values-nl/pull_refresh_strings.xml @@ -1,6 +1,6 @@ - Sleep om te vernieuwen… - Loslaten om te vernieuwen… - Laden… + Sleep om te vernieuwen… + Loslaten om te vernieuwen… + Laden… diff --git a/plugins/Android-PullToRefresh/library/res/values-pl/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-pl/pull_refresh_strings.xml index 8b7f398bd..7d474c189 100755 --- a/plugins/Android-PullToRefresh/library/res/values-pl/pull_refresh_strings.xml +++ b/plugins/Android-PullToRefresh/library/res/values-pl/pull_refresh_strings.xml @@ -1,6 +1,6 @@ - Pociągnij, aby odświeżyć… - Puść, aby odświeżyć… - Trwa ładowanie… + Pociągnij, aby odświeżyć… + Puść, aby odświeżyć… + Wczytywanie… diff --git a/plugins/Android-PullToRefresh/library/res/values-pt-rBR/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-pt-rBR/pull_refresh_strings.xml index bdd1cd4af..1a4359a86 100755 --- a/plugins/Android-PullToRefresh/library/res/values-pt-rBR/pull_refresh_strings.xml +++ b/plugins/Android-PullToRefresh/library/res/values-pt-rBR/pull_refresh_strings.xml @@ -1,6 +1,6 @@ - Puxe para atualizar… - Libere para atualizar… - Carregando… + Puxe para atualizar… + Libere para atualizar… + Carregando… diff --git a/plugins/Android-PullToRefresh/library/res/values-pt/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-pt/pull_refresh_strings.xml index 8f5b27536..71eea31ac 100755 --- a/plugins/Android-PullToRefresh/library/res/values-pt/pull_refresh_strings.xml +++ b/plugins/Android-PullToRefresh/library/res/values-pt/pull_refresh_strings.xml @@ -1,6 +1,6 @@ - Puxe para atualizar… - Liberação para atualizar… - A carregar… + Puxe para atualizar… + Liberação para atualizar… + A carregar… diff --git a/plugins/Android-PullToRefresh/library/res/values-ro/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-ro/pull_refresh_strings.xml new file mode 100644 index 000000000..c89e80a98 --- /dev/null +++ b/plugins/Android-PullToRefresh/library/res/values-ro/pull_refresh_strings.xml @@ -0,0 +1,6 @@ + + + Trage pentru a reîmprospăta… + Eliberează pentru a reîmprospăta… + Încărcare… + diff --git a/plugins/Android-PullToRefresh/library/res/values-ru/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-ru/pull_refresh_strings.xml index 4fdb8354b..ca364ff8e 100755 --- a/plugins/Android-PullToRefresh/library/res/values-ru/pull_refresh_strings.xml +++ b/plugins/Android-PullToRefresh/library/res/values-ru/pull_refresh_strings.xml @@ -1,6 +1,6 @@ - Потяните для обновления… - Отпустите для обновления… - Загрузка… + Потяните для обновления… + Отпустите для обновления… + Загрузка… diff --git a/plugins/Android-PullToRefresh/library/res/values-zh/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values-zh/pull_refresh_strings.xml index 2fff9e248..397376be9 100755 --- a/plugins/Android-PullToRefresh/library/res/values-zh/pull_refresh_strings.xml +++ b/plugins/Android-PullToRefresh/library/res/values-zh/pull_refresh_strings.xml @@ -1,6 +1,6 @@ - 下拉刷新… - 松手刷新… - 载入中… + 下拉刷新… + 放开以刷新… + 正在载入… diff --git a/plugins/Android-PullToRefresh/library/res/values/attrs.xml b/plugins/Android-PullToRefresh/library/res/values/attrs.xml index fddbfaa85..a3408ae7d 100644 --- a/plugins/Android-PullToRefresh/library/res/values/attrs.xml +++ b/plugins/Android-PullToRefresh/library/res/values/attrs.xml @@ -2,27 +2,79 @@ - + + + + + + + + + + + + + + + + + - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + \ No newline at end of file diff --git a/plugins/Android-PullToRefresh/library/res/values/dimens.xml b/plugins/Android-PullToRefresh/library/res/values/dimens.xml index 92031cac7..24339b5ba 100644 --- a/plugins/Android-PullToRefresh/library/res/values/dimens.xml +++ b/plugins/Android-PullToRefresh/library/res/values/dimens.xml @@ -4,8 +4,7 @@ 10dp 12dp 4dp - 25dp - 10dp - 20dp + 24dp + 12dp \ No newline at end of file diff --git a/plugins/Android-PullToRefresh/library/res/values/pull_refresh_strings.xml b/plugins/Android-PullToRefresh/library/res/values/pull_refresh_strings.xml index e89139feb..fe48f3bc0 100755 --- a/plugins/Android-PullToRefresh/library/res/values/pull_refresh_strings.xml +++ b/plugins/Android-PullToRefresh/library/res/values/pull_refresh_strings.xml @@ -1,9 +1,9 @@ - Pull to refresh… - Release to refresh… - Loading… + Pull to refresh… + Release to refresh… + Loading… @string/pull_to_refresh_pull_label diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/ILoadingLayout.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/ILoadingLayout.java new file mode 100644 index 000000000..ff2a95722 --- /dev/null +++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/ILoadingLayout.java @@ -0,0 +1,57 @@ +package com.handmark.pulltorefresh.library; + +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; + +public interface ILoadingLayout { + + /** + * Set the Last Updated Text. This displayed under the main label when + * Pulling + * + * @param label - Label to set + */ + public void setLastUpdatedLabel(CharSequence label); + + /** + * Set the drawable used in the loading layout. This is the same as calling + * setLoadingDrawable(drawable, Mode.BOTH) + * + * @param drawable - Drawable to display + */ + public void setLoadingDrawable(Drawable drawable); + + /** + * Set Text to show when the Widget is being Pulled + * setPullLabel(releaseLabel, Mode.BOTH) + * + * @param pullLabel - CharSequence to display + */ + public void setPullLabel(CharSequence pullLabel); + + /** + * Set Text to show when the Widget is refreshing + * setRefreshingLabel(releaseLabel, Mode.BOTH) + * + * @param refreshingLabel - CharSequence to display + */ + public void setRefreshingLabel(CharSequence refreshingLabel); + + /** + * Set Text to show when the Widget is being pulled, and will refresh when + * released. This is the same as calling + * setReleaseLabel(releaseLabel, Mode.BOTH) + * + * @param releaseLabel - CharSequence to display + */ + public void setReleaseLabel(CharSequence releaseLabel); + + /** + * Set's the Sets the typeface and style in which the text should be + * displayed. Please see + * {@link android.widget.TextView#setTypeface(Typeface) + * TextView#setTypeface(Typeface)}. + */ + public void setTextTypeface(Typeface tf); + +} diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/IPullToRefresh.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/IPullToRefresh.java index 777af4528..a06cdd7cf 100644 --- a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/IPullToRefresh.java +++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/IPullToRefresh.java @@ -15,7 +15,6 @@ *******************************************************************************/ package com.handmark.pulltorefresh.library; -import android.graphics.drawable.Drawable; import android.view.View; import android.view.animation.Interpolator; @@ -27,6 +26,17 @@ import com.handmark.pulltorefresh.library.PullToRefreshBase.State; public interface IPullToRefresh { + /** + * Demos the Pull-to-Refresh functionality to the user so that they are + * aware it is there. This could be useful when the user first opens your + * app, etc. The animation will only happen if the Refresh View (ListView, + * ScrollView, etc) is in a state where a Pull-to-Refresh could occur by a + * user's touch gesture (i.e. scrolled to the top/bottom). + * + * @return true - if the Demo has been started, false if not. + */ + public boolean demo(); + /** * Get the mode that this view is currently in. This is only really useful * when using Mode.BOTH. @@ -46,6 +56,34 @@ public interface IPullToRefresh { */ public boolean getFilterTouchEvents(); + /** + * Returns a proxy object which allows you to call methods on all of the + * LoadingLayouts (the Views which show when Pulling/Refreshing). + *

+ * You should not keep the result of this method any longer than you need + * it. + * + * @return Object which will proxy any calls you make on it, to all of the + * LoadingLayouts. + */ + public ILoadingLayout getLoadingLayoutProxy(); + + /** + * Returns a proxy object which allows you to call methods on the + * LoadingLayouts (the Views which show when Pulling/Refreshing). The actual + * LoadingLayout(s) which will be affected, are chosen by the parameters you + * give. + *

+ * You should not keep the result of this method any longer than you need + * it. + * + * @param includeStart - Whether to include the Start/Header Views + * @param includeEnd - Whether to include the End/Footer Views + * @return Object which will proxy any calls you make on it, to the + * LoadingLayouts included. + */ + public ILoadingLayout getLoadingLayoutProxy(boolean includeStart, boolean includeEnd); + /** * Get the mode that this view has been set to. If this returns * Mode.BOTH, you can use getCurrentMode() to @@ -77,12 +115,11 @@ public interface IPullToRefresh { public State getState(); /** - * Returns whether the widget has disabled scrolling on the Refreshable View - * while refreshing. + * Whether Pull-to-Refresh is enabled * - * @return true if the widget has disabled scrolling while refreshing + * @return enabled */ - public boolean isDisableScrollingWhileRefreshing(); + public boolean isPullToRefreshEnabled(); /** * Gets whether Overscroll support is enabled. This is different to @@ -94,13 +131,6 @@ public interface IPullToRefresh { */ public boolean isPullToRefreshOverScrollEnabled(); - /** - * Whether Pull-to-Refresh is enabled - * - * @return enabled - */ - public boolean isPullToRefreshEnabled(); - /** * Returns whether the Widget is currently in the Refreshing mState * @@ -108,21 +138,20 @@ public interface IPullToRefresh { */ public boolean isRefreshing(); + /** + * Returns whether the widget has enabled scrolling on the Refreshable View + * while refreshing. + * + * @return true if the widget has enabled scrolling while refreshing + */ + public boolean isScrollingWhileRefreshingEnabled(); + /** * Mark the current Refresh as complete. Will Reset the UI and hide the * Refreshing View */ public void onRefreshComplete(); - /** - * By default the Widget disabled scrolling on the Refreshable View while - * refreshing. This method can change this behaviour. - * - * @param disableScrollingWhileRefreshing - * - true if you want to disable scrolling while refreshing - */ - public void setDisableScrollingWhileRefreshing(boolean disableScrollingWhileRefreshing); - /** * Set the Touch Events to be filtered or not. If set to true, then the View * will only use touch events where the difference in the Y-axis is greater @@ -131,54 +160,22 @@ public interface IPullToRefresh { * ViewPager), but will restrict which types of finger scrolls will trigger * the View. * - * @param filterEvents - * - true if you want to filter Touch Events. Default is true. + * @param filterEvents - true if you want to filter Touch Events. Default is + * true. */ public void setFilterTouchEvents(boolean filterEvents); - /** - * Set the Last Updated Text. This displayed under the main label when - * Pulling - * - * @param label - * - Label to set - */ - public void setLastUpdatedLabel(CharSequence label); - - /** - * Set the drawable used in the loading layout. This is the same as calling - * setLoadingDrawable(drawable, Mode.BOTH) - * - * @param drawable - * - Drawable to display - */ - public void setLoadingDrawable(Drawable drawable); - - /** - * Set the drawable used in the loading layout. - * - * @param drawable - * - Drawable to display - * @param mode - * - Controls which Header/Footer Views will be updated. - * Mode.BOTH will update all available, other values - * will update the relevant View. - */ - public void setLoadingDrawable(Drawable drawable, Mode mode); - /** * Set the mode of Pull-to-Refresh that this view will use. * - * @param mode - * - Mode to set the View to + * @param mode - Mode to set the View to */ public void setMode(Mode mode); /** * Set OnPullEventListener for the Widget * - * @param listener - * - Listener to be used when the Widget has a pull event to + * @param listener - Listener to be used when the Widget has a pull event to * propogate. */ public void setOnPullEventListener(OnPullEventListener listener); @@ -186,16 +183,14 @@ public interface IPullToRefresh { /** * Set OnRefreshListener for the Widget * - * @param listener - * - Listener to be used when the Widget is set to Refresh + * @param listener - Listener to be used when the Widget is set to Refresh */ public void setOnRefreshListener(OnRefreshListener listener); /** * Set OnRefreshListener for the Widget * - * @param listener - * - Listener to be used when the Widget is set to Refresh + * @param listener - Listener to be used when the Widget is set to Refresh */ public void setOnRefreshListener(OnRefreshListener2 listener); @@ -204,32 +199,10 @@ public interface IPullToRefresh { * Android's standard Overscroll support (the edge-glow). This setting only * takes effect when running on device with Android v2.3 or greater. * - * @param enabled - * - true if you want Overscroll enabled + * @param enabled - true if you want Overscroll enabled */ public void setPullToRefreshOverScrollEnabled(boolean enabled); - /** - * Set Text to show when the Widget is being Pulled - * setPullLabel(releaseLabel, Mode.BOTH) - * - * @param releaseLabel - * - CharSequence to display - */ - public void setPullLabel(CharSequence pullLabel); - - /** - * Set Text to show when the Widget is being Pulled - * - * @param pullLabel - * - CharSequence to display - * @param mode - * - Controls which Header/Footer Views will be updated. - * Mode.BOTH will update all available, other values - * will update the relevant View. - */ - public void setPullLabel(CharSequence pullLabel, Mode mode); - /** * Sets the Widget to be in the refresh state. The UI will be updated to * show the 'Refreshing' view, and be scrolled to show such. @@ -240,64 +213,28 @@ public interface IPullToRefresh { * Sets the Widget to be in the refresh state. The UI will be updated to * show the 'Refreshing' view. * - * @param doScroll - * - true if you want to force a scroll to the Refreshing view. + * @param doScroll - true if you want to force a scroll to the Refreshing + * view. */ public void setRefreshing(boolean doScroll); - /** - * Set Text to show when the Widget is refreshing - * setRefreshingLabel(releaseLabel, Mode.BOTH) - * - * @param releaseLabel - * - CharSequence to display - */ - public void setRefreshingLabel(CharSequence refreshingLabel); - - /** - * Set Text to show when the Widget is refreshing - * - * @param refreshingLabel - * - CharSequence to display - * @param mode - * - Controls which Header/Footer Views will be updated. - * Mode.BOTH will update all available, other values - * will update the relevant View. - */ - public void setRefreshingLabel(CharSequence refreshingLabel, Mode mode); - - /** - * Set Text to show when the Widget is being pulled, and will refresh when - * released. This is the same as calling - * setReleaseLabel(releaseLabel, Mode.BOTH) - * - * @param releaseLabel - * - CharSequence to display - */ - public void setReleaseLabel(CharSequence releaseLabel); - - /** - * Set Text to show when the Widget is being pulled, and will refresh when - * released - * - * @param releaseLabel - * - CharSequence to display - * @param mode - * - Controls which Header/Footer Views will be updated. - * Mode.BOTH will update all available, other values - * will update the relevant View. - */ - public void setReleaseLabel(CharSequence releaseLabel, Mode mode); - /** * Sets the Animation Interpolator that is used for animated scrolling. * Defaults to a DecelerateInterpolator * - * @param interpolator - * - Interpolator to use + * @param interpolator - Interpolator to use */ public void setScrollAnimationInterpolator(Interpolator interpolator); + /** + * By default the Widget disables scrolling on the Refreshable View while + * refreshing. This method can change this behaviour. + * + * @param scrollingWhileRefreshingEnabled - true if you want to enable + * scrolling while refreshing + */ + public void setScrollingWhileRefreshingEnabled(boolean scrollingWhileRefreshingEnabled); + /** * A mutator to enable/disable whether the 'Refreshing' View should be * automatically shown when refreshing. diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/LoadingLayoutProxy.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/LoadingLayoutProxy.java new file mode 100644 index 000000000..5f76645d2 --- /dev/null +++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/LoadingLayoutProxy.java @@ -0,0 +1,73 @@ +package com.handmark.pulltorefresh.library; + +import java.util.HashSet; + +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; + +import com.handmark.pulltorefresh.library.internal.LoadingLayout; + +public class LoadingLayoutProxy implements ILoadingLayout { + + private final HashSet mLoadingLayouts; + + LoadingLayoutProxy() { + mLoadingLayouts = new HashSet(); + } + + /** + * This allows you to add extra LoadingLayout instances to this proxy. This + * is only necessary if you keep your own instances, and want to have them + * included in any + * {@link PullToRefreshBase#createLoadingLayoutProxy(boolean, boolean) + * createLoadingLayoutProxy(...)} calls. + * + * @param layout - LoadingLayout to have included. + */ + public void addLayout(LoadingLayout layout) { + if (null != layout) { + mLoadingLayouts.add(layout); + } + } + + @Override + public void setLastUpdatedLabel(CharSequence label) { + for (LoadingLayout layout : mLoadingLayouts) { + layout.setLastUpdatedLabel(label); + } + } + + @Override + public void setLoadingDrawable(Drawable drawable) { + for (LoadingLayout layout : mLoadingLayouts) { + layout.setLoadingDrawable(drawable); + } + } + + @Override + public void setRefreshingLabel(CharSequence refreshingLabel) { + for (LoadingLayout layout : mLoadingLayouts) { + layout.setRefreshingLabel(refreshingLabel); + } + } + + @Override + public void setPullLabel(CharSequence label) { + for (LoadingLayout layout : mLoadingLayouts) { + layout.setPullLabel(label); + } + } + + @Override + public void setReleaseLabel(CharSequence label) { + for (LoadingLayout layout : mLoadingLayouts) { + layout.setReleaseLabel(label); + } + } + + public void setTextTypeface(Typeface tf) { + for (LoadingLayout layout : mLoadingLayouts) { + layout.setTextTypeface(tf); + } + } +} diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/OverscrollHelper.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/OverscrollHelper.java index 1c3d569a8..52a20de24 100644 --- a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/OverscrollHelper.java +++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/OverscrollHelper.java @@ -20,9 +20,10 @@ import android.util.Log; import android.view.View; import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; +import com.handmark.pulltorefresh.library.PullToRefreshBase.State; @TargetApi(9) -final class OverscrollHelper { +public final class OverscrollHelper { static final String LOG_TAG = "OverscrollHelper"; static final float DEFAULT_OVERSCROLL_SCALE = 1f; @@ -30,26 +31,26 @@ final class OverscrollHelper { /** * Helper method for Overscrolling that encapsulates all of the necessary * function. - * + *

* This should only be used on AdapterView's such as ListView as it just * calls through to overScrollBy() with the scrollRange = 0. AdapterView's * do not have a scroll range (i.e. getScrollY() doesn't work). * - * @param view - * - PullToRefreshView that is calling this. - * @param deltaY - * - Change in Y in pixels, passed through from from overScrollBy - * call - * @param scrollY - * - Current Y scroll value in pixels before applying deltaY, + * @param view - PullToRefreshView that is calling this. + * @param deltaX - Change in X in pixels, passed through from from + * overScrollBy call + * @param scrollX - Current X scroll value in pixels before applying deltaY, * passed through from from overScrollBy call - * @param isTouchEvent - * - true if this scroll operation is the result of a touch - * event, passed through from from overScrollBy call + * @param deltaY - Change in Y in pixels, passed through from from + * overScrollBy call + * @param scrollY - Current Y scroll value in pixels before applying deltaY, + * passed through from from overScrollBy call + * @param isTouchEvent - true if this scroll operation is the result of a + * touch event, passed through from from overScrollBy call */ - static void overScrollBy(final PullToRefreshBase view, final int deltaY, final int scrollY, - final boolean isTouchEvent) { - overScrollBy(view, deltaY, scrollY, 0, isTouchEvent); + public static void overScrollBy(final PullToRefreshBase view, final int deltaX, final int scrollX, + final int deltaY, final int scrollY, final boolean isTouchEvent) { + overScrollBy(view, deltaX, scrollX, deltaY, scrollY, 0, isTouchEvent); } /** @@ -57,81 +58,116 @@ final class OverscrollHelper { * function. This version of the call is used for Views that need to specify * a Scroll Range but scroll back to it's edge correctly. * - * @param view - * - PullToRefreshView that is calling this. - * @param deltaY - * - Change in Y in pixels, passed through from from overScrollBy - * call - * @param scrollY - * - Current Y scroll value in pixels before applying deltaY, + * @param view - PullToRefreshView that is calling this. + * @param deltaX - Change in X in pixels, passed through from from + * overScrollBy call + * @param scrollX - Current X scroll value in pixels before applying deltaY, * passed through from from overScrollBy call - * @param scrollRange - * - Scroll Range of the View, specifically needed for ScrollView - * @param isTouchEvent - * - true if this scroll operation is the result of a touch - * event, passed through from from overScrollBy call + * @param deltaY - Change in Y in pixels, passed through from from + * overScrollBy call + * @param scrollY - Current Y scroll value in pixels before applying deltaY, + * passed through from from overScrollBy call + * @param scrollRange - Scroll Range of the View, specifically needed for + * ScrollView + * @param isTouchEvent - true if this scroll operation is the result of a + * touch event, passed through from from overScrollBy call */ - static void overScrollBy(final PullToRefreshBase view, final int deltaY, final int scrollY, - final int scrollRange, final boolean isTouchEvent) { - overScrollBy(view, deltaY, scrollY, scrollRange, 0, DEFAULT_OVERSCROLL_SCALE, isTouchEvent); + public static void overScrollBy(final PullToRefreshBase view, final int deltaX, final int scrollX, + final int deltaY, final int scrollY, final int scrollRange, final boolean isTouchEvent) { + overScrollBy(view, deltaX, scrollX, deltaY, scrollY, scrollRange, 0, DEFAULT_OVERSCROLL_SCALE, isTouchEvent); } /** * Helper method for Overscrolling that encapsulates all of the necessary * function. This is the advanced version of the call. * - * @param view - * - PullToRefreshView that is calling this. - * @param deltaY - * - Change in Y in pixels, passed through from from overScrollBy - * call - * @param scrollY - * - Current Y scroll value in pixels before applying deltaY, + * @param view - PullToRefreshView that is calling this. + * @param deltaX - Change in X in pixels, passed through from from + * overScrollBy call + * @param scrollX - Current X scroll value in pixels before applying deltaY, * passed through from from overScrollBy call - * @param scrollRange - * - Scroll Range of the View, specifically needed for ScrollView - * @param fuzzyThreshold - * - Threshold for which the values how fuzzy we should treat the - * other values. Needed for WebView as it doesn't always scroll - * back to it's edge. 0 = no fuzziness. - * @param scaleFactor - * - Scale Factor for overscroll amount - * @param isTouchEvent - * - true if this scroll operation is the result of a touch - * event, passed through from from overScrollBy call + * @param deltaY - Change in Y in pixels, passed through from from + * overScrollBy call + * @param scrollY - Current Y scroll value in pixels before applying deltaY, + * passed through from from overScrollBy call + * @param scrollRange - Scroll Range of the View, specifically needed for + * ScrollView + * @param fuzzyThreshold - Threshold for which the values how fuzzy we + * should treat the other values. Needed for WebView as it + * doesn't always scroll back to it's edge. 0 = no fuzziness. + * @param scaleFactor - Scale Factor for overscroll amount + * @param isTouchEvent - true if this scroll operation is the result of a + * touch event, passed through from from overScrollBy call */ - static void overScrollBy(final PullToRefreshBase view, final int deltaY, final int scrollY, - final int scrollRange, final int fuzzyThreshold, final float scaleFactor, final boolean isTouchEvent) { + public static void overScrollBy(final PullToRefreshBase view, final int deltaX, final int scrollX, + final int deltaY, final int scrollY, final int scrollRange, final int fuzzyThreshold, + final float scaleFactor, final boolean isTouchEvent) { - // Check that OverScroll is enabled - if (view.isPullToRefreshOverScrollEnabled()) { + final int deltaValue, currentScrollValue, scrollValue; + switch (view.getPullToRefreshScrollDirection()) { + case HORIZONTAL: + deltaValue = deltaX; + scrollValue = scrollX; + currentScrollValue = view.getScrollX(); + break; + case VERTICAL: + default: + deltaValue = deltaY; + scrollValue = scrollY; + currentScrollValue = view.getScrollY(); + break; + } + + // Check that OverScroll is enabled and that we're not currently + // refreshing. + if (view.isPullToRefreshOverScrollEnabled() && !view.isRefreshing()) { final Mode mode = view.getMode(); - // Check that we're not disabled, and the event isn't from touch - if (mode != Mode.DISABLED && !isTouchEvent && deltaY != 0) { - final int newY = (deltaY + scrollY); + // Check that Pull-to-Refresh is enabled, and the event isn't from + // touch + if (mode.permitsPullToRefresh() && !isTouchEvent && deltaValue != 0) { + final int newScrollValue = (deltaValue + scrollValue); if (PullToRefreshBase.DEBUG) { - Log.d(LOG_TAG, "OverScroll. DeltaY: " + deltaY + ", ScrollY: " + scrollY + ", NewY: " + newY - + ", ScrollRange: " + scrollRange); + Log.d(LOG_TAG, "OverScroll. DeltaX: " + deltaX + ", ScrollX: " + scrollX + ", DeltaY: " + deltaY + + ", ScrollY: " + scrollY + ", NewY: " + newScrollValue + ", ScrollRange: " + scrollRange + + ", CurrentScroll: " + currentScrollValue); } - if (newY < (0 - fuzzyThreshold)) { + if (newScrollValue < (0 - fuzzyThreshold)) { // Check the mode supports the overscroll direction, and // then move scroll - if (mode.canPullDown()) { - view.setHeaderScroll((int) (scaleFactor * (view.getScrollY() + newY))); + if (mode.showHeaderLoadingLayout()) { + // If we're currently at zero, we're about to start + // overscrolling, so change the state + if (currentScrollValue == 0) { + view.setState(State.OVERSCROLLING); + } + + view.setHeaderScroll((int) (scaleFactor * (currentScrollValue + newScrollValue))); } - } else if (newY > (scrollRange + fuzzyThreshold)) { + } else if (newScrollValue > (scrollRange + fuzzyThreshold)) { // Check the mode supports the overscroll direction, and // then move scroll - if (mode.canPullUp()) { - view.setHeaderScroll((int) (scaleFactor * (view.getScrollY() + newY - scrollRange))); + if (mode.showFooterLoadingLayout()) { + // If we're currently at zero, we're about to start + // overscrolling, so change the state + if (currentScrollValue == 0) { + view.setState(State.OVERSCROLLING); + } + + view.setHeaderScroll((int) (scaleFactor * (currentScrollValue + newScrollValue - scrollRange))); } - } else if (Math.abs(newY) <= fuzzyThreshold || Math.abs(newY - scrollRange) <= fuzzyThreshold) { + } else if (Math.abs(newScrollValue) <= fuzzyThreshold + || Math.abs(newScrollValue - scrollRange) <= fuzzyThreshold) { // Means we've stopped overscrolling, so scroll back to 0 - view.smoothScrollToLonger(0); + view.setState(State.RESET); } + } else if (isTouchEvent && State.OVERSCROLLING == view.getState()) { + // This condition means that we were overscrolling from a fling, + // but the user has touched the View and is now overscrolling + // from touch instead. We need to just reset. + view.setState(State.RESET); } } } diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshAdapterViewBase.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshAdapterViewBase.java index 2f3eaf446..b5132ed6a 100644 --- a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshAdapterViewBase.java +++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshAdapterViewBase.java @@ -19,7 +19,6 @@ import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.util.Log; -import android.view.ContextMenu.ContextMenuInfo; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; @@ -30,6 +29,7 @@ import android.widget.Adapter; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.FrameLayout; +import android.widget.LinearLayout; import android.widget.ListAdapter; import com.handmark.pulltorefresh.library.internal.EmptyViewMethodAccessor; @@ -38,7 +38,23 @@ import com.handmark.pulltorefresh.library.internal.IndicatorLayout; public abstract class PullToRefreshAdapterViewBase extends PullToRefreshBase implements OnScrollListener { - private int mSavedLastVisibleIndex = -1; + private static FrameLayout.LayoutParams convertEmptyViewLayoutParams(ViewGroup.LayoutParams lp) { + FrameLayout.LayoutParams newLp = null; + + if (null != lp) { + newLp = new FrameLayout.LayoutParams(lp); + + if (lp instanceof LinearLayout.LayoutParams) { + newLp.gravity = ((LinearLayout.LayoutParams) lp).gravity; + } else { + newLp.gravity = Gravity.CENTER; + } + } + + return newLp; + } + + private boolean mLastItemVisible; private OnScrollListener mOnScrollListener; private OnLastItemVisibleListener mOnLastItemVisibleListener; private View mEmptyView; @@ -64,14 +80,17 @@ public abstract class PullToRefreshAdapterViewBase extend mRefreshableView.setOnScrollListener(this); } - abstract public ContextMenuInfo getContextMenuInfo(); + public PullToRefreshAdapterViewBase(Context context, Mode mode, AnimationStyle animStyle) { + super(context, mode, animStyle); + mRefreshableView.setOnScrollListener(this); + } /** * Gets whether an indicator graphic should be displayed when the View is in * a state where a Pull-to-Refresh can happen. An example of this state is * when the Adapter View is scrolled to the top and the mode is set to - * {@link Mode#PULL_DOWN_TO_REFRESH}. The default value is true - * if {@link PullToRefreshBase#isPullToRefreshOverScrollEnabled() + * {@link Mode#PULL_FROM_START}. The default value is true if + * {@link PullToRefreshBase#isPullToRefreshOverScrollEnabled() * isPullToRefreshOverScrollEnabled()} returns false. * * @return true if the indicators will be shown @@ -85,26 +104,15 @@ public abstract class PullToRefreshAdapterViewBase extend if (DEBUG) { Log.d(LOG_TAG, "First Visible: " + firstVisibleItem + ". Visible Count: " + visibleItemCount - + ". Total Items: " + totalItemCount); + + ". Total Items:" + totalItemCount); } - // If we have a OnItemVisibleListener, do check... + /** + * Set whether the Last Item is Visible. lastVisibleItemIndex is a + * zero-based index, so we minus one totalItemCount to check + */ if (null != mOnLastItemVisibleListener) { - - // Detect whether the last visible item has changed - final int lastVisibleItemIndex = firstVisibleItem + visibleItemCount; - - /** - * Check that the last item has changed, we have any items, and that - * the last item is visible. lastVisibleItemIndex is a zero-based - * index, so we add one to it to check against totalItemCount. - */ - if (visibleItemCount > 0 && (lastVisibleItemIndex + 1) == totalItemCount) { - if (lastVisibleItemIndex != mSavedLastVisibleIndex) { - mSavedLastVisibleIndex = lastVisibleItemIndex; - mOnLastItemVisibleListener.onLastItemVisible(); - } - } + mLastItemVisible = (totalItemCount > 0) && (firstVisibleItem + visibleItemCount >= totalItemCount - 1); } // If we're showing the indicator, check positions... @@ -118,19 +126,27 @@ public abstract class PullToRefreshAdapterViewBase extend } } - public final void onScrollStateChanged(final AbsListView view, final int scrollState) { + public final void onScrollStateChanged(final AbsListView view, final int state) { + /** + * Check that the scrolling has stopped, and that the last item is + * visible. + */ + if (state == OnScrollListener.SCROLL_STATE_IDLE && null != mOnLastItemVisibleListener && mLastItemVisible) { + mOnLastItemVisibleListener.onLastItemVisible(); + } + if (null != mOnScrollListener) { - mOnScrollListener.onScrollStateChanged(view, scrollState); + mOnScrollListener.onScrollStateChanged(view, state); } } /** * Pass-through method for {@link PullToRefreshBase#getRefreshableView() - * getRefreshableView()}.{@link AdapterView#setAdapter(ListAdapter) + * getRefreshableView()}. + * {@link AdapterView#setAdapter(android.widget.Adapter)} * setAdapter(adapter)}. This is just for convenience! * - * @param adapter - * - Adapter to set + * @param adapter - Adapter to set */ public void setAdapter(ListAdapter adapter) { ((AdapterView) mRefreshableView).setAdapter(adapter); @@ -138,17 +154,16 @@ public abstract class PullToRefreshAdapterViewBase extend /** * Sets the Empty View to be used by the Adapter View. - * + *

* We need it handle it ourselves so that we can Pull-to-Refresh when the * Empty View is shown. - * + *

* Please note, you do not usually need to call this method * yourself. Calling setEmptyView on the AdapterView will automatically call * this method and set everything up. This includes when the Android * Framework automatically sets the Empty View based on it's ID. * - * @param newEmptyView - * - Empty View to be used + * @param newEmptyView - Empty View to be used */ public final void setEmptyView(View newEmptyView) { FrameLayout refreshableViewWrapper = getRefreshableViewWrapper(); @@ -168,8 +183,14 @@ public abstract class PullToRefreshAdapterViewBase extend ((ViewGroup) newEmptyViewParent).removeView(newEmptyView); } - refreshableViewWrapper.addView(newEmptyView, ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT); + // We need to convert any LayoutParams so that it works in our + // FrameLayout + FrameLayout.LayoutParams lp = convertEmptyViewLayoutParams(newEmptyView.getLayoutParams()); + if (null != lp) { + refreshableViewWrapper.addView(newEmptyView, lp); + } else { + refreshableViewWrapper.addView(newEmptyView); + } } if (mRefreshableView instanceof EmptyViewMethodAccessor) { @@ -186,8 +207,7 @@ public abstract class PullToRefreshAdapterViewBase extend * {@link AdapterView#setOnItemClickListener(OnItemClickListener) * setOnItemClickListener(listener)}. This is just for convenience! * - * @param listener - * - OnItemClickListener to use + * @param listener - OnItemClickListener to use */ public void setOnItemClickListener(OnItemClickListener listener) { mRefreshableView.setOnItemClickListener(listener); @@ -209,10 +229,9 @@ public abstract class PullToRefreshAdapterViewBase extend * Sets whether an indicator graphic should be displayed when the View is in * a state where a Pull-to-Refresh can happen. An example of this state is * when the Adapter View is scrolled to the top and the mode is set to - * {@link Mode#PULL_DOWN_TO_REFRESH} + * {@link Mode#PULL_FROM_START} * - * @param showIndicator - * - true if the indicators should be shown. + * @param showIndicator - true if the indicators should be shown. */ public void setShowIndicator(boolean showIndicator) { mShowIndicator = showIndicator; @@ -224,25 +243,30 @@ public abstract class PullToRefreshAdapterViewBase extend // If not, then remove then removeIndicatorViews(); } - }; + } + + ; @Override - void onPullToRefresh() { + protected void onPullToRefresh() { super.onPullToRefresh(); if (getShowIndicatorInternal()) { switch (getCurrentMode()) { - case PULL_UP_TO_REFRESH: + case PULL_FROM_END: mIndicatorIvBottom.pullToRefresh(); break; - case PULL_DOWN_TO_REFRESH: + case PULL_FROM_START: mIndicatorIvTop.pullToRefresh(); break; + default: + // NO-OP + break; } } } - void onRefreshing(boolean doScroll) { + protected void onRefreshing(boolean doScroll) { super.onRefreshing(doScroll); if (getShowIndicatorInternal()) { @@ -251,23 +275,26 @@ public abstract class PullToRefreshAdapterViewBase extend } @Override - void onReleaseToRefresh() { + protected void onReleaseToRefresh() { super.onReleaseToRefresh(); if (getShowIndicatorInternal()) { switch (getCurrentMode()) { - case PULL_UP_TO_REFRESH: + case PULL_FROM_END: mIndicatorIvBottom.releaseToRefresh(); break; - case PULL_DOWN_TO_REFRESH: + case PULL_FROM_START: mIndicatorIvTop.releaseToRefresh(); break; + default: + // NO-OP + break; } } } @Override - void onReset() { + protected void onReset() { super.onReset(); if (getShowIndicatorInternal()) { @@ -281,11 +308,11 @@ public abstract class PullToRefreshAdapterViewBase extend mShowIndicator = a.getBoolean(R.styleable.PullToRefresh_ptrShowIndicator, !isPullToRefreshOverScrollEnabled()); } - protected boolean isReadyForPullDown() { + protected boolean isReadyForPullStart() { return isFirstItemVisible(); } - protected boolean isReadyForPullUp() { + protected boolean isReadyForPullEnd() { return isLastItemVisible(); } @@ -313,31 +340,31 @@ public abstract class PullToRefreshAdapterViewBase extend Mode mode = getMode(); FrameLayout refreshableViewWrapper = getRefreshableViewWrapper(); - if (mode.canPullDown() && null == mIndicatorIvTop) { + if (mode.showHeaderLoadingLayout() && null == mIndicatorIvTop) { // If the mode can pull down, and we don't have one set already - mIndicatorIvTop = new IndicatorLayout(getContext(), Mode.PULL_DOWN_TO_REFRESH); + mIndicatorIvTop = new IndicatorLayout(getContext(), Mode.PULL_FROM_START); FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); params.rightMargin = getResources().getDimensionPixelSize(R.dimen.indicator_right_padding); params.gravity = Gravity.TOP | Gravity.RIGHT; refreshableViewWrapper.addView(mIndicatorIvTop, params); - } else if (!mode.canPullDown() && null != mIndicatorIvTop) { + } else if (!mode.showHeaderLoadingLayout() && null != mIndicatorIvTop) { // If we can't pull down, but have a View then remove it refreshableViewWrapper.removeView(mIndicatorIvTop); mIndicatorIvTop = null; } - if (mode.canPullUp() && null == mIndicatorIvBottom) { + if (mode.showFooterLoadingLayout() && null == mIndicatorIvBottom) { // If the mode can pull down, and we don't have one set already - mIndicatorIvBottom = new IndicatorLayout(getContext(), Mode.PULL_UP_TO_REFRESH); + mIndicatorIvBottom = new IndicatorLayout(getContext(), Mode.PULL_FROM_END); FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); params.rightMargin = getResources().getDimensionPixelSize(R.dimen.indicator_right_padding); params.gravity = Gravity.BOTTOM | Gravity.RIGHT; refreshableViewWrapper.addView(mIndicatorIvBottom, params); - } else if (!mode.canPullUp() && null != mIndicatorIvBottom) { + } else if (!mode.showFooterLoadingLayout() && null != mIndicatorIvBottom) { // If we can't pull down, but have a View then remove it refreshableViewWrapper.removeView(mIndicatorIvBottom); mIndicatorIvBottom = null; @@ -427,7 +454,7 @@ public abstract class PullToRefreshAdapterViewBase extend private void updateIndicatorViewsVisibility() { if (null != mIndicatorIvTop) { - if (!isRefreshing() && isReadyForPullDown()) { + if (!isRefreshing() && isReadyForPullStart()) { if (!mIndicatorIvTop.isVisible()) { mIndicatorIvTop.show(); } @@ -439,7 +466,7 @@ public abstract class PullToRefreshAdapterViewBase extend } if (null != mIndicatorIvBottom) { - if (!isRefreshing() && isReadyForPullUp()) { + if (!isRefreshing() && isReadyForPullEnd()) { if (!mIndicatorIvBottom.isVisible()) { mIndicatorIvBottom.show(); } diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshBase.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshBase.java index 37d2bf7f3..a76b32891 100644 --- a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshBase.java +++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshBase.java @@ -24,6 +24,7 @@ import android.os.Bundle; import android.os.Parcelable; import android.util.AttributeSet; import android.util.Log; +import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; @@ -36,7 +37,8 @@ import android.widget.LinearLayout; import com.handmark.pulltorefresh.library.internal.FlipLoadingLayout; import com.handmark.pulltorefresh.library.internal.LoadingLayout; import com.handmark.pulltorefresh.library.internal.RotateLoadingLayout; -import com.handmark.pulltorefresh.library.internal.SDK16; +import com.handmark.pulltorefresh.library.internal.Utils; +import com.handmark.pulltorefresh.library.internal.ViewCompat; public abstract class PullToRefreshBase extends LinearLayout implements IPullToRefresh { @@ -44,7 +46,7 @@ public abstract class PullToRefreshBase extends LinearLayout imp // Constants // =========================================================== - static final boolean DEBUG = false; + static final boolean DEBUG = true; static final String LOG_TAG = "PullToRefresh"; @@ -52,13 +54,12 @@ public abstract class PullToRefreshBase extends LinearLayout imp public static final int SMOOTH_SCROLL_DURATION_MS = 200; public static final int SMOOTH_SCROLL_LONG_DURATION_MS = 325; - - static final Mode DEFAULT_MODE = Mode.PULL_DOWN_TO_REFRESH; + static final int DEMO_SCROLL_INTERVAL = 225; static final String STATE_STATE = "ptr_state"; static final String STATE_MODE = "ptr_mode"; static final String STATE_CURRENT_MODE = "ptr_current_mode"; - static final String STATE_DISABLE_SCROLLING_REFRESHING = "ptr_disable_scrolling"; + static final String STATE_SCROLLING_REFRESHING_ENABLED = "ptr_disable_scrolling"; static final String STATE_SHOW_REFRESHING_VIEW = "ptr_show_refreshing_view"; static final String STATE_SUPER = "ptr_super"; @@ -67,32 +68,29 @@ public abstract class PullToRefreshBase extends LinearLayout imp // =========================================================== private int mTouchSlop; - private float mLastMotionX; - private float mLastMotionY; - private float mInitialMotionY; + private float mLastMotionX, mLastMotionY; + private float mInitialMotionX, mInitialMotionY; private boolean mIsBeingDragged = false; private State mState = State.RESET; - private Mode mMode = DEFAULT_MODE; + private Mode mMode = Mode.getDefault(); private Mode mCurrentMode; T mRefreshableView; private FrameLayout mRefreshableViewWrapper; private boolean mShowViewWhileRefreshing = true; - private boolean mDisableScrollingWhileRefreshing = true; + private boolean mScrollingWhileRefreshingEnabled = false; private boolean mFilterTouchEvents = true; private boolean mOverScrollEnabled = true; + private boolean mLayoutVisibilityChangesEnabled = true; private Interpolator mScrollAnimationInterpolator; - private AnimationStyle mLoadingAnimationStyle; + private AnimationStyle mLoadingAnimationStyle = AnimationStyle.getDefault(); private LoadingLayout mHeaderLayout; private LoadingLayout mFooterLayout; - private int mHeaderHeight; - private int mFooterHeight; - private OnRefreshListener mOnRefreshListener; private OnRefreshListener2 mOnRefreshListener2; private OnPullEventListener mOnPullEventListener; @@ -119,6 +117,13 @@ public abstract class PullToRefreshBase extends LinearLayout imp init(context, null); } + public PullToRefreshBase(Context context, Mode mode, AnimationStyle animStyle) { + super(context); + mMode = mode; + mLoadingAnimationStyle = animStyle; + init(context, null); + } + @Override public void addView(View child, int index, ViewGroup.LayoutParams params) { if (DEBUG) { @@ -134,6 +139,19 @@ public abstract class PullToRefreshBase extends LinearLayout imp } } + @Override + public final boolean demo() { + if (mMode.showHeaderLoadingLayout() && isReadyForPullStart()) { + smoothScrollToAndBack(-getHeaderSize() * 2); + return true; + } else if (mMode.showFooterLoadingLayout() && isReadyForPullEnd()) { + smoothScrollToAndBack(getFooterSize() * 2); + return true; + } + + return false; + } + @Override public final Mode getCurrentMode() { return mCurrentMode; @@ -144,6 +162,16 @@ public abstract class PullToRefreshBase extends LinearLayout imp return mFilterTouchEvents; } + @Override + public final ILoadingLayout getLoadingLayoutProxy() { + return getLoadingLayoutProxy(true, true); + } + + @Override + public final ILoadingLayout getLoadingLayoutProxy(boolean includeStart, boolean includeEnd) { + return createLoadingLayoutProxy(includeStart, includeEnd); + } + @Override public final Mode getMode() { return mMode; @@ -165,21 +193,15 @@ public abstract class PullToRefreshBase extends LinearLayout imp } /** - * @deprecated Use the value from getCurrentMode() instead - * @return true if the current mode is Mode.PULL_DOWN_TO_REFRESH + * @deprecated See {@link #isScrollingWhileRefreshingEnabled()}. */ - public final boolean hasPullFromTop() { - return mCurrentMode == Mode.PULL_DOWN_TO_REFRESH; - } - - @Override public final boolean isDisableScrollingWhileRefreshing() { - return mDisableScrollingWhileRefreshing; + return !isScrollingWhileRefreshingEnabled(); } @Override public final boolean isPullToRefreshEnabled() { - return mMode != Mode.DISABLED; + return mMode.permitsPullToRefresh(); } @Override @@ -193,6 +215,11 @@ public abstract class PullToRefreshBase extends LinearLayout imp return mState == State.REFRESHING || mState == State.MANUAL_REFRESHING; } + @Override + public final boolean isScrollingWhileRefreshingEnabled() { + return mScrollingWhileRefreshingEnabled; + } + @Override public final boolean onInterceptTouchEvent(MotionEvent event) { @@ -214,28 +241,43 @@ public abstract class PullToRefreshBase extends LinearLayout imp switch (action) { case MotionEvent.ACTION_MOVE: { // If we're refreshing, and the flag is set. Eat all MOVE events - if (mDisableScrollingWhileRefreshing && isRefreshing()) { + if (!mScrollingWhileRefreshingEnabled && isRefreshing()) { return true; } if (isReadyForPull()) { - final float y = event.getY(); - final float dy = y - mLastMotionY; - final float yDiff = Math.abs(dy); - final float xDiff = Math.abs(event.getX() - mLastMotionX); + final float y = event.getY(), x = event.getX(); + final float diff, oppositeDiff, absDiff; - if (yDiff > mTouchSlop && (!mFilterTouchEvents || yDiff > xDiff)) { - if (mMode.canPullDown() && dy >= 1f && isReadyForPullDown()) { + // We need to use the correct values, based on scroll + // direction + switch (getPullToRefreshScrollDirection()) { + case HORIZONTAL: + diff = x - mLastMotionX; + oppositeDiff = y - mLastMotionY; + break; + case VERTICAL: + default: + diff = y - mLastMotionY; + oppositeDiff = x - mLastMotionX; + break; + } + absDiff = Math.abs(diff); + + if (absDiff > mTouchSlop && (!mFilterTouchEvents || absDiff > Math.abs(oppositeDiff))) { + if (mMode.showHeaderLoadingLayout() && diff >= 1f && isReadyForPullStart()) { mLastMotionY = y; + mLastMotionX = x; mIsBeingDragged = true; if (mMode == Mode.BOTH) { - mCurrentMode = Mode.PULL_DOWN_TO_REFRESH; + mCurrentMode = Mode.PULL_FROM_START; } - } else if (mMode.canPullUp() && dy <= -1f && isReadyForPullUp()) { + } else if (mMode.showFooterLoadingLayout() && diff <= -1f && isReadyForPullEnd()) { mLastMotionY = y; + mLastMotionX = x; mIsBeingDragged = true; if (mMode == Mode.BOTH) { - mCurrentMode = Mode.PULL_UP_TO_REFRESH; + mCurrentMode = Mode.PULL_FROM_END; } } } @@ -245,7 +287,7 @@ public abstract class PullToRefreshBase extends LinearLayout imp case MotionEvent.ACTION_DOWN: { if (isReadyForPull()) { mLastMotionY = mInitialMotionY = event.getY(); - mLastMotionX = event.getX(); + mLastMotionX = mInitialMotionX = event.getX(); mIsBeingDragged = false; } break; @@ -270,7 +312,7 @@ public abstract class PullToRefreshBase extends LinearLayout imp } // If we're refreshing, and the flag is set. Eat the event - if (mDisableScrollingWhileRefreshing && isRefreshing()) { + if (!mScrollingWhileRefreshingEnabled && isRefreshing()) { return true; } @@ -282,6 +324,7 @@ public abstract class PullToRefreshBase extends LinearLayout imp case MotionEvent.ACTION_MOVE: { if (mIsBeingDragged) { mLastMotionY = event.getY(); + mLastMotionX = event.getX(); pullEvent(); return true; } @@ -291,6 +334,7 @@ public abstract class PullToRefreshBase extends LinearLayout imp case MotionEvent.ACTION_DOWN: { if (isReadyForPull()) { mLastMotionY = mInitialMotionY = event.getY(); + mLastMotionX = mInitialMotionX = event.getX(); return true; } break; @@ -310,15 +354,21 @@ public abstract class PullToRefreshBase extends LinearLayout imp } else if (null != mOnRefreshListener2) { setState(State.REFRESHING, true); - if (mCurrentMode == Mode.PULL_DOWN_TO_REFRESH) { + if (mCurrentMode == Mode.PULL_FROM_START) { mOnRefreshListener2.onPullDownToRefresh(this); - } else if (mCurrentMode == Mode.PULL_UP_TO_REFRESH) { + } else if (mCurrentMode == Mode.PULL_FROM_END) { mOnRefreshListener2.onPullUpToRefresh(this); } return true; } } + // If we're already refreshing, just scroll back to the top + if (isRefreshing()) { + smoothScrollTo(0); + return true; + } + // If we haven't returned by here, then we're not in a state // to pull, so just reset setState(State.RESET); @@ -332,9 +382,15 @@ public abstract class PullToRefreshBase extends LinearLayout imp return false; } - @Override - public final void setDisableScrollingWhileRefreshing(boolean disableScrollingWhileRefreshing) { - mDisableScrollingWhileRefreshing = disableScrollingWhileRefreshing; + public final void setScrollingWhileRefreshingEnabled(boolean allowScrollingWhileRefreshing) { + mScrollingWhileRefreshingEnabled = allowScrollingWhileRefreshing; + } + + /** + * @deprecated See {@link #setScrollingWhileRefreshingEnabled(boolean)} + */ + public void setDisableScrollingWhileRefreshing(boolean disableScrollingWhileRefreshing) { + setScrollingWhileRefreshingEnabled(!disableScrollingWhileRefreshing); } @Override @@ -342,35 +398,29 @@ public abstract class PullToRefreshBase extends LinearLayout imp mFilterTouchEvents = filterEvents; } - @Override + /** + * @deprecated You should now call this method on the result of + * {@link #getLoadingLayoutProxy()}. + */ public void setLastUpdatedLabel(CharSequence label) { - if (null != mHeaderLayout) { - mHeaderLayout.setSubHeaderText(label); - } - if (null != mFooterLayout) { - mFooterLayout.setSubHeaderText(label); - } - - // Refresh Height as it may have changed - refreshLoadingViewsHeight(); + getLoadingLayoutProxy().setLastUpdatedLabel(label); } - @Override + /** + * @deprecated You should now call this method on the result of + * {@link #getLoadingLayoutProxy()}. + */ public void setLoadingDrawable(Drawable drawable) { - setLoadingDrawable(drawable, Mode.BOTH); + getLoadingLayoutProxy().setLoadingDrawable(drawable); } - @Override + /** + * @deprecated You should now call this method on the result of + * {@link #getLoadingLayoutProxy(boolean, boolean)}. + */ public void setLoadingDrawable(Drawable drawable, Mode mode) { - if (null != mHeaderLayout && mode.canPullDown()) { - mHeaderLayout.setLoadingDrawable(drawable); - } - if (null != mFooterLayout && mode.canPullUp()) { - mFooterLayout.setLoadingDrawable(drawable); - } - - // The Loading Height may have changed, so refresh - refreshLoadingViewsHeight(); + getLoadingLayoutProxy(mode.showHeaderLoadingLayout(), mode.showFooterLoadingLayout()).setLoadingDrawable( + drawable); } @Override @@ -405,30 +455,29 @@ public abstract class PullToRefreshBase extends LinearLayout imp mOnRefreshListener = null; } - @Override + /** + * @deprecated You should now call this method on the result of + * {@link #getLoadingLayoutProxy()}. + */ public void setPullLabel(CharSequence pullLabel) { - setPullLabel(pullLabel, Mode.BOTH); - } - - @Override - public void setPullLabel(CharSequence pullLabel, Mode mode) { - if (null != mHeaderLayout && mode.canPullDown()) { - mHeaderLayout.setPullLabel(pullLabel); - } - if (null != mFooterLayout && mode.canPullUp()) { - mFooterLayout.setPullLabel(pullLabel); - } + getLoadingLayoutProxy().setPullLabel(pullLabel); } /** + * @deprecated You should now call this method on the result of + * {@link #getLoadingLayoutProxy(boolean, boolean)}. + */ + public void setPullLabel(CharSequence pullLabel, Mode mode) { + getLoadingLayoutProxy(mode.showHeaderLoadingLayout(), mode.showFooterLoadingLayout()).setPullLabel(pullLabel); + } + + /** + * @param enable Whether Pull-To-Refresh should be used * @deprecated This simple calls setMode with an appropriate mode based on * the passed value. - * - * @param enable - * Whether Pull-To-Refresh should be used */ public final void setPullToRefreshEnabled(boolean enable) { - setMode(enable ? DEFAULT_MODE : Mode.DISABLED); + setMode(enable ? Mode.getDefault() : Mode.DISABLED); } @Override @@ -448,34 +497,38 @@ public abstract class PullToRefreshBase extends LinearLayout imp } } - @Override + /** + * @deprecated You should now call this method on the result of + * {@link #getLoadingLayoutProxy()}. + */ public void setRefreshingLabel(CharSequence refreshingLabel) { - setRefreshingLabel(refreshingLabel, Mode.BOTH); + getLoadingLayoutProxy().setRefreshingLabel(refreshingLabel); } - @Override + /** + * @deprecated You should now call this method on the result of + * {@link #getLoadingLayoutProxy(boolean, boolean)}. + */ public void setRefreshingLabel(CharSequence refreshingLabel, Mode mode) { - if (null != mHeaderLayout && mode.canPullDown()) { - mHeaderLayout.setRefreshingLabel(refreshingLabel); - } - if (null != mFooterLayout && mode.canPullUp()) { - mFooterLayout.setRefreshingLabel(refreshingLabel); - } + getLoadingLayoutProxy(mode.showHeaderLoadingLayout(), mode.showFooterLoadingLayout()).setRefreshingLabel( + refreshingLabel); } - @Override + /** + * @deprecated You should now call this method on the result of + * {@link #getLoadingLayoutProxy()}. + */ public void setReleaseLabel(CharSequence releaseLabel) { setReleaseLabel(releaseLabel, Mode.BOTH); } - @Override + /** + * @deprecated You should now call this method on the result of + * {@link #getLoadingLayoutProxy(boolean, boolean)}. + */ public void setReleaseLabel(CharSequence releaseLabel, Mode mode) { - if (null != mHeaderLayout && mode.canPullDown()) { - mHeaderLayout.setReleaseLabel(releaseLabel); - } - if (null != mFooterLayout && mode.canPullUp()) { - mFooterLayout.setReleaseLabel(releaseLabel); - } + getLoadingLayoutProxy(mode.showHeaderLoadingLayout(), mode.showFooterLoadingLayout()).setReleaseLabel( + releaseLabel); } public void setScrollAnimationInterpolator(Interpolator interpolator) { @@ -488,80 +541,40 @@ public abstract class PullToRefreshBase extends LinearLayout imp } /** - * Called when the UI has been to be updated to be in the - * {@link State#PULL_TO_REFRESH} state. + * @return Either {@link Orientation#VERTICAL} or + * {@link Orientation#HORIZONTAL} depending on the scroll direction. */ - void onPullToRefresh() { - switch (mCurrentMode) { - case PULL_UP_TO_REFRESH: - mFooterLayout.pullToRefresh(); + public abstract Orientation getPullToRefreshScrollDirection(); + + final void setState(State state, final boolean... params) { + mState = state; + if (DEBUG) { + Log.d(LOG_TAG, "State: " + mState.name()); + } + + switch (mState) { + case RESET: + onReset(); break; - case PULL_DOWN_TO_REFRESH: - mHeaderLayout.pullToRefresh(); + case PULL_TO_REFRESH: + onPullToRefresh(); + break; + case RELEASE_TO_REFRESH: + onReleaseToRefresh(); + break; + case REFRESHING: + case MANUAL_REFRESHING: + onRefreshing(params[0]); + break; + case OVERSCROLLING: + // NO-OP break; } - } - /** - * Called when the UI has been to be updated to be in the - * {@link State#REFRESHING} or {@link State#MANUAL_REFRESHING} state. - * - * @param doScroll - * - Whether the UI should scroll for this event. - */ - void onRefreshing(final boolean doScroll) { - if (mMode.canPullDown()) { - mHeaderLayout.refreshing(); + // Call OnPullEventListener + if (null != mOnPullEventListener) { + mOnPullEventListener.onPullEvent(this, mState, mCurrentMode); } - if (mMode.canPullUp()) { - mFooterLayout.refreshing(); - } - - if (doScroll) { - if (mShowViewWhileRefreshing) { - smoothScrollTo(mCurrentMode == Mode.PULL_DOWN_TO_REFRESH ? -mHeaderHeight : mFooterHeight); - } else { - smoothScrollTo(0); - } - } - - // Call the deprecated method - setRefreshingInternal(doScroll); - } - - /** - * Called when the UI has been to be updated to be in the - * {@link State#RELEASE_TO_REFRESH} state. - */ - void onReleaseToRefresh() { - switch (mCurrentMode) { - case PULL_UP_TO_REFRESH: - mFooterLayout.releaseToRefresh(); - break; - case PULL_DOWN_TO_REFRESH: - mHeaderLayout.releaseToRefresh(); - break; - } - } - - /** - * Called when the UI has been to be updated to be in the - * {@link State#RESET} state. - */ - void onReset() { - mIsBeingDragged = false; - - if (mMode.canPullDown()) { - mHeaderLayout.reset(); - } - if (mMode.canPullUp()) { - mFooterLayout.reset(); - } - - smoothScrollTo(0); - - // Call the deprecated method - resetHeader(); } /** @@ -581,43 +594,65 @@ public abstract class PullToRefreshBase extends LinearLayout imp } protected LoadingLayout createLoadingLayout(Context context, Mode mode, TypedArray attrs) { - return mLoadingAnimationStyle.createLoadingLayout(context, mode, attrs); + LoadingLayout layout = mLoadingAnimationStyle.createLoadingLayout(context, mode, + getPullToRefreshScrollDirection(), attrs); + layout.setVisibility(View.INVISIBLE); + return layout; + } + + /** + * Used internally for {@link #getLoadingLayoutProxy(boolean, boolean)}. + * Allows derivative classes to include any extra LoadingLayouts. + */ + protected LoadingLayoutProxy createLoadingLayoutProxy(final boolean includeStart, final boolean includeEnd) { + LoadingLayoutProxy proxy = new LoadingLayoutProxy(); + + if (includeStart && mMode.showHeaderLoadingLayout()) { + proxy.addLayout(mHeaderLayout); + } + if (includeEnd && mMode.showFooterLoadingLayout()) { + proxy.addLayout(mFooterLayout); + } + + return proxy; } /** * This is implemented by derived classes to return the created View. If you * need to use a custom View (such as a custom ListView), override this * method and return an instance of your custom class. - * + *

* Be sure to set the ID of the view in this method, especially if you're * using a ListActivity or ListFragment. * - * @param context - * Context to create view with - * @param attrs - * AttributeSet from wrapped class. Means that anything you + * @param context Context to create view with + * @param attrs AttributeSet from wrapped class. Means that anything you * include in the XML layout declaration will be routed to the * created View * @return New instance of the Refreshable View */ protected abstract T createRefreshableView(Context context, AttributeSet attrs); - protected final int getFooterHeight() { - return mFooterHeight; + protected final void disableLoadingLayoutVisibilityChanges() { + mLayoutVisibilityChangesEnabled = false; } protected final LoadingLayout getFooterLayout() { return mFooterLayout; } - protected final int getHeaderHeight() { - return mHeaderHeight; + protected final int getFooterSize() { + return mFooterLayout.getContentSize(); } protected final LoadingLayout getHeaderLayout() { return mHeaderLayout; } + protected final int getHeaderSize() { + return mHeaderLayout.getContentSize(); + } + protected int getPullToRefreshScrollDuration() { return SMOOTH_SCROLL_DURATION_MS; } @@ -634,36 +669,34 @@ public abstract class PullToRefreshBase extends LinearLayout imp * Allows Derivative classes to handle the XML Attrs without creating a * TypedArray themsevles * - * @param a - * - TypedArray of PullToRefresh Attributes + * @param a - TypedArray of PullToRefresh Attributes */ protected void handleStyledAttributes(TypedArray a) { } /** - * Implemented by derived class to return whether the View is in a mState - * where the user can Pull to Refresh by scrolling down. + * Implemented by derived class to return whether the View is in a state + * where the user can Pull to Refresh by scrolling from the end. * - * @return true if the View is currently the correct mState (for example, - * top of a ListView) - */ - protected abstract boolean isReadyForPullDown(); - - /** - * Implemented by derived class to return whether the View is in a mState - * where the user can Pull to Refresh by scrolling up. - * - * @return true if the View is currently in the correct mState (for example, + * @return true if the View is currently in the correct state (for example, * bottom of a ListView) */ - protected abstract boolean isReadyForPullUp(); + protected abstract boolean isReadyForPullEnd(); + + /** + * Implemented by derived class to return whether the View is in a state + * where the user can Pull to Refresh by scrolling from the start. + * + * @return true if the View is currently the correct state (for example, top + * of a ListView) + */ + protected abstract boolean isReadyForPullStart(); /** * Called by {@link #onRestoreInstanceState(Parcelable)} so that derivative * classes can handle their saved instance state. * - * @param savedInstanceState - * - Bundle which contains saved instance state. + * @param savedInstanceState - Bundle which contains saved instance state. */ protected void onPtrRestoreInstanceState(Bundle savedInstanceState) { } @@ -672,12 +705,94 @@ public abstract class PullToRefreshBase extends LinearLayout imp * Called by {@link #onSaveInstanceState()} so that derivative classes can * save their instance state. * - * @param saveState - * - Bundle to be updated with saved state. + * @param saveState - Bundle to be updated with saved state. */ protected void onPtrSaveInstanceState(Bundle saveState) { } + /** + * Called when the UI has been to be updated to be in the + * {@link State#PULL_TO_REFRESH} state. + */ + protected void onPullToRefresh() { + switch (mCurrentMode) { + case PULL_FROM_END: + mFooterLayout.pullToRefresh(); + break; + case PULL_FROM_START: + mHeaderLayout.pullToRefresh(); + break; + default: + // NO-OP + break; + } + } + + /** + * Called when the UI has been to be updated to be in the + * {@link State#REFRESHING} or {@link State#MANUAL_REFRESHING} state. + * + * @param doScroll - Whether the UI should scroll for this event. + */ + protected void onRefreshing(final boolean doScroll) { + if (mMode.showHeaderLoadingLayout()) { + mHeaderLayout.refreshing(); + } + if (mMode.showFooterLoadingLayout()) { + mFooterLayout.refreshing(); + } + + if (doScroll) { + if (mShowViewWhileRefreshing) { + switch (mCurrentMode) { + case MANUAL_REFRESH_ONLY: + case PULL_FROM_END: + smoothScrollTo(getFooterSize()); + break; + default: + case PULL_FROM_START: + smoothScrollTo(-getHeaderSize()); + break; + } + } else { + smoothScrollTo(0); + } + } + } + + /** + * Called when the UI has been to be updated to be in the + * {@link State#RELEASE_TO_REFRESH} state. + */ + protected void onReleaseToRefresh() { + switch (mCurrentMode) { + case PULL_FROM_END: + mFooterLayout.releaseToRefresh(); + break; + case PULL_FROM_START: + mHeaderLayout.releaseToRefresh(); + break; + default: + // NO-OP + break; + } + } + + /** + * Called when the UI has been to be updated to be in the + * {@link State#RESET} state. + */ + protected void onReset() { + mIsBeingDragged = false; + mLayoutVisibilityChangesEnabled = true; + + // Always reset both layouts, just in case... + mHeaderLayout.reset(); + mFooterLayout.reset(); + + smoothScrollTo(0); + } + @Override protected final void onRestoreInstanceState(Parcelable state) { if (state instanceof Bundle) { @@ -686,7 +801,7 @@ public abstract class PullToRefreshBase extends LinearLayout imp setMode(Mode.mapIntToValue(bundle.getInt(STATE_MODE, 0))); mCurrentMode = Mode.mapIntToValue(bundle.getInt(STATE_CURRENT_MODE, 0)); - mDisableScrollingWhileRefreshing = bundle.getBoolean(STATE_DISABLE_SCROLLING_REFRESHING, true); + mScrollingWhileRefreshingEnabled = bundle.getBoolean(STATE_SCROLLING_REFRESHING_ENABLED, false); mShowViewWhileRefreshing = bundle.getBoolean(STATE_SHOW_REFRESHING_VIEW, true); // Let super Restore Itself @@ -716,65 +831,169 @@ public abstract class PullToRefreshBase extends LinearLayout imp bundle.putInt(STATE_STATE, mState.getIntValue()); bundle.putInt(STATE_MODE, mMode.getIntValue()); bundle.putInt(STATE_CURRENT_MODE, mCurrentMode.getIntValue()); - bundle.putBoolean(STATE_DISABLE_SCROLLING_REFRESHING, mDisableScrollingWhileRefreshing); + bundle.putBoolean(STATE_SCROLLING_REFRESHING_ENABLED, mScrollingWhileRefreshingEnabled); bundle.putBoolean(STATE_SHOW_REFRESHING_VIEW, mShowViewWhileRefreshing); bundle.putParcelable(STATE_SUPER, super.onSaveInstanceState()); return bundle; } - /** - * @deprecated This is a deprecated callback. If you're overriding this - * method then use - * {@link #setOnPullEventListener(OnPullEventListener) - * setOnPullEventListener()} instead to be notified when the - * state changes to {@link State#RESET RESET}. This deprecated - * method will be removed in the future. - */ - protected void resetHeader() { + @Override + protected final void onSizeChanged(int w, int h, int oldw, int oldh) { + if (DEBUG) { + Log.d(LOG_TAG, String.format("onSizeChanged. W: %d, H: %d", w, h)); + } + + super.onSizeChanged(w, h, oldw, oldh); + + // We need to update the header/footer when our size changes + refreshLoadingViewsSize(); + + // Update the Refreshable View layout + refreshRefreshableViewSize(w, h); + + /** + * As we're currently in a Layout Pass, we need to schedule another one + * to layout any changes we've made here + */ + post(new Runnable() { + @Override + public void run() { + requestLayout(); + } + }); } /** - * Helper method which just calls scrollTo() but with a zero x value. + * Re-measure the Loading Views height, and adjust internal padding as + * necessary + */ + protected final void refreshLoadingViewsSize() { + final int maximumPullScroll = (int) (getMaximumPullScroll() * 1.2f); + + int pLeft = getPaddingLeft(); + int pTop = getPaddingTop(); + int pRight = getPaddingRight(); + int pBottom = getPaddingBottom(); + + switch (getPullToRefreshScrollDirection()) { + case HORIZONTAL: + if (mMode.showHeaderLoadingLayout()) { + mHeaderLayout.setWidth(maximumPullScroll); + pLeft = -maximumPullScroll; + } else { + pLeft = 0; + } + + if (mMode.showFooterLoadingLayout()) { + mFooterLayout.setWidth(maximumPullScroll); + pRight = -maximumPullScroll; + } else { + pRight = 0; + } + break; + + case VERTICAL: + if (mMode.showHeaderLoadingLayout()) { + mHeaderLayout.setHeight(maximumPullScroll); + pTop = -maximumPullScroll; + } else { + pTop = 0; + } + + if (mMode.showFooterLoadingLayout()) { + mFooterLayout.setHeight(maximumPullScroll); + pBottom = -maximumPullScroll; + } else { + pBottom = 0; + } + break; + } + + if (DEBUG) { + Log.d(LOG_TAG, String.format("Setting Padding. L: %d, T: %d, R: %d, B: %d", pLeft, pTop, pRight, pBottom)); + } + setPadding(pLeft, pTop, pRight, pBottom); + } + + protected final void refreshRefreshableViewSize(int width, int height) { + // We need to set the Height of the Refreshable View to the same as + // this layout + LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mRefreshableViewWrapper.getLayoutParams(); + + switch (getPullToRefreshScrollDirection()) { + case HORIZONTAL: + if (lp.width != width) { + lp.width = width; + mRefreshableViewWrapper.requestLayout(); + } + break; + case VERTICAL: + if (lp.height != height) { + lp.height = height; + mRefreshableViewWrapper.requestLayout(); + } + break; + } + } + + /** + * Helper method which just calls scrollTo() in the correct scrolling + * direction. * - * @param y + * @param value - New Scroll value */ - protected final void setHeaderScroll(int y) { - scrollTo(0, y); + protected final void setHeaderScroll(final int value) { + if (DEBUG) { + Log.d(LOG_TAG, "setHeaderScroll: " + value); + } + + if (mLayoutVisibilityChangesEnabled) { + if (value < 0) { + mHeaderLayout.setVisibility(View.VISIBLE); + } else if (value > 0) { + mFooterLayout.setVisibility(View.VISIBLE); + } else { + mHeaderLayout.setVisibility(View.INVISIBLE); + mFooterLayout.setVisibility(View.INVISIBLE); + } + } + + /** + * Use a Hardware Layer on the Refreshable View if we've scrolled at + * all. We don't use them on the Header/Footer Views as they change + * often, which would negate any HW layer performance boost. + */ + ViewCompat.setLayerType(mRefreshableViewWrapper, value != 0 ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE); + + switch (getPullToRefreshScrollDirection()) { + case VERTICAL: + scrollTo(0, value); + break; + case HORIZONTAL: + scrollTo(value, 0); + break; + } } /** - * @deprecated This is a deprecated callback. If you're overriding this - * method then use - * {@link #setOnPullEventListener(OnPullEventListener) - * setOnPullEventListener()} instead to be notified when the - * state changes to {@link State#REFRESHING REFRESHING} or - * {@link State#MANUAL_REFRESHING MANUAL_REFRESHING}. This - * deprecated method will be removed in the future. - */ - protected void setRefreshingInternal(final boolean doScroll) { - } - - /** - * Smooth Scroll to Y position using the default duration of + * Smooth Scroll to position using the default duration of * {@value #SMOOTH_SCROLL_DURATION_MS} ms. * - * @param y - * - Y position to scroll to + * @param scrollValue - Position to scroll to */ - protected final void smoothScrollTo(int y) { - smoothScrollTo(y, getPullToRefreshScrollDuration()); + protected final void smoothScrollTo(int scrollValue) { + smoothScrollTo(scrollValue, getPullToRefreshScrollDuration()); } /** - * Smooth Scroll to Y position using the longer default duration of + * Smooth Scroll to position using the longer default duration of * {@value #SMOOTH_SCROLL_LONG_DURATION_MS} ms. * - * @param y - * - Y position to scroll to + * @param scrollValue - Position to scroll to */ - protected final void smoothScrollToLonger(int y) { - smoothScrollTo(y, getPullToRefreshScrollDurationLonger()); + protected final void smoothScrollToLonger(int scrollValue) { + smoothScrollTo(scrollValue, getPullToRefreshScrollDurationLonger()); } /** @@ -782,42 +1001,56 @@ public abstract class PullToRefreshBase extends LinearLayout imp * checking that the mode is different to current state so always updates. */ protected void updateUIForMode() { + // We need to use the correct LayoutParam values, based on scroll + // direction + final LinearLayout.LayoutParams lp = getLoadingLayoutLayoutParams(); + // Remove Header, and then add Header Loading View again if needed if (this == mHeaderLayout.getParent()) { removeView(mHeaderLayout); } - if (mMode.canPullDown()) { - addViewInternal(mHeaderLayout, 0, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT)); + if (mMode.showHeaderLoadingLayout()) { + addViewInternal(mHeaderLayout, 0, lp); } // Remove Footer, and then add Footer Loading View again if needed if (this == mFooterLayout.getParent()) { removeView(mFooterLayout); } - if (mMode.canPullUp()) { - addViewInternal(mFooterLayout, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT)); + if (mMode.showFooterLoadingLayout()) { + addViewInternal(mFooterLayout, lp); } // Hide Loading Views - refreshLoadingViewsHeight(); + refreshLoadingViewsSize(); // If we're not using Mode.BOTH, set mCurrentMode to mMode, otherwise // set it to pull down - mCurrentMode = (mMode != Mode.BOTH) ? mMode : Mode.PULL_DOWN_TO_REFRESH; + mCurrentMode = (mMode != Mode.BOTH) ? mMode : Mode.PULL_FROM_START; } private void addRefreshableView(Context context, T refreshableView) { mRefreshableViewWrapper = new FrameLayout(context); mRefreshableViewWrapper.addView(refreshableView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); - addViewInternal(mRefreshableViewWrapper, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 0, 1.0f)); + + addViewInternal(mRefreshableViewWrapper, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, + LayoutParams.MATCH_PARENT)); } @SuppressWarnings("deprecation") private void init(Context context, AttributeSet attrs) { - setOrientation(LinearLayout.VERTICAL); + switch (getPullToRefreshScrollDirection()) { + case HORIZONTAL: + setOrientation(LinearLayout.HORIZONTAL); + break; + case VERTICAL: + default: + setOrientation(LinearLayout.VERTICAL); + break; + } + + setGravity(Gravity.CENTER); ViewConfiguration config = ViewConfiguration.get(context); mTouchSlop = config.getScaledTouchSlop(); @@ -829,8 +1062,10 @@ public abstract class PullToRefreshBase extends LinearLayout imp mMode = Mode.mapIntToValue(a.getInteger(R.styleable.PullToRefresh_ptrMode, 0)); } - mLoadingAnimationStyle = AnimationStyle.mapIntToValue(a.getInteger(R.styleable.PullToRefresh_ptrAnimationStyle, - 0)); + if (a.hasValue(R.styleable.PullToRefresh_ptrAnimationStyle)) { + mLoadingAnimationStyle = AnimationStyle.mapIntToValue(a.getInteger( + R.styleable.PullToRefresh_ptrAnimationStyle, 0)); + } // Refreshable View // By passing the attrs, we can add ListView/GridView params via XML @@ -838,26 +1073,34 @@ public abstract class PullToRefreshBase extends LinearLayout imp addRefreshableView(context, mRefreshableView); // We need to create now layouts now - mHeaderLayout = createLoadingLayout(context, Mode.PULL_DOWN_TO_REFRESH, a); - mFooterLayout = createLoadingLayout(context, Mode.PULL_UP_TO_REFRESH, a); + mHeaderLayout = createLoadingLayout(context, Mode.PULL_FROM_START, a); + mFooterLayout = createLoadingLayout(context, Mode.PULL_FROM_END, a); - // Styleables from XML - if (a.hasValue(R.styleable.PullToRefresh_ptrHeaderBackground)) { - Drawable background = a.getDrawable(R.styleable.PullToRefresh_ptrHeaderBackground); + /** + * Styleables from XML + */ + if (a.hasValue(R.styleable.PullToRefresh_ptrRefreshableViewBackground)) { + Drawable background = a.getDrawable(R.styleable.PullToRefresh_ptrRefreshableViewBackground); if (null != background) { - setBackgroundDrawable(background); + mRefreshableView.setBackgroundDrawable(background); } - } - if (a.hasValue(R.styleable.PullToRefresh_ptrAdapterViewBackground)) { + } else if (a.hasValue(R.styleable.PullToRefresh_ptrAdapterViewBackground)) { + Utils.warnDeprecation("ptrAdapterViewBackground", "ptrRefreshableViewBackground"); Drawable background = a.getDrawable(R.styleable.PullToRefresh_ptrAdapterViewBackground); if (null != background) { mRefreshableView.setBackgroundDrawable(background); } } + if (a.hasValue(R.styleable.PullToRefresh_ptrOverScroll)) { mOverScrollEnabled = a.getBoolean(R.styleable.PullToRefresh_ptrOverScroll, true); } + if (a.hasValue(R.styleable.PullToRefresh_ptrScrollingWhileRefreshingEnabled)) { + mScrollingWhileRefreshingEnabled = a.getBoolean( + R.styleable.PullToRefresh_ptrScrollingWhileRefreshingEnabled, false); + } + // Let the derivative classes have a go at handling attributes, then // recycle them... handleStyledAttributes(a); @@ -869,31 +1112,15 @@ public abstract class PullToRefreshBase extends LinearLayout imp private boolean isReadyForPull() { switch (mMode) { - case PULL_DOWN_TO_REFRESH: - return isReadyForPullDown(); - case PULL_UP_TO_REFRESH: - return isReadyForPullUp(); + case PULL_FROM_START: + return isReadyForPullStart(); + case PULL_FROM_END: + return isReadyForPullEnd(); case BOTH: - return isReadyForPullUp() || isReadyForPullDown(); + return isReadyForPullEnd() || isReadyForPullStart(); + default: + return false; } - return false; - } - - private void measureView(View child) { - ViewGroup.LayoutParams p = child.getLayoutParams(); - if (p == null) { - p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); - } - - int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0, p.width); - int lpHeight = p.height; - int childHeightSpec; - if (lpHeight > 0) { - childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); - } else { - childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - } - child.measure(childWidthSpec, childHeightSpec); } /** @@ -903,126 +1130,130 @@ public abstract class PullToRefreshBase extends LinearLayout imp * change */ private void pullEvent() { - final int newScrollY; - final int itemHeight; + final int newScrollValue; + final int itemDimension; + final float initialMotionValue, lastMotionValue; - switch (mCurrentMode) { - case PULL_UP_TO_REFRESH: - newScrollY = Math.round(Math.max(mInitialMotionY - mLastMotionY, 0) / FRICTION); - itemHeight = mFooterHeight; + switch (getPullToRefreshScrollDirection()) { + case HORIZONTAL: + initialMotionValue = mInitialMotionX; + lastMotionValue = mLastMotionX; break; - case PULL_DOWN_TO_REFRESH: + case VERTICAL: default: - newScrollY = Math.round(Math.min(mInitialMotionY - mLastMotionY, 0) / FRICTION); - itemHeight = mHeaderHeight; + initialMotionValue = mInitialMotionY; + lastMotionValue = mLastMotionY; break; } - setHeaderScroll(newScrollY); + switch (mCurrentMode) { + case PULL_FROM_END: + newScrollValue = Math.round(Math.max(initialMotionValue - lastMotionValue, 0) / FRICTION); + itemDimension = getFooterSize(); + break; + case PULL_FROM_START: + default: + newScrollValue = Math.round(Math.min(initialMotionValue - lastMotionValue, 0) / FRICTION); + itemDimension = getHeaderSize(); + break; + } - if (newScrollY != 0) { - float scale = Math.abs(newScrollY) / (float) itemHeight; + setHeaderScroll(newScrollValue); + + if (newScrollValue != 0 && !isRefreshing()) { + float scale = Math.abs(newScrollValue) / (float) itemDimension; switch (mCurrentMode) { - case PULL_UP_TO_REFRESH: - mFooterLayout.onPullY(scale); + case PULL_FROM_END: + mFooterLayout.onPull(scale); break; - case PULL_DOWN_TO_REFRESH: - mHeaderLayout.onPullY(scale); + case PULL_FROM_START: + default: + mHeaderLayout.onPull(scale); break; } - if (mState != State.PULL_TO_REFRESH && itemHeight >= Math.abs(newScrollY)) { + if (mState != State.PULL_TO_REFRESH && itemDimension >= Math.abs(newScrollValue)) { setState(State.PULL_TO_REFRESH); - } else if (mState == State.PULL_TO_REFRESH && itemHeight < Math.abs(newScrollY)) { + } else if (mState == State.PULL_TO_REFRESH && itemDimension < Math.abs(newScrollValue)) { setState(State.RELEASE_TO_REFRESH); } } } - /** - * Re-measure the Loading Views height, and adjust internal padding as - * necessary - */ - private void refreshLoadingViewsHeight() { - mHeaderHeight = mFooterHeight = 0; - - if (mMode.canPullDown()) { - measureView(mHeaderLayout); - mHeaderHeight = mHeaderLayout.getMeasuredHeight(); - } - if (mMode.canPullUp()) { - measureView(mFooterLayout); - mFooterHeight = mFooterLayout.getMeasuredHeight(); - } - - // Hide Loading Views - switch (mMode) { - case DISABLED: - setPadding(0, 0, 0, 0); - case BOTH: - setPadding(0, -mHeaderHeight, 0, -mFooterHeight); - break; - case PULL_UP_TO_REFRESH: - setPadding(0, 0, 0, -mFooterHeight); - break; - case PULL_DOWN_TO_REFRESH: + private LinearLayout.LayoutParams getLoadingLayoutLayoutParams() { + switch (getPullToRefreshScrollDirection()) { + case HORIZONTAL: + return new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.MATCH_PARENT); + case VERTICAL: default: - setPadding(0, -mHeaderHeight, 0, 0); - break; + return new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT); } } - private void setState(State state, final boolean... params) { - mState = state; - if (DEBUG) { - Log.d(LOG_TAG, "State: " + mState.name()); - } - - switch (mState) { - case RESET: - onReset(); - break; - case PULL_TO_REFRESH: - onPullToRefresh(); - break; - case RELEASE_TO_REFRESH: - onReleaseToRefresh(); - break; - case REFRESHING: - case MANUAL_REFRESHING: - onRefreshing(params[0]); - break; - } - - // Call OnPullEventListener - if (null != mOnPullEventListener) { - mOnPullEventListener.onPullEvent(this, mState, mCurrentMode); + private int getMaximumPullScroll() { + switch (getPullToRefreshScrollDirection()) { + case HORIZONTAL: + return Math.round(getWidth() / FRICTION); + case VERTICAL: + default: + return Math.round(getHeight() / FRICTION); } } /** - * Smooth Scroll to Y position using the specific duration + * Smooth Scroll to position using the specific duration * - * @param y - * - Y position to scroll to - * @param duration - * - Duration of animation in milliseconds + * @param scrollValue - Position to scroll to + * @param duration - Duration of animation in milliseconds */ - private final void smoothScrollTo(int y, long duration) { + private final void smoothScrollTo(int scrollValue, long duration) { + smoothScrollTo(scrollValue, duration, 0, null); + } + + private final void smoothScrollTo(int newScrollValue, long duration, long delayMillis, + OnSmoothScrollFinishedListener listener) { if (null != mCurrentSmoothScrollRunnable) { mCurrentSmoothScrollRunnable.stop(); } - if (getScrollY() != y) { + final int oldScrollValue; + switch (getPullToRefreshScrollDirection()) { + case HORIZONTAL: + oldScrollValue = getScrollX(); + break; + case VERTICAL: + default: + oldScrollValue = getScrollY(); + break; + } + + if (oldScrollValue != newScrollValue) { if (null == mScrollAnimationInterpolator) { // Default interpolator is a Decelerate Interpolator mScrollAnimationInterpolator = new DecelerateInterpolator(); } - mCurrentSmoothScrollRunnable = new SmoothScrollRunnable(getScrollY(), y, duration); - post(mCurrentSmoothScrollRunnable); + mCurrentSmoothScrollRunnable = new SmoothScrollRunnable(oldScrollValue, newScrollValue, duration, listener); + + if (delayMillis > 0) { + postDelayed(mCurrentSmoothScrollRunnable, delayMillis); + } else { + post(mCurrentSmoothScrollRunnable); + } } } + private final void smoothScrollToAndBack(int y) { + smoothScrollTo(y, SMOOTH_SCROLL_DURATION_MS, 0, new OnSmoothScrollFinishedListener() { + + @Override + public void onSmoothScrollFinished() { + smoothScrollTo(0, SMOOTH_SCROLL_DURATION_MS, DEMO_SCROLL_INTERVAL, null); + } + }); + } + public static enum AnimationStyle { /** * This is the default for Android-PullToRefresh. Allows you to use any @@ -1036,17 +1267,19 @@ public abstract class PullToRefreshBase extends LinearLayout imp */ FLIP; + static AnimationStyle getDefault() { + return ROTATE; + } + /** * Maps an int to a specific mode. This is needed when saving state, or * inflating the view from XML where the mode is given through a attr * int. * - * @param modeInt - * - int to map a Mode to - * @return Mode that modeInt maps to, or PULL_DOWN_TO_REFRESH by - * default. + * @param modeInt - int to map a Mode to + * @return Mode that modeInt maps to, or ROTATE by default. */ - public static AnimationStyle mapIntToValue(int modeInt) { + static AnimationStyle mapIntToValue(int modeInt) { switch (modeInt) { case 0x0: default: @@ -1056,62 +1289,81 @@ public abstract class PullToRefreshBase extends LinearLayout imp } } - public LoadingLayout createLoadingLayout(Context context, Mode mode, TypedArray attrs) { + LoadingLayout createLoadingLayout(Context context, Mode mode, Orientation scrollDirection, TypedArray attrs) { switch (this) { case ROTATE: default: - return new RotateLoadingLayout(context, mode, attrs); + return new RotateLoadingLayout(context, mode, scrollDirection, attrs); case FLIP: - return new FlipLoadingLayout(context, mode, attrs); + return new FlipLoadingLayout(context, mode, scrollDirection, attrs); } } } public static enum Mode { + /** - * Disable all Pull-to-Refresh gesture handling + * Disable all Pull-to-Refresh gesture and Refreshing handling */ DISABLED(0x0), /** - * Only allow the user to Pull Down from the top to refresh, this is the - * default. + * Only allow the user to Pull from the start of the Refreshable View to + * refresh. The start is either the Top or Left, depending on the + * scrolling direction. */ - PULL_DOWN_TO_REFRESH(0x1), + PULL_FROM_START(0x1), /** - * Only allow the user to Pull Up from the bottom to refresh. + * Only allow the user to Pull from the end of the Refreshable View to + * refresh. The start is either the Bottom or Right, depending on the + * scrolling direction. */ - PULL_UP_TO_REFRESH(0x2), + PULL_FROM_END(0x2), /** - * Allow the user to both Pull Down from the top, and Pull Up from the - * bottom to refresh. + * Allow the user to both Pull from the start, from the end to refresh. */ - BOTH(0x3); + BOTH(0x3), + + /** + * Disables Pull-to-Refresh gesture handling, but allows manually + * setting the Refresh state via + * {@link PullToRefreshBase#setRefreshing() setRefreshing()}. + */ + MANUAL_REFRESH_ONLY(0x4); + + /** + * @deprecated Use {@link #PULL_FROM_START} from now on. + */ + public static Mode PULL_DOWN_TO_REFRESH = Mode.PULL_FROM_START; + + /** + * @deprecated Use {@link #PULL_FROM_END} from now on. + */ + public static Mode PULL_UP_TO_REFRESH = Mode.PULL_FROM_END; /** * Maps an int to a specific mode. This is needed when saving state, or * inflating the view from XML where the mode is given through a attr * int. * - * @param modeInt - * - int to map a Mode to - * @return Mode that modeInt maps to, or PULL_DOWN_TO_REFRESH by - * default. + * @param modeInt - int to map a Mode to + * @return Mode that modeInt maps to, or PULL_FROM_START by default. */ - public static Mode mapIntToValue(int modeInt) { - switch (modeInt) { - case 0x0: - return DISABLED; - case 0x1: - default: - return PULL_DOWN_TO_REFRESH; - case 0x2: - return PULL_UP_TO_REFRESH; - case 0x3: - return BOTH; + static Mode mapIntToValue(final int modeInt) { + for (Mode value : Mode.values()) { + if (modeInt == value.getIntValue()) { + return value; + } } + + // If not, return default + return getDefault(); + } + + static Mode getDefault() { + return PULL_FROM_START; } private int mIntValue; @@ -1122,17 +1374,24 @@ public abstract class PullToRefreshBase extends LinearLayout imp } /** - * @return true if this mode permits Pulling Down from the top + * @return true if the mode permits Pull-to-Refresh */ - boolean canPullDown() { - return this == PULL_DOWN_TO_REFRESH || this == BOTH; + boolean permitsPullToRefresh() { + return !(this == DISABLED || this == MANUAL_REFRESH_ONLY); } /** - * @return true if this mode permits Pulling Up from the bottom + * @return true if this mode wants the Loading Layout Header to be shown */ - boolean canPullUp() { - return this == PULL_UP_TO_REFRESH || this == BOTH; + public boolean showHeaderLoadingLayout() { + return this == PULL_FROM_START || this == BOTH; + } + + /** + * @return true if this mode wants the Loading Layout Footer to be shown + */ + public boolean showFooterLoadingLayout() { + return this == PULL_FROM_END || this == BOTH || this == MANUAL_REFRESH_ONLY; } int getIntValue() { @@ -1141,13 +1400,16 @@ public abstract class PullToRefreshBase extends LinearLayout imp } + // =========================================================== + // Inner, Anonymous Classes, and Enumerations + // =========================================================== + /** * Simple Listener that allows you to be notified when the user has scrolled * to the end of the AdapterView. See ( * {@link PullToRefreshAdapterViewBase#setOnLastItemVisibleListener}. * * @author Chris Banes - * */ public static interface OnLastItemVisibleListener { @@ -1158,10 +1420,6 @@ public abstract class PullToRefreshBase extends LinearLayout imp } - // =========================================================== - // Inner and Anonymous Classes - // =========================================================== - /** * Listener that allows you to be notified when the user has started or * finished a touch event. Useful when you want to append extra UI events @@ -1169,7 +1427,6 @@ public abstract class PullToRefreshBase extends LinearLayout imp * {@link PullToRefreshAdapterViewBase#setOnPullEventListener}. * * @author Chris Banes - * */ public static interface OnPullEventListener { @@ -1177,15 +1434,12 @@ public abstract class PullToRefreshBase extends LinearLayout imp * Called when the internal state has been changed, usually by the user * pulling. * - * @param refreshView - * - View which has had it's state change. - * @param state - * - The new state of View. - * @param direction - * - One of {@link Mode#PULL_UP_TO_REFRESH} or - * {@link Mode#PULL_UP_TO_REFRESH} depending on which - * direction the user is pulling. Only useful when - * state is {@link State#PULL_TO_REFRESH} or + * @param refreshView - View which has had it's state change. + * @param state - The new state of View. + * @param direction - One of {@link Mode#PULL_FROM_START} or + * {@link Mode#PULL_FROM_END} depending on which direction + * the user is pulling. Only useful when state is + * {@link State#PULL_TO_REFRESH} or * {@link State#RELEASE_TO_REFRESH}. */ public void onPullEvent(final PullToRefreshBase refreshView, State state, Mode direction); @@ -1200,8 +1454,8 @@ public abstract class PullToRefreshBase extends LinearLayout imp public static interface OnRefreshListener { /** - * onRefresh will be called for both Pull Down from top, and Pull Up - * from Bottom + * onRefresh will be called for both a Pull from start, and Pull from + * end */ public void onRefresh(final PullToRefreshBase refreshView); @@ -1215,21 +1469,26 @@ public abstract class PullToRefreshBase extends LinearLayout imp * @author Chris Banes */ public static interface OnRefreshListener2 { + // TODO These methods need renaming to START/END rather than DOWN/UP /** - * onPullDownToRefresh will be called only when the user has Pulled Down - * from the top, and released. + * onPullDownToRefresh will be called only when the user has Pulled from + * the start, and released. */ public void onPullDownToRefresh(final PullToRefreshBase refreshView); /** - * onPullUpToRefresh will be called only when the user has Pulled Up - * from the bottom, and released. + * onPullUpToRefresh will be called only when the user has Pulled from + * the end, and released. */ public void onPullUpToRefresh(final PullToRefreshBase refreshView); } + public static enum Orientation { + VERTICAL, HORIZONTAL; + } + public static enum State { /** @@ -1259,29 +1518,29 @@ public abstract class PullToRefreshBase extends LinearLayout imp * When the UI is currently refreshing, caused by a call to * {@link PullToRefreshBase#setRefreshing() setRefreshing()}. */ - MANUAL_REFRESHING(0x9); + MANUAL_REFRESHING(0x9), + + /** + * When the UI is currently overscrolling, caused by a fling on the + * Refreshable View. + */ + OVERSCROLLING(0x10); /** * Maps an int to a specific state. This is needed when saving state. * - * @param stateInt - * - int to map a State to + * @param stateInt - int to map a State to * @return State that stateInt maps to */ - public static State mapIntToValue(int stateInt) { - switch (stateInt) { - default: - case 0x0: - return RESET; - case 0x1: - return PULL_TO_REFRESH; - case 0x2: - return RELEASE_TO_REFRESH; - case 0x8: - return REFRESHING; - case 0x9: - return MANUAL_REFRESHING; + static State mapIntToValue(final int stateInt) { + for (State value : State.values()) { + if (stateInt == value.getIntValue()) { + return value; + } } + + // If not, return default + return RESET; } private int mIntValue; @@ -1296,23 +1555,22 @@ public abstract class PullToRefreshBase extends LinearLayout imp } final class SmoothScrollRunnable implements Runnable { - - static final int ANIMATION_DELAY = 10; - private final Interpolator mInterpolator; private final int mScrollToY; private final int mScrollFromY; private final long mDuration; + private OnSmoothScrollFinishedListener mListener; private boolean mContinueRunning = true; private long mStartTime = -1; private int mCurrentY = -1; - public SmoothScrollRunnable(int fromY, int toY, long duration) { + public SmoothScrollRunnable(int fromY, int toY, long duration, OnSmoothScrollFinishedListener listener) { mScrollFromY = fromY; mScrollToY = toY; mInterpolator = mScrollAnimationInterpolator; mDuration = duration; + mListener = listener; } @Override @@ -1342,10 +1600,10 @@ public abstract class PullToRefreshBase extends LinearLayout imp // If we're not at the target Y, keep going... if (mContinueRunning && mScrollToY != mCurrentY) { - if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) { - SDK16.postOnAnimation(PullToRefreshBase.this, this); - } else { - postDelayed(this, ANIMATION_DELAY); + ViewCompat.postOnAnimation(PullToRefreshBase.this, this); + } else { + if (null != mListener) { + mListener.onSmoothScrollFinished(); } } } @@ -1356,4 +1614,8 @@ public abstract class PullToRefreshBase extends LinearLayout imp } } + static interface OnSmoothScrollFinishedListener { + void onSmoothScrollFinished(); + } + } diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshExpandableListView.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshExpandableListView.java index ed42c0fe1..649020c6d 100644 --- a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshExpandableListView.java +++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshExpandableListView.java @@ -20,7 +20,6 @@ import android.content.Context; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.util.AttributeSet; -import android.view.ContextMenu.ContextMenuInfo; import android.view.View; import android.widget.ExpandableListView; @@ -40,13 +39,17 @@ public class PullToRefreshExpandableListView extends PullToRefreshAdapterViewBas super(context, mode); } - @Override - public ContextMenuInfo getContextMenuInfo() { - return ((InternalExpandableListView) getRefreshableView()).getContextMenuInfo(); + public PullToRefreshExpandableListView(Context context, Mode mode, AnimationStyle style) { + super(context, mode, style); } @Override - protected final ExpandableListView createRefreshableView(Context context, AttributeSet attrs) { + public final Orientation getPullToRefreshScrollDirection() { + return Orientation.VERTICAL; + } + + @Override + protected ExpandableListView createRefreshableView(Context context, AttributeSet attrs) { final ExpandableListView lv; if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) { lv = new InternalExpandableListViewSDK9(context, attrs); @@ -65,10 +68,6 @@ public class PullToRefreshExpandableListView extends PullToRefreshAdapterViewBas super(context, attrs); } - public ContextMenuInfo getContextMenuInfo() { - return super.getContextMenuInfo(); - } - @Override public void setEmptyView(View emptyView) { PullToRefreshExpandableListView.this.setEmptyView(emptyView); @@ -95,7 +94,8 @@ public class PullToRefreshExpandableListView extends PullToRefreshAdapterViewBas scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); // Does all of the hard work... - OverscrollHelper.overScrollBy(PullToRefreshExpandableListView.this, deltaY, scrollY, isTouchEvent); + OverscrollHelper.overScrollBy(PullToRefreshExpandableListView.this, deltaX, scrollX, deltaY, scrollY, + isTouchEvent); return returnValue; } diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshGridView.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshGridView.java index 59e7525c4..f9506889a 100644 --- a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshGridView.java +++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshGridView.java @@ -20,7 +20,6 @@ import android.content.Context; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.util.AttributeSet; -import android.view.ContextMenu.ContextMenuInfo; import android.view.View; import android.widget.GridView; @@ -40,9 +39,13 @@ public class PullToRefreshGridView extends PullToRefreshAdapterViewBase { + + public PullToRefreshHorizontalScrollView(Context context) { + super(context); + } + + public PullToRefreshHorizontalScrollView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public PullToRefreshHorizontalScrollView(Context context, Mode mode) { + super(context, mode); + } + + public PullToRefreshHorizontalScrollView(Context context, Mode mode, AnimationStyle style) { + super(context, mode, style); + } + + @Override + public final Orientation getPullToRefreshScrollDirection() { + return Orientation.HORIZONTAL; + } + + @Override + protected HorizontalScrollView createRefreshableView(Context context, AttributeSet attrs) { + HorizontalScrollView scrollView; + + if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) { + scrollView = new InternalHorizontalScrollViewSDK9(context, attrs); + } else { + scrollView = new HorizontalScrollView(context, attrs); + } + + scrollView.setId(R.id.scrollview); + return scrollView; + } + + @Override + protected boolean isReadyForPullStart() { + return mRefreshableView.getScrollX() == 0; + } + + @Override + protected boolean isReadyForPullEnd() { + View scrollViewChild = mRefreshableView.getChildAt(0); + if (null != scrollViewChild) { + return mRefreshableView.getScrollX() >= (scrollViewChild.getWidth() - getWidth()); + } + return false; + } + + @TargetApi(9) + final class InternalHorizontalScrollViewSDK9 extends HorizontalScrollView { + + public InternalHorizontalScrollViewSDK9(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, + int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { + + final boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, + scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); + + // Does all of the hard work... + OverscrollHelper.overScrollBy(PullToRefreshHorizontalScrollView.this, deltaX, scrollX, deltaY, scrollY, + getScrollRange(), isTouchEvent); + + return returnValue; + } + + /** + * Taken from the AOSP ScrollView source + */ + private int getScrollRange() { + int scrollRange = 0; + if (getChildCount() > 0) { + View child = getChildAt(0); + scrollRange = Math.max(0, child.getWidth() - (getWidth() - getPaddingLeft() - getPaddingRight())); + } + return scrollRange; + } + } +} diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshListView.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshListView.java index 7c2a0e5f8..0aa9a27d6 100644 --- a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshListView.java +++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/PullToRefreshListView.java @@ -19,11 +19,11 @@ import android.annotation.TargetApi; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; -import android.graphics.drawable.Drawable; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.util.AttributeSet; -import android.view.ContextMenu.ContextMenuInfo; +import android.view.Gravity; +import android.view.MotionEvent; import android.view.View; import android.widget.FrameLayout; import android.widget.ListAdapter; @@ -39,124 +39,80 @@ public class PullToRefreshListView extends PullToRefreshAdapterViewBase

*

    *
  • {@link PullToRefreshWebView} doesn't work correctly because you're using * overflow:scroll or something else which means @@ -35,14 +35,15 @@ import com.handmark.pulltorefresh.library.PullToRefreshWebView; *
  • You control the web content being displayed, as you need to write some * Javascript callbacks.
  • *
- *

- * + *

+ *

* The way this call works is that when a PullToRefresh gesture is in action, * the following Javascript methods will be called: * isReadyForPullDown() and isReadyForPullUp(), it is * your job to calculate whether the view is in a state where a PullToRefresh * can happen, and return the result via the callback mechanism. An example can * be seen below: + *

* *

  * function isReadyForPullDown() {
@@ -92,7 +93,7 @@ public class PullToRefreshWebView2 extends PullToRefreshWebView {
 	}
 
 	@Override
-	protected boolean isReadyForPullDown() {
+	protected boolean isReadyForPullStart() {
 		// Call Javascript...
 		getRefreshableView().loadUrl(DEF_JS_READY_PULL_DOWN_CALL);
 
@@ -103,7 +104,7 @@ public class PullToRefreshWebView2 extends PullToRefreshWebView {
 	}
 
 	@Override
-	protected boolean isReadyForPullUp() {
+	protected boolean isReadyForPullEnd() {
 		// Call Javascript...
 		getRefreshableView().loadUrl(DEF_JS_READY_PULL_UP_CALL);
 
diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/extras/SoundPullEventListener.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/extras/SoundPullEventListener.java
index 58a9fe899..a7aac306a 100644
--- a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/extras/SoundPullEventListener.java
+++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/extras/SoundPullEventListener.java
@@ -35,8 +35,7 @@ public class SoundPullEventListener implements PullToRefreshBase
 	/**
 	 * Constructor
 	 * 
-	 * @param context
-	 *            - Context
+	 * @param context - Context
 	 */
 	public SoundPullEventListener(Context context) {
 		mContext = context;
@@ -55,14 +54,12 @@ public class SoundPullEventListener implements PullToRefreshBase
 	 * Set the Sounds to be played when a Pull Event happens. You specify which
 	 * sound plays for which events by calling this method multiple times for
 	 * each event.
-	 * 
+	 * 

* If you've already set a sound for a certain event, and add another sound * for that event, only the new sound will be played. * - * @param event - * - The event for which the sound will be played. - * @param resId - * - Resource Id of the sound file to be played (e.g. + * @param event - The event for which the sound will be played. + * @param resId - Resource Id of the sound file to be played (e.g. * R.raw.pull_sound) */ public void addSoundEvent(State event, int resId) { diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/EmptyViewMethodAccessor.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/EmptyViewMethodAccessor.java index 9b561ece4..369f21e87 100644 --- a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/EmptyViewMethodAccessor.java +++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/EmptyViewMethodAccessor.java @@ -28,8 +28,7 @@ public interface EmptyViewMethodAccessor { /** * Calls upto AdapterView.setEmptyView() * - * @param View - * to set as Empty View + * @param emptyView - to set as Empty View */ public void setEmptyViewInternal(View emptyView); @@ -37,8 +36,7 @@ public interface EmptyViewMethodAccessor { * Should call PullToRefreshBase.setEmptyView() which will then * automatically call through to setEmptyViewInternal() * - * @param View - * to set as Empty View + * @param emptyView - to set as Empty View */ public void setEmptyView(View emptyView); diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/FlipLoadingLayout.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/FlipLoadingLayout.java index 83377269a..fef31605f 100644 --- a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/FlipLoadingLayout.java +++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/FlipLoadingLayout.java @@ -15,30 +15,35 @@ *******************************************************************************/ package com.handmark.pulltorefresh.library.internal; +import android.annotation.SuppressLint; import android.content.Context; import android.content.res.TypedArray; +import android.graphics.Matrix; import android.graphics.drawable.Drawable; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.RotateAnimation; +import android.widget.ImageView.ScaleType; import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; +import com.handmark.pulltorefresh.library.PullToRefreshBase.Orientation; import com.handmark.pulltorefresh.library.R; +@SuppressLint("ViewConstructor") public class FlipLoadingLayout extends LoadingLayout { static final int FLIP_ANIMATION_DURATION = 150; private final Animation mRotateAnimation, mResetRotateAnimation; - public FlipLoadingLayout(Context context, Mode mode, TypedArray attrs) { - super(context, mode, attrs); - - final int rotateAngle = mode == Mode.PULL_DOWN_TO_REFRESH ? 180 : -180; + public FlipLoadingLayout(Context context, final Mode mode, final Orientation scrollDirection, TypedArray attrs) { + super(context, mode, scrollDirection, attrs); - mRotateAnimation = new RotateAnimation(0, rotateAngle, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, - 0.5f); + final int rotateAngle = mode == Mode.PULL_FROM_START ? -180 : 180; + + mRotateAnimation = new RotateAnimation(0, rotateAngle, Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f); mRotateAnimation.setInterpolator(ANIMATION_INTERPOLATOR); mRotateAnimation.setDuration(FLIP_ANIMATION_DURATION); mRotateAnimation.setFillAfter(true); @@ -52,20 +57,33 @@ public class FlipLoadingLayout extends LoadingLayout { @Override protected void onLoadingDrawableSet(Drawable imageDrawable) { - /** - * We need to set the width/height of the ImageView so that it is square - * with each side the size of the largest drawable dimension. This is so - * that it doesn't clip when rotated. - */ if (null != imageDrawable) { + final int dHeight = imageDrawable.getIntrinsicHeight(); + final int dWidth = imageDrawable.getIntrinsicWidth(); + + /** + * We need to set the width/height of the ImageView so that it is + * square with each side the size of the largest drawable dimension. + * This is so that it doesn't clip when rotated. + */ ViewGroup.LayoutParams lp = mHeaderImage.getLayoutParams(); - lp.width = lp.height = Math.max(imageDrawable.getIntrinsicWidth(), imageDrawable.getIntrinsicHeight()); + lp.width = lp.height = Math.max(dHeight, dWidth); mHeaderImage.requestLayout(); + + /** + * We now rotate the Drawable so that is at the correct rotation, + * and is centered. + */ + mHeaderImage.setScaleType(ScaleType.MATRIX); + Matrix matrix = new Matrix(); + matrix.postTranslate((lp.width - dWidth) / 2f, (lp.height - dHeight) / 2f); + matrix.postRotate(getDrawableRotationAngle(), lp.width / 2f, lp.height / 2f); + mHeaderImage.setImageMatrix(matrix); } } @Override - protected void onPullYImpl(float scaleOfHeight) { + protected void onPullImpl(float scaleOfLayout) { // NO-OP } @@ -97,13 +115,32 @@ public class FlipLoadingLayout extends LoadingLayout { } @Override - protected int getDefaultTopDrawableResId() { - return R.drawable.default_ptr_flip_top; + protected int getDefaultDrawableResId() { + return R.drawable.default_ptr_flip; } - @Override - protected int getDefaultBottomDrawableResId() { - return R.drawable.default_ptr_flip_bottom; + private float getDrawableRotationAngle() { + float angle = 0f; + switch (mMode) { + case PULL_FROM_END: + if (mScrollDirection == Orientation.HORIZONTAL) { + angle = 90f; + } else { + angle = 180f; + } + break; + + case PULL_FROM_START: + if (mScrollDirection == Orientation.HORIZONTAL) { + angle = 270f; + } + break; + + default: + break; + } + + return angle; } } diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/IndicatorLayout.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/IndicatorLayout.java index 401c0a3d7..a9069f2a4 100644 --- a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/IndicatorLayout.java +++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/IndicatorLayout.java @@ -15,7 +15,10 @@ *******************************************************************************/ package com.handmark.pulltorefresh.library.internal; +import android.annotation.SuppressLint; import android.content.Context; +import android.graphics.Matrix; +import android.graphics.drawable.Drawable; import android.view.View; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; @@ -25,10 +28,12 @@ import android.view.animation.LinearInterpolator; import android.view.animation.RotateAnimation; import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.ImageView.ScaleType; import com.handmark.pulltorefresh.library.PullToRefreshBase; import com.handmark.pulltorefresh.library.R; +@SuppressLint("ViewConstructor") public class IndicatorLayout extends FrameLayout implements AnimationListener { static final int DEFAULT_ROTATION_ANIMATION_DURATION = 150; @@ -40,26 +45,33 @@ public class IndicatorLayout extends FrameLayout implements AnimationListener { public IndicatorLayout(Context context, PullToRefreshBase.Mode mode) { super(context); - mArrowImageView = new ImageView(context); + + Drawable arrowD = getResources().getDrawable(R.drawable.indicator_arrow); + mArrowImageView.setImageDrawable(arrowD); + final int padding = getResources().getDimensionPixelSize(R.dimen.indicator_internal_padding); mArrowImageView.setPadding(padding, padding, padding, padding); addView(mArrowImageView); int inAnimResId, outAnimResId; switch (mode) { - case PULL_UP_TO_REFRESH: + case PULL_FROM_END: inAnimResId = R.anim.slide_in_from_bottom; outAnimResId = R.anim.slide_out_to_bottom; setBackgroundResource(R.drawable.indicator_bg_bottom); - mArrowImageView.setImageResource(R.drawable.arrow_up); + + // Rotate Arrow so it's pointing the correct way + mArrowImageView.setScaleType(ScaleType.MATRIX); + Matrix matrix = new Matrix(); + matrix.setRotate(180f, arrowD.getIntrinsicWidth() / 2f, arrowD.getIntrinsicHeight() / 2f); + mArrowImageView.setImageMatrix(matrix); break; default: - case PULL_DOWN_TO_REFRESH: + case PULL_FROM_START: inAnimResId = R.anim.slide_in_from_top; outAnimResId = R.anim.slide_out_to_top; setBackgroundResource(R.drawable.indicator_bg_top); - mArrowImageView.setImageResource(R.drawable.arrow_down); break; } diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/LoadingLayout.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/LoadingLayout.java index 8888a8a54..b9e715050 100644 --- a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/LoadingLayout.java +++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/LoadingLayout.java @@ -15,10 +15,11 @@ *******************************************************************************/ package com.handmark.pulltorefresh.library.internal; +import android.annotation.SuppressLint; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; -import android.graphics.Color; +import android.graphics.Typeface; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.Drawable; import android.text.TextUtils; @@ -26,57 +27,80 @@ import android.util.TypedValue; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; +import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.TextView; +import com.handmark.pulltorefresh.library.ILoadingLayout; import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; +import com.handmark.pulltorefresh.library.PullToRefreshBase.Orientation; import com.handmark.pulltorefresh.library.R; -public abstract class LoadingLayout extends LinearLayout { +@SuppressLint("ViewConstructor") +public abstract class LoadingLayout extends FrameLayout implements ILoadingLayout { + + static final String LOG_TAG = "PullToRefresh-LoadingLayout"; static final Interpolator ANIMATION_INTERPOLATOR = new LinearInterpolator(); + private FrameLayout mInnerLayout; + protected final ImageView mHeaderImage; protected final ProgressBar mHeaderProgress; - private boolean mUseIntrinisicAnimation; + private boolean mUseIntrinsicAnimation; private final TextView mHeaderText; private final TextView mSubHeaderText; + protected final Mode mMode; + protected final Orientation mScrollDirection; + private CharSequence mPullLabel; private CharSequence mRefreshingLabel; private CharSequence mReleaseLabel; - public LoadingLayout(Context context, final Mode mode, TypedArray attrs) { + public LoadingLayout(Context context, final Mode mode, final Orientation scrollDirection, TypedArray attrs) { super(context); + mMode = mode; + mScrollDirection = scrollDirection; - setGravity(Gravity.CENTER_VERTICAL); + switch (scrollDirection) { + case HORIZONTAL: + LayoutInflater.from(context).inflate(R.layout.pull_to_refresh_header_horizontal, this); + break; + case VERTICAL: + default: + LayoutInflater.from(context).inflate(R.layout.pull_to_refresh_header_vertical, this); + break; + } - final int tbPadding = getResources().getDimensionPixelSize(R.dimen.header_footer_top_bottom_padding); - final int lrPadding = getResources().getDimensionPixelSize(R.dimen.header_footer_left_right_padding); - setPadding(lrPadding, tbPadding, lrPadding, tbPadding); + mInnerLayout = (FrameLayout) findViewById(R.id.fl_inner); + mHeaderText = (TextView) mInnerLayout.findViewById(R.id.pull_to_refresh_text); + mHeaderProgress = (ProgressBar) mInnerLayout.findViewById(R.id.pull_to_refresh_progress); + mSubHeaderText = (TextView) mInnerLayout.findViewById(R.id.pull_to_refresh_sub_text); + mHeaderImage = (ImageView) mInnerLayout.findViewById(R.id.pull_to_refresh_image); - LayoutInflater.from(context).inflate(R.layout.pull_to_refresh_header, this); - mHeaderText = (TextView) findViewById(R.id.pull_to_refresh_text); - mHeaderProgress = (ProgressBar) findViewById(R.id.pull_to_refresh_progress); - mSubHeaderText = (TextView) findViewById(R.id.pull_to_refresh_sub_text); - mHeaderImage = (ImageView) findViewById(R.id.pull_to_refresh_image); + FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mInnerLayout.getLayoutParams(); switch (mode) { - case PULL_UP_TO_REFRESH: + case PULL_FROM_END: + lp.gravity = scrollDirection == Orientation.VERTICAL ? Gravity.TOP : Gravity.LEFT; + // Load in labels mPullLabel = context.getString(R.string.pull_to_refresh_from_bottom_pull_label); mRefreshingLabel = context.getString(R.string.pull_to_refresh_from_bottom_refreshing_label); mReleaseLabel = context.getString(R.string.pull_to_refresh_from_bottom_release_label); break; - case PULL_DOWN_TO_REFRESH: + case PULL_FROM_START: default: + lp.gravity = scrollDirection == Orientation.VERTICAL ? Gravity.BOTTOM : Gravity.RIGHT; + // Load in labels mPullLabel = context.getString(R.string.pull_to_refresh_pull_label); mRefreshingLabel = context.getString(R.string.pull_to_refresh_refreshing_label); @@ -84,18 +108,10 @@ public abstract class LoadingLayout extends LinearLayout { break; } - if (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderTextColor)) { - ColorStateList colors = attrs.getColorStateList(R.styleable.PullToRefresh_ptrHeaderTextColor); - setTextColor(null != colors ? colors : ColorStateList.valueOf(Color.BLACK)); - } - if (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderSubTextColor)) { - ColorStateList colors = attrs.getColorStateList(R.styleable.PullToRefresh_ptrHeaderSubTextColor); - setSubTextColor(null != colors ? colors : ColorStateList.valueOf(Color.BLACK)); - } if (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderBackground)) { Drawable background = attrs.getDrawable(R.styleable.PullToRefresh_ptrHeaderBackground); if (null != background) { - setBackgroundDrawable(background); + ViewCompat.setBackground(this, background); } } @@ -110,6 +126,20 @@ public abstract class LoadingLayout extends LinearLayout { setSubTextAppearance(styleID.data); } + // Text Color attrs need to be set after TextAppearance attrs + if (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderTextColor)) { + ColorStateList colors = attrs.getColorStateList(R.styleable.PullToRefresh_ptrHeaderTextColor); + if (null != colors) { + setTextColor(colors); + } + } + if (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderSubTextColor)) { + ColorStateList colors = attrs.getColorStateList(R.styleable.PullToRefresh_ptrHeaderSubTextColor); + if (null != colors) { + setSubTextColor(colors); + } + } + // Try and get defined drawable from Attrs Drawable imageDrawable = null; if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawable)) { @@ -118,19 +148,30 @@ public abstract class LoadingLayout extends LinearLayout { // Check Specific Drawable from Attrs, these overrite the generic // drawable attr above - if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableTop) && mode == Mode.PULL_DOWN_TO_REFRESH) { - imageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableTop); - } else if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableBottom) && mode == Mode.PULL_UP_TO_REFRESH) { - imageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableTop); + switch (mode) { + case PULL_FROM_START: + default: + if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableStart)) { + imageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableStart); + } else if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableTop)) { + Utils.warnDeprecation("ptrDrawableTop", "ptrDrawableStart"); + imageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableTop); + } + break; + + case PULL_FROM_END: + if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableEnd)) { + imageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableEnd); + } else if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableBottom)) { + Utils.warnDeprecation("ptrDrawableBottom", "ptrDrawableEnd"); + imageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableBottom); + } + break; } // If we don't have a user defined drawable, load the default if (null == imageDrawable) { - if (mode == Mode.PULL_DOWN_TO_REFRESH) { - imageDrawable = context.getResources().getDrawable(getDefaultBottomDrawableResId()); - } else { - imageDrawable = context.getResources().getDrawable(getDefaultTopDrawableResId()); - } + imageDrawable = context.getResources().getDrawable(getDefaultDrawableResId()); } // Set Drawable, and save width/height @@ -139,61 +180,115 @@ public abstract class LoadingLayout extends LinearLayout { reset(); } - public final void onPullY(float scaleOfHeight) { - if (!mUseIntrinisicAnimation) { - onPullYImpl(scaleOfHeight); + public final void setHeight(int height) { + ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) getLayoutParams(); + lp.height = height; + requestLayout(); + } + + public final void setWidth(int width) { + ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) getLayoutParams(); + lp.width = width; + requestLayout(); + } + + public final int getContentSize() { + switch (mScrollDirection) { + case HORIZONTAL: + return mInnerLayout.getWidth(); + case VERTICAL: + default: + return mInnerLayout.getHeight(); + } + } + + public final void hideAllViews() { + if (View.VISIBLE == mHeaderText.getVisibility()) { + mHeaderText.setVisibility(View.INVISIBLE); + } + if (View.VISIBLE == mHeaderProgress.getVisibility()) { + mHeaderProgress.setVisibility(View.INVISIBLE); + } + if (View.VISIBLE == mHeaderImage.getVisibility()) { + mHeaderImage.setVisibility(View.INVISIBLE); + } + if (View.VISIBLE == mSubHeaderText.getVisibility()) { + mSubHeaderText.setVisibility(View.INVISIBLE); + } + } + + public final void onPull(float scaleOfLayout) { + if (!mUseIntrinsicAnimation) { + onPullImpl(scaleOfLayout); } } public final void pullToRefresh() { - mHeaderText.setText(mPullLabel); + if (null != mHeaderText) { + mHeaderText.setText(mPullLabel); + } // Now call the callback pullToRefreshImpl(); } public final void refreshing() { - mHeaderText.setText(mRefreshingLabel); + if (null != mHeaderText) { + mHeaderText.setText(mRefreshingLabel); + } - if (mUseIntrinisicAnimation) { + if (mUseIntrinsicAnimation) { ((AnimationDrawable) mHeaderImage.getDrawable()).start(); } else { // Now call the callback refreshingImpl(); } - mSubHeaderText.setVisibility(View.GONE); + if (null != mSubHeaderText) { + mSubHeaderText.setVisibility(View.GONE); + } } public final void releaseToRefresh() { - mHeaderText.setText(mReleaseLabel); + if (null != mHeaderText) { + mHeaderText.setText(mReleaseLabel); + } // Now call the callback releaseToRefreshImpl(); } public final void reset() { - mHeaderText.setText(mPullLabel); + if (null != mHeaderText) { + mHeaderText.setText(mPullLabel); + } mHeaderImage.setVisibility(View.VISIBLE); - if (mUseIntrinisicAnimation) { + if (mUseIntrinsicAnimation) { ((AnimationDrawable) mHeaderImage.getDrawable()).stop(); } else { // Now call the callback resetImpl(); } - if (TextUtils.isEmpty(mSubHeaderText.getText())) { - mSubHeaderText.setVisibility(View.GONE); - } else { - mSubHeaderText.setVisibility(View.VISIBLE); + if (null != mSubHeaderText) { + if (TextUtils.isEmpty(mSubHeaderText.getText())) { + mSubHeaderText.setVisibility(View.GONE); + } else { + mSubHeaderText.setVisibility(View.VISIBLE); + } } } + @Override + public void setLastUpdatedLabel(CharSequence label) { + setSubHeaderText(label); + } + public final void setLoadingDrawable(Drawable imageDrawable) { // Set Drawable mHeaderImage.setImageDrawable(imageDrawable); - mUseIntrinisicAnimation = (imageDrawable instanceof AnimationDrawable); + mUseIntrinsicAnimation = (imageDrawable instanceof AnimationDrawable); // Now call the callback onLoadingDrawableSet(imageDrawable); @@ -211,52 +306,35 @@ public abstract class LoadingLayout extends LinearLayout { mReleaseLabel = releaseLabel; } - public void setSubHeaderText(CharSequence label) { - if (TextUtils.isEmpty(label)) { - mSubHeaderText.setVisibility(View.GONE); - } else { - mSubHeaderText.setText(label); + @Override + public void setTextTypeface(Typeface tf) { + mHeaderText.setTypeface(tf); + } + + public final void showInvisibleViews() { + if (View.INVISIBLE == mHeaderText.getVisibility()) { + mHeaderText.setVisibility(View.VISIBLE); + } + if (View.INVISIBLE == mHeaderProgress.getVisibility()) { + mHeaderProgress.setVisibility(View.VISIBLE); + } + if (View.INVISIBLE == mHeaderImage.getVisibility()) { + mHeaderImage.setVisibility(View.VISIBLE); + } + if (View.INVISIBLE == mSubHeaderText.getVisibility()) { mSubHeaderText.setVisibility(View.VISIBLE); } } - public void setSubTextAppearance(int value) { - mSubHeaderText.setTextAppearance(getContext(), value); - } - - public void setSubTextColor(ColorStateList color) { - mSubHeaderText.setTextColor(color); - } - - public void setSubTextColor(int color) { - setSubTextColor(ColorStateList.valueOf(color)); - } - - public void setTextAppearance(int value) { - mHeaderText.setTextAppearance(getContext(), value); - mSubHeaderText.setTextAppearance(getContext(), value); - } - - public void setTextColor(ColorStateList color) { - mHeaderText.setTextColor(color); - mSubHeaderText.setTextColor(color); - } - - public void setTextColor(int color) { - setTextColor(ColorStateList.valueOf(color)); - } - /** * Callbacks for derivative Layouts */ - protected abstract int getDefaultBottomDrawableResId(); - - protected abstract int getDefaultTopDrawableResId(); + protected abstract int getDefaultDrawableResId(); protected abstract void onLoadingDrawableSet(Drawable imageDrawable); - protected abstract void onPullYImpl(float scaleOfHeight); + protected abstract void onPullImpl(float scaleOfLayout); protected abstract void pullToRefreshImpl(); @@ -266,4 +344,45 @@ public abstract class LoadingLayout extends LinearLayout { protected abstract void resetImpl(); + private void setSubHeaderText(CharSequence label) { + if (null != mSubHeaderText) { + if (TextUtils.isEmpty(label)) { + mSubHeaderText.setVisibility(View.GONE); + } else { + mSubHeaderText.setText(label); + mSubHeaderText.setVisibility(View.VISIBLE); + } + } + } + + private void setSubTextAppearance(int value) { + if (null != mSubHeaderText) { + mSubHeaderText.setTextAppearance(getContext(), value); + } + } + + private void setSubTextColor(ColorStateList color) { + if (null != mSubHeaderText) { + mSubHeaderText.setTextColor(color); + } + } + + private void setTextAppearance(int value) { + if (null != mHeaderText) { + mHeaderText.setTextAppearance(getContext(), value); + } + if (null != mSubHeaderText) { + mSubHeaderText.setTextAppearance(getContext(), value); + } + } + + private void setTextColor(ColorStateList color) { + if (null != mHeaderText) { + mHeaderText.setTextColor(color); + } + if (null != mSubHeaderText) { + mSubHeaderText.setTextColor(color); + } + } + } diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/RotateLoadingLayout.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/RotateLoadingLayout.java index 71d3499e4..325fa4089 100644 --- a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/RotateLoadingLayout.java +++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/RotateLoadingLayout.java @@ -24,6 +24,7 @@ import android.view.animation.RotateAnimation; import android.widget.ImageView.ScaleType; import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; +import com.handmark.pulltorefresh.library.PullToRefreshBase.Orientation; import com.handmark.pulltorefresh.library.R; public class RotateLoadingLayout extends LoadingLayout { @@ -35,8 +36,12 @@ public class RotateLoadingLayout extends LoadingLayout { private float mRotationPivotX, mRotationPivotY; - public RotateLoadingLayout(Context context, Mode mode, TypedArray attrs) { - super(context, mode, attrs); + private final boolean mRotateDrawableWhilePulling; + + public RotateLoadingLayout(Context context, Mode mode, Orientation scrollDirection, TypedArray attrs) { + super(context, mode, scrollDirection, attrs); + + mRotateDrawableWhilePulling = attrs.getBoolean(R.styleable.PullToRefresh_ptrRotateDrawableWhilePulling, true); mHeaderImage.setScaleType(ScaleType.MATRIX); mHeaderImageMatrix = new Matrix(); @@ -57,8 +62,15 @@ public class RotateLoadingLayout extends LoadingLayout { } } - protected void onPullYImpl(float scaleOfHeight) { - mHeaderImageMatrix.setRotate(scaleOfHeight * 90, mRotationPivotX, mRotationPivotY); + protected void onPullImpl(float scaleOfLayout) { + float angle; + if (mRotateDrawableWhilePulling) { + angle = scaleOfLayout * 90f; + } else { + angle = Math.max(0f, Math.min(180f, scaleOfLayout * 360f - 180f)); + } + + mHeaderImageMatrix.setRotate(angle, mRotationPivotX, mRotationPivotY); mHeaderImage.setImageMatrix(mHeaderImageMatrix); } @@ -91,12 +103,7 @@ public class RotateLoadingLayout extends LoadingLayout { } @Override - protected int getDefaultTopDrawableResId() { - return R.drawable.default_ptr_rotate; - } - - @Override - protected int getDefaultBottomDrawableResId() { + protected int getDefaultDrawableResId() { return R.drawable.default_ptr_rotate; } diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/SDK16.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/SDK16.java deleted file mode 100644 index 7a62afa14..000000000 --- a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/SDK16.java +++ /dev/null @@ -1,28 +0,0 @@ -/******************************************************************************* - * Copyright 2011, 2012 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 com.handmark.pulltorefresh.library.internal; - -import android.annotation.TargetApi; -import android.view.View; - -@TargetApi(16) -public class SDK16 { - - public static void postOnAnimation(View view, Runnable runnable) { - view.postOnAnimation(runnable); - } - -} diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/Utils.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/Utils.java new file mode 100644 index 000000000..734321890 --- /dev/null +++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/Utils.java @@ -0,0 +1,13 @@ +package com.handmark.pulltorefresh.library.internal; + +import android.util.Log; + +public class Utils { + + static final String LOG_TAG = "PullToRefresh"; + + public static void warnDeprecation(String depreacted, String replacement) { + Log.w(LOG_TAG, "You're using the deprecated " + depreacted + " attr, please switch over to " + replacement); + } + +} diff --git a/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/ViewCompat.java b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/ViewCompat.java new file mode 100644 index 000000000..618bace02 --- /dev/null +++ b/plugins/Android-PullToRefresh/library/src/com/handmark/pulltorefresh/library/internal/ViewCompat.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright 2011, 2012 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 com.handmark.pulltorefresh.library.internal; + +import android.annotation.TargetApi; +import android.graphics.drawable.Drawable; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; +import android.view.View; + +@SuppressWarnings("deprecation") +public class ViewCompat { + + public static void postOnAnimation(View view, Runnable runnable) { + if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) { + SDK16.postOnAnimation(view, runnable); + } else { + view.postDelayed(runnable, 16); + } + } + + public static void setBackground(View view, Drawable background) { + if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) { + SDK16.setBackground(view, background); + } else { + view.setBackgroundDrawable(background); + } + } + + public static void setLayerType(View view, int layerType) { + if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) { + SDK11.setLayerType(view, layerType); + } + } + + @TargetApi(11) + static class SDK11 { + + public static void setLayerType(View view, int layerType) { + view.setLayerType(layerType, null); + } + } + + @TargetApi(16) + static class SDK16 { + + public static void postOnAnimation(View view, Runnable runnable) { + view.postOnAnimation(runnable); + } + + public static void setBackground(View view, Drawable background) { + view.setBackground(background); + } + + } + +} diff --git a/plugins/Android-PullToRefresh/pom.xml b/plugins/Android-PullToRefresh/pom.xml index 038b41cb4..516f13b16 100644 --- a/plugins/Android-PullToRefresh/pom.xml +++ b/plugins/Android-PullToRefresh/pom.xml @@ -4,7 +4,7 @@ com.github.chrisbanes.pulltorefresh parent pom - 1.4.2 + 2.1.1 Android-PullToRefresh Project Implementation of the Pull-to-Refresh UI Pattern for Android. https://github.com/chrisbanes/Android-PullToRefresh @@ -24,7 +24,7 @@ https://github.com/chrisbanes/Android-PullToRefresh scm:git:git://github.com/chrisbanes/Android-PullToRefresh.git scm:git:git@github.com:chrisbanes/Android-PullToRefresh.git - v1.4.2 + v2.1.1 @@ -65,6 +65,10 @@ org.apache.maven.plugins maven-compiler-plugin 2.3.2 + + ${java.version} + ${java.version} + org.apache.maven.plugins diff --git a/plugins/Android-PullToRefresh/sample/AndroidManifest.xml b/plugins/Android-PullToRefresh/sample/AndroidManifest.xml index 3eee0edee..af06dffa8 100755 --- a/plugins/Android-PullToRefresh/sample/AndroidManifest.xml +++ b/plugins/Android-PullToRefresh/sample/AndroidManifest.xml @@ -1,17 +1,17 @@ + android:versionCode="2110" + android:versionName="2.1.1" > + android:targetSdkVersion="15" /> + android:label="@string/app_name" > @@ -29,6 +29,10 @@ android:name=".PullToRefreshListFragmentActivity" android:label="PtR ListView Fragment" > + + @@ -45,6 +49,14 @@ android:name=".PullToRefreshScrollViewActivity" android:label="PtR ScrollView" > + + + + diff --git a/plugins/Android-PullToRefresh/sample/LICENSE b/plugins/Android-PullToRefresh/sample/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/plugins/Android-PullToRefresh/sample/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/plugins/Android-PullToRefresh/sample/libs/android-support-v4.jar b/plugins/Android-PullToRefresh/sample/libs/android-support-v4.jar new file mode 100644 index 000000000..feaf44f80 Binary files /dev/null and b/plugins/Android-PullToRefresh/sample/libs/android-support-v4.jar differ diff --git a/plugins/Android-PullToRefresh/sample/pom.xml b/plugins/Android-PullToRefresh/sample/pom.xml index 80b0ebcb9..7f18729d6 100644 --- a/plugins/Android-PullToRefresh/sample/pom.xml +++ b/plugins/Android-PullToRefresh/sample/pom.xml @@ -10,7 +10,7 @@ com.github.chrisbanes.pulltorefresh parent - 1.4.2 + 2.1.1 @@ -30,6 +30,12 @@ apklib ${project.version} + + ${project.groupId} + extra-viewpager + apklib + ${project.version} + diff --git a/plugins/Android-PullToRefresh/sample/project.properties b/plugins/Android-PullToRefresh/sample/project.properties index 0c37987ca..bcee3ff1d 100755 --- a/plugins/Android-PullToRefresh/sample/project.properties +++ b/plugins/Android-PullToRefresh/sample/project.properties @@ -11,3 +11,4 @@ target=android-15 android.library.reference.1=../library android.library.reference.2=../extras/PullToRefreshListFragment +android.library.reference.3=../extras/PullToRefreshViewPager diff --git a/plugins/Android-PullToRefresh/sample/res/drawable-nodpi/wallpaper.jpg b/plugins/Android-PullToRefresh/sample/res/drawable-nodpi/wallpaper.jpg new file mode 100644 index 000000000..6bc52926c Binary files /dev/null and b/plugins/Android-PullToRefresh/sample/res/drawable-nodpi/wallpaper.jpg differ diff --git a/plugins/Android-PullToRefresh/sample/res/layout/activity_ptr_expandable_list.xml b/plugins/Android-PullToRefresh/sample/res/layout/activity_ptr_expandable_list.xml index 6d6194dc3..d366c3443 100755 --- a/plugins/Android-PullToRefresh/sample/res/layout/activity_ptr_expandable_list.xml +++ b/plugins/Android-PullToRefresh/sample/res/layout/activity_ptr_expandable_list.xml @@ -1,17 +1,16 @@ + android:layout_height="fill_parent" + android:orientation="vertical" > - + diff --git a/plugins/Android-PullToRefresh/sample/res/layout/activity_ptr_horizontalscrollview.xml b/plugins/Android-PullToRefresh/sample/res/layout/activity_ptr_horizontalscrollview.xml new file mode 100644 index 000000000..5f9307b12 --- /dev/null +++ b/plugins/Android-PullToRefresh/sample/res/layout/activity_ptr_horizontalscrollview.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/Android-PullToRefresh/sample/res/layout/activity_ptr_list_in_vp.xml b/plugins/Android-PullToRefresh/sample/res/layout/activity_ptr_list_in_vp.xml new file mode 100644 index 000000000..a04737689 --- /dev/null +++ b/plugins/Android-PullToRefresh/sample/res/layout/activity_ptr_list_in_vp.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/plugins/Android-PullToRefresh/sample/res/layout/activity_ptr_viewpager.xml b/plugins/Android-PullToRefresh/sample/res/layout/activity_ptr_viewpager.xml new file mode 100644 index 000000000..03c8eee7b --- /dev/null +++ b/plugins/Android-PullToRefresh/sample/res/layout/activity_ptr_viewpager.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/plugins/Android-PullToRefresh/sample/res/layout/layout_listview_in_viewpager.xml b/plugins/Android-PullToRefresh/sample/res/layout/layout_listview_in_viewpager.xml new file mode 100644 index 000000000..3bfc689d4 --- /dev/null +++ b/plugins/Android-PullToRefresh/sample/res/layout/layout_listview_in_viewpager.xml @@ -0,0 +1,6 @@ + + diff --git a/plugins/Android-PullToRefresh/sample/res/values/styles.xml b/plugins/Android-PullToRefresh/sample/res/values/styles.xml new file mode 100644 index 000000000..609c2762f --- /dev/null +++ b/plugins/Android-PullToRefresh/sample/res/values/styles.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/LauncherActivity.java b/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/LauncherActivity.java index 7a3a299f7..8eb47bc91 100644 --- a/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/LauncherActivity.java +++ b/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/LauncherActivity.java @@ -25,7 +25,7 @@ import android.widget.ListView; public class LauncherActivity extends ListActivity { public static final String[] options = { "ListView", "ExpandableListView", "GridView", "WebView", "ScrollView", - "ListView Fragment", "WebView Advanced" }; + "Horizontal ScrollView", "ViewPager", "ListView Fragment", "WebView Advanced", "ListView in ViewPager" }; @Override protected void onCreate(Bundle savedInstanceState) { @@ -55,11 +55,20 @@ public class LauncherActivity extends ListActivity { intent = new Intent(this, PullToRefreshScrollViewActivity.class); break; case 5: - intent = new Intent(this, PullToRefreshListFragmentActivity.class); + intent = new Intent(this, PullToRefreshHorizontalScrollViewActivity.class); break; case 6: + intent = new Intent(this, PullToRefreshViewPagerActivity.class); + break; + case 7: + intent = new Intent(this, PullToRefreshListFragmentActivity.class); + break; + case 8: intent = new Intent(this, PullToRefreshWebView2Activity.class); break; + case 9: + intent = new Intent(this, PullToRefreshListInViewPagerActivity.class); + break; } startActivity(intent); diff --git a/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshExpandableListActivity.java b/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshExpandableListActivity.java index d50c44145..05de38c82 100644 --- a/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshExpandableListActivity.java +++ b/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshExpandableListActivity.java @@ -16,9 +16,7 @@ package com.handmark.pulltorefresh.samples; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -34,7 +32,10 @@ import com.handmark.pulltorefresh.library.PullToRefreshExpandableListView; public final class PullToRefreshExpandableListActivity extends ExpandableListActivity { private static final String KEY = "key"; - private LinkedList mListItems, mGroupItems; + + private List> groupData = new ArrayList>(); + private List>> childData = new ArrayList>>(); + private PullToRefreshExpandableListView mPullRefreshListView; private SimpleExpandableListAdapter mAdapter; @@ -55,13 +56,6 @@ public final class PullToRefreshExpandableListActivity extends ExpandableListAct } }); - mListItems = new LinkedList(); - mListItems.addAll(Arrays.asList(mChildStrings)); - mGroupItems = new LinkedList(); - mGroupItems.addAll(Arrays.asList(mGroupStrings)); - - List> groupData = new ArrayList>(); - List>> childData = new ArrayList>>(); for (String group : mGroupStrings) { Map groupMap1 = new HashMap(); groupData.add(groupMap1); @@ -96,7 +90,18 @@ public final class PullToRefreshExpandableListActivity extends ExpandableListAct @Override protected void onPostExecute(String[] result) { - mListItems.addFirst("Added after refresh..."); + Map newMap = new HashMap(); + newMap.put(KEY, "Added after refresh..."); + groupData.add(newMap); + + List> childList = new ArrayList>(); + for (String string : mChildStrings) { + Map childMap = new HashMap(); + childMap.put(KEY, string); + childList.add(childMap); + } + childData.add(childList); + mAdapter.notifyDataSetChanged(); // Call onRefreshComplete when the list has been refreshed. @@ -106,8 +111,7 @@ public final class PullToRefreshExpandableListActivity extends ExpandableListAct } } - private final String[] mChildStrings = { "Child One", "Child Two", "Child Three", "Child Four", "Child Five", - "Child Six" }; + private String[] mChildStrings = { "Child One", "Child Two", "Child Three", "Child Four", "Child Five", "Child Six" }; - private final String[] mGroupStrings = { "Group One", "Group Two", "Group Three" }; + private String[] mGroupStrings = { "Group One", "Group Two", "Group Three" }; } diff --git a/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshGridActivity.java b/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshGridActivity.java index 69c2d2512..9d87e357c 100644 --- a/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshGridActivity.java +++ b/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshGridActivity.java @@ -116,7 +116,7 @@ public final class PullToRefreshGridActivity extends Activity { @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuItem setModeItem = menu.findItem(MENU_SET_MODE); - setModeItem.setTitle(mPullRefreshGridView.getMode() == Mode.BOTH ? "Change to MODE_PULL_DOWN" + setModeItem.setTitle(mPullRefreshGridView.getMode() == Mode.BOTH ? "Change to MODE_PULL_FROM_START" : "Change to MODE_PULL_BOTH"); return super.onPrepareOptionsMenu(menu); @@ -127,7 +127,7 @@ public final class PullToRefreshGridActivity extends Activity { switch (item.getItemId()) { case MENU_SET_MODE: mPullRefreshGridView - .setMode(mPullRefreshGridView.getMode() == Mode.BOTH ? Mode.PULL_DOWN_TO_REFRESH + .setMode(mPullRefreshGridView.getMode() == Mode.BOTH ? Mode.PULL_FROM_START : Mode.BOTH); break; } diff --git a/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshHorizontalScrollViewActivity.java b/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshHorizontalScrollViewActivity.java new file mode 100644 index 000000000..81e21652d --- /dev/null +++ b/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshHorizontalScrollViewActivity.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright 2011, 2012 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 com.handmark.pulltorefresh.samples; + +import android.app.Activity; +import android.os.AsyncTask; +import android.os.Bundle; +import android.widget.HorizontalScrollView; + +import com.handmark.pulltorefresh.library.PullToRefreshBase; +import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener; +import com.handmark.pulltorefresh.library.PullToRefreshHorizontalScrollView; + +public final class PullToRefreshHorizontalScrollViewActivity extends Activity { + + PullToRefreshHorizontalScrollView mPullRefreshScrollView; + HorizontalScrollView mScrollView; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_ptr_horizontalscrollview); + + mPullRefreshScrollView = (PullToRefreshHorizontalScrollView) findViewById(R.id.pull_refresh_horizontalscrollview); + mPullRefreshScrollView.setOnRefreshListener(new OnRefreshListener() { + + @Override + public void onRefresh(PullToRefreshBase refreshView) { + new GetDataTask().execute(); + } + }); + + mScrollView = mPullRefreshScrollView.getRefreshableView(); + } + + private class GetDataTask extends AsyncTask { + + @Override + protected String[] doInBackground(Void... params) { + // Simulates a background job. + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + } + return null; + } + + @Override + protected void onPostExecute(String[] result) { + // Do some stuff here + + // Call onRefreshComplete when the list has been refreshed. + mPullRefreshScrollView.onRefreshComplete(); + + super.onPostExecute(result); + } + } + +} diff --git a/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListActivity.java b/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListActivity.java index 57536084b..13b572ea2 100755 --- a/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListActivity.java +++ b/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListActivity.java @@ -22,8 +22,12 @@ import android.app.ListActivity; import android.os.AsyncTask; import android.os.Bundle; import android.text.format.DateUtils; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; import android.view.Menu; import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast; @@ -41,6 +45,7 @@ public final class PullToRefreshListActivity extends ListActivity { static final int MENU_MANUAL_REFRESH = 0; static final int MENU_DISABLE_SCROLL = 1; static final int MENU_SET_MODE = 2; + static final int MENU_DEMO = 3; private LinkedList mListItems; private PullToRefreshListView mPullRefreshListView; @@ -58,9 +63,11 @@ public final class PullToRefreshListActivity extends ListActivity { mPullRefreshListView.setOnRefreshListener(new OnRefreshListener() { @Override public void onRefresh(PullToRefreshBase refreshView) { - mPullRefreshListView.setLastUpdatedLabel(DateUtils.formatDateTime(getApplicationContext(), - System.currentTimeMillis(), DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE - | DateUtils.FORMAT_ABBREV_ALL)); + String label = DateUtils.formatDateTime(getApplicationContext(), System.currentTimeMillis(), + DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL); + + // Update the LastUpdatedLabel + refreshView.getLoadingLayoutProxy().setLastUpdatedLabel(label); // Do work to refresh the list here. new GetDataTask().execute(); @@ -78,6 +85,9 @@ public final class PullToRefreshListActivity extends ListActivity { ListView actualListView = mPullRefreshListView.getRefreshableView(); + // Need to use the Actual ListView when registering for Context Menu + registerForContextMenu(actualListView); + mListItems = new LinkedList(); mListItems.addAll(Arrays.asList(mStrings)); @@ -125,22 +135,36 @@ public final class PullToRefreshListActivity extends ListActivity { public boolean onCreateOptionsMenu(Menu menu) { menu.add(0, MENU_MANUAL_REFRESH, 0, "Manual Refresh"); menu.add(0, MENU_DISABLE_SCROLL, 1, - mPullRefreshListView.isDisableScrollingWhileRefreshing() ? "Enable Scrolling while Refreshing" - : "Disable Scrolling while Refreshing"); + mPullRefreshListView.isScrollingWhileRefreshingEnabled() ? "Disable Scrolling while Refreshing" + : "Enable Scrolling while Refreshing"); menu.add(0, MENU_SET_MODE, 0, mPullRefreshListView.getMode() == Mode.BOTH ? "Change to MODE_PULL_DOWN" : "Change to MODE_PULL_BOTH"); + menu.add(0, MENU_DEMO, 0, "Demo"); return super.onCreateOptionsMenu(menu); } + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { + AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo; + + menu.setHeaderTitle("Item: " + getListView().getItemAtPosition(info.position)); + menu.add("Item 1"); + menu.add("Item 2"); + menu.add("Item 3"); + menu.add("Item 4"); + + super.onCreateContextMenu(menu, v, menuInfo); + } + @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuItem disableItem = menu.findItem(MENU_DISABLE_SCROLL); disableItem - .setTitle(mPullRefreshListView.isDisableScrollingWhileRefreshing() ? "Enable Scrolling while Refreshing" - : "Disable Scrolling while Refreshing"); + .setTitle(mPullRefreshListView.isScrollingWhileRefreshingEnabled() ? "Disable Scrolling while Refreshing" + : "Enable Scrolling while Refreshing"); MenuItem setModeItem = menu.findItem(MENU_SET_MODE); - setModeItem.setTitle(mPullRefreshListView.getMode() == Mode.BOTH ? "Change to MODE_PULL_DOWN" + setModeItem.setTitle(mPullRefreshListView.getMode() == Mode.BOTH ? "Change to MODE_FROM_START" : "Change to MODE_PULL_BOTH"); return super.onPrepareOptionsMenu(menu); @@ -155,13 +179,16 @@ public final class PullToRefreshListActivity extends ListActivity { mPullRefreshListView.setRefreshing(false); break; case MENU_DISABLE_SCROLL: - mPullRefreshListView.setDisableScrollingWhileRefreshing(!mPullRefreshListView - .isDisableScrollingWhileRefreshing()); + mPullRefreshListView.setScrollingWhileRefreshingEnabled(!mPullRefreshListView + .isScrollingWhileRefreshingEnabled()); break; case MENU_SET_MODE: - mPullRefreshListView.setMode(mPullRefreshListView.getMode() == Mode.BOTH ? Mode.PULL_DOWN_TO_REFRESH + mPullRefreshListView.setMode(mPullRefreshListView.getMode() == Mode.BOTH ? Mode.PULL_FROM_START : Mode.BOTH); break; + case MENU_DEMO: + mPullRefreshListView.demo(); + break; } return super.onOptionsItemSelected(item); diff --git a/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListInViewPagerActivity.java b/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListInViewPagerActivity.java new file mode 100644 index 000000000..45b9b1e32 --- /dev/null +++ b/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListInViewPagerActivity.java @@ -0,0 +1,110 @@ +package com.handmark.pulltorefresh.samples; + +import java.util.Arrays; + +import android.app.Activity; +import android.content.Context; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; +import android.widget.ListView; + +import com.handmark.pulltorefresh.library.PullToRefreshBase; +import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener; +import com.handmark.pulltorefresh.library.PullToRefreshListView; + +public class PullToRefreshListInViewPagerActivity extends Activity implements OnRefreshListener { + + private static final String[] STRINGS = { "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", + "Ackawi", "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre", + "Allgauer Emmentaler", "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi", + "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre", + "Allgauer Emmentaler" }; + + private ViewPager mViewPager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_ptr_list_in_vp); + + mViewPager = (ViewPager) findViewById(R.id.vp_list); + mViewPager.setAdapter(new ListViewPagerAdapter()); + } + + private class ListViewPagerAdapter extends PagerAdapter { + + @Override + public View instantiateItem(ViewGroup container, int position) { + Context context = container.getContext(); + + PullToRefreshListView plv = (PullToRefreshListView) LayoutInflater.from(context).inflate( + R.layout.layout_listview_in_viewpager, container, false); + + ListAdapter adapter = new ArrayAdapter(context, android.R.layout.simple_list_item_1, + Arrays.asList(STRINGS)); + plv.setAdapter(adapter); + + plv.setOnRefreshListener(PullToRefreshListInViewPagerActivity.this); + + // Now just add ListView to ViewPager and return it + container.addView(plv, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + + return plv; + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + container.removeView((View) object); + } + + @Override + public boolean isViewFromObject(View view, Object object) { + return view == object; + } + + @Override + public int getCount() { + return 3; + } + + } + + @Override + public void onRefresh(PullToRefreshBase refreshView) { + new GetDataTask(refreshView).execute(); + } + + private static class GetDataTask extends AsyncTask { + + PullToRefreshBase mRefreshedView; + + public GetDataTask(PullToRefreshBase refreshedView) { + mRefreshedView = refreshedView; + } + + @Override + protected Void doInBackground(Void... params) { + // Simulates a background job. + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + } + return null; + } + + @Override + protected void onPostExecute(Void result) { + mRefreshedView.onRefreshComplete(); + super.onPostExecute(result); + } + } + +} diff --git a/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshViewPagerActivity.java b/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshViewPagerActivity.java new file mode 100644 index 000000000..df05fddc4 --- /dev/null +++ b/plugins/Android-PullToRefresh/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshViewPagerActivity.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright 2011, 2012 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 com.handmark.pulltorefresh.samples; + +import android.app.Activity; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.ImageView; + +import com.handmark.pulltorefresh.extras.viewpager.PullToRefreshViewPager; +import com.handmark.pulltorefresh.library.PullToRefreshBase; +import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener; + +public class PullToRefreshViewPagerActivity extends Activity implements OnRefreshListener { + + private PullToRefreshViewPager mPullToRefreshViewPager; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_ptr_viewpager); + + mPullToRefreshViewPager = (PullToRefreshViewPager) findViewById(R.id.pull_refresh_viewpager); + mPullToRefreshViewPager.setOnRefreshListener(this); + + ViewPager vp = mPullToRefreshViewPager.getRefreshableView(); + vp.setAdapter(new SamplePagerAdapter()); + } + + @Override + public void onRefresh(PullToRefreshBase refreshView) { + new GetDataTask().execute(); + } + + static class SamplePagerAdapter extends PagerAdapter { + + private static int[] sDrawables = { R.drawable.wallpaper, R.drawable.wallpaper, R.drawable.wallpaper, + R.drawable.wallpaper, R.drawable.wallpaper, R.drawable.wallpaper }; + + @Override + public int getCount() { + return sDrawables.length; + } + + @Override + public View instantiateItem(ViewGroup container, int position) { + ImageView imageView = new ImageView(container.getContext()); + imageView.setImageResource(sDrawables[position]); + + // Now just add ImageView to ViewPager and return it + container.addView(imageView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + + return imageView; + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + container.removeView((View) object); + } + + @Override + public boolean isViewFromObject(View view, Object object) { + return view == object; + } + } + + private class GetDataTask extends AsyncTask { + + @Override + protected Void doInBackground(Void... params) { + // Simulates a background job. + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + } + return null; + } + + @Override + protected void onPostExecute(Void result) { + mPullToRefreshViewPager.onRefreshComplete(); + super.onPostExecute(result); + } + } + +}