[
  {
    "path": ".gitignore",
    "content": "#Android generated\nbin\ngen\nlibrary/build/\n\n#Eclipse\n.project\n.classpath\n.settings\n\n#IntelliJ IDEA\n.idea\n*.iml\n*.ipr\n*.iws\nout\n\n#Maven\ntarget\nrelease.properties\npom.xml.*\n\n#Ant\nbuild.xml\nlocal.properties\nproguard.cfg\n\n#OSX\n.DS_Store\n"
  },
  {
    "path": "LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "# Pull To Refresh Views for Android `Renewal`! v3.2\n### This project is a fork of Chris Banes' Android-PullToRefresh project. The project provides flexibility in customization in addition to adding brand new features listed below.\n- __New!__ AAR package support\n- Google-like pull to refresh animation support (in Android 3.x or 4.x)\n\n  *__NOTE__: This style is now supported in [Android Support Library](http://developer.android.com/reference/android/support/v4/widget/SwipeRefreshLayout.html).\n  I recommend you to use the support library instead of this library, unless you are already using and want to change the style from old style to it.*\n\n- Easy layout customization - no need to include the library's source code directly into your project. \n- Easily Customizable loading layouts, labels, and icons. \n- Ability to customize and add multiple indicator layouts. \n- Configurable friction and smooth scroll duration. \n- This fork project is __not__ being deprecated. Please send issues or pull requests to me, and I will provide you with feedbacks.\n\n- __Are you are using Pull To Refresh v2.1.x? You'd better [MIGRATE](https://github.com/nhnopensource/android-pull-to-refresh/wiki/Migration-from-v2.1.x-to-v3.0.0) to v3.2 now!__\n\n### Introduction\n* * *\n\n![Screenshot](https://github.com/nhnopensource/android-pull-to-refresh/raw/master/header_graphic.png)\n\nThis project aims to provide a reusable Pull to Refresh widget for Android. It was originally based on Johan Nilsson's [library](https://github.com/johannilsson/android-pulltorefresh) (mainly for graphics, strings and animations), but these have been replaced since.\n\n## Included Features\n\n * Supports both Pulling Down from the top, and Pulling Up from the bottom (or even both).\n * Animated Scrolling for all devices.\n * Over Scroll supports for devices on Android v2.3+.\n * Currently works with:\n    * **ListView**\n    * **ExpandableListView**\n    * **GridView**\n    * **WebView**\n    * **ScrollView**\n    * **HorizontalScrollView**\n    * **ViewPager**\n * Integrated End of List Listener for use of detecting when the user has scrolled to the bottom.\n * Maven Central Support.\n * Indicators to show the user when a Pull-to-Refresh is available.\n * Support for **ListFragment**!\n * Lots of [Customization](https://github.com/nhnopensource/android-pull-to-refresh/wiki/Customization) options!\n\nRepository at <https://github.com/nhnopensource/android-pull-to-refresh>.\n\n## Sample Application\nSample application is being provided as APK file (the source is in the repository):\n\n[Download Here!](http://search.maven.org/remotecontent?filepath=com/navercorp/pulltorefresh/sample/3.2.2/sample-3.2.2.apk)\n\n## Usage\nTo begin using the library, please see the [Quick Start Guide](https://github.com/nhnopensource/android-pull-to-refresh/wiki/Quick-Start-Guide).\n\n### Customization\nOur [Customization](https://github.com/nhnopensource/android-pull-to-refresh/wiki/Customization) page contains detailed information on how to change the behaviour and look of the View.\n\n### Pull Up to Refresh\nBy default this library is set to Pull Down to Refresh, but if you want to allow Pull Up to Refresh then you can do so. You can even set the View to enable both Pull Up and Pull Down using the 'both' setting. See the [Customization](https://github.com/nhnopensource/android-pull-to-refresh/wiki/Customization) page for more information on how to set this.\n\n## Apps\nWant to see which Apps are already using Android-PullToRefresh? Have a look [here](https://github.com/nhnopensource/android-pull-to-refresh/wiki/Apps). \n\n## Changelog\nPlease see the new [Changelog](https://github.com/nhnopensource/android-pull-to-refresh/wiki/Changelog) page to see what's recently changed.\n\n## Pull Requests\n\nI will gladly accept pull requests for fixes and feature enhancements but please do them in the dev branch. The master branch is for the latest stable code,  dev is where I try things out before releasing them as stable. Any pull requests that are against master from now on will be closed asking for you to do another pull against dev.\n\n## Acknowledgments\n\n* [Stefano Dacchille](https://github.com/stefanodacchille)\n* [Steve Lhomme](https://github.com/robUx4)\n* [Maxim Galkin](https://github.com/mgalkin)\n* [Scorcher](https://github.com/Scorcher)\n\n## License\n\n    Copyright 2011, 2012 Chris Banes\n    Copyright 2013 Naver Business Platform Corp.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n"
  },
  {
    "path": "build.gradle",
    "content": "buildscript {\n    repositories {\n        mavenCentral()\n    }\n\n    dependencies {\n        classpath 'com.android.tools.build:gradle:0.11.+'\n    }\n}\n\nallprojects {\n\tversion = PULLTOREFRESH_RELEASE_VERSION\n\tgroup = PULLTOREFRESH_RELEASE_GROUP\n\n    repositories {\n        mavenCentral()\n    }\n}\n"
  },
  {
    "path": "extras/PullToRefreshListFragment/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.handmark.pulltorefresh.extras.listfragment\"\n    android:versionCode=\"2110\"\n    android:versionName=\"2.1.1\" >\n\n    <uses-sdk android:minSdkVersion=\"4\" />\n    <application />\n\n</manifest>\n"
  },
  {
    "path": "extras/PullToRefreshListFragment/LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "extras/PullToRefreshListFragment/build.gradle",
    "content": "apply plugin: 'android-library'\n\ndependencies {\n\tcompile project(':library')\n\tcompile 'com.android.support:support-v4:18.0.+'\n}\n\narchivesBaseName = 'extra-listfragment'\n\nandroid {\n    compileSdkVersion Integer.parseInt(ANDROID_COMPILE_SDK_VERSION)\n    buildToolsVersion ANDROID_BUILD_TOOLS_VERSION\n    \n    sourceSets {\n    \tmain {\n    \t\tmanifest.srcFile 'AndroidManifest.xml'\n    \t\tjava.srcDirs=['src']\n    \t\tres.srcDirs=['res']\n    \t}\n    }\n}\n\n"
  },
  {
    "path": "extras/PullToRefreshListFragment/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t\n\t<groupId>com.navercorp.pulltorefresh</groupId>\n\t<artifactId>extra-listfragment</artifactId>\n\t<packaging>apklib</packaging>\n\t<name>Android-PullToRefresh Extras: ListFragment</name>\n\t\n\t<parent>\n\t\t<groupId>com.navercorp.pulltorefresh</groupId>\n\t\t<artifactId>extras</artifactId>\n\t\t<version>3.3.0-SNAPSHOT</version>\n\t</parent>\n\t\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>com.google.android</groupId>\n\t\t\t<artifactId>android</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.google.android</groupId>\n\t\t\t<artifactId>support-v4</artifactId>\n\t\t\t<version>r7</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>${project.groupId}</groupId>\n\t\t\t<artifactId>library</artifactId>\n\t\t\t<type>apklib</type>\n\t\t\t<version>${project.version}</version>\n\t\t</dependency>\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.jayway.maven.plugins.android.generation2</groupId>\n\t\t\t\t<artifactId>android-maven-plugin</artifactId>\n\t\t\t\t<version>3.7.0</version>\n\t\t\t</plugin>\n\t\t\t<!-- extracted from actionbarsherlock's pom -->\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.codehaus.mojo</groupId>\n\t\t\t\t<artifactId>build-helper-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>attach-artifact</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<artifacts>\n\t\t\t\t\t\t\t\t<artifact>\n\t\t\t\t\t\t\t\t\t<type>aar</type>\n\t\t\t\t\t\t\t\t\t<file>${project.basedir}/build/libs/${project.artifactId}-${parent.version}.aar</file>\n\t\t\t\t\t\t\t\t</artifact>\n\t\t\t\t\t\t\t</artifacts>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\t\t\t\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-eclipse-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "extras/PullToRefreshListFragment/project.properties",
    "content": "# This file is automatically generated by Android Tools.\n# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n#\n# This file must be checked in Version Control Systems.\n#\n# To customize properties used by the Ant build system edit\n# \"ant.properties\", and override values to adapt the script to your\n# project structure.\n#\n# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):\n#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt\n\nandroid.library=true\n# Project target.\ntarget=android-16\nandroid.library.reference.1=../../library\n"
  },
  {
    "path": "extras/PullToRefreshListFragment/res/layout/need_this_for_maven.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\" >\n    \n    <!-- Need this for Maven, otherwise it doesn't build. I hate Maven. -->\n\n</LinearLayout>"
  },
  {
    "path": "extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshBaseListFragment.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.extras.listfragment;\n\nimport android.os.Bundle;\nimport android.support.v4.app.ListFragment;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.AbsListView;\nimport android.widget.ListView;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshBase;\n\nabstract class PullToRefreshBaseListFragment<T extends PullToRefreshBase<? extends AbsListView>> extends ListFragment {\n\n\tprivate T mPullToRefreshListView;\n\n\t@Override\n\tpublic final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {\n\t\tView layout = super.onCreateView(inflater, container, savedInstanceState);\n\n\t\tListView lv = (ListView) layout.findViewById(android.R.id.list);\n\t\tViewGroup parent = (ViewGroup) lv.getParent();\n\n\t\t// Remove ListView and add PullToRefreshListView in its place\n\t\tint lvIndex = parent.indexOfChild(lv);\n\t\tparent.removeViewAt(lvIndex);\n\t\tmPullToRefreshListView = onCreatePullToRefreshListView(inflater, savedInstanceState);\n\t\tparent.addView(mPullToRefreshListView, lvIndex, lv.getLayoutParams());\n\n\t\treturn layout;\n\t}\n\n\t/**\n\t * @return The {@link PullToRefreshBase} attached to this ListFragment.\n\t */\n\tpublic final T getPullToRefreshListView() {\n\t\treturn mPullToRefreshListView;\n\t}\n\n\t/**\n\t * Returns the {@link PullToRefreshBase} which will replace the ListView\n\t * created from ListFragment. You should override this method if you wish to\n\t * customise the {@link PullToRefreshBase} from the default.\n\t * \n\t * @param inflater - LayoutInflater which can be used to inflate from XML.\n\t * @param savedInstanceState - Bundle passed through from\n\t *            {@link ListFragment#onCreateView(LayoutInflater, ViewGroup, Bundle)\n\t *            onCreateView(...)}\n\t * @return The {@link PullToRefreshBase} which will replace the ListView.\n\t */\n\tprotected abstract T onCreatePullToRefreshListView(LayoutInflater inflater, Bundle savedInstanceState);\n\n}"
  },
  {
    "path": "extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshExpandableListFragment.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.extras.listfragment;\n\nimport android.os.Bundle;\nimport android.support.v4.app.ListFragment;\nimport android.view.LayoutInflater;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshExpandableListView;\n\n/**\n * A sample implementation of how to use {@link PullToRefreshExpandableListView}\n * with {@link ListFragment}. This implementation simply replaces the ListView\n * that {@code ListFragment} creates with a new\n * {@code PullToRefreshExpandableListView}. This means that ListFragment still\n * works 100% (e.g. <code>setListShown(...)</code> ).\n * <p/>\n * The new PullToRefreshListView is created in the method\n * {@link #onCreatePullToRefreshListView(LayoutInflater, Bundle)}. If you wish\n * to customise the {@code PullToRefreshExpandableListView} then override this\n * method and return your customised instance.\n * \n * @author Chris Banes\n * \n */\npublic class PullToRefreshExpandableListFragment extends PullToRefreshBaseListFragment<PullToRefreshExpandableListView> {\n\n\tprotected PullToRefreshExpandableListView onCreatePullToRefreshListView(LayoutInflater inflater,\n\t\t\tBundle savedInstanceState) {\n\t\treturn new PullToRefreshExpandableListView(getActivity());\n\t}\n\n}"
  },
  {
    "path": "extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshListFragment.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.extras.listfragment;\n\nimport android.os.Bundle;\nimport android.support.v4.app.ListFragment;\nimport android.view.LayoutInflater;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshListView;\n\n/**\n * A sample implementation of how to use {@link PullToRefreshListView} with\n * {@link ListFragment}. This implementation simply replaces the ListView that\n * {@code ListFragment} creates with a new PullToRefreshListView. This means\n * that ListFragment still works 100% (e.g. <code>setListShown(...)</code> ).\n * <p/>\n * The new PullToRefreshListView is created in the method\n * {@link #onCreatePullToRefreshListView(LayoutInflater, Bundle)}. If you wish\n * to customise the {@code PullToRefreshListView} then override this method and\n * return your customised instance.\n * \n * @author Chris Banes\n * \n */\npublic class PullToRefreshListFragment extends PullToRefreshBaseListFragment<PullToRefreshListView> {\n\n\tprotected PullToRefreshListView onCreatePullToRefreshListView(LayoutInflater inflater, Bundle savedInstanceState) {\n\t\treturn new PullToRefreshListView(getActivity());\n\t}\n\n}"
  },
  {
    "path": "extras/PullToRefreshViewPager/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.handmark.pulltorefresh.extras.viewpager\"\n   android:versionCode=\"2110\"\n    android:versionName=\"2.1.1\" >\n\n    <uses-sdk android:minSdkVersion=\"4\" />\n\n    <application />\n\n</manifest>"
  },
  {
    "path": "extras/PullToRefreshViewPager/ant.properties",
    "content": "# This file is used to override default values used by the Ant build system.\n#\n# This file must be checked into Version Control Systems, as it is\n# integral to the build system of your project.\n\n# This file is only used by the Ant script.\n\n# You can use this to override default values such as\n#  'source.dir' for the location of your java source folder and\n#  'out.dir' for the location of your output folder.\n\n# You can also use it define how the release builds are signed by declaring\n# the following properties:\n#  'key.store' for the location of your keystore and\n#  'key.alias' for the name of the key to use.\n# The password will be asked during the build when you use the 'release' target.\n\n"
  },
  {
    "path": "extras/PullToRefreshViewPager/build.gradle",
    "content": "apply plugin: 'android-library'\n\nbuildscript {\n    repositories {\n        mavenCentral()\n    }\n\n    dependencies {\n        classpath 'com.android.tools.build:gradle:0.6.+'\n    }\n}\n\narchivesBaseName = 'extra-viewpager'\n\ndependencies {\n\tcompile project(':library')\n\tcompile 'com.android.support:support-v4:18.0.+'\n}\n\nandroid {\n    compileSdkVersion Integer.parseInt(ANDROID_COMPILE_SDK_VERSION)\n    buildToolsVersion ANDROID_BUILD_TOOLS_VERSION\n\n    sourceSets {\n    \tmain {\n    \t\tmanifest.srcFile 'AndroidManifest.xml'\n    \t\tjava.srcDirs=['src']\n    \t\tres.srcDirs=['res']\n    \t}\n    }\n}\n"
  },
  {
    "path": "extras/PullToRefreshViewPager/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t\n\t<groupId>com.navercorp.pulltorefresh</groupId>\n\t<artifactId>extra-viewpager</artifactId>\n\t<packaging>apklib</packaging>\n\t<name>Android-PullToRefresh Extras: ViewPager</name>\n\t\n\t<parent>\n\t\t<groupId>com.navercorp.pulltorefresh</groupId>\n\t\t<artifactId>extras</artifactId>\n\t\t<version>3.3.0-SNAPSHOT</version>\n\t</parent>\n\t\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>com.google.android</groupId>\n\t\t\t<artifactId>android</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>com.google.android</groupId>\n\t\t\t<artifactId>support-v4</artifactId>\n\t\t\t<version>r7</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>${project.groupId}</groupId>\n\t\t\t<artifactId>library</artifactId>\n\t\t\t<type>apklib</type>\n\t\t\t<version>${project.version}</version>\n\t\t</dependency>\n\t</dependencies>\n\t\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.jayway.maven.plugins.android.generation2</groupId>\n\t\t\t\t<artifactId>android-maven-plugin</artifactId>\n\t\t\t\t<version>3.7.0</version>\n\t\t\t</plugin>\n\t\t\t<!-- extracted from actionbarsherlock's pom -->\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.codehaus.mojo</groupId>\n\t\t\t\t<artifactId>build-helper-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>attach-artifact</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<artifacts>\n\t\t\t\t\t\t\t\t<artifact>\n\t\t\t\t\t\t\t\t\t<type>aar</type>\n\t\t\t\t\t\t\t\t\t<file>${project.basedir}/build/libs/${project.artifactId}-${parent.version}.aar</file>\n\t\t\t\t\t\t\t\t</artifact>\n\t\t\t\t\t\t\t</artifacts>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-eclipse-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "extras/PullToRefreshViewPager/proguard-project.txt",
    "content": "# To enable ProGuard in your project, edit project.properties\n# to define the proguard.config property as described in that file.\n#\n# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in ${sdk.dir}/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the ProGuard\n# include property in project.properties.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "extras/PullToRefreshViewPager/project.properties",
    "content": "# This file is automatically generated by Android Tools.\n# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n#\n# This file must be checked in Version Control Systems.\n#\n# To customize properties used by the Ant build system edit\n# \"ant.properties\", and override values to adapt the script to your\n# project structure.\n#\n# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):\n#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt\n\nandroid.library=true\n# Project target.\ntarget=android-16\nandroid.library.reference.1=../../library\n"
  },
  {
    "path": "extras/PullToRefreshViewPager/res/layout/need_this_for_maven.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\" >\n    \n    <!-- Need this for Maven, otherwise it doesn't build. I hate Maven. -->\n\n</LinearLayout>"
  },
  {
    "path": "extras/PullToRefreshViewPager/res/values/ids.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <item type=\"id\" name=\"viewpager\" />\n\n</resources>"
  },
  {
    "path": "extras/PullToRefreshViewPager/src/com/handmark/pulltorefresh/extras/viewpager/PullToRefreshViewPager.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.extras.viewpager;\n\nimport android.content.Context;\nimport android.support.v4.view.PagerAdapter;\nimport android.support.v4.view.ViewPager;\nimport android.util.AttributeSet;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshBase;\n\npublic class PullToRefreshViewPager extends PullToRefreshBase<ViewPager> {\n\n\tpublic PullToRefreshViewPager(Context context) {\n\t\tsuper(context);\n\t}\n\n\tpublic PullToRefreshViewPager(Context context, AttributeSet attrs) {\n\t\tsuper(context, attrs);\n\t}\n\n\t@Override\n\tpublic final Orientation getPullToRefreshScrollDirection() {\n\t\treturn Orientation.HORIZONTAL;\n\t}\n\n\t@Override\n\tprotected ViewPager createRefreshableView(Context context, AttributeSet attrs) {\n\t\tViewPager viewPager = new ViewPager(context, attrs);\n\t\tviewPager.setId(R.id.viewpager);\n\t\treturn viewPager;\n\t}\n\n\t@Override\n\tprotected boolean isReadyForPullStart() {\n\t\tViewPager refreshableView = getRefreshableView();\n\n\t\tPagerAdapter adapter = refreshableView.getAdapter();\n\t\tif (null != adapter) {\n\t\t\treturn refreshableView.getCurrentItem() == 0;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tprotected boolean isReadyForPullEnd() {\n\t\tViewPager refreshableView = getRefreshableView();\n\n\t\tPagerAdapter adapter = refreshableView.getAdapter();\n\t\tif (null != adapter) {\n\t\t\treturn refreshableView.getCurrentItem() == adapter.getCount() - 1;\n\t\t}\n\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "extras/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t\n\t<groupId>com.navercorp.pulltorefresh</groupId>\n\t<artifactId>extras</artifactId>\n\t<packaging>pom</packaging>\n\t<name>Android-PullToRefresh Extras</name>\n\t\n\t<parent>\n\t\t<groupId>com.navercorp.pulltorefresh</groupId>\n\t\t<artifactId>parent</artifactId>\n\t\t<version>3.3.0-SNAPSHOT</version>\n\t</parent>\n\t\n\t<modules>\n\t\t<module>PullToRefreshListFragment</module>\n\t\t<module>PullToRefreshViewPager</module>\n\t</modules>\n</project>\n"
  },
  {
    "path": "gradle.properties",
    "content": "PULLTOREFRESH_RELEASE_VERSION=3.2.3\nPULLTOREFRESH_RELEASE_GROUP=com.navercorp.pulltorefresh\n\nANDROID_COMPILE_SDK_VERSION=19\nANDROID_BUILD_TOOLS_VERSION=19.1.0\n"
  },
  {
    "path": "library/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.handmark.pulltorefresh.library\"\n    android:versionCode=\"2110\"\n    android:versionName=\"2.1.1\" >\n\n    <uses-sdk android:minSdkVersion=\"4\" />\n\n    <application />\n\n</manifest>"
  },
  {
    "path": "library/LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "library/build.gradle",
    "content": "apply plugin: 'android-library'\n\nbuildscript {\n    repositories {\n        mavenCentral()\n    }\n\n    dependencies {\n        classpath 'com.android.tools.build:gradle:0.11.+'\n    }\n}\n\napply plugin: 'maven'\napply plugin: 'signing'\n\nandroid {\n    compileSdkVersion Integer.parseInt(ANDROID_COMPILE_SDK_VERSION)\n    buildToolsVersion ANDROID_BUILD_TOOLS_VERSION\n\n    sourceSets {\n    \tmain {\n    \t\tmanifest.srcFile 'AndroidManifest.xml'\n    \t\tjava.srcDirs=['src/main/java']\n    \t\tres.srcDirs=['res']\n    \t}\n    }\n}\n"
  },
  {
    "path": "library/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<artifactId>library</artifactId>\n\t<packaging>apklib</packaging>\n\t<name>Android-PullToRefresh Library</name>\n\t<parent>\n\t\t<groupId>com.navercorp.pulltorefresh</groupId>\n\t\t<artifactId>parent</artifactId>\n\t\t<version>3.3.0-SNAPSHOT</version>\n\t</parent>\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<android.version>4.1.1.4</android.version>\n\t\t<android.platform>16</android.platform>\n\t\t<android-support.version>r7</android-support.version>\n\t\t<java.version>1.6</java.version>\n\t</properties>\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>com.google.android</groupId>\n\t\t\t<artifactId>android</artifactId>\n\t\t\t<version>${android.version}</version>\n\t\t</dependency>\n\t</dependencies>\n\t<build>\n\t\t<sourceDirectory>src/main/java</sourceDirectory>\n\t\t<testSourceDirectory>src/test/java</testSourceDirectory>\n\t\t<testOutputDirectory>target/test-classes</testOutputDirectory>\n\t\t<testResources>\n\t\t\t<testResource>\n\t\t\t\t<directory>src/test/resources</directory>\n\t\t\t</testResource>\n\t\t</testResources>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.jayway.maven.plugins.android.generation2</groupId>\n\t\t\t\t<artifactId>android-maven-plugin</artifactId>\n\t\t\t\t<version>3.7.0</version>\n\t\t\t</plugin>\n\t\t\t<!-- extracted from actionbarsherlock's pom -->\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.codehaus.mojo</groupId>\n\t\t\t\t<artifactId>build-helper-maven-plugin</artifactId>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>attach-artifact</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t<artifacts>\n\t\t\t\t\t\t\t\t<artifact>\n\t\t\t\t\t\t\t\t\t<type>aar</type>\n\t\t\t\t\t\t\t\t\t<file>${project.basedir}/build/libs/${project.artifactId}-${parent.version}.aar</file>\n\t\t\t\t\t\t\t\t</artifact>\n\t\t\t\t\t\t\t</artifacts>\n\t\t\t\t\t\t</configuration>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t<version>3.1</version>\n\t\t\t\t<configuration>\n\t\t\t\t\t<source>${java.version}</source>\n\t\t\t\t\t<target>${java.version}</target>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-source-plugin</artifactId>\n\t\t\t\t<version>2.2.1</version>\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>attach-sources</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>jar</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-javadoc-plugin</artifactId>\n\t\t\t\t<version>2.9</version>\n\t\t\t\t<configuration>\n\t\t\t\t     <!-- TODO: sourceFileExcludes doesn't work in 2.9 and 2.9.1 both. :(\n\t\t\t\t     \t\t\tI hope that this feature works well. -->\n\t\t\t\t    <sourceFileExcludes>\n\t\t\t\t        <sourceFileExclude>**/R.java</sourceFileExclude>\n\t\t\t\t    </sourceFileExcludes>\n\t\t\t\t</configuration>\n\t\t\t\t\n\t\t\t\t<executions>\n\t\t\t\t\t<execution>\n\t\t\t\t\t\t<id>attach-javadocs</id>\n\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t<goal>jar</goal>\n\t\t\t\t\t\t</goals>\n\t\t\t\t\t</execution>\n\t\t\t\t</executions>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "library/project.properties",
    "content": "# This file is automatically generated by Android Tools.\n# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n#\n# This file must be checked in Version Control Systems.\n#\n# To customize properties used by the Ant build system use,\n# \"ant.properties\", and override values to adapt the script to your\n# project structure.\n\n# Project target.\ntarget=android-16\nandroid.library=true\n"
  },
  {
    "path": "library/res/anim/slide_in_from_bottom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n     Copyright (C) 2009 The Android Open Source Project\n\n     Licensed under the Apache License, Version 2.0 (the \"License\");\n     you may not use this file except in compliance with the License.\n     You may obtain a copy of the License at\n\n          http://www.apache.org/licenses/LICENSE-2.0\n\n     Unless required by applicable law or agreed to in writing, software\n     distributed under the License is distributed on an \"AS IS\" BASIS,\n     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     See the License for the specific language governing permissions and\n     limitations under the License.\n-->\n\n<translate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:duration=\"@android:integer/config_longAnimTime\"\n    android:fromYDelta=\"100%p\"\n    android:toYDelta=\"0\" />\n"
  },
  {
    "path": "library/res/anim/slide_in_from_top.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n     Copyright (C) 2009 The Android Open Source Project\n\n     Licensed under the Apache License, Version 2.0 (the \"License\");\n     you may not use this file except in compliance with the License.\n     You may obtain a copy of the License at\n\n          http://www.apache.org/licenses/LICENSE-2.0\n\n     Unless required by applicable law or agreed to in writing, software\n     distributed under the License is distributed on an \"AS IS\" BASIS,\n     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     See the License for the specific language governing permissions and\n     limitations under the License.\n-->\n\n<translate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:duration=\"@android:integer/config_longAnimTime\"\n    android:fromYDelta=\"-100%p\"\n    android:toYDelta=\"0\" />\n"
  },
  {
    "path": "library/res/anim/slide_out_to_bottom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n     Copyright (C) 2009 The Android Open Source Project\n\n     Licensed under the Apache License, Version 2.0 (the \"License\");\n     you may not use this file except in compliance with the License.\n     You may obtain a copy of the License at\n\n          http://www.apache.org/licenses/LICENSE-2.0\n\n     Unless required by applicable law or agreed to in writing, software\n     distributed under the License is distributed on an \"AS IS\" BASIS,\n     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     See the License for the specific language governing permissions and\n     limitations under the License.\n-->\n\n<translate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:duration=\"@android:integer/config_longAnimTime\"\n    android:fromYDelta=\"0\"\n    android:toYDelta=\"100%p\" />\n"
  },
  {
    "path": "library/res/anim/slide_out_to_top.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n     Copyright (C) 2009 The Android Open Source Project\n\n     Licensed under the Apache License, Version 2.0 (the \"License\");\n     you may not use this file except in compliance with the License.\n     You may obtain a copy of the License at\n\n          http://www.apache.org/licenses/LICENSE-2.0\n\n     Unless required by applicable law or agreed to in writing, software\n     distributed under the License is distributed on an \"AS IS\" BASIS,\n     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     See the License for the specific language governing permissions and\n     limitations under the License.\n-->\n\n<translate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:duration=\"@android:integer/config_longAnimTime\"\n    android:fromYDelta=\"0\"\n    android:toYDelta=\"-100%p\" />\n"
  },
  {
    "path": "library/res/drawable/indicator_bg_bottom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\" >\n\n    <solid android:color=\"#40000000\" />\n\n    <!--\n    I know the android:radius is useless here but it's needed to fix an old bug:\n    http://code.google.com/p/android/issues/detail?id=939\n    -->\n    <corners\n        android:bottomLeftRadius=\"0dp\"\n        android:bottomRightRadius=\"0dp\"\n        android:radius=\"1dp\"\n        android:topLeftRadius=\"@dimen/indicator_corner_radius\"\n        android:topRightRadius=\"@dimen/indicator_corner_radius\" />\n\n</shape>"
  },
  {
    "path": "library/res/drawable/indicator_bg_top.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\" >\n\n    <solid android:color=\"#40000000\" />\n\n    <!--\n    I know the android:radius is useless here but it's needed to fix an old bug:\n    http://code.google.com/p/android/issues/detail?id=939\n    -->\n    <corners\n        android:bottomLeftRadius=\"@dimen/indicator_corner_radius\"\n        android:bottomRightRadius=\"@dimen/indicator_corner_radius\"\n        android:radius=\"1dp\"\n        android:topLeftRadius=\"0dp\"\n        android:topRightRadius=\"0dp\" />\n\n</shape>"
  },
  {
    "path": "library/res/drawable/progress_horizontal_holo_light.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Copyright (C) 2010 The Android Open Source Project\n\n     Licensed under the Apache License, Version 2.0 (the \"License\");\n     you may not use this file except in compliance with the License.\n     You may obtain a copy of the License at\n\n          http://www.apache.org/licenses/LICENSE-2.0\n\n     Unless required by applicable law or agreed to in writing, software\n     distributed under the License is distributed on an \"AS IS\" BASIS,\n     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     See the License for the specific language governing permissions and\n     limitations under the License.\n-->\n\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:id=\"@android:id/background\"\n          android:drawable=\"@drawable/progress_bg_holo_light\" />\n\n    <item android:id=\"@android:id/secondaryProgress\">\n        <scale android:scaleWidth=\"100%\"\n               android:drawable=\"@drawable/progress_secondary_holo_light\" />\n    </item>\n\n    <item android:id=\"@android:id/progress\">\n        <scale android:scaleWidth=\"100%\"\n               android:drawable=\"@drawable/progress_primary_holo_light\" />\n    </item>\n\n</layer-list>"
  },
  {
    "path": "library/res/drawable/progress_horizontal_holo_light_right.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Copyright (C) 2010 The Android Open Source Project\n\n     Licensed under the Apache License, Version 2.0 (the \"License\");\n     you may not use this file except in compliance with the License.\n     You may obtain a copy of the License at\n\n          http://www.apache.org/licenses/LICENSE-2.0\n\n     Unless required by applicable law or agreed to in writing, software\n     distributed under the License is distributed on an \"AS IS\" BASIS,\n     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     See the License for the specific language governing permissions and\n     limitations under the License.\n-->\n\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:id=\"@android:id/background\"\n          android:drawable=\"@drawable/progress_bg_holo_light\" />\n\n    <item android:id=\"@android:id/secondaryProgress\">\n        <scale android:scaleWidth=\"100%\"\n               android:drawable=\"@drawable/progress_secondary_holo_light\" />\n    </item>\n\n    <item android:id=\"@android:id/progress\">\n        <scale android:scaleWidth=\"100%\"\n               android:drawable=\"@drawable/progress_primary_holo_light\" />\n    </item>\n\n</layer-list>"
  },
  {
    "path": "library/res/drawable/progress_indeterminate_horizontal_holo.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n/*\n** Copyright 2011, The Android Open Source Project\n**\n** Licensed under the Apache License, Version 2.0 (the \"License\"); \n** you may not use this file except in compliance with the License. \n** You may obtain a copy of the License at \n**\n**     http://www.apache.org/licenses/LICENSE-2.0 \n**\n** Unless required by applicable law or agreed to in writing, software \n** distributed under the License is distributed on an \"AS IS\" BASIS, \n** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. \n** See the License for the specific language governing permissions and \n** limitations under the License.\n*/\n-->\n<animation-list\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:oneshot=\"false\">\n    <item android:drawable=\"@drawable/progressbar_indeterminate_holo1\" android:duration=\"50\" />\n    <item android:drawable=\"@drawable/progressbar_indeterminate_holo2\" android:duration=\"50\" />\n    <item android:drawable=\"@drawable/progressbar_indeterminate_holo3\" android:duration=\"50\" />\n    <item android:drawable=\"@drawable/progressbar_indeterminate_holo4\" android:duration=\"50\" />\n    <item android:drawable=\"@drawable/progressbar_indeterminate_holo5\" android:duration=\"50\" />\n    <item android:drawable=\"@drawable/progressbar_indeterminate_holo6\" android:duration=\"50\" />\n    <item android:drawable=\"@drawable/progressbar_indeterminate_holo7\" android:duration=\"50\" />\n    <item android:drawable=\"@drawable/progressbar_indeterminate_holo8\" android:duration=\"50\" />\n</animation-list>"
  },
  {
    "path": "library/res/layout/pull_to_refresh_header_google_style.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<merge xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <FrameLayout\n        android:id=\"@+id/fl_inner_for_google_style\"\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"wrap_content\" >\n\n        <RelativeLayout\n            android:layout_width=\"fill_parent\"\n            android:layout_height=\"fill_parent\" >\n\n            <TextView\n                android:id=\"@+id/pull_to_refresh_text\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_centerInParent=\"true\"\n                android:singleLine=\"true\"\n                android:textAppearance=\"?android:attr/textAppearance\"\n                android:textStyle=\"bold\" />\n\n            <TextView\n                android:id=\"@+id/pull_to_refresh_sub_text\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_centerInParent=\"true\"\n                android:singleLine=\"true\"\n                android:textAppearance=\"?android:attr/textAppearanceSmall\"\n                android:visibility=\"gone\" />\n        </RelativeLayout>\n    </FrameLayout>\n\n</merge>"
  },
  {
    "path": "library/res/layout/pull_to_refresh_header_horizontal.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<merge xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <FrameLayout\n        android:id=\"@+id/fl_inner\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"fill_parent\"\n        android:paddingBottom=\"@dimen/header_footer_top_bottom_padding\"\n        android:paddingLeft=\"@dimen/header_footer_left_right_padding\"\n        android:paddingRight=\"@dimen/header_footer_left_right_padding\"\n        android:paddingTop=\"@dimen/header_footer_top_bottom_padding\" >\n\n        <ImageView\n            android:id=\"@+id/pull_to_refresh_image\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:padding=\"@dimen/header_pull_to_refresh_image_padding\"\n            android:layout_gravity=\"center\" />\n\n        <ProgressBar\n            android:id=\"@+id/pull_to_refresh_progress\"\n            style=\"?android:attr/progressBarStyleSmall\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center\"\n            android:indeterminate=\"true\"\n            android:visibility=\"gone\" />\n    </FrameLayout>\n\n</merge>"
  },
  {
    "path": "library/res/layout/pull_to_refresh_header_vertical.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<merge xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <FrameLayout\n        android:id=\"@+id/fl_inner\"\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"wrap_content\"\n        android:paddingBottom=\"@dimen/header_footer_top_bottom_padding\"\n        android:paddingLeft=\"@dimen/header_footer_left_right_padding\"\n        android:paddingRight=\"@dimen/header_footer_left_right_padding\"\n        android:paddingTop=\"@dimen/header_footer_top_bottom_padding\" >\n\n        <FrameLayout\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"left|center_vertical\" >\n\n            <ImageView\n                android:id=\"@+id/pull_to_refresh_image\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:padding=\"@dimen/header_pull_to_refresh_image_padding\"\n                android:layout_gravity=\"center\" />\n\n            <ProgressBar\n                android:id=\"@+id/pull_to_refresh_progress\"\n                style=\"?android:attr/progressBarStyleSmall\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_gravity=\"center\"\n                android:indeterminate=\"true\"\n                android:visibility=\"gone\" />\n        </FrameLayout>\n\n        <LinearLayout\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center\"\n            android:gravity=\"center_horizontal\"\n            android:orientation=\"vertical\" >\n\n            <TextView\n                android:id=\"@+id/pull_to_refresh_text\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:singleLine=\"true\"\n                android:textAppearance=\"?android:attr/textAppearance\"\n                android:textStyle=\"bold\" />\n\n            <TextView\n                android:id=\"@+id/pull_to_refresh_sub_text\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:singleLine=\"true\"\n                android:textAppearance=\"?android:attr/textAppearanceSmall\"\n                android:visibility=\"gone\" />\n        </LinearLayout>\n    </FrameLayout>\n\n</merge>"
  },
  {
    "path": "library/res/layout/pull_to_refresh_progress_google_style.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"wrap_content\">\n    <com.handmark.pulltorefresh.library.internal.PullingProgressLayout \n        android:id=\"@+id/pulling_progress\"\n        android:layout_width=\"fill_parent\"\n    \tandroid:layout_height=\"wrap_content\"\n    \tandroid:visibility=\"visible\"\n        >\n    </com.handmark.pulltorefresh.library.internal.PullingProgressLayout>  \n    <ProgressBar \n    \tandroid:layout_width=\"fill_parent\"\n    \tandroid:layout_height=\"wrap_content\"\n\t\tstyle=\"?android:attr/progressBarStyleHorizontal\"\n        android:id=\"@+id/refreshing_progress\"\n        android:indeterminate=\"true\"\n        android:max=\"100\"\n        android:progress=\"0\"\n        android:indeterminateDrawable=\"@drawable/progress_indeterminate_horizontal_holo\"\n        android:visibility=\"gone\" \n        />\n</FrameLayout>\n"
  },
  {
    "path": "library/res/layout/pulling_progress_layout.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"horizontal\" >\n    \n\t<com.handmark.pulltorefresh.library.internal.FlippedProgressBar\n            android:id=\"@+id/pulling_left_progressbar\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_weight=\"5\"\n            android:layout_gravity=\"left\"\n            style=\"?android:attr/progressBarStyleHorizontal\"\n            android:indeterminate=\"false\">\n\t</com.handmark.pulltorefresh.library.internal.FlippedProgressBar>\n\t<ProgressBar\n            android:id=\"@+id/pulling_right_progressbar\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"right\"\n            android:layout_weight=\"5\"\n            style=\"?android:attr/progressBarStyleHorizontal\"\n            android:indeterminate=\"false\">\n\t</ProgressBar>\n</LinearLayout>\n"
  },
  {
    "path": "library/res/values/attrs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <declare-styleable name=\"PullToRefresh\">\n\n        <!-- A drawable to use as the background of the Refreshable View -->\n        <attr name=\"ptrRefreshableViewBackground\" format=\"reference|color\" />\n\n        <!-- A drawable to use as the background of the Header and Footer Loading Views -->\n        <attr name=\"ptrHeaderBackground\" format=\"reference|color\" />\n\n        <!-- Text Color of the Header and Footer Loading Views -->\n        <attr name=\"ptrHeaderTextColor\" format=\"reference|color\" />\n\n        <!-- Text Color of the Header and Footer Loading Views Sub Header -->\n        <attr name=\"ptrHeaderSubTextColor\" format=\"reference|color\" />\n\n        <!-- Mode of Pull-to-Refresh that should be used -->\n        <attr name=\"ptrMode\">\n            <flag name=\"disabled\" value=\"0x0\" />\n            <flag name=\"pullFromStart\" value=\"0x1\" />\n            <flag name=\"pullFromEnd\" value=\"0x2\" />\n            <flag name=\"both\" value=\"0x3\" />\n            <flag name=\"manualOnly\" value=\"0x4\" />\n            <flag name=\"google\" value=\"0x5\" />\n\n            <!-- These last two are depreacted -->\n            <flag name=\"pullDownFromTop\" value=\"0x1\" />\n            <flag name=\"pullUpFromBottom\" value=\"0x2\" />\n        </attr>\n\n        <!-- Whether the Indicator overlay(s) should be used -->\n        <attr name=\"ptrShowIndicator\" format=\"reference|boolean\" />\n\n        <!-- Drawable to use as Loading Indicator. Changes both Header and Footer. -->\n        <attr name=\"ptrDrawable\" format=\"reference\" />\n\n        <!-- Drawable to use as Loading Indicator in the Header View. Overrides value set in ptrDrawable. -->\n        <attr name=\"ptrDrawableStart\" format=\"reference\" />\n\n        <!-- Drawable to use as Loading Indicator in the Footer View. Overrides value set in ptrDrawable. -->\n        <attr name=\"ptrDrawableEnd\" format=\"reference\" />\n\n        <!-- Whether Android's built-in Over Scroll should be utilised for Pull-to-Refresh. -->\n        <attr name=\"ptrOverScroll\" format=\"reference|boolean\" />\n\n        <!-- Base text color, typeface, size, and style for Header and Footer Loading Views -->\n        <attr name=\"ptrHeaderTextAppearance\" format=\"reference\" />\n\n        <!-- Base text color, typeface, size, and style for Header and Footer Loading Views Sub Header -->\n        <attr name=\"ptrSubHeaderTextAppearance\" format=\"reference\" />\n\n        <!-- Style of Animation should be used displayed when pulling. -->\n        <attr name=\"ptrAnimationStyle\" format=\"string\">\n        </attr>\n        <!--  -->\n        <attr name=\"ptrIndicatorStyle\" format=\"string\">\n        </attr>\n \n        <!-- Styles of Animation for google style pull to refresh -->\n        <attr name=\"ptrGoogleViewStyle\" format=\"string\">\n        </attr>\n\t\t<!-- Styles of Progress Bar Layout for google style pull to refresh -->\n        <attr name=\"ptrGoogleProgressStyle\" format=\"string\">\n        </attr>\n\n        <!-- Label attributes of Loading layout -->\n        <attr name=\"ptrPullLabel\" format=\"string\" />\n        <attr name=\"ptrRefreshLabel\" format=\"string\" />\n        <attr name=\"ptrReleaseLabel\" format=\"string\" />\n        \n        <attr name=\"ptrFriction\" format=\"float\" value=\"2.0\" />\n        <attr name=\"ptrSmoothScrollDuration\" format=\"integer\" value=\"200\" />\n        <attr name=\"ptrSmoothScrollLongDuration\" format=\"integer\" value=\"325\" />\n        \n        <!-- Whether the user can scroll while the View is Refreshing -->\n        <attr name=\"ptrScrollingWhileRefreshingEnabled\" format=\"reference|boolean\" />\n\n        <!--\n        \tWhether PullToRefreshListView has it's extras enabled. This allows the user to be \n        \table to scroll while refreshing, and behaves better. It acheives this by adding\n        \tHeader and/or Footer Views to the ListView.\n        -->\n        <attr name=\"ptrListViewExtrasEnabled\" format=\"reference|boolean\" />\n\n        <!--\n        \tWhether the Drawable should be continually rotated as you pull. This only\n        \ttakes effect when using the 'Rotate' Animation Style.\n        -->\n        <attr name=\"ptrRotateDrawableWhilePulling\" format=\"reference|boolean\" />\n\n        <!-- Whether Google style view layout's size is set to ActionBar's size \n        \t (Don't set to false as possible, it's hard to control height if this flag is false) -->\n        <attr name=\"ptrSetGoogleViewLayoutSizeToActionbarHeight\" format=\"reference|boolean\" />\n        <!-- Animation Options only for google Style mode  -->\n\t\t<!--  Whether Google style view layout's fade-in animation is shown when pulling -->\n        <attr name=\"ptrShowGoogleStyleViewAnimationEnabled\" format=\"reference|boolean\" />\n       <!-- Whether Refreshable view is hidden when refreshing -->\n        <attr name=\"ptrHideRefeshableViewWhileRefreshingEnabled\" format=\"reference|boolean\" />\n        <!-- Whether Rotating progress bar is shown when refreshing -->\n        <attr name=\"ptrViewRefeshableViewProgressBarOnCenterWhileRefreshingEnabled\" format=\"reference|boolean\" />\n        <!-- Duration of Google style view layout's fade-in/out animation -->\n        <attr name=\"ptrShowGoogleStyleViewAnimationDuration\" format=\"integer\" value=\"100\" />\n        <!-- Duration of  Refreshable view's fade-in/out animation -->\n        <attr name=\"ptrHideRefeshableViewWhileRefreshingDuration\" format=\"integer\" value=\"500\" />\n        <!-- Duration of rotating progress bar's fade-in/out animation -->\n        <attr name=\"ptrViewRefeshableViewProgressBarOnCenterWhileRefreshingDuration\" format=\"integer\" value=\"200\" />\n\t\t\n\t\t<!-- These attrs are enabled to set width or height of Rotating progress bar on center -->\n        <attr name=\"ptrRefeshableViewProgressBarOnCenterWidth\" format=\"integer\" value=\"200\" />\n        <attr name=\"ptrRefeshableViewProgressBarOnCenterHeight\" format=\"integer\" value=\"200\" />\n\n        <!-- BELOW HERE ARE DEPRECEATED. DO NOT USE. -->\n        <attr name=\"ptrAdapterViewBackground\" format=\"reference|color\" />\n        <attr name=\"ptrDrawableTop\" format=\"reference\" />\n        <attr name=\"ptrDrawableBottom\" format=\"reference\" />\n     \n    </declare-styleable>\n</resources>\n"
  },
  {
    "path": "library/res/values/dimens.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <dimen name=\"indicator_right_padding\">10dp</dimen>\n    <dimen name=\"indicator_corner_radius\">12dp</dimen>\n    <dimen name=\"indicator_internal_padding\">4dp</dimen>\n    <dimen name=\"header_footer_left_right_padding\">24dp</dimen>\n    <dimen name=\"header_footer_top_bottom_padding\">12dp</dimen>\n    <dimen name=\"header_pull_to_refresh_image_padding\">10px</dimen>\n</resources>"
  },
  {
    "path": "library/res/values/ids.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <item type=\"id\" name=\"gridview\" />\n    <item type=\"id\" name=\"webview\" />\n    <item type=\"id\" name=\"scrollview\" />\n\n</resources>"
  },
  {
    "path": "library/res/values/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <string name=\"pull_to_refresh_pull_label\">Pull to refresh…</string>\n    <string name=\"pull_to_refresh_release_label\">Release to refresh…</string>\n    <string name=\"pull_to_refresh_refreshing_label\">Loading…</string>\n\n    <!-- Just use standard Pull Down String when pulling up. These can be set for languages which require it -->\n    <string name=\"pull_to_refresh_from_bottom_pull_label\">@string/pull_to_refresh_pull_label</string>\n    <string name=\"pull_to_refresh_from_bottom_release_label\">@string/pull_to_refresh_release_label</string>\n    <string name=\"pull_to_refresh_from_bottom_refreshing_label\">@string/pull_to_refresh_refreshing_label</string>\n\n</resources>"
  },
  {
    "path": "library/res/values-ar/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">اسحب للتحديث…</string>\r\n  <string name=\"pull_to_refresh_release_label\">اترك للتحديث…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">تحميل…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/values-cs/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">Tažením aktualizujete…</string>\r\n  <string name=\"pull_to_refresh_release_label\">Uvolněním aktualizujete…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">Načítání…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/values-de/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">Ziehen zum Aktualisieren…</string>\r\n  <string name=\"pull_to_refresh_release_label\">Loslassen zum Aktualisieren…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">Laden…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/values-es/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">Tirar para actualizar…</string>\r\n  <string name=\"pull_to_refresh_release_label\">Soltar para actualizar…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">Cargando…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/values-fi/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <string name=\"pull_to_refresh_pull_label\">Päivitä vetämällä alas…</string>\n    <string name=\"pull_to_refresh_release_label\">Päivitä vapauttamalla…</string>\n    <string name=\"pull_to_refresh_refreshing_label\">Päivitetään…</string>\n\n    <!-- Just use standard Pull Down String when pulling up. These can be set for languages which require it -->\n    <string name=\"pull_to_refresh_from_bottom_pull_label\">Päivitä vetämällä ylös…</string>\n    <string name=\"pull_to_refresh_from_bottom_release_label\">@string/pull_to_refresh_release_label</string>\n    <string name=\"pull_to_refresh_from_bottom_refreshing_label\">@string/pull_to_refresh_refreshing_label</string>\n\n</resources>"
  },
  {
    "path": "library/res/values-fr/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">Tirez pour rafraîchir…</string>\r\n  <string name=\"pull_to_refresh_release_label\">Relâcher pour rafraîchir…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">Chargement…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/values-he/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">משוך לרענון…</string>\r\n  <string name=\"pull_to_refresh_release_label\">שחרר לרענון…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">טוען…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/values-it/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">Tira per aggiornare…</string>\r\n  <string name=\"pull_to_refresh_release_label\">Rilascia per aggionare…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">Caricamento…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/values-iw/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">משוך לרענון…</string>\r\n  <string name=\"pull_to_refresh_release_label\">שחרר לרענון…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">טוען…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/values-ja/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">画面を引っ張って…</string>\r\n  <string name=\"pull_to_refresh_release_label\">指を離して更新…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">読み込み中…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/values-ko/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">당겨서 새로 고침…</string>\r\n  <string name=\"pull_to_refresh_release_label\">놓아서 새로 고침…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">로드 중…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/values-nl/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">Sleep om te vernieuwen…</string>\r\n  <string name=\"pull_to_refresh_release_label\">Loslaten om te vernieuwen…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">Laden…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/values-pl/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">Pociągnij, aby odświeżyć…</string>\r\n  <string name=\"pull_to_refresh_release_label\">Puść, aby odświeżyć…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">Wczytywanie…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/values-pt/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">Puxe para atualizar…</string>\r\n  <string name=\"pull_to_refresh_release_label\">Liberação para atualizar…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">A carregar…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/values-pt-rBR/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">Puxe para atualizar…</string>\r\n  <string name=\"pull_to_refresh_release_label\">Libere para atualizar…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">Carregando…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/values-ro/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">Trage pentru a reîmprospăta…</string>\r\n  <string name=\"pull_to_refresh_release_label\">Eliberează pentru a reîmprospăta…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">Încărcare…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/values-ru/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">Потяните для обновления…</string>\r\n  <string name=\"pull_to_refresh_release_label\">Отпустите для обновления…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">Загрузка…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/values-zh/pull_refresh_strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<resources>\r\n  <string name=\"pull_to_refresh_pull_label\">下拉刷新…</string>\r\n  <string name=\"pull_to_refresh_release_label\">放开以刷新…</string>\r\n  <string name=\"pull_to_refresh_refreshing_label\">正在载入…</string>\r\n</resources>\r\n"
  },
  {
    "path": "library/res/xml/pulltorefresh.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<PullToRefresh>\n    <LoadingLayouts>\n       <layout name=\"rotate\">com.handmark.pulltorefresh.library.internal.RotateLoadingLayout</layout>\n       <layout name=\"flip\">com.handmark.pulltorefresh.library.internal.FlipLoadingLayout</layout>\n    </LoadingLayouts>\n    <IndicatorLayouts>\n       <layout name=\"default\">com.handmark.pulltorefresh.library.internal.DefaultIndicatorLayout</layout>\n    </IndicatorLayouts>\n    <GoogleStyleViewLayouts>\n       <layout name=\"default\">com.handmark.pulltorefresh.library.internal.DefaultGoogleStyleViewLayout</layout> \n    </GoogleStyleViewLayouts>\n    <GoogleStyleProgressLayouts>\n       <layout name=\"default\">com.handmark.pulltorefresh.library.internal.DefaultGoogleStyleProgressLayout</layout> \n    </GoogleStyleProgressLayouts>    \n</PullToRefresh>"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/configuration/xml/ExtendedXmlConfigParserFactory.java",
    "content": "/*******************************************************************************\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.configuration.xml;\n\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.io.InputStream;\n\nimport org.xmlpull.v1.XmlPullParser;\nimport org.xmlpull.v1.XmlPullParserException;\nimport org.xmlpull.v1.XmlPullParserFactory;\n\nimport android.content.Context;\nimport android.content.res.AssetManager;\nimport android.util.Log;\n/**\n * Parser of assets/pulltorefresh.xml creation factory \n * @author Wonjun Kim\n */\nclass ExtendedConfigXmlParserFactory {\n\t\n\tprivate static final String LOG_TAG = ExtendedConfigXmlParserFactory.class.getName();\n\t/**\n\t * pulltorefresh.xml path in assets folder\n\t */\n\tprivate static final String XML_PATH_IN_ASSETS = \"pulltorefresh.xml\";\n\t/**\n\t * pulltorefresh.xml encoding type\n\t */\n\tprivate static final String DEFAULT_ENCODING_TYPE = \"utf-8\";\n\t/**\n\t * Create a parser of assets/pulltorefresh.xml \n\t * @param context\n\t * @return {@code parser} if creating parser has done, or {@code null} if an error occured during creation\n\t */\n\tpublic static XmlPullParser createParser(Context context) {\n\t\tAssetManager am = context.getAssets();\n\t\tXmlPullParser parser = null;\n\t\ttry {\n\t\t\tInputStream is = am.open(XML_PATH_IN_ASSETS);\n\t\t\tparser = XmlPullParserFactory.newInstance().newPullParser();\n\t\t\tparser.setInput(is, DEFAULT_ENCODING_TYPE);\n\t\t\t\n\t\t} catch (FileNotFoundException e) {\n\t\t\tLog.d(LOG_TAG, \"The configuration file 'assets/\" + XML_PATH_IN_ASSETS + \"' is missing. But the file is just an option. It is necessary only if you want to customize something in Pull To Refresh.\");\n\t\t\t// explicitly assign null\n\t\t\tparser = null;\n\t\t} catch (XmlPullParserException e) {\n\t\t\tLog.w(LOG_TAG, \"The error occurs below when generating parser.\", e);\n\t\t\t// explicitly assign null\n\t\t\tparser = null;\n\t\t} catch (IOException e) {\n\t\t\tLog.w(LOG_TAG, \"Loading \"+XML_PATH_IN_ASSETS+\" file has failed.\", e);\n\t\t\t// explicitly assign null\n\t\t\tparser = null;\n\t\t}\n\t\t\n\t\t// NOTE: this code makes a fatal error. so omit the code.\n\t\t// am.close();\n\t\t\n\t\treturn parser;\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/configuration/xml/PullToRefreshConfigXmlParser.java",
    "content": "/*******************************************************************************\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.configuration.xml;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport org.xmlpull.v1.XmlPullParser;\nimport org.xmlpull.v1.XmlPullParserException;\n\nimport com.handmark.pulltorefresh.library.internal.Assert;\n/**\n * {@code PullToRefreshConfigXmlParser} does parsing pulltorefresh.xml as {@code XmlPullNode}s\n * @author Wonjun Kim\n */\nfinal class PullToRefreshConfigXmlParser extends XmlPullNodeParser<PullToRefreshNode> {\n\t/**\n\t * Repetition limit is only one\n\t */ \n\tprivate static final int ONLY_ONE_REPEAT = 1;\n\t/**\n\t * Parsed data\n\t */\n\tprivate PullToRefreshResult result;\n\t/**\n\t * @param parser Must be not null \n\t */\n\tpublic PullToRefreshConfigXmlParser(XmlPullParserWrapper parser) {\n\t\tsuper(parser);\n\t}\n\t/**\n\t * Generate a node tree matched by pulltorefresh.xml\n\t * @return root node of a tree\n\t */\n\tprivate XmlPullNode init() {\n\t\t// prepare a result instance\n\t\tresult = new PullToRefreshResult();\n\t\t// make nodes \n\t\tXmlPullNode root = new XmlPullNode(\"PullToRefresh\");\n\t\tXmlPullNode loadingLayouts = new XmlPullNode(\"LoadingLayouts\");\n\t\tXmlPullNode indicatorLayouts = new XmlPullNode(\"IndicatorLayouts\");\n\t\tXmlPullNode googleStyleViewLayouts = new XmlPullNode(\"GoogleStyleViewLayouts\");\n\t\tXmlPullNode googleStyleProgressLayouts = new XmlPullNode(\"GoogleStyleProgressLayouts\");\n\t\tXmlPullNode loadingLayout = new XmlPullNode(\"layout\",new LayoutNodeCallback(result.loadingLayoutClazzNameMap));\n\t\tXmlPullNode indicatorLayout = new XmlPullNode(\"layout\",new LayoutNodeCallback(result.indicatorLayoutClazzNameMap));\n\t\tXmlPullNode googleStyleViewLayout = new XmlPullNode(\"layout\",new LayoutNodeCallback(result.googleStyleViewLayoutClazzNameMap));\n\t\tXmlPullNode googleStyleProgressLayout = new XmlPullNode(\"layout\",new LayoutNodeCallback(result.googleStyleProgressLayoutClazzNameMap));\n\t\t// make a tree structure\n\t\troot.addChildNode(loadingLayouts, ONLY_ONE_REPEAT);\n\t\troot.addChildNode(indicatorLayouts, ONLY_ONE_REPEAT);\n\t\troot.addChildNode(googleStyleViewLayouts, ONLY_ONE_REPEAT);\n\t\troot.addChildNode(googleStyleProgressLayouts, ONLY_ONE_REPEAT);\n\t\tloadingLayouts.addChildNode(loadingLayout);\n\t\tindicatorLayouts.addChildNode(indicatorLayout);\n\t\tgoogleStyleViewLayouts.addChildNode(googleStyleViewLayout);\n\t\tgoogleStyleProgressLayouts.addChildNode(googleStyleProgressLayout);\n\t\t// return root node\n\t\treturn root;\n\t}\n\t/**\n\t * @return root node of a tree\n\t */\n\t@Override\n\tprotected XmlPullNode generateRootNode() {\n\t\treturn init();\n\t}\n\t/**\n\t *  @return Parsed result data as {@code PullToRefreshNode} instance  \n\t */\n\t@Override\n\tprotected PullToRefreshNode getResult() {\n\t\treturn new PullToRefreshNode(result.loadingLayoutClazzNameMap, result.indicatorLayoutClazzNameMap, result.googleStyleViewLayoutClazzNameMap, result.googleStyleProgressLayoutClazzNameMap);\n\t}\n\t/**\n\t * Parsed Result to be sent to {@code PullToRefreshNode}\n\t * @author Wonjun Kim\n\t *\n\t */\n\tprivate static class PullToRefreshResult {\n\t\tpublic final Map<String, String> loadingLayoutClazzNameMap = new HashMap<String, String>();\n\t\tpublic final Map<String, String> indicatorLayoutClazzNameMap = new HashMap<String, String>();\n\t\tpublic final Map<String, String> googleStyleViewLayoutClazzNameMap = new HashMap<String, String>();\n\t\tpublic final Map<String, String> googleStyleProgressLayoutClazzNameMap = new HashMap<String, String>();\n\t}\n\t\t\n\t/**\n\t * Callback of the node 'PullToRefresh/IndicatorLayouts/layout' and 'PullToRefresh/LoadingLayouts/layout' \n\t * @author Wonjun Kim\n\t *\n\t */\n\tprivate static class LayoutNodeCallback implements XmlPullNode.XmlPullNodeCallback {\n\t\t/**\n\t\t * {@code Map} storing Layouts' information \n\t\t */\n\t\tprivate Map<String, String> layoutClazzNameMap;\n\t\t/**\n\t\t * @param layoutClazzNameMap Must not be null and be clean for which put new values\n\t\t */\n\t\tpublic LayoutNodeCallback(Map<String, String> layoutClazzNameMap) {\n\t\t\tAssert.notNull(layoutClazzNameMap, \"Class Map\");\n\t\t\tthis.layoutClazzNameMap = layoutClazzNameMap;\n\t\t}\n\t\t/**\n\t\t * Be called when parser has found 'layout' node at a time\n\t\t */\n\t\t@Override\n\t\tpublic void process(XmlPullParser parser) throws XmlPullParserException, IOException {\n\n\t\t\tint attributesCount = parser.getAttributeCount();\n\t\t\tString attributeName, attributeValue;\n\t\t\t// Iterate attributes!\t\t\t\n\t\t\tfor (int i = 0; i < attributesCount; ++i) {\n\t\t\t\tattributeName = parser.getAttributeName(i);\n\t\t\t\tattributeValue = parser.getAttributeValue(i);\n\t\t\t\t// The 'name' attribute is as a layout code of each layout's class  \n\t\t\t\tif ( \"name\".equals(attributeName)) {\n\t\t\t\t\t// Skip if attribute value is null or empty \n\t\t\t\t\tif ( attributeValue == null || attributeValue.length() == 0 ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// Get layout's class name\n\t\t\t\t\tString clazzName = parser.nextText();\n\t\t\t\t\t\n\t\t\t\t\t// Insert new class name \n\t\t\t\t\tlayoutClazzNameMap.put(attributeValue, clazzName);\n\n\t\t\t\t\t// Do 'break' because nextText() method has been called\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/configuration/xml/PullToRefreshNode.java",
    "content": "/*******************************************************************************\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.configuration.xml;\n\nimport java.util.Map;\n\nimport com.handmark.pulltorefresh.library.internal.Assert;\n/**\n * {@code PullToRefreshNode} has an information in contents of pulltorefresh.xml, <br /> such as loading layout and indicator layout class name\n * @author Wonjun Kim\n *\n */\nclass PullToRefreshNode {\n\t/**\n\t * Map Storing LoadingLayout class names<br />\n\t * Key : layout code (String) <br />\n\t * Value : class name (String)\n\t */\n\tprivate final Map<String, String> loadingLayoutClazzNameMap;\n\t/**\n\t * Map Storing IndicatorLayout class names<br />\n\t * Key : layout code (String) <br />\n\t * Value : Class name (String)\n\t */\n\tprivate final Map<String, String> indicatorLayoutClazzNameMap;\n\t/**\n\t * Map Storing GoogleStyleViewLayout class names<br />\n\t * Key : layout code (String) <br />\n\t * Value : Class name (String)\n\t */\t\n\tprivate Map<String, String> googleStyleViewLayoutClazzNameMap;\n\t/**\n\t * Map Storing GoogleStyleProgressLayout class names<br />\n\t * Key : layout code (String) <br />\n\t * Value : Class name (String)\n\t */\t\n\tprivate Map<String, String> googleStyleProgressLayoutClazzNameMap;\t\n\t/**\n\t * Constructor needs two class name {@code Map}s, which are LoadingLayout class name map and Indicator class name {@code map}.<br />\n\t * NOTE: Parameters must go in order. First Parameter : loading layout / Second Parameter : indicator layout  \n\t * @param loadingLayoutClazzNameMap LoadingLayout class names\n\t * @param indicatorLayoutClazzNameMap\n\t */\n\tpublic PullToRefreshNode(Map<String, String> loadingLayoutClazzNameMap,\n\t\t\tMap<String, String> indicatorLayoutClazzNameMap, Map<String, String> googleStyleViewLayoutClazzNameMap, Map<String, String> googleStyleProgressLayoutClazzNameMap) {\n\t\tAssert.notNull(loadingLayoutClazzNameMap, \"LoadingLayout Class Name Map\");\n\t\tAssert.notNull(indicatorLayoutClazzNameMap, \"Loading Layout Class Name Map\");\n\t\tthis.loadingLayoutClazzNameMap = loadingLayoutClazzNameMap;\n\t\tthis.indicatorLayoutClazzNameMap = indicatorLayoutClazzNameMap;\n\t\tthis.googleStyleViewLayoutClazzNameMap = googleStyleViewLayoutClazzNameMap;\n\t\tthis.googleStyleProgressLayoutClazzNameMap = googleStyleProgressLayoutClazzNameMap;\n\t}\n\t/**\n\t * @param layoutCode LoadingLayout layout code\n\t * @return LoadingLayout class name\n\t */\n\tpublic String getIndicatorLayoutClazzName(String layoutCode) {\n\t\treturn indicatorLayoutClazzNameMap.get(layoutCode);\n\t}\n\t/**\n\t * @param layoutCode LoadingLayout layout code\n\t * @return LoadingLayout class name\n\t */\n\tpublic String getLoadingLayoutClazzName(String layoutCode) {\n\t\treturn loadingLayoutClazzNameMap.get(layoutCode);\n\t}\n\t/**\n\t * @param layoutCode GoogleStyleViewLayout layout code\n\t * @return GoogleStyleViewLayout class name\n\t */\t\n\tpublic String getGoogleStyleViewLayoutClazzName(String layoutCode) {\n\t\treturn googleStyleViewLayoutClazzNameMap.get(layoutCode);\n\t}\n\t/**\n\t * @param layoutCode GoogleStyleProgressLayout layout code\n\t * @return GoogleStyleProgressLayout class name\n\t */\t\n\tpublic String getGoogleStyleProgressLayoutClazzName(String layoutCode) {\n\t\treturn googleStyleProgressLayoutClazzNameMap.get(layoutCode);\n\t}\t\t\n\t/**\n\t * Add an information from other {@code PullToRefreshNode} instance\n\t * @param extendedNode Other {@code PullToRefresNode} to be combined\n\t */\n\tpublic void extendProperties(PullToRefreshNode extendedNode) {\n\t\tAssert.notNull(extendedNode, \"Extended Node\");\n\t\tMap<String, String> indicatorMap = extendedNode.indicatorLayoutClazzNameMap;\n\t\tMap<String, String> loadingMap = extendedNode.loadingLayoutClazzNameMap;\n\t\tMap<String, String> googleStyleViewMap = extendedNode.googleStyleViewLayoutClazzNameMap;\n\t\tMap<String, String> googleStyleProgressMap = extendedNode.googleStyleProgressLayoutClazzNameMap;\n\t\t\n\t\tindicatorLayoutClazzNameMap.putAll(indicatorMap);\n\t\tloadingLayoutClazzNameMap.putAll(loadingMap);\n\t\tgoogleStyleViewLayoutClazzNameMap.putAll(googleStyleViewMap);\n\t\tgoogleStyleProgressLayoutClazzNameMap.putAll(googleStyleProgressMap);\n\t}\n\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/configuration/xml/PullToRefreshXmlConfiguration.java",
    "content": "/*******************************************************************************\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.configuration.xml;\n\nimport java.io.IOException;\n\nimport org.xmlpull.v1.XmlPullParser;\nimport org.xmlpull.v1.XmlPullParserException;\n\nimport com.handmark.pulltorefresh.library.R;\nimport com.handmark.pulltorefresh.library.internal.Assert;\nimport com.handmark.pulltorefresh.library.internal.Utils;\n\nimport android.content.Context;\nimport android.content.res.Resources;\nimport android.util.Log;\n\n/**\n * {@code PullToRefreshXmlConfiguration} is an information set of PullToRefresh. It contains a list of indicator layouts and of loading layouts. An information set of PullToRefresh is converted from pulltorefresh.xml.<br />\n * This Class is Singleton, and you <b>MUST</b> call {@link #init(Context)} before using this class.  \n * @author Wonjun Kim\n */\npublic class PullToRefreshXmlConfiguration {\n\t\n\tprivate static final String LOG_TAG = PullToRefreshXmlConfiguration.class.getName();\n\t\n\t/**\n\t * Singleton instance\n\t * @author Wonjun Kim\n\t */\n\tprivate static class InstanceHolder {\n\t\tprivate final static PullToRefreshXmlConfiguration instance = new PullToRefreshXmlConfiguration();\n\t\t\n\t\tprivate static PullToRefreshXmlConfiguration getInstance() {\n\t\t\treturn instance;\n\t\t}\n\t} \n\t/**\n\t * Parsed information from pulltorefresh.xml \n\t */\n\tprivate PullToRefreshNode node = null; \n\t/**\n\t * Default pulltorefresh path id is got from R class.\n\t */\n\tprivate static final int XML_PATH_ID = R.xml.pulltorefresh;\n\t/**\n\t * flag whether it has called {@link #init(Context)} \n\t */\n\tprivate boolean initialized = false;\n\t/**\n\t * Constructor <br />\n\t * nothing to do\n\t */\n\tprivate PullToRefreshXmlConfiguration() {}\n\t/**\n\t * Get singleton instance\n\t * @return {@code PullToRefreshXmlConfiguration} instance\n\t */\n\tpublic static PullToRefreshXmlConfiguration getInstance() {\n\t\treturn InstanceHolder.getInstance();\n\t}\n\t/**\n\t * Initialize the instance before using. <br />\n\t * Load 'res/xml/pulltorefresh.xml' in PullToRefresh library package and 'assets/pulltofresh.xml' in Android Project if it exists. <br />\n\t * Combine information of 'res/xml/pulltorefresh.xml' and 'assets/pulltofresh.xml', and then save the information into the instance's fields.<br />\n\t * <br />\n\t * NOTE: This method <b>MUST</b> be called before using! \n\t * @param context Context instance and not null\n\t */\n\tpublic void init(Context context) {\n\t\t// If an initialization was happened already, skip.\n\t\tif ( initialized == true ) {\n\t\t\treturn;\n\t\t}\n\t\tAssert.notNull(context, \"Context\");\n\t\t// get resources\n\t\tResources resources = context.getResources();\n\t\t// read the file\n\t\tXmlPullParser parser = resources.getXml(XML_PATH_ID);\n\t\t// parser the xml\n\t\tXmlPullParserWrapper wrapper = new XmlPullParserWrapper(parser);\n\t\t\n\t\ttry {\n\t\t\tnode = new PullToRefreshConfigXmlParser(wrapper).parse();\n\n\t\t\t// load extended xml \n\t\t\tXmlPullParser extendedXmlParser = ExtendedConfigXmlParserFactory.createParser(context);\n\t\t\tif ( extendedXmlParser != null) {\n\t\t\t\tXmlPullParserWrapper extendedXmlWrapper = new XmlPullParserWrapper(extendedXmlParser);\n\t\t\t\t// NOTE : if some exception is thrown from PullToRefreshConfigXmlParser, Loading extended xml will be skipped.\n\t\t\t\tPullToRefreshNode extendedNode = new PullToRefreshConfigXmlParser(extendedXmlWrapper).parse();\n\t\t\t\tnode.extendProperties(extendedNode);\n\t\t\t}\n\t\t} catch (XmlPullParserException e) {\n\t\t\tLog.d(LOG_TAG, \"It has failed to parse the xmlpullparser xml.\", e);\n\t\t} catch (IOException e) {\n\t\t\tLog.d(LOG_TAG, \"It has failed to parse the xmlpullparser xml.\\n \", e);\n\t\t}\n\t\t\n\t\t// Intialization can be done whether reading XML has failed or not! \n\t\tinitialized = true;\n\t}\n\t/**\n\t * @param layoutCode Layout name\n\t * @return Layout Class name ( ex: com.handmark.pulltorefresh.library.internal.FlipLoadingLayout )\n\t */\n\tpublic String getLoadingLayoutClazzName(String layoutCode) {\n\t\tassertInitialized();\n\t\tif ( isNodeNull() ) {\n\t\t\treturn null;\n\t\t}\n\t\treturn node.getLoadingLayoutClazzName(layoutCode);\n\t}\n\t/**\n\t * @param layoutCode Layout name\n\t * @return Layout Class name ( ex: com.handmark.pulltorefresh.library.internal.DefaultLoadingLayout )\n\t */\n\tpublic String getIndicatorLayoutClazzName(String layoutCode) {\n\t\tassertInitialized();\n\t\tif ( isNodeNull() ) {\n\t\t\treturn null;\n\t\t}\n\t\treturn node.getIndicatorLayoutClazzName(layoutCode);\n\t}\n\t/**\n\t * @param layoutCode Layout name\n\t * @return Layout Class name ( ex: com.handmark.pulltorefresh.library.internal.DefaultGoogleStyleViewLayout )\n\t */\n\tpublic String getGoogleStyleViewLayoutClazzName(String layoutCode) {\n\t\tassertInitialized();\n\t\tif ( isNodeNull() ) {\n\t\t\treturn null;\n\t\t}\n\t\treturn node.getGoogleStyleViewLayoutClazzName(layoutCode);\n\t}\n\t/**\n\t * @param layoutCode Layout name\n\t * @return Layout Class name ( ex: com.handmark.pulltorefresh.library.internal.DefaultGoogleStyleProgressLayout )\n\t */\n\tpublic String getGoogleStyleProgressLayoutClazzName(String layoutCode) {\n\t\tassertInitialized();\n\t\tif ( isNodeNull() ) {\n\t\t\treturn null;\n\t\t}\n\t\treturn node.getGoogleStyleProgressLayoutClazzName(layoutCode);\n\t}\t\n\t/**\n\t * @return true if {@code node} is null\n\t */\n\tprivate boolean isNodeNull() {\n\t\treturn node == null;\n\t}\n\t/**\n\t * @return true if {@link #init(Context)} method has not been called  \n\t */\n\tprivate boolean notInitialized() {\n\t\treturn !initialized;\n\t}\n\t/**\n\t * @return throw an exception if {@link #init(Context)} method has not been called  \n\t */\n\tprivate void assertInitialized() {\n\t\tif ( notInitialized() ) {\n\t\t\tthrow new IllegalStateException(PullToRefreshXmlConfiguration.class.getName()+\" has not initialized. Call init() method first.\");\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/configuration/xml/XmlPullNode.java",
    "content": "/*******************************************************************************\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.configuration.xml;\n\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.TreeMap;\n\nimport org.xmlpull.v1.XmlPullParser;\nimport org.xmlpull.v1.XmlPullParserException;\n\nimport com.handmark.pulltorefresh.library.internal.Assert;\n/**\n * {@code XmlPullNode} is used for parsing xml as a node tree.<br />\n * If you implement {@link XmlPullNode#XmlPullNodeCallback} and pass that on to this class,<br /> {@link XmlPullNodeParser} calls {@link XmlPullNode#XmlPullNodeCallback#process(XmlPullParser)} when it has found this current node during parse.<br />\n * When it has found a child node of current node' children, and if the child node has been added in current node as child XmlPullNode, {@link XmlPullNodeParser} continues parsing at the child.  \n * @author Wonjun Kim\n *\n */\nclass XmlPullNode {\n\t/**\n\t * Unlimited repeat value <br />\n\t * If you add a child (by calling {@link #addChildNode(XmlPullNode, int)} with setting repeat limit and the limit is {@code INFINITE}, the limit becomes meaningless.<br /> \n\t */\n\tpublic static final int INFINITE = -1;\n\t/**\n\t * Map which store children<br /> \n\t * child's node name can have upper case or lower. all is the same whether that is upper or lower. \n\t */\n\tprivate final Map<String, XmlPullNodeContainer> children = new TreeMap<String, XmlPullNodeContainer>(\n\t\t\tString.CASE_INSENSITIVE_ORDER);\n\t/**\n\t * Current node's name\n\t */\n\tprivate final String tagName;\n\t/**\n\t * Callback <br /> {@code XmlPullNodeCallback.process(XmlPullParser)} method is called when this node has found in xml.\n\t */\n\tprivate final XmlPullNodeCallback callback;\n\t/**\n\t * Default callback. This doesn't any kind of action.\n\t */\n\tprivate static final XmlPullNodeCallback nullCallback = new XmlPullNodeCallback() {\n\t\t@Override\n\t\tpublic void process(XmlPullParser parser) {\n\t\t\t// do nothing\n\t\t}\n\t};\n\t/**\n\t * Default Constructor (only set a node name)\n\t * @param tagName Node name. this must not be null\n\t */\n\tpublic XmlPullNode(String tagName) {\n\t\tthis(tagName, null);\n\t}\n\t/**\n\t * Constructor with {@code tagName} and {@code callback}\n\t * @param tagName Node name. this must not be null\n\t * @param callback  \n\t */\n\tpublic XmlPullNode(String tagName, XmlPullNodeCallback callback) {\n\t\tAssert.notNull(tagName, \"Tag Name\");\n\t\tthis.tagName = tagName;\n\t\tthis.callback = (callback == null) ? nullCallback : callback;\n\t}\n\t/**\n\t * @return Current node name\n\t */\n\tpublic String getName() {\n\t\treturn tagName;\n\t}\n\t/**\n\t * Add a child node into this node without repeat limit<br />\n\t * NOTE: When it has found a child node of current node' children, and if the child node has been added in current node as child XmlPullNode, {@link XmlPullNodeParser} continues parsing at the child.  \n\t * @param node Child node to add\n\t * @return true if it is successful to add\n\t */\n\tpublic boolean addChildNode(XmlPullNode node) {\n\t\treturn addChildNode(node, INFINITE);\n\t}\n\t/**\n\t * Add a child node into this node with repeat limit<br />\n\t * NOTE: When it has found a child node of current node' children, and if the child node has been added in current node as child XmlPullNode, {@link XmlPullNodeParser} continues parsing at the child.  \n\t * @param node Child node to add\n\t * @param repeatLimit Repeat limit. if a child repeats over the limit, an error occurs during parse. \n\t * @return true if it is successful to add\n\t */\n\tpublic boolean addChildNode(XmlPullNode node, int repeatLimit) {\n\t\tXmlPullNodeContainer pullNodeContainer = children.get(node.getName());\n\t\tif (pullNodeContainer != null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tchildren.put(node.getName(),\n\t\t\t\tnew XmlPullNodeContainer(node, repeatLimit));\n\t\treturn true;\n\t}\t\n\t/**\n\t * Get a child of this node's chidren\n\t * @param tagName Child node name to find\n\t * @return Child node if the child has been found or null\n\t * @throws XmlPullParserException\n\t */\n\tpublic XmlPullNode getChild(String tagName) throws XmlPullParserException {\n\t\tXmlPullNodeContainer pullNodeContainer = children.get(tagName);\n\t\tif (pullNodeContainer == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn pullNodeContainer.takeXmlPullNode();\n\n\t}\n\t/**\n\t * @return Callback instance\n\t */\n\tpublic XmlPullNodeCallback getCallback() {\n\t\treturn callback;\n\t}\n\t/**\n\t * Callback to process some action for {@code XmlPullNode}. <br />\n\t * \n\t * NOTE: If you implement {@link XmlPullNode#XmlPullNodeCallback} and pass that on to {@code XmlPullNode} class,<br /> {@link XmlPullNodeParser} calls {@link XmlPullNode#XmlPullNodeCallback#process(XmlPullParser)} when it has found this the node during parse.\n\t * @author Wonjun Kim\n\t *\n\t */\n\tpublic static interface XmlPullNodeCallback {\n\t\t/**\n\t\t * @param parser {@code XmlPullParser} instance which are parsing xml. WARNING: Must carefully use {@code parser}. using {@code parser} can affect to cause an parsing error. Because {@code parser} can easily go to some wrong position during usage.   \n\t\t * @throws XmlPullParserException\n\t\t * @throws IOException\n\t\t */\n\t\tvoid process(XmlPullParser parser) throws XmlPullParserException, IOException;\n\t}\n\t\n\t/**\n\t * {@XmlPullNodeContainer} is a container for saving {@code repeatLimit}. And check the limit to occur an error. <br />\n\t * NOTE : Justly, this Class is not thread-safe. :)\n\t * @author Wonjun Kim\n\t *\n\t */\n\tprivate static class XmlPullNodeContainer {\n\t\t/**\n\t\t * Real {@code XmlPullnode} instance\n\t\t */\n\t\tprivate XmlPullNode node;\n\t\t/**\n\t\t * Repetition limit value decreasing one by which a node occurs at a time\n\t\t */\n\t\tprivate int repeatLimit; \n\t\t/**\n\t\t * Default Constructor \n\t\t * @param node Infinite repeat {@code XmlPullNode} instance\n\t\t */\n\t\tpublic XmlPullNodeContainer(XmlPullNode node) {\n\t\t\tthis(node, INFINITE);\n\t\t}\n\t\t/**\n\t\t * Constructor with {@code node} and {@code repeatLimit}\n\t\t * @param node Finite repeat (only if you set positive {@code repeatLimit}) {@code XmlPullNode} instance\n\t\t * @param repeatLimit Repeat limit value. This must be positive.\n\t\t */\n\t\tpublic XmlPullNodeContainer(XmlPullNode node, int repeatLimit) {\n\t\t\tAssert.notNull(node, \"XmlPullNode\");\n\t\t\tthis.node = node;\n\t\t\tthis.repeatLimit = repeatLimit;\n\t\t}\n\t\t/**\n\t\t * Return {@code XmlPullNode} instance or throw a limit error\n\t\t * @return {@code XmlPullNode} instance if the node repeats under the limit \n\t\t * @throws XmlPullParserException if a number of repetitions reaches the limit \n\t\t */\n\t\tpublic XmlPullNode takeXmlPullNode() throws XmlPullParserException {\n\t\t\tif (repeatLimit > 0) {\n\t\t\t\tdecreaseRepeatLimit();\n\t\t\t\treturn node;\n\t\t\t}\n\t\t\t\n\t\t\t// throw an error\n\t\t\tif (repeatLimit == 0) {\n\t\t\t\tString tagName = node.getName();\n\t\t\t\tthrow new XmlPullParserException(\"Tag '\" + tagName\n\t\t\t\t\t\t+ \"' should not have more \" + repeatLimit + \" nodes.\");\n\t\t\t}\n\n\t\t\t// if infinite repeats,\n\t\t\treturn node;\n\n\t\t}\n\t\t/**\n\t\t * one step forward to the limit error!\n\t\t */\n\t\tprivate void decreaseRepeatLimit() {\n\t\t\t--repeatLimit;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/configuration/xml/XmlPullNodeParser.java",
    "content": "/*******************************************************************************\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.configuration.xml;\n\n\nimport java.io.IOException;\n\nimport org.xmlpull.v1.XmlPullParser;\nimport org.xmlpull.v1.XmlPullParserException;\n\nimport android.util.Log;\n\nimport com.handmark.pulltorefresh.configuration.xml.XmlPullParserWrapper.DocumentState;\nimport com.handmark.pulltorefresh.library.internal.Assert;\n/**\n * \n * {@code XmlPullNode}-based Parser using XmlPullParser <br />\n * When you override this class, you must define parse strategies, and return the root node (in {@link #generateRootNode()} of {@code XmlPullNode}s containing each parse strategy, \n * and return the result (in {@link #getResult()} for which provide that to client after parse.  \n * @author Wonjun Kim\n * @param <R> Result type \n */\nabstract class XmlPullNodeParser<R> {\n\tprivate final XmlPullParserWrapper parser;\n\tprivate final XmlPullNode rootNode;\n\t/**\n\t * this flag prevents duplicate parse.\n\t */\n\tprivate boolean isParsed = false;\n\t/**\n\t * @param parser which has not been read yet. <br /> throw {@code NullPointerException} if {@code parser} is null\n\t */\n\tpublic XmlPullNodeParser(XmlPullParserWrapper parser) {\n\t\tAssert.notNull(parser, \"XmlPullParser\");\n\t\tthis.parser = parser;\n\t\tthis.rootNode = generateRootNode();\n\t}\n\t/**\n\t * @return entry point for {@code XmlPullNode}-based parse\n\t */\n\tprotected abstract XmlPullNode generateRootNode();\n\t/**\n\t * Parse the data and return {@code <R>} type result <br />\n\t * even if you call this methods several times, parsing happens once and no more duplicate parse\n\t * @return parsed data\n\t * @throws XmlPullParserException\n\t * @throws IOException\n\t */\n\tpublic final R parse() throws XmlPullParserException, IOException {\n\n\t\t// avoid duplicate parse \n\t\tif ( isParsed == true ) {\n\t\t\treturn getResult();\n\t\t}\n\t\t\n\t\t// First, Find the root node.\n\t\tDocumentState documentState;\n\t\t\n\t\tString rootName = rootNode.getName();\n\t\tdocumentState = parser.nextStartTagByName(rootName);\n\t\t\n\t\tif ( documentState.END.equals(documentState)) {\n\t\t\tthrow new XmlPullParserException(rootName + \" tag has not found.\");\n\t\t}\n\t\t// deeply parsing\n\t\tparseInternal(rootNode);\n\t\tisParsed = true;\n\t\treturn getResult();\n\t}\n\t/**\n\t * Return a result after parse <br />Be called from {@link #parse()} method \n\t * @return result value to return after parsing is done\n\t */\n\tprotected abstract R getResult();\n\t/**\n\t * Call {@link XmlPullNode.XmlPullNodeCallback#process(XmlPullParser)} and parse child nodes of current node\n\t * \n\t * @param currentNode target of which call a callback and parse children\n\t * @throws XmlPullParserException\n\t * @throws IOException\n\t */\n\tprivate void parseInternal(XmlPullNode currentNode) throws XmlPullParserException, IOException {\n\t\t// NOTE : too many permissions to node\n\t\tcurrentNode.getCallback().process(parser);\n\t\t\n\t\twhile ( true ) {\n\t\n\t\t\t// if document is end during finding the end tag of this current node, it throws the exception below. \n\t\t\tif ( parser.isEndDocument() ) {\n\t\t\t\tthrow new XmlPullParserException(\"XML document is invalid.\");\n\t\t\t}\t\t\t\n\t\t\t\n\t\t\t// if the end tag is found, parsing this scope is being ended.\n\t\t\tif ( parser.isEndTag() && parser.matchCurrentTagName(currentNode.getName())) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\t// get next tag\n\t\t\tparser.next();\n\t\t\t\n\t\t\t// when a child node is found, deeply parsing\n\t\t\tif ( parser.isStartTag() ) {\n\t\t\t\t\n\t\t\t\tString currentTagName = parser.getName();\n\t\t\t\tXmlPullNode childNode = currentNode.getChild(currentTagName);\n\t\t\t\tif ( childNode != null ) {\n\t\t\t\t\t// recursively!\n\t\t\t\t\tparseInternal(childNode);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} \n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/configuration/xml/XmlPullParserWrapper.java",
    "content": "/*******************************************************************************\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.configuration.xml;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.Reader;\n\nimport org.xmlpull.v1.XmlPullParser;\nimport org.xmlpull.v1.XmlPullParserException;\n\nimport com.handmark.pulltorefresh.library.internal.Assert;\n/**\n * <p>\n * {@code XmlPullParser} Wrapper <br />\n * This class provide util methods such as {@link #nextStartTag()}, {@link #isStartTag()} , and so on  \n * </p>\n * @author Wonjun Kim\n *\n */\nclass XmlPullParserWrapper implements XmlPullParser {\n\t/**\t\n\t * {@code XmlPullParserWrapper} call this {@code parser} as delegatee\n\t */\n\tprivate final XmlPullParser parser;\n\t/**\n\t * <p>\n\t * Need {@code XmlPullParser} <br /> \n\t * If {@code parser} is null, It throws {@code NullPointerException}\n\t * </p> \n\t * @param parser delegated {@link XmlPullParser}\n\t */\n\tpublic XmlPullParserWrapper(XmlPullParser parser) {\n\t\tAssert.notNull(parser, \"XmlPullParser\");\n\t\tthis.parser = parser;\n\t}\n\t/**\n\t * <p>\n\t * {@code DocumentState} represents current state (instead of event type) of a document which the parser reads.<br /> \n\t * </p>\n\t * @author Wonjun Kim\n\t *\n\t */\n\tpublic static enum DocumentState {\n\t\t/**\n\t\t * READ : Document is readable yet\n\t\t */\n\t\tREAD, \n\t\t/**\n\t\t * FOUNDTAG : Document is readable yet and current event is a tag type\n\t\t */\n\t\tFOUNDTAG, \n\t\t/**\n\t\t * END : Document is completely read. There is no more token\n\t\t */\n\t\tEND;\n\t}\n\t/**\n\t * @return true if current type is {@code START_TAG}\n\t * @throws XmlPullParserException\n\t */\n\tpublic boolean isStartTag() throws XmlPullParserException {\n\t\treturn getEventType() == START_TAG;\n\t}\n\t/**\n\t * @return true if current type is {@code END_TAG}\n\t * @throws XmlPullParserException\n\t */\n\tpublic boolean isEndTag() throws XmlPullParserException {\n\t\treturn getEventType() == END_TAG;\n\t}\n\t/**\n\t * @return true if current type is {@code TEXT}\n\t * @throws XmlPullParserException\n\t */\n\tpublic boolean isText() throws XmlPullParserException {\n\t\treturn getEventType() == TEXT;\n\t}\n\t/**\n\t * @return true if current type is {@code START_DOCUMENT}\n\t * @throws XmlPullParserException\n\t */\n\tpublic boolean isStartDocument() throws XmlPullParserException {\n\t\treturn getEventType() == START_DOCUMENT;\n\t}\n\t/**\n\t * @return true if current type is {@code END_DOCUMENT}\n\t * @throws XmlPullParserException\n\t */\n\tpublic boolean isEndDocument() throws XmlPullParserException {\n\t\treturn getEventType() == END_DOCUMENT;\n\t}\n\t/**\n\t * @return true if current type is {@code COMMENT}\n\t * @throws XmlPullParserException\n\t */\n\tpublic boolean isComment() throws XmlPullParserException {\n\t\treturn getEventType() == COMMENT;\n\t}\n\t/**\n\t * <p>\n\t * Find next start tag by calling {@link XmlPullParser#next()} again and again \n\t * If the parser reaches the end of a document, this method will returns {@code DocumentState.END}\n\t * </p>\n\t * @return {@link DocumentState.FOUNDTAG} if start tag has been found \n\t * \t\t   {@link DocumentState.END} if the parser reaches the end of a document\n\t * @throws XmlPullParserException\n\t * @throws IOException\n\t */\n\tpublic DocumentState nextStartTag() throws XmlPullParserException,\n\t\t\tIOException {\n\t\twhile (true) {\n\n\t\t\tint evt = next();\n\n\t\t\tif (evt == XmlPullParser.START_TAG) {\n\t\t\t\treturn DocumentState.FOUNDTAG;\n\t\t\t}\n\n\t\t\tif (evt == XmlPullParser.END_DOCUMENT) {\n\t\t\t\treturn DocumentState.END;\n\t\t\t}\n\t\t}\n\t}\n\t/**\n\t * <p>\n\t * Find next start tag whose name is same as {@code tagName} by calling {@link XmlPullParser#next()} again and again \n\t * If the parser reaches the end of a document, this method will returns {@code DocumentState.END}\n\t * </p>\n\t * @param tagName Tag name you want to find\n\t * @return {@link DocumentState.FOUNDTAG} if start tag has been found \n\t * \t\t   {@link DocumentState.END} if the parser reaches the end of a document\n\t * @throws XmlPullParserException\n\t * @throws IOException\n\t */\n\tpublic DocumentState nextStartTagByName(String tagName)\n\t\t\tthrows XmlPullParserException, IOException {\n\t\twhile (true) {\n\t\t\tDocumentState documentState = nextStartTag();\n\n\t\t\tif (documentState.equals(DocumentState.END)) {\n\t\t\t\treturn documentState;\n\t\t\t}\n\t\t\t\n\t\t\tif (matchCurrentTagName(tagName)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn DocumentState.FOUNDTAG;\n\t}\n\t/**\n\t * <p>\n\t * Find next end tag by calling {@link XmlPullParser#next()} again and again \n\t * If the parser reaches the end of a document, this method will returns {@code DocumentState.END}\n\t * </p>\n\t * @return {@link DocumentState.FOUNDTAG} if end tag has been found \n\t * \t\t   {@link DocumentState.END} if the parser reaches the end of a document\n\t * @throws XmlPullParserException\n\t * @throws IOException\n\t */\n\tpublic DocumentState nextEndTag() throws XmlPullParserException,\n\t\t\tIOException {\n\t\twhile (true) {\n\n\t\t\tint evt = next();\n\n\t\t\tif (evt == XmlPullParser.END_TAG) {\n\t\t\t\treturn DocumentState.FOUNDTAG;\n\t\t\t}\n\n\t\t\tif (evt == XmlPullParser.END_DOCUMENT) {\n\t\t\t\treturn DocumentState.END;\n\t\t\t}\n\t\t}\n\t}\n\t/**\n\t * <p>\n\t * Find next end tag whose name is same as {@code tagName} by calling {@link XmlPullParser#next()} again and again \n\t * If the parser reaches the end of a document, this method will returns {@code DocumentState.END}\n\t * </p>\n\t * @param tagName Tag name you want to find\n\t * @return {@link DocumentState.FOUNDTAG} if start tag has been found \n\t * \t\t   {@link DocumentState.END} if the parser reaches the end of a document\n\t * @throws XmlPullParserException\n\t * @throws IOException\n\t */\n\tpublic DocumentState nextEndTagByName(String tagName)\n\t\t\tthrows XmlPullParserException, IOException {\n\t\twhile (true) {\n\t\t\tDocumentState documentState = nextEndTag();\n\n\t\t\tif (documentState.equals(DocumentState.END)) {\n\t\t\t\treturn documentState;\n\t\t\t}\n\t\t\t\n\t\t\tif (matchCurrentTagName(tagName)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn DocumentState.FOUNDTAG;\n\t}\n\t/**\n\t * Check that current tag name is same as {@code tagName} \n\t * \n\t * @param tagName Tag name you want to check whether current tag is same as \n\t * @return true if current tag name is same \n\t * @throws XmlPullParserException\n\t * @throws IOException\n\t */\n\tpublic boolean matchCurrentTagName(String tagName) {\n\t\tAssert.notNull(tagName, \"Tag Name\");\n\t\treturn getName().equals(tagName);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#setFeature(String, boolean)} */\n\t@Override\n\tpublic void setFeature(String name, boolean state)\n\t\t\tthrows XmlPullParserException {\n\t\tparser.setFeature(name, state);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getFeature(String)} */\n\t@Override\n\tpublic boolean getFeature(String name) {\n\t\treturn parser.getFeature(name);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#setProperty(String, Object)} */\n\t@Override\n\tpublic void setProperty(String name, Object value)\n\t\t\tthrows XmlPullParserException {\n\t\tparser.setProperty(name, value);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getProperty(String)} */\n\t@Override\n\tpublic Object getProperty(String name) {\n\t\treturn parser.getProperty(name);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#setInput(Reader)} */\n\t@Override\n\tpublic void setInput(Reader in) throws XmlPullParserException {\n\t\tparser.setInput(in);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#setInput(InputStream, String)} */\n\t@Override\n\tpublic void setInput(InputStream inputStream, String inputEncoding)\n\t\t\tthrows XmlPullParserException {\n\t\tparser.setInput(inputStream, inputEncoding);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getInputEncoding()} */\n\t@Override\n\tpublic String getInputEncoding() {\n\t\treturn parser.getInputEncoding();\n\t}\n\t/** Wrapper method for {@link XmlPullParser#defineEntityReplacementText(String, String)} */\n\t@Override\n\tpublic void defineEntityReplacementText(String entityName,\n\t\t\tString replacementText) throws XmlPullParserException {\n\t\tparser.defineEntityReplacementText(entityName, replacementText);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getNamespaceCount(int)} */\n\t@Override\n\tpublic int getNamespaceCount(int depth) throws XmlPullParserException {\n\t\t// TODO Auto-generated method stub\n\t\treturn parser.getNamespaceCount(depth);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getNamespacePrefix(int)} */\n\t@Override\n\tpublic String getNamespacePrefix(int pos) throws XmlPullParserException {\n\t\treturn parser.getNamespacePrefix(pos);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getNamespaceUri(int)} */\n\t@Override\n\tpublic String getNamespaceUri(int pos) throws XmlPullParserException {\n\t\treturn parser.getNamespaceUri(pos);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getNamespace(String)} */\n\t@Override\n\tpublic String getNamespace(String prefix) {\n\t\treturn parser.getNamespace(prefix);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getDepth()} */\n\t@Override\n\tpublic int getDepth() {\n\t\treturn parser.getDepth();\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getPositionDescription()} */\n\t@Override\n\tpublic String getPositionDescription() {\n\t\treturn parser.getPositionDescription();\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getLineNumber()} */\n\t@Override\n\tpublic int getLineNumber() {\n\t\treturn parser.getLineNumber();\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getColumnNumber()} */\n\t@Override\n\tpublic int getColumnNumber() {\n\t\treturn parser.getColumnNumber();\n\t}\n\t/** Wrapper method for {@link XmlPullParser#isWhiteSpace()} */\n\t@Override\n\tpublic boolean isWhitespace() throws XmlPullParserException {\n\t\treturn parser.isWhitespace();\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getText()} */\n\t@Override\n\tpublic String getText() {\n\t\treturn parser.getText();\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getTextCharacters(int[])} */\n\t@Override\n\tpublic char[] getTextCharacters(int[] holderForStartAndLength) {\n\t\treturn parser.getTextCharacters(holderForStartAndLength);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getNamespace()} */\n\t@Override\n\tpublic String getNamespace() {\n\t\treturn parser.getNamespace();\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getName()} */\n\t@Override\n\tpublic String getName() {\n\t\treturn parser.getName();\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getPrefix()} */\n\t@Override\n\tpublic String getPrefix() {\n\t\treturn parser.getPrefix();\n\t}\n\t/** Wrapper method for {@link XmlPullParser#isEmptyElementTag()} */\n\t@Override\n\tpublic boolean isEmptyElementTag() throws XmlPullParserException {\n\t\treturn parser.isEmptyElementTag();\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getAttributeCount()} */\n\t@Override\n\tpublic int getAttributeCount() {\n\t\treturn parser.getAttributeCount();\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getAttributeNamespace(int)} */\n\t@Override\n\tpublic String getAttributeNamespace(int index) {\n\t\treturn parser.getAttributeNamespace(index);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getAttributeName(int)} */\n\t@Override\n\tpublic String getAttributeName(int index) {\n\t\treturn parser.getAttributeName(index);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getAttributePrefix(int)} */\n\t@Override\n\tpublic String getAttributePrefix(int index) {\n\t\treturn parser.getAttributePrefix(index);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getAttributeType(int)} */\n\t@Override\n\tpublic String getAttributeType(int index) {\n\t\treturn parser.getAttributeType(index);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#isAttributeDefault(int)} */\n\t@Override\n\tpublic boolean isAttributeDefault(int index) {\n\t\treturn parser.isAttributeDefault(index);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getAttributeValue(int)} */\n\t@Override\n\tpublic String getAttributeValue(int index) {\n\t\treturn parser.getAttributeValue(index);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getAttributeValue(String, String)} */\n\t@Override\n\tpublic String getAttributeValue(String namespace, String name) {\n\t\treturn parser.getAttributeValue(namespace, name);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#getEventType()} */\n\t@Override\n\tpublic int getEventType() throws XmlPullParserException {\n\t\treturn parser.getEventType();\n\t}\n\t/** Wrapper method for {@link XmlPullParser#next()} */\n\t@Override\n\tpublic int next() throws XmlPullParserException, IOException {\n\t\treturn parser.next();\n\t}\n\t/** Wrapper method for {@link XmlPullParser#nextToken()} */\n\t@Override\n\tpublic int nextToken() throws XmlPullParserException, IOException {\n\t\treturn parser.nextToken();\n\t}\n\t/** Wrapper method for {@link XmlPullParser#require(int, String, String)} */\n\t@Override\n\tpublic void require(int type, String namespace, String name)\n\t\t\tthrows XmlPullParserException, IOException {\n\t\tparser.require(type, namespace, name);\n\t}\n\t/** Wrapper method for {@link XmlPullParser#nextTag()} */\n\t@Override\n\tpublic String nextText() throws XmlPullParserException, IOException {\n\t\treturn parser.nextText();\n\t}\n\t/** Wrapper method for {@link XmlPullParser#nextTag()} */\n\t@Override\n\tpublic int nextTag() throws XmlPullParserException, IOException {\n\t\treturn parser.nextTag();\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/AlphaAnimator.java",
    "content": "/*******************************************************************************\n * Copyright 2014 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport android.view.View;\nimport android.view.animation.AlphaAnimation;\nimport android.view.animation.Animation.AnimationListener;\n/**\n * AlphaAnimation Helper\n * Just supports fade-in and fade-out\n * @author Wonjun Kim\n *\n */\nclass AlphaAnimator {\n\t\n\tpublic static void fadein(View view, int duration) {\n\t\tfadein(view, duration, null);\n\t}\n\tpublic static void fadein(View view, int duration, AnimationListener listener) {\n\t\tanimate(view, duration, listener, 0.0f, 1.0f);\n\t}\n\t\n\tpublic static void fadeout(View view, int duration) {\n\t\tfadeout(view, duration, null);\n\t}\n\t\n\tpublic static void fadeout(View view, int duration, AnimationListener listener) {\n\t\tanimate(view, duration, listener, 1.0f, 0.0f);\n\t}\n\t\n\tprivate static void animate(View view, int duration, AnimationListener listener, float fromAlpha, float targetAlpha) {\n\t\t// Create new animation\n\t\tAlphaAnimation newAnimation = new AlphaAnimation(fromAlpha, targetAlpha);\n\t\t\n\t\tnewAnimation.setDuration(duration);\n\t\t// Force fillAfter flag to be true\n\t\tnewAnimation.setFillAfter(true);\n\t\tnewAnimation.setAnimationListener(listener);\n\t\t// Start fading\n\t\tview.startAnimation(newAnimation);\n\t\t\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/GoogleStyleProgressLayout.java",
    "content": "/*******************************************************************************\n * Copyright 2014 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.view.ViewGroup;\nimport android.widget.FrameLayout;\n/**\n * Abstract class of Google style progress layout\n * You can override this class and implement specific layout, for example, {@see DefaultGoogleStyleProgressLayout}.\n * \n * @author Wonjun Kim\n *\n */\npublic abstract class GoogleStyleProgressLayout extends FrameLayout implements IGoogleStyleProgressLayout {\n\tpublic GoogleStyleProgressLayout(Context context, TypedArray attrs){\n\t\tsuper(context);\n\t\t\n\t}\n\t/**\n\t * Set Y position of this layout by using margin property.<br /> \n\t * If you don't want to set default y position given by {@code PullToRefreshBase}, you have to this method and customize it.     \n\t */\n\tpublic void setTopMargin(int height) {\n\t\tViewGroup.LayoutParams params = getLayoutParams();\n\t\tif ( params instanceof FrameLayout.LayoutParams ) {\n\t\t\t((FrameLayout.LayoutParams) params).topMargin = height;\n\t\t}\n\t}\n\t/**\n\t * Create a specific {@code LayoutParams}.<br /> \n\t * Pull To Refresh will add this layout with applying this {@code LayoutParams} to the layout     \n\t * @return {@code LayoutParams} you implemented\n\t */\t\n\tpublic FrameLayout.LayoutParams createLayoutParams() {\n\t\treturn GoogleStyleProgressLayout.createDefaultLayoutParams(getContext());\n\t}\n\t/**\n\t * Create a default specific {@code LayoutParams}.<br /> \n\t * @param Context     \n\t * @return Default {@code LayoutParams}  \n\t */\n\tpublic static FrameLayout.LayoutParams createDefaultLayoutParams(Context context) {\n\t\t@SuppressWarnings(\"deprecation\")\n\t\tFrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n\t\treturn params;\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/GoogleStyleProgressLayoutFactory.java",
    "content": "/*******************************************************************************\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport java.lang.reflect.Constructor;\n\nimport java.lang.reflect.InvocationTargetException;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.util.Log;\nimport android.view.View;\n\nimport com.handmark.pulltorefresh.configuration.xml.PullToRefreshXmlConfiguration;\nimport com.handmark.pulltorefresh.library.internal.DefaultGoogleStyleProgressLayout;\nimport com.handmark.pulltorefresh.library.GoogleStyleProgressLayout;\n/**\n * Factory which creates google style progress layouts \n * <br />Google style progress layouts must be listed in pulltorefresh.xml as \"PullToRefresh/GoogleStyleProgressLayouts/layout\" nodes\n * @author Wonjun Kim\n */\nclass GoogleStyleProgressLayoutFactory {\n\n\tprivate static final String LOG_TAG = GoogleStyleProgressLayoutFactory.class\n\t\t\t.getSimpleName();\n\t/**\n\t * Create the class token matched by <b>{@code layoutCode}</b>\n\t * @param layoutCode Google style progress layout code, which must be defined in pulltorefresh.xml \n\t * @return Class token which is matched by {@code layoutCode}, or the class token of {@code RotateGoogleStyleProgressLayout} instance if not\n\t */\n\tpublic static Class<? extends GoogleStyleProgressLayout> createGoogleStyleProgressLayoutClazzByLayoutCode(String layoutCode) {\n\t\tString clazzName = PullToRefreshXmlConfiguration.getInstance().getGoogleStyleProgressLayoutClazzName(layoutCode);\n\t\treturn createGoogleStyleProgressLayoutClazz(clazzName);\n\t}\n\t/**\n\t * Create a {@code GoogleStyleProgressLayout} instance matched by <b>{@code clazz} token</b> \n\t * @param layoutCode Google style progress layout code, which must be defined in pulltorefresh.xml\n\t * @param context \n\t * @return {@code GoogleStyleProgressLayout} instance if the class matched by {@code layoutCode} exists, or {@code RotateGoogleStyleProgressLayout} instance if not  \n\t */\n\t@SuppressWarnings(\"unchecked\")\n\tpublic static Class<? extends GoogleStyleProgressLayout> createGoogleStyleProgressLayoutClazz(\n\t\t\tString clazzName) {\n\t\tClass<? extends GoogleStyleProgressLayout> googleStyleProgressLayoutClazz = null;\n\t\tif ( clazzName == null ) {\n\t\t\tgoogleStyleProgressLayoutClazz = DefaultGoogleStyleProgressLayoutFactory.createGoogleStyleProgressLayoutClazz(clazzName);\n\t\t\treturn googleStyleProgressLayoutClazz;\n\t\t}\n\t\t\n\t\ttry {\n\t\t\tgoogleStyleProgressLayoutClazz = (Class<GoogleStyleProgressLayout>) Class.forName(clazzName);\n\n\t\t} catch (ClassNotFoundException e) {\n\t\t\tLog.e(LOG_TAG,\"The google style progress layout you have chosen class has not been found.\", e);\n\t\t\tgoogleStyleProgressLayoutClazz = DefaultGoogleStyleProgressLayoutFactory.createGoogleStyleProgressLayoutClazz(clazzName);\n\t\t} \n\n\t\treturn googleStyleProgressLayoutClazz;\n\t}\n\t/**\n\t * Create a {@code GoogleStyleProgressLayout} instance matched by <b>{@code layoutCode}</b> \n\t * @param layoutCode Google style progress layout code, which must be defined in pulltorefresh.xml\n\t * @param context \n\t * @return {@code GoogleStyleProgressLayout} instance if the class matched by {@code layoutCode} exists, or {@code DefaultGoogleStyleProgressLayout} instance if not  \n\t */\n\tpublic static GoogleStyleProgressLayout createGoogleStyleProgressLayout(String layoutCode, Context context, TypedArray attrs) {\n\t\tClass<? extends GoogleStyleProgressLayout> clazz = createGoogleStyleProgressLayoutClazz(layoutCode);\n\t\treturn createGoogleStyleProgressLayout(clazz, context, attrs);\n\t}\n\t/**\n\t * Create a {@code GoogleStyleProgressLayout} instance matched by <b>{@code clazz} token</b> \n\t * @param layoutCode Google style progress layout code, which must be defined in pulltorefresh.xml\n\t * @param context \n\t * @return {@code GoogleStyleProgressLayout} instance if the class matched by {@code layoutCode} exists, or {@code DefaultGoogleStyleProgressLayout} instance if not  \n\t */\n\tpublic static GoogleStyleProgressLayout createGoogleStyleProgressLayout(\n\t\t\tClass<? extends GoogleStyleProgressLayout> clazz, Context context, TypedArray attrs) {\n\t\tGoogleStyleProgressLayout layout = null;\n\t\t// Prevent NullPointerException\n\t\tif ( clazz == null ) {\n\t\t\tLog.i(LOG_TAG, \"The Class token of the GoogleStyleProgressLayout is missing. Default google style progress layout will be used.\");\n\t\t\tclazz = DefaultGoogleStyleProgressLayoutFactory.createGoogleStyleProgressLayoutClazz(\"\");\n\t\t}\n\t\t\n\t\tlayout = tryNewInstance(clazz, context, attrs);\n\n\t\t// If trying to create new instance has failed,\n\t\tif (layout == null) {\n\t\t\tlayout = DefaultGoogleStyleProgressLayoutFactory.createGoogleStyleProgressLayout(clazz, context, attrs);\n\t\t}\n\n\t\tlayout.setVisibility(View.INVISIBLE);\n\t\treturn layout;\n\t}\n\tprivate static GoogleStyleProgressLayout tryNewInstance(\n\t\t\tClass<? extends GoogleStyleProgressLayout> clazz, Context context, TypedArray attrs) {\n\t\tGoogleStyleProgressLayout layout = null;\n\t\ttry {\n\t\t\tConstructor<? extends GoogleStyleProgressLayout> constructor = clazz\n\t\t\t\t\t.getConstructor(Context.class, TypedArray.class);\n\t\t\tlayout = (GoogleStyleProgressLayout) constructor.newInstance(context, attrs);\n\n\t\t} catch (IllegalArgumentException e) {\n\t\t\tLog.e(LOG_TAG, \"The google style progress layout has failed to be created. \", e);\n\t\t} catch (InvocationTargetException e) {\n\t\t\tLog.e(LOG_TAG, \"The google style progress layout has failed to be created. \", e);\n\t\t} catch (SecurityException e) {\n\t\t\tLog.e(LOG_TAG, \"The google style progress layout has failed to be created. \", e);\n\t\t} catch (NoSuchMethodException e) {\n\t\t\tLog.e(LOG_TAG, \"The google style progress layout has failed to be created. \", e);\n\t\t} catch (InstantiationException e) {\n\t\t\tLog.e(LOG_TAG, \"The google style progress layout has failed to be created. \", e);\n\t\t} catch (IllegalAccessException e) {\n\t\t\tLog.e(LOG_TAG, \"The google style progress layout has failed to be created. \", e);\n\t\t} catch (NullPointerException e) {\n\t\t\tLog.e(LOG_TAG, \"The google style progress layout has failed to be created. \", e);\n\t\t}\n\t\treturn layout;\n\t}\n\t/**\n\t * Factory which creates a default google style progress layout instance. This is used when {@code GoogleStyleProgressLayoutFactory} fails to create a instance\n\t * @author Wonjun Kim\n\t *\n\t */\n\tprivate static class DefaultGoogleStyleProgressLayoutFactory {\n\t\t/**\n\t\t * @param clazzName This class name is being ignored\n\t\t * @return Class token of {@code DefaultGoogleStyleProgressLayout}\n\t\t */\n\t\tpublic static Class<? extends GoogleStyleProgressLayout> createGoogleStyleProgressLayoutClazz(\n\t\t\t\tString clazzName) {\n\t\t\treturn DefaultGoogleStyleProgressLayout.class;\n\t\t}\n\t\t/**\n\t\t * @param clazz Class token is being ignored.\n\t\t * @param context\n\t\t * @return {@code DefaultGoogleStyleProgressLayout} instance\n\t\t */\n\t\tpublic static GoogleStyleProgressLayout createGoogleStyleProgressLayout(\n\t\t\t\tClass<? extends GoogleStyleProgressLayout> clazz, Context context, TypedArray attrs) {\n\n\t\t\treturn new DefaultGoogleStyleProgressLayout(context, attrs);\n\t\t}\n\n\t}\n\n}"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/GoogleStyleViewLayout.java",
    "content": "/*******************************************************************************\n * Copyright 2014 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.view.ViewGroup;\nimport android.widget.FrameLayout;\n/**\n * Abstract class of Google style view layout\n * You can override this class and implement specific layout like {@link LoadingLayout} style.\n * @author Wonjun Kim\n *\n */\npublic abstract class GoogleStyleViewLayout extends FrameLayout implements IGoogleStyleViewLayout {\n\n\tpublic GoogleStyleViewLayout(Context context, TypedArray attrs) {\n\t\tsuper(context);\n\t}\n\t\n\tpublic void setHeight(int height) {\n\t\tViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) getLayoutParams();\n\t\tlp.height = height;\n\t\trequestLayout();\n\t}\n\n\tpublic void setWidth(int width) {\n\t\tViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) getLayoutParams();\n\t\tlp.width = width;\n\t\trequestLayout();\n\t}\n\n\tpublic int getContentSize() {\n\t\treturn getHeight();\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/GoogleStyleViewLayoutFactory.java",
    "content": "/*******************************************************************************\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport java.lang.reflect.Constructor;\n\nimport java.lang.reflect.InvocationTargetException;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.util.Log;\nimport android.view.View;\n\nimport com.handmark.pulltorefresh.configuration.xml.PullToRefreshXmlConfiguration;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Orientation;\nimport com.handmark.pulltorefresh.library.internal.DefaultGoogleStyleViewLayout;\nimport com.handmark.pulltorefresh.library.GoogleStyleViewLayout;\n/**\n * Factory which creates google style view layouts \n * <br />Google style view layouts must be listed in pulltorefresh.xml as \"PullToRefresh/GoogleStyleViewLayouts/layout\" nodes\n * @author Wonjun Kim\n */\nclass GoogleStyleViewLayoutFactory {\n\n\tprivate static final String LOG_TAG = GoogleStyleViewLayoutFactory.class\n\t\t\t.getSimpleName();\n\t/**\n\t * Create the class token matched by <b>{@code layoutCode}</b>\n\t * @param layoutCode Google style view layout code, which must be defined in pulltorefresh.xml \n\t * @return Class token which is matched by {@code layoutCode}, or the class token of {@code RotateGoogleStyleViewLayout} instance if not\n\t */\n\tpublic static Class<? extends GoogleStyleViewLayout> createGoogleStyleViewLayoutClazzByLayoutCode(String layoutCode) {\n\t\tString clazzName = PullToRefreshXmlConfiguration.getInstance().getGoogleStyleViewLayoutClazzName(layoutCode);\n\t\treturn createGoogleStyleViewLayoutClazz(clazzName);\n\t}\n\t/**\n\t * Create a {@code GoogleStyleViewLayout} instance matched by <b>{@code clazz} token</b> \n\t * @param layoutCode Google style view layout code, which must be defined in pulltorefresh.xml\n\t * @param context \n\t * @return {@code GoogleStyleViewLayout} instance if the class matched by {@code layoutCode} exists, or {@code RotateGoogleStyleViewLayout} instance if not  \n\t */\n\t@SuppressWarnings(\"unchecked\")\n\tpublic static Class<? extends GoogleStyleViewLayout> createGoogleStyleViewLayoutClazz(\n\t\t\tString clazzName) {\n\t\tClass<? extends GoogleStyleViewLayout> googleStyleViewLayoutClazz = null;\n\t\tif ( clazzName == null ) {\n\t\t\tgoogleStyleViewLayoutClazz = DefaultGoogleStyleViewLayoutFactory.createGoogleStyleViewLayoutClazz(clazzName);\n\t\t\treturn googleStyleViewLayoutClazz;\n\t\t}\n\t\t\n\t\ttry {\n\t\t\tgoogleStyleViewLayoutClazz = (Class<GoogleStyleViewLayout>) Class.forName(clazzName);\n\n\t\t} catch (ClassNotFoundException e) {\n\t\t\tLog.e(LOG_TAG,\"The google style view layout you have chosen class has not been found.\", e);\n\t\t\tgoogleStyleViewLayoutClazz = DefaultGoogleStyleViewLayoutFactory.createGoogleStyleViewLayoutClazz(clazzName);\n\t\t} \n\n\t\treturn googleStyleViewLayoutClazz;\n\t}\n\t/**\n\t * Create a {@code GoogleStyleViewLayout} instance matched by <b>{@code layoutCode}</b> \n\t * @param layoutCode Google style view layout code, which must be defined in pulltorefresh.xml\n\t * @param context \n\t * @return {@code GoogleStyleViewLayout} instance if the class matched by {@code layoutCode} exists, or {@code DefaultGoogleStyleViewLayout} instance if not  \n\t */\n\tpublic static GoogleStyleViewLayout createGoogleStyleViewLayout(String layoutCode, Context context, TypedArray attrs) {\n\t\tClass<? extends GoogleStyleViewLayout> clazz = createGoogleStyleViewLayoutClazz(layoutCode);\n\t\treturn createGoogleStyleViewLayout(clazz, context, attrs);\n\t}\n\t/**\n\t * Create a {@code GoogleStyleViewLayout} instance matched by <b>{@code clazz} token</b> \n\t * @param layoutCode Google style view layout code, which must be defined in pulltorefresh.xml\n\t * @param context \n\t * @return {@code GoogleStyleViewLayout} instance if the class matched by {@code layoutCode} exists, or {@code DefaultGoogleStyleViewLayout} instance if not  \n\t */\n\tpublic static GoogleStyleViewLayout createGoogleStyleViewLayout(\n\t\t\tClass<? extends GoogleStyleViewLayout> clazz, Context context, TypedArray attrs) {\n\t\tGoogleStyleViewLayout layout = null;\n\t\t// Prevent NullPointerException\n\t\tif ( clazz == null ) {\n\t\t\tLog.i(LOG_TAG, \"The Class token of the GoogleStyleViewLayout is missing. Default google style view layout will be used.\");\n\t\t\tclazz = DefaultGoogleStyleViewLayoutFactory.createGoogleStyleViewLayoutClazz(\"\");\n\t\t}\n\t\t\n\t\tlayout = tryNewInstance(clazz, context, attrs);\n\n\t\t// If trying to create new instance has failed,\n\t\tif (layout == null) {\n\t\t\tlayout = DefaultGoogleStyleViewLayoutFactory.createGoogleStyleViewLayout(clazz, context, attrs);\n\t\t}\n\n\t\tlayout.setVisibility(View.INVISIBLE);\n\t\treturn layout;\n\t}\n\tprivate static GoogleStyleViewLayout tryNewInstance(\n\t\t\tClass<? extends GoogleStyleViewLayout> clazz, Context context, TypedArray attrs) {\n\t\tGoogleStyleViewLayout layout = null;\n\t\ttry {\n\t\t\tConstructor<? extends GoogleStyleViewLayout> constructor = clazz\n\t\t\t\t\t.getConstructor(Context.class, TypedArray.class);\n\t\t\tlayout = (GoogleStyleViewLayout) constructor.newInstance(context, attrs);\n\n\t\t} catch (IllegalArgumentException e) {\n\t\t\tLog.e(LOG_TAG, \"The google style view layout has failed to be created. \", e);\n\t\t} catch (InvocationTargetException e) {\n\t\t\tLog.e(LOG_TAG, \"The google style view layout has failed to be created. \", e);\n\t\t} catch (SecurityException e) {\n\t\t\tLog.e(LOG_TAG, \"The google style view layout has failed to be created. \", e);\n\t\t} catch (NoSuchMethodException e) {\n\t\t\tLog.e(LOG_TAG, \"The google style view layout has failed to be created. \", e);\n\t\t} catch (InstantiationException e) {\n\t\t\tLog.e(LOG_TAG, \"The google style view layout has failed to be created. \", e);\n\t\t} catch (IllegalAccessException e) {\n\t\t\tLog.e(LOG_TAG, \"The google style view layout has failed to be created. \", e);\n\t\t} catch (NullPointerException e) {\n\t\t\tLog.e(LOG_TAG, \"The google style view layout has failed to be created. \", e);\n\t\t}\n\t\treturn layout;\n\t}\n\t/**\n\t * Factory which creates a default google style view layout instance. This is used when {@code GoogleStyleViewLayoutFactory} fails to create a instance\n\t * @author Wonjun Kim\n\t *\n\t */\n\tprivate static class DefaultGoogleStyleViewLayoutFactory {\n\t\t/**\n\t\t * @param clazzName This class name is being ignored\n\t\t * @return Class token of {@code DefaultGoogleStyleViewLayout}\n\t\t */\n\t\tpublic static Class<? extends GoogleStyleViewLayout> createGoogleStyleViewLayoutClazz(\n\t\t\t\tString clazzName) {\n\t\t\treturn DefaultGoogleStyleViewLayout.class;\n\t\t}\n\t\t/**\n\t\t * @param clazz Class token is being ignored.\n\t\t * @param context\n\t\t * @return {@code DefaultGoogleStyleViewLayout} instance\n\t\t */\n\t\tpublic static GoogleStyleViewLayout createGoogleStyleViewLayout(\n\t\t\t\tClass<? extends GoogleStyleViewLayout> clazz, Context context, TypedArray attrs) {\n\n\t\t\treturn new DefaultGoogleStyleViewLayout(context, attrs);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/IGoogleStyleProgressLayout.java",
    "content": "/*******************************************************************************\n * Copyright 2014 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n/**\n * Marker interface for Google style progress layout\n * @author Wonjun Kim\n *\n */\npublic interface IGoogleStyleProgressLayout extends IPullToRefreshConsumer {\n\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/IGoogleStyleViewLayout.java",
    "content": "/*******************************************************************************\n * Copyright 2014 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n/**\n * Marker interface for Google style progress layout\n * @author Wonjun Kim\n *\n */\npublic interface IGoogleStyleViewLayout extends IPullToRefreshConsumer {\n\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/IIndicatorLayout.java",
    "content": "/*******************************************************************************\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport com.handmark.pulltorefresh.library.internal.IndicatorLayout;\n\n/**\n * Indicator layout which react pulling or releasing of Pull To Refresh\n * <br />\n * NOTE : To make new Indicator layout, You have to override {@link IndicatorLayout} instead of IIndicatorLayout. \n * <br /> Because {@link PullToRefreshAdapterViewBase} uses indicator layouts as a kind of View component. {@link IndicatorLayout} is a descendant class of {@code View}.\n * \n * @author Wonjun Kim\n */\npublic interface IIndicatorLayout {\n\t/**\n\t * Show the Indicator Layout \n\t */\n\tpublic void show();\n\t/**\n\t * Hide the Indicator Layout \n\t */\n\tpublic void hide();\n\t/**\n\t * Check whether this indicator layout is being shown or not\n\t * @return true if the indicator layout is visible now \n\t */\n\tpublic boolean isVisible();\n\t/**\n\t * Make a Action when \"PullToRefresh\" event has been fired\n\t */\n\tpublic void pullToRefresh();\n\t/**\n\t * Make a Action when \"ReleaseToRefresh\" event has been fired\n\t */\n\tpublic void releaseToRefresh();\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/ILoadingLayout.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport android.graphics.Typeface;\nimport android.graphics.drawable.Drawable;\n\npublic interface ILoadingLayout {\n\n\t/**\n\t * Set the Last Updated Text. This displayed under the main label when\n\t * Pulling\n\t * \n\t * @param label - Label to set\n\t */\n\tpublic void setLastUpdatedLabel(CharSequence label);\n\n\t/**\n\t * Set the drawable used in the loading layout. This is the same as calling\n\t * <code>setLoadingDrawable(drawable, Mode.BOTH)</code>\n\t * \n\t * @param drawable - Drawable to display\n\t */\n\tpublic void setLoadingDrawable(Drawable drawable);\n\n\t/**\n\t * Set Text to show when the Widget is being Pulled\n\t * <code>setPullLabel(releaseLabel, Mode.BOTH)</code>\n\t * \n\t * @param pullLabel - CharSequence to display\n\t */\n\tpublic void setPullLabel(CharSequence pullLabel);\n\n\t/**\n\t * Set Text to show when the Widget is refreshing\n\t * <code>setRefreshingLabel(releaseLabel, Mode.BOTH)</code>\n\t * \n\t * @param refreshingLabel - CharSequence to display\n\t */\n\tpublic void setRefreshingLabel(CharSequence refreshingLabel);\n\n\t/**\n\t * Set Text to show when the Widget is being pulled, and will refresh when\n\t * released. This is the same as calling\n\t * <code>setReleaseLabel(releaseLabel, Mode.BOTH)</code>\n\t * \n\t * @param releaseLabel - CharSequence to display\n\t */\n\tpublic void setReleaseLabel(CharSequence releaseLabel);\n\n\t/**\n\t * Set's the Sets the typeface and style in which the text should be\n\t * displayed. Please see\n\t * {@link android.widget.TextView#setTypeface(Typeface)\n\t * TextView#setTypeface(Typeface)}.\n\t */\n\tpublic void setTextTypeface(Typeface tf);\n\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/IPullToRefresh.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport android.view.View;\nimport android.view.animation.Interpolator;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.OnPullEventListener;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener2;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.State;\n\npublic interface IPullToRefresh<T extends View> {\n\n\t/**\n\t * Demos the Pull-to-Refresh functionality to the user so that they are\n\t * aware it is there. This could be useful when the user first opens your\n\t * app, etc. The animation will only happen if the Refresh View (ListView,\n\t * ScrollView, etc) is in a state where a Pull-to-Refresh could occur by a\n\t * user's touch gesture (i.e. scrolled to the top/bottom).\n\t * \n\t * @return true - if the Demo has been started, false if not.\n\t */\n\t@Deprecated\n\tpublic boolean demo();\n\n\t/**\n\t * Get the mode that this view is currently in. This is only really useful\n\t * when using <code>Mode.BOTH</code>.\n\t * \n\t * @return Mode that the view is currently in\n\t */\n\tpublic Mode getCurrentMode();\n\n\t/**\n\t * Returns whether the Touch Events are filtered or not. If true is\n\t * returned, then the View will only use touch events where the difference\n\t * in the Y-axis is greater than the difference in the X-axis. This means\n\t * that the View will not interfere when it is used in a horizontal\n\t * scrolling View (such as a ViewPager).\n\t * \n\t * @return boolean - true if the View is filtering Touch Events\n\t */\n\tpublic boolean getFilterTouchEvents();\n\n\t/**\n\t * Returns a proxy object which allows you to call methods on all of the\n\t * LoadingLayouts (the Views which show when Pulling/Refreshing).\n\t * <p />\n\t * You should not keep the result of this method any longer than you need\n\t * it.\n\t * \n\t * @return Object which will proxy any calls you make on it, to all of the\n\t *         LoadingLayouts.\n\t */\n\tpublic ILoadingLayout getLoadingLayoutProxy();\n\n\t/**\n\t * Returns a proxy object which allows you to call methods on the\n\t * LoadingLayouts (the Views which show when Pulling/Refreshing). The actual\n\t * LoadingLayout(s) which will be affected, are chosen by the parameters you\n\t * give.\n\t * <p />\n\t * You should not keep the result of this method any longer than you need\n\t * it.\n\t * \n\t * @param includeStart - Whether to include the Start/Header Views\n\t * @param includeEnd - Whether to include the End/Footer Views\n\t * @return Object which will proxy any calls you make on it, to the\n\t *         LoadingLayouts included.\n\t */\n\tpublic ILoadingLayout getLoadingLayoutProxy(boolean includeStart, boolean includeEnd);\n\n\t/**\n\t * Get the mode that this view has been set to. If this returns\n\t * <code>Mode.BOTH</code>, you can use <code>getCurrentMode()</code> to\n\t * check which mode the view is currently in\n\t * \n\t * @return Mode that the view has been set to\n\t */\n\tpublic Mode getMode();\n\n\t/**\n\t * Get the Wrapped Refreshable View. Anything returned here has already been\n\t * added to the content view.\n\t * \n\t * @return The View which is currently wrapped\n\t */\n\tpublic T getRefreshableView();\n\n\t/**\n\t * Get whether the 'Refreshing' View should be automatically shown when\n\t * refreshing. Returns true by default.\n\t * \n\t * @return - true if the Refreshing View will be show\n\t */\n\tpublic boolean getShowViewWhileRefreshing();\n\n\t/**\n\t * @return - The state that the View is currently in.\n\t */\n\tpublic State getState();\n\n\t/**\n\t * Whether Pull-to-Refresh is enabled\n\t * \n\t * @return enabled\n\t */\n\tpublic boolean isPullToRefreshEnabled();\n\n\t/**\n\t * Gets whether Overscroll support is enabled. This is different to\n\t * Android's standard Overscroll support (the edge-glow) which is available\n\t * from GINGERBREAD onwards\n\t * \n\t * @return true - if both PullToRefresh-OverScroll and Android's inbuilt\n\t *         OverScroll are enabled\n\t */\n\tpublic boolean isPullToRefreshOverScrollEnabled();\n\n\t/**\n\t * Returns whether the Widget is currently in the Refreshing mState\n\t * \n\t * @return true if the Widget is currently refreshing\n\t */\n\tpublic boolean isRefreshing();\n\n    /**\n     * Stops the current refreshing view when the user needs to stop.\n     * This method is only an alias to onRefreshComplete.\n     *\n     * */\n    public void stopRefreshing();\n\n\t/**\n\t * Returns whether the widget has enabled scrolling on the Refreshable View\n\t * while refreshing.\n\t * \n\t * @return true if the widget has enabled scrolling while refreshing\n\t */\n\tpublic boolean isScrollingWhileRefreshingEnabled();\n\n\t/**\n\t * Mark the current Refresh as complete. Will Reset the UI and hide the\n\t * Refreshing View\n\t */\n\tpublic void onRefreshComplete();\n\n\t/**\n\t * Set the Touch Events to be filtered or not. If set to true, then the View\n\t * will only use touch events where the difference in the Y-axis is greater\n\t * than the difference in the X-axis. This means that the View will not\n\t * interfere when it is used in a horizontal scrolling View (such as a\n\t * ViewPager), but will restrict which types of finger scrolls will trigger\n\t * the View.\n\t * \n\t * @param filterEvents - true if you want to filter Touch Events. Default is\n\t *            true.\n\t */\n\tpublic void setFilterTouchEvents(boolean filterEvents);\n\n\t/**\n\t * Set the mode of Pull-to-Refresh that this view will use.\n\t * \n\t * @param mode - Mode to set the View to\n\t */\n\tpublic void setMode(Mode mode);\n\n\t/**\n\t * Set OnPullEventListener for the Widget\n\t * \n\t * @param listener - Listener to be used when the Widget has a pull event to\n\t *            propogate.\n\t */\n\tpublic void setOnPullEventListener(OnPullEventListener<T> listener);\n\n\t/**\n\t * Set OnRefreshListener for the Widget\n\t * \n\t * @param listener - Listener to be used when the Widget is set to Refresh\n\t */\n\tpublic void setOnRefreshListener(OnRefreshListener<T> listener);\n\n\t/**\n\t * Set OnRefreshListener for the Widget\n\t * \n\t * @param listener - Listener to be used when the Widget is set to Refresh\n\t */\n\tpublic void setOnRefreshListener(OnRefreshListener2<T> listener);\n\n\t/**\n\t * Sets whether Overscroll support is enabled. This is different to\n\t * Android's standard Overscroll support (the edge-glow). This setting only\n\t * takes effect when running on device with Android v2.3 or greater.\n\t * \n\t * @param enabled - true if you want Overscroll enabled\n\t */\n\tpublic void setPullToRefreshOverScrollEnabled(boolean enabled);\n\n\t/**\n\t * Sets the Widget to be in the refresh state. The UI will be updated to\n\t * show the 'Refreshing' view, and be scrolled to show such.\n\t */\n\tpublic void setRefreshing();\n\n\t/**\n\t * Sets the Widget to be in the refresh state. The UI will be updated to\n\t * show the 'Refreshing' view.\n\t * \n\t * @param doScroll - true if you want to force a scroll to the Refreshing\n\t *            view.\n\t */\n\tpublic void setRefreshing(boolean doScroll);\n\n\t/**\n\t * Sets the Animation Interpolator that is used for animated scrolling.\n\t * Defaults to a DecelerateInterpolator\n\t * \n\t * @param interpolator - Interpolator to use\n\t */\n\tpublic void setScrollAnimationInterpolator(Interpolator interpolator);\n\n\t/**\n\t * By default the Widget disables scrolling on the Refreshable View while\n\t * refreshing. This method can change this behaviour.\n\t * \n\t * @param scrollingWhileRefreshingEnabled - true if you want to enable\n\t *            scrolling while refreshing\n\t */\n\tpublic void setScrollingWhileRefreshingEnabled(boolean scrollingWhileRefreshingEnabled);\n\n\t/**\n\t * A mutator to enable/disable whether the 'Refreshing' View should be\n\t * automatically shown when refreshing.\n\t * \n\t * @param showView\n\t */\n\tpublic void setShowViewWhileRefreshing(boolean showView);\n\n}"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/IPullToRefreshConsumer.java",
    "content": "/*******************************************************************************\n * Copyright 2014 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n/**\n * Interface for communations with {@code PullToRefreshBase} \n * @author Wonjun Kim\n *\n */\npublic interface IPullToRefreshConsumer {\n\tvoid reset();\n\tvoid refreshing();\n\tvoid releaseToRefresh();\n\tvoid pullToRefresh();\n\tvoid onPull(float scale);\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/IndicatorLayoutFactory.java",
    "content": "/*******************************************************************************\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.InvocationTargetException;\n\nimport android.content.Context;\nimport android.util.Log;\nimport android.view.View;\n\nimport com.handmark.pulltorefresh.configuration.xml.PullToRefreshXmlConfiguration;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;\nimport com.handmark.pulltorefresh.library.internal.IndicatorLayout;\nimport com.handmark.pulltorefresh.library.internal.DefaultIndicatorLayout;\nimport com.handmark.pulltorefresh.library.internal.Utils;\n/**\n * Factory which creates indicator layouts \n * <br />Indicator layouts must be listed in pulltorefresh.xml as \"PullToRefresh/IndicatorLayouts/layout\" nodes\n * @author Wonjun Kim\n */\npublic class IndicatorLayoutFactory {\n\n\tprivate static final String LOG_TAG = IndicatorLayoutFactory.class.getName();\n\t/**\n\t * Create the class token matched by <b>{@code layoutCode}</b>\n\t * @param layoutCode Indicator layout code, which must be defined in pulltorefresh.xml \n\t * @return Class token which is matched by {@code layoutCode}, or the class token of {@code DefaultIndicatorLayout} instance if not\n\t */\n\tpublic static Class<? extends IndicatorLayout> createIndicatorLayoutClazzByLayoutCode(String layoutCode) {\n\t\tString clazzName = PullToRefreshXmlConfiguration.getInstance().getIndicatorLayoutClazzName(layoutCode);\n\t\treturn createIndicatorLayoutClazz(clazzName);\n\t}\n\t/**\n\t * Create the class token matched by <b>class name</b>\n\t * @param clazzName Class name such as \"com.handmark.pulltorefresh.library.internal.DefaultIndicatorLayout\"\n\t * @return Class token if the class matched by class name exists, or the class token of {@code DefaultIndicatorLayout} instance if not  \n\t */\n\t@SuppressWarnings(\"unchecked\")\n\tpublic static Class<? extends IndicatorLayout> createIndicatorLayoutClazz(String clazzName) {\n\t\tClass<? extends IndicatorLayout> clazz = null;\n\t\tif (clazzName == null) {\n\t\t\tclazz = DefaultIndicatorLayoutFactory.createIndicatorLayoutClazz(clazzName);\n\t\t\treturn clazz;\n\t\t}\n\t\t\n \t\ttry {\n\t\t\tclazz = (Class<? extends IndicatorLayout> )Class.forName(clazzName);\n\t\t\t\n\t\t} catch (ClassNotFoundException e) {\n\t\t\tLog.e(LOG_TAG, \"The indicator layout you have chosen class has not been found.\", e);\n\t\t\tclazz = DefaultIndicatorLayoutFactory.createIndicatorLayoutClazz(clazzName);\n\t\t\t\n\t\t}\n\t\t\n\t\treturn clazz;\n\t}\n\t/**\n\t * Create a {@code IndicatorLayout} instance matched by <b>{@code layoutCode}</b> \n\t * @param layoutCode Indicator layout code, which must be defined in pulltorefresh.xml\n\t * @param context \n\t * @param mode \n\t * @return {@code IndicatorLayout} instance if the class matched by {@code layoutCode} exists, or {@code DefaultIndicatorLayout} instance if not  \n\t */\n\tpublic static IndicatorLayout createIndicatorLayout(String layoutCode, Context context, PullToRefreshBase.Mode mode) {\n\t\tClass<? extends IndicatorLayout> clazz = createIndicatorLayoutClazz(layoutCode);\n\t\treturn createIndicatorLayout(clazz, context, mode);\n\t}\n\t/**\n\t * Create a {@code IndicatorLayout} instance matched by <b>{@code clazz} token</b> \n\t * @param clazz Indicator layout class token, which must be defined in pulltorefresh.xml\n\t * @param context \n\t * @param mode \n\t * @return {@code IndicatorLayout} instance if the class matched by {@code layoutCode} exists, or {@code DefaultIndicatorLayout} instance if not  \n\t */\n\tpublic static IndicatorLayout createIndicatorLayout(\n\t\t\tClass<? extends IndicatorLayout> clazz, Context context, Mode mode) {\n\t\tIndicatorLayout layout = null;\n\t\t// Prevent NullPointerException \n\t\tif ( clazz == null ) {\n\t\t\tLog.i(LOG_TAG, \"The Class token of the Indicator Layout is missing. Default Indicator Layout will be used.\");\n\t\t\tclazz = DefaultIndicatorLayoutFactory.createIndicatorLayoutClazz(\"\");\n\t\t}\n\t\t\n\t\tlayout = tryNewInstance(clazz, context, mode);\n\t\t\n\t\t// If trying to create new instance has failed,\n\t\tif (layout == null) {\n\t\t\tlayout = DefaultIndicatorLayoutFactory.createIndicatorLayout(clazz, context, mode);\n\t\t}\n\n\t\tlayout.setVisibility(View.INVISIBLE);\n\t\treturn layout;\n\t}\n\t\n\tprivate static IndicatorLayout tryNewInstance(\n\t\t\tClass<? extends IndicatorLayout> clazz, Context context, Mode mode) {\n\t\tIndicatorLayout layout = null;\n\t\ttry {\n\t\t\tConstructor<? extends IndicatorLayout> constructor = clazz\n\t\t\t\t\t.getConstructor(Context.class, Mode.class);\n\t\t\tlayout = (IndicatorLayout) constructor.newInstance(context, mode);\n\n\t\t} catch (IllegalArgumentException e) {\n\t\t\tLog.e(LOG_TAG, \"The indicator layout has failed to be created. \", e);\n\t\t} catch (InvocationTargetException e) {\n\t\t\tLog.e(LOG_TAG, \"The indicator layout has failed to be created. \", e);\n\t\t} catch (SecurityException e) {\n\t\t\tLog.e(LOG_TAG, \"The indicator layout has failed to be created. \", e);\n\t\t} catch (NoSuchMethodException e) {\n\t\t\tLog.e(LOG_TAG, \"The indicator layout has failed to be created. \", e);\n\t\t} catch (InstantiationException e) {\n\t\t\tLog.e(LOG_TAG, \"The indicator layout has failed to be created. \", e);\n\t\t} catch (IllegalAccessException e) {\n\t\t\tLog.e(LOG_TAG, \"The indicator layout has failed to be created. \", e);\n\t\t} catch (NullPointerException e) {\n\t\t\tLog.e(LOG_TAG, \"The indicator layout has failed to be created. \", e);\n\t\t}\n\t\t\n\t\treturn layout;\n\t}\t\n\t/**\n\t * Factory which creates a default indicator layout instance. This is used when {@code IndicatorLayoutFactory} fails to create a instance\n\t * @author Wonjun Kim\n\t *\n\t */\n\tprivate static class DefaultIndicatorLayoutFactory {\n\t\t/**\n\t\t * @param clazzName This class name is being ignored\n\t\t * @return Class token of {@code DefaultIndicatorLayout}\n\t\t */\n\t\tpublic static Class<? extends IndicatorLayout> createIndicatorLayoutClazz(String clazzName) {\n\t\t\treturn DefaultIndicatorLayout.class;\n\t\t}\n\t\t/**\n\t\t * @param clazz Class token is being ignored.\n\t\t * @param context\n\t\t * @param mode\n\t\t * @return {@code DefaultIndicatorLayout} instance\n\t\t */\n\t\tpublic static IndicatorLayout createIndicatorLayout(Class<? extends IndicatorLayout> clazz, Context context, PullToRefreshBase.Mode mode) {\n\t\t\treturn new DefaultIndicatorLayout(context, mode);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/LoadingLayoutFactory.java",
    "content": "/*******************************************************************************\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport java.lang.reflect.Constructor;\n\nimport java.lang.reflect.InvocationTargetException;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.util.Log;\nimport android.view.View;\n\nimport com.handmark.pulltorefresh.configuration.xml.PullToRefreshXmlConfiguration;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Orientation;\nimport com.handmark.pulltorefresh.library.internal.RotateLoadingLayout;\nimport com.handmark.pulltorefresh.library.internal.LoadingLayout;\n/**\n * Factory which creates loading layouts \n * <br />Loading layouts must be listed in pulltorefresh.xml as \"PullToRefresh/LoadingLayouts/layout\" nodes\n * @author Wonjun Kim\n */\nclass LoadingLayoutFactory {\n\n\tprivate static final String LOG_TAG = LoadingLayoutFactory.class\n\t\t\t.getSimpleName();\n\t/**\n\t * Create the class token matched by <b>{@code layoutCode}</b>\n\t * @param layoutCode Loading layout code, which must be defined in pulltorefresh.xml \n\t * @return Class token which is matched by {@code layoutCode}, or the class token of {@code RotateLoadingLayout} instance if not\n\t */\n\tpublic static Class<? extends LoadingLayout> createLoadingLayoutClazzByLayoutCode(String layoutCode) {\n\t\tString clazzName = PullToRefreshXmlConfiguration.getInstance().getLoadingLayoutClazzName(layoutCode);\n\t\treturn createLoadingLayoutClazz(clazzName);\n\t}\n\t/**\n\t * Create a {@code LoadingLayout} instance matched by <b>{@code clazz} token</b> \n\t * @param layoutCode Loading layout code, which must be defined in pulltorefresh.xml\n\t * @param context \n\t * @param mode \n\t * @return {@code LoadingLayout} instance if the class matched by {@code layoutCode} exists, or {@code RotateLoadingLayout} instance if not  \n\t */\n\t@SuppressWarnings(\"unchecked\")\n\tpublic static Class<? extends LoadingLayout> createLoadingLayoutClazz(\n\t\t\tString clazzName) {\n\t\tClass<? extends LoadingLayout> loadingLayoutClazz = null;\n\t\tif ( clazzName == null ) {\n\t\t\tloadingLayoutClazz = DefaultLoadingLayoutFactory.createLoadingLayoutClazz(clazzName);\n\t\t\treturn loadingLayoutClazz;\n\t\t}\n\t\t\n\t\ttry {\n\t\t\tloadingLayoutClazz = (Class<LoadingLayout>) Class.forName(clazzName);\n\n\t\t} catch (ClassNotFoundException e) {\n\t\t\tLog.e(LOG_TAG,\"The loading layout you have chosen class has not been found.\", e);\n\t\t\tloadingLayoutClazz = DefaultLoadingLayoutFactory.createLoadingLayoutClazz(clazzName);\n\t\t} \n\n\t\treturn loadingLayoutClazz;\n\t}\n\t/**\n\t * Create a {@code LoadingLayout} instance matched by <b>{@code layoutCode}</b> \n\t * @param layoutCode Loading layout code, which must be defined in pulltorefresh.xml\n\t * @param context \n\t * @param mode \n\t * @return {@code LoadingLayout} instance if the class matched by {@code layoutCode} exists, or {@code RotateLoadingLayout} instance if not  \n\t */\n\tpublic static LoadingLayout createLoadingLayout(String layoutCode, Context context, Mode mode,\n\t\t\tOrientation orientation, TypedArray attrs) {\n\t\tClass<? extends LoadingLayout> clazz = createLoadingLayoutClazz(layoutCode);\n\t\treturn createLoadingLayout(clazz, context, mode, orientation, attrs);\n\t}\n\t/**\n\t * Create a {@code LoadingLayout} instance matched by <b>{@code clazz} token</b> \n\t * @param layoutCode Loading layout code, which must be defined in pulltorefresh.xml\n\t * @param context \n\t * @param mode \n\t * @return {@code LoadingLayout} instance if the class matched by {@code layoutCode} exists, or {@code RotateLoadingLayout} instance if not  \n\t */\n\tpublic static LoadingLayout createLoadingLayout(\n\t\t\tClass<? extends LoadingLayout> clazz, Context context, Mode mode,\n\t\t\tOrientation orientation, TypedArray attrs) {\n\t\tLoadingLayout layout = null;\n\t\t// Prevent NullPointerException\n\t\tif ( clazz == null ) {\n\t\t\tLog.i(LOG_TAG, \"The Class token of the Loading Layout is missing. Default Loading Layout will be used.\");\n\t\t\tclazz = DefaultLoadingLayoutFactory.createLoadingLayoutClazz(\"\");\n\t\t}\n\t\t\n\t\tlayout = tryNewInstance(clazz, context, mode, orientation, attrs);\n\n\t\t// If trying to create new instance has failed,\n\t\tif (layout == null) {\n\t\t\tlayout = DefaultLoadingLayoutFactory.createLoadingLayout(clazz, context, mode, orientation, attrs);\n\t\t}\n\n\t\tlayout.setVisibility(View.INVISIBLE);\n\t\treturn layout;\n\t}\n\tprivate static LoadingLayout tryNewInstance(\n\t\t\tClass<? extends LoadingLayout> clazz, Context context, Mode mode,\n\t\t\tOrientation orientation, TypedArray attrs) {\n\t\tLoadingLayout layout = null;\n\t\ttry {\n\t\t\tConstructor<? extends LoadingLayout> constructor = clazz\n\t\t\t\t\t.getConstructor(Context.class, Mode.class,\n\t\t\t\t\t\t\tOrientation.class, TypedArray.class);\n\t\t\tlayout = (LoadingLayout) constructor.newInstance(context, mode,\n\t\t\t\t\torientation, attrs);\n\n\t\t} catch (IllegalArgumentException e) {\n\t\t\tLog.e(LOG_TAG, \"The loading layout has failed to be created. \", e);\n\t\t} catch (InvocationTargetException e) {\n\t\t\tLog.e(LOG_TAG, \"The loading layout has failed to be created. \", e);\n\t\t} catch (SecurityException e) {\n\t\t\tLog.e(LOG_TAG, \"The loading layout has failed to be created. \", e);\n\t\t} catch (NoSuchMethodException e) {\n\t\t\tLog.e(LOG_TAG, \"The loading layout has failed to be created. \", e);\n\t\t} catch (InstantiationException e) {\n\t\t\tLog.e(LOG_TAG, \"The loading layout has failed to be created. \", e);\n\t\t} catch (IllegalAccessException e) {\n\t\t\tLog.e(LOG_TAG, \"The loading layout has failed to be created. \", e);\n\t\t} catch (NullPointerException e) {\n\t\t\tLog.e(LOG_TAG, \"The loading layout has failed to be created. \", e);\n\t\t}\n\t\treturn layout;\n\t}\n\t/**\n\t * Factory which creates a default loading layout instance. This is used when {@code LoadingLayoutFactory} fails to create a instance\n\t * @author Wonjun Kim\n\t *\n\t */\n\tprivate static class DefaultLoadingLayoutFactory {\n\t\t/**\n\t\t * @param clazzName This class name is being ignored\n\t\t * @return Class token of {@code RotateLoadingLayout}\n\t\t */\n\t\tpublic static Class<? extends LoadingLayout> createLoadingLayoutClazz(\n\t\t\t\tString clazzName) {\n\t\t\treturn RotateLoadingLayout.class;\n\t\t}\n\t\t/**\n\t\t * @param clazz Class token is being ignored.\n\t\t * @param context\n\t\t * @param mode\n\t\t * @return {@code RotateLoadingLayout} instance\n\t\t */\n\t\tpublic static LoadingLayout createLoadingLayout(\n\t\t\t\tClass<? extends LoadingLayout> clazz, Context context,\n\t\t\t\tMode mode, Orientation orientation, TypedArray attrs) {\n\n\t\t\treturn new RotateLoadingLayout(context, mode, orientation, attrs);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/LoadingLayoutProxy.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport java.util.HashSet;\n\nimport android.graphics.Typeface;\nimport android.graphics.drawable.Drawable;\n\nimport com.handmark.pulltorefresh.library.internal.LoadingLayout;\n\npublic class LoadingLayoutProxy implements ILoadingLayout {\n\n\tprivate final HashSet<LoadingLayout> mLoadingLayouts;\n\n\tLoadingLayoutProxy() {\n\t\tmLoadingLayouts = new HashSet<LoadingLayout>();\n\t}\n\n\t/**\n\t * This allows you to add extra LoadingLayout instances to this proxy. This\n\t * is only necessary if you keep your own instances, and want to have them\n\t * included in any\n\t * {@link PullToRefreshBase#createLoadingLayoutProxy(boolean, boolean)\n\t * createLoadingLayoutProxy(...)} calls.\n\t * \n\t * @param layout - LoadingLayout to have included.\n\t */\n\tpublic void addLayout(LoadingLayout layout) {\n\t\tif (null != layout) {\n\t\t\tmLoadingLayouts.add(layout);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setLastUpdatedLabel(CharSequence label) {\n\t\tfor (LoadingLayout layout : mLoadingLayouts) {\n\t\t\tlayout.setLastUpdatedLabel(label);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setLoadingDrawable(Drawable drawable) {\n\t\tfor (LoadingLayout layout : mLoadingLayouts) {\n\t\t\tlayout.setLoadingDrawable(drawable);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setRefreshingLabel(CharSequence refreshingLabel) {\n\t\tfor (LoadingLayout layout : mLoadingLayouts) {\n\t\t\tlayout.setRefreshingLabel(refreshingLabel);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setPullLabel(CharSequence label) {\n\t\tfor (LoadingLayout layout : mLoadingLayouts) {\n\t\t\tlayout.setPullLabel(label);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setReleaseLabel(CharSequence label) {\n\t\tfor (LoadingLayout layout : mLoadingLayouts) {\n\t\t\tlayout.setReleaseLabel(label);\n\t\t}\n\t}\n\n\tpublic void setTextTypeface(Typeface tf) {\n\t\tfor (LoadingLayout layout : mLoadingLayouts) {\n\t\t\tlayout.setTextTypeface(tf);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/OverscrollHelper.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport android.annotation.TargetApi;\nimport android.util.Log;\nimport android.view.View;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.State;\n\n@TargetApi(9)\npublic final class OverscrollHelper {\n\n\tstatic final String LOG_TAG = \"OverscrollHelper\";\n\tstatic final float DEFAULT_OVERSCROLL_SCALE = 1f;\n\n\t/**\n\t * Helper method for Overscrolling that encapsulates all of the necessary\n\t * function.\n\t * <p/>\n\t * This should only be used on AdapterView's such as ListView as it just\n\t * calls through to overScrollBy() with the scrollRange = 0. AdapterView's\n\t * do not have a scroll range (i.e. getScrollY() doesn't work).\n\t * \n\t * @param view - PullToRefreshView that is calling this.\n\t * @param deltaX - Change in X in pixels, passed through from from\n\t *            overScrollBy call\n\t * @param scrollX - Current X scroll value in pixels before applying deltaY,\n\t *            passed through from from overScrollBy call\n\t * @param deltaY - Change in Y in pixels, passed through from from\n\t *            overScrollBy call\n\t * @param scrollY - Current Y scroll value in pixels before applying deltaY,\n\t *            passed through from from overScrollBy call\n\t * @param isTouchEvent - true if this scroll operation is the result of a\n\t *            touch event, passed through from from overScrollBy call\n\t */\n\tpublic static void overScrollBy(final PullToRefreshBase<?> view, final int deltaX, final int scrollX,\n\t\t\tfinal int deltaY, final int scrollY, final boolean isTouchEvent) {\n\t\toverScrollBy(view, deltaX, scrollX, deltaY, scrollY, 0, isTouchEvent);\n\t}\n\n\t/**\n\t * Helper method for Overscrolling that encapsulates all of the necessary\n\t * function. This version of the call is used for Views that need to specify\n\t * a Scroll Range but scroll back to it's edge correctly.\n\t * \n\t * @param view - PullToRefreshView that is calling this.\n\t * @param deltaX - Change in X in pixels, passed through from from\n\t *            overScrollBy call\n\t * @param scrollX - Current X scroll value in pixels before applying deltaY,\n\t *            passed through from from overScrollBy call\n\t * @param deltaY - Change in Y in pixels, passed through from from\n\t *            overScrollBy call\n\t * @param scrollY - Current Y scroll value in pixels before applying deltaY,\n\t *            passed through from from overScrollBy call\n\t * @param scrollRange - Scroll Range of the View, specifically needed for\n\t *            ScrollView\n\t * @param isTouchEvent - true if this scroll operation is the result of a\n\t *            touch event, passed through from from overScrollBy call\n\t */\n\tpublic static void overScrollBy(final PullToRefreshBase<?> view, final int deltaX, final int scrollX,\n\t\t\tfinal int deltaY, final int scrollY, final int scrollRange, final boolean isTouchEvent) {\n\t\toverScrollBy(view, deltaX, scrollX, deltaY, scrollY, scrollRange, 0, DEFAULT_OVERSCROLL_SCALE, isTouchEvent);\n\t}\n\n\t/**\n\t * Helper method for Overscrolling that encapsulates all of the necessary\n\t * function. This is the advanced version of the call.\n\t * \n\t * @param view - PullToRefreshView that is calling this.\n\t * @param deltaX - Change in X in pixels, passed through from from\n\t *            overScrollBy call\n\t * @param scrollX - Current X scroll value in pixels before applying deltaY,\n\t *            passed through from from overScrollBy call\n\t * @param deltaY - Change in Y in pixels, passed through from from\n\t *            overScrollBy call\n\t * @param scrollY - Current Y scroll value in pixels before applying deltaY,\n\t *            passed through from from overScrollBy call\n\t * @param scrollRange - Scroll Range of the View, specifically needed for\n\t *            ScrollView\n\t * @param fuzzyThreshold - Threshold for which the values how fuzzy we\n\t *            should treat the other values. Needed for WebView as it\n\t *            doesn't always scroll back to it's edge. 0 = no fuzziness.\n\t * @param scaleFactor - Scale Factor for overscroll amount\n\t * @param isTouchEvent - true if this scroll operation is the result of a\n\t *            touch event, passed through from from overScrollBy call\n\t */\n\tpublic static void overScrollBy(final PullToRefreshBase<?> view, final int deltaX, final int scrollX,\n\t\t\tfinal int deltaY, final int scrollY, final int scrollRange, final int fuzzyThreshold,\n\t\t\tfinal float scaleFactor, final boolean isTouchEvent) {\n\n\t\tfinal int deltaValue, currentScrollValue, scrollValue;\n\t\tswitch (view.getPullToRefreshScrollDirection()) {\n\t\t\tcase HORIZONTAL:\n\t\t\t\tdeltaValue = deltaX;\n\t\t\t\tscrollValue = scrollX;\n\t\t\t\tcurrentScrollValue = view.getScrollX();\n\t\t\t\tbreak;\n\t\t\tcase VERTICAL:\n\t\t\tdefault:\n\t\t\t\tdeltaValue = deltaY;\n\t\t\t\tscrollValue = scrollY;\n\t\t\t\tcurrentScrollValue = view.getScrollY();\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// Check that OverScroll is enabled and that we're not currently\n\t\t// refreshing.\n\t\tif (view.isPullToRefreshOverScrollEnabled() && !view.isRefreshing()) {\n\t\t\tfinal Mode mode = view.getMode();\n\n\t\t\t// Check that Pull-to-Refresh is enabled, and the event isn't from\n\t\t\t// touch\n\t\t\tif (mode.permitsPullToRefresh() && !isTouchEvent && deltaValue != 0) {\n\t\t\t\tfinal int newScrollValue = (deltaValue + scrollValue);\n\n\t\t\t\tif (PullToRefreshBase.DEBUG) {\n\t\t\t\t\tLog.d(LOG_TAG, \"OverScroll. DeltaX: \" + deltaX + \", ScrollX: \" + scrollX + \", DeltaY: \" + deltaY\n\t\t\t\t\t\t\t+ \", ScrollY: \" + scrollY + \", NewY: \" + newScrollValue + \", ScrollRange: \" + scrollRange\n\t\t\t\t\t\t\t+ \", CurrentScroll: \" + currentScrollValue);\n\t\t\t\t}\n\n\t\t\t\tif (newScrollValue < (0 - fuzzyThreshold)) {\n\t\t\t\t\t// Check the mode supports the overscroll direction, and\n\t\t\t\t\t// then move scroll\n\t\t\t\t\tif (mode.showHeaderLoadingLayout()) {\n\t\t\t\t\t\t// If we're currently at zero, we're about to start\n\t\t\t\t\t\t// overscrolling, so change the state\n\t\t\t\t\t\tif (currentScrollValue == 0) {\n\t\t\t\t\t\t\tview.setState(State.OVERSCROLLING);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tview.setHeaderScroll((int) (scaleFactor * (currentScrollValue + newScrollValue)));\n\t\t\t\t\t}\n\t\t\t\t} else if (newScrollValue > (scrollRange + fuzzyThreshold)) {\n\t\t\t\t\t// Check the mode supports the overscroll direction, and\n\t\t\t\t\t// then move scroll\n\t\t\t\t\tif (mode.showFooterLoadingLayout()) {\n\t\t\t\t\t\t// If we're currently at zero, we're about to start\n\t\t\t\t\t\t// overscrolling, so change the state\n\t\t\t\t\t\tif (currentScrollValue == 0) {\n\t\t\t\t\t\t\tview.setState(State.OVERSCROLLING);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tview.setHeaderScroll((int) (scaleFactor * (currentScrollValue + newScrollValue - scrollRange)));\n\t\t\t\t\t}\n\t\t\t\t} else if (Math.abs(newScrollValue) <= fuzzyThreshold\n\t\t\t\t\t\t|| Math.abs(newScrollValue - scrollRange) <= fuzzyThreshold) {\n\t\t\t\t\t// Means we've stopped overscrolling, so scroll back to 0\n\t\t\t\t\tview.setState(State.RESET);\n\t\t\t\t}\n\t\t\t} else if (isTouchEvent && State.OVERSCROLLING == view.getState()) {\n\t\t\t\t// This condition means that we were overscrolling from a fling,\n\t\t\t\t// but the user has touched the View and is now overscrolling\n\t\t\t\t// from touch instead. We need to just reset.\n\t\t\t\tview.setState(State.RESET);\n\t\t\t}\n\t\t}\n\t}\n\n\tstatic boolean isAndroidOverScrollEnabled(View view) {\n\t\treturn view.getOverScrollMode() != View.OVER_SCROLL_NEVER;\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshAdapterViewBase.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.Gravity;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.ViewParent;\nimport android.widget.AbsListView;\nimport android.widget.AbsListView.OnScrollListener;\nimport android.widget.Adapter;\nimport android.widget.AdapterView;\nimport android.widget.AdapterView.OnItemClickListener;\nimport android.widget.ArrayAdapter;\nimport android.widget.FrameLayout;\nimport android.widget.LinearLayout;\nimport android.widget.ListAdapter;\n\nimport com.handmark.pulltorefresh.library.internal.IndicatorLayout;\nimport com.handmark.pulltorefresh.library.internal.EmptyViewMethodAccessor;\nimport com.handmark.pulltorefresh.library.internal.LoadingLayout;\n\npublic abstract class PullToRefreshAdapterViewBase<T extends AbsListView> extends PullToRefreshBase<T> implements\n\t\tOnScrollListener {\n\n\tprivate static FrameLayout.LayoutParams convertEmptyViewLayoutParams(ViewGroup.LayoutParams lp) {\n\t\tFrameLayout.LayoutParams newLp = null;\n\n\t\tif (null != lp) {\n\t\t\tnewLp = new FrameLayout.LayoutParams(lp);\n\n\t\t\tif (lp instanceof LinearLayout.LayoutParams) {\n\t\t\t\tnewLp.gravity = ((LinearLayout.LayoutParams) lp).gravity;\n\t\t\t} else {\n\t\t\t\tnewLp.gravity = Gravity.CENTER;\n\t\t\t}\n\t\t}\n\n\t\treturn newLp;\n\t}\n\n\tprivate boolean mLastItemVisible;\n\tprivate OnScrollListener mOnScrollListener;\n\tprivate OnLastItemVisibleListener mOnLastItemVisibleListener;\n\tprivate View mEmptyView;\n\n\tprivate IndicatorLayout mIndicatorIvTop;\n\tprivate IndicatorLayout mIndicatorIvBottom;\n\n\tprivate boolean mShowIndicator;\n\tprivate boolean mScrollEmptyView = true;\n\t/**\n\t * <p>\n\t * Indicator Layout Class Token <br /> {@link IndicatorLayoutFactory} will create instances by using this class token.\n\t * The token must not be null. {@link IndicatorLayoutFacoty} ensures that class token exists always.\n\t * Assignment some class token into this variable is implemented at {@link #handleStyledAttributes(TypedArray)}.\n\t * </p>\n\t */\n\tprivate Class<? extends IndicatorLayout> mIndicatorLayoutClazz;\n\n\tpublic PullToRefreshAdapterViewBase(Context context) {\n\t\tsuper(context);\n\t\tmRefreshableView.setOnScrollListener(this);\n\t}\n\n\tpublic PullToRefreshAdapterViewBase(Context context, AttributeSet attrs) {\n\t\tsuper(context, attrs);\n\t\tmRefreshableView.setOnScrollListener(this);\n\t}\n\n\tpublic PullToRefreshAdapterViewBase(Context context, Mode mode) {\n\t\tsuper(context, mode);\n\t\tmRefreshableView.setOnScrollListener(this);\n\t}\n\n\tpublic PullToRefreshAdapterViewBase(Context context, Mode mode, Class<? extends LoadingLayout> loadingLayoutClazz) {\n\t\tsuper(context, mode, loadingLayoutClazz);\n\t\tmRefreshableView.setOnScrollListener(this);\n\t}\n\n\t/**\n\t * Gets whether an indicator graphic should be displayed when the View is in\n\t * a state where a Pull-to-Refresh can happen. An example of this state is\n\t * when the Adapter View is scrolled to the top and the mode is set to\n\t * {@link PullToRefreshBase.Mode#PULL_FROM_START}. The default value is <var>true</var> if\n\t * {@link PullToRefreshBase#isPullToRefreshOverScrollEnabled()\n\t * isPullToRefreshOverScrollEnabled()} returns false.\n\t * \n\t * @return true if the indicators will be shown\n\t */\n\tpublic boolean getShowIndicator() {\n\t\treturn mShowIndicator;\n\t}\n\n\tpublic final void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount,\n\t\t\tfinal int totalItemCount) {\n\n\t\tif (DEBUG) {\n\t\t\tLog.d(LOG_TAG, \"First Visible: \" + firstVisibleItem + \". Visible Count: \" + visibleItemCount\n\t\t\t\t\t+ \". Total Items:\" + totalItemCount);\n\t\t}\n\n\t\t/**\n\t\t * Set whether the Last Item is Visible. lastVisibleItemIndex is a\n\t\t * zero-based index, so we minus one totalItemCount to check\n\t\t */\n\t\tif (null != mOnLastItemVisibleListener) {\n\t\t\tmLastItemVisible = (totalItemCount > 0) && (firstVisibleItem + visibleItemCount >= totalItemCount - 1);\n\t\t}\n\n\t\t// If we're showing the indicator, check positions...\n\t\tif (getShowIndicatorInternal()) {\n\t\t\tupdateIndicatorViewsVisibility();\n\t\t}\n\n\t\t// Finally call OnScrollListener if we have one\n\t\tif (null != mOnScrollListener) {\n\t\t\tmOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);\n\t\t}\n\t}\n\n\tpublic final void onScrollStateChanged(final AbsListView view, final int state) {\n\t\t/**\n\t\t * Check that the scrolling has stopped, and that the last item is\n\t\t * visible.\n\t\t */\n\t\tif (state == OnScrollListener.SCROLL_STATE_IDLE && null != mOnLastItemVisibleListener && mLastItemVisible) {\n\t\t\tmOnLastItemVisibleListener.onLastItemVisible();\n\t\t}\n\n\t\tif (null != mOnScrollListener) {\n\t\t\tmOnScrollListener.onScrollStateChanged(view, state);\n\t\t}\n\t}\n\n\t/**\n\t * Pass-through method for {@link PullToRefreshBase#getRefreshableView()\n\t * getRefreshableView()}.\n\t * {@link AdapterView#setAdapter(android.widget.Adapter)}\n\t * setAdapter(adapter)}. This is just for convenience!\n\t * \n\t * @param adapter - Adapter to set\n\t */\n\tpublic void setAdapter(ListAdapter adapter) {\n\t\t((AdapterView<ListAdapter>) mRefreshableView).setAdapter(adapter);\n\t}\n\n\t/**\n\t * Sets the Empty View to be used by the Adapter View.\n\t * <p/>\n\t * We need it handle it ourselves so that we can Pull-to-Refresh when the\n\t * Empty View is shown.\n\t * <p/>\n\t * Please note, you do <strong>not</strong> usually need to call this method\n\t * yourself. Calling setEmptyView on the AdapterView will automatically call\n\t * this method and set everything up. This includes when the Android\n\t * Framework automatically sets the Empty View based on it's ID.\n\t * \n\t * @param newEmptyView - Empty View to be used\n\t */\n\tpublic final void setEmptyView(View newEmptyView) {\n\t\tFrameLayout refreshableViewWrapper = getRefreshableViewWrapper();\n\n\t\tif (null != newEmptyView) {\n\t\t\t// New view needs to be clickable so that Android recognizes it as a\n\t\t\t// target for Touch Events\n\t\t\tnewEmptyView.setClickable(true);\n\n\t\t\tViewParent newEmptyViewParent = newEmptyView.getParent();\n\t\t\tif (null != newEmptyViewParent && newEmptyViewParent instanceof ViewGroup) {\n\t\t\t\t((ViewGroup) newEmptyViewParent).removeView(newEmptyView);\n\t\t\t}\n\n\t\t\t// We need to convert any LayoutParams so that it works in our\n\t\t\t// FrameLayout\n\t\t\tFrameLayout.LayoutParams lp = convertEmptyViewLayoutParams(newEmptyView.getLayoutParams());\n\t\t\tif (null != lp) {\n\t\t\t\trefreshableViewWrapper.addView(newEmptyView, lp);\n\t\t\t} else {\n\t\t\t\trefreshableViewWrapper.addView(newEmptyView);\n\t\t\t}\n\t\t}\n\n\t\tif (mRefreshableView instanceof EmptyViewMethodAccessor) {\n\t\t\t((EmptyViewMethodAccessor) mRefreshableView).setEmptyViewInternal(newEmptyView);\n\t\t} else {\n\t\t\tmRefreshableView.setEmptyView(newEmptyView);\n\t\t}\n\t\tmEmptyView = newEmptyView;\n\t}\n\n\t/**\n\t * Pass-through method for {@link PullToRefreshBase#getRefreshableView()\n\t * getRefreshableView()}.\n\t * {@link AdapterView#setOnItemClickListener(OnItemClickListener)\n\t * setOnItemClickListener(listener)}. This is just for convenience!\n\t * \n\t * @param listener - OnItemClickListener to use\n\t */\n\tpublic void setOnItemClickListener(OnItemClickListener listener) {\n\t\tmRefreshableView.setOnItemClickListener(listener);\n\t}\n\n\tpublic final void setOnLastItemVisibleListener(OnLastItemVisibleListener listener) {\n\t\tmOnLastItemVisibleListener = listener;\n\t}\n\n    public final void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) {\n        mRefreshableView.setOnItemLongClickListener(listener);\n    }\n\n\tpublic final void setOnScrollListener(OnScrollListener listener) {\n\t\tmOnScrollListener = listener;\n\t}\n\n\tpublic final void setScrollEmptyView(boolean doScroll) {\n\t\tmScrollEmptyView = doScroll;\n\t}\n\n\t/**\n\t * Sets whether an indicator graphic should be displayed when the View is in\n\t * a state where a Pull-to-Refresh can happen. An example of this state is\n\t * when the Adapter View is scrolled to the top and the mode is set to\n\t * {@link PullToRefreshBase.Mode#PULL_FROM_START}\n\t * \n\t * @param showIndicator - true if the indicators should be shown.\n\t */\n\tpublic void setShowIndicator(boolean showIndicator) {\n\t\tmShowIndicator = showIndicator;\n\n\t\tif (getShowIndicatorInternal()) {\n\t\t\t// If we're set to Show Indicator, add/update them\n\t\t\taddIndicatorViews();\n\t\t} else {\n\t\t\t// If not, then remove then\n\t\t\tremoveIndicatorViews();\n\t\t}\n\t}\n\n\t;\n\n\t@Override\n\tprotected void onPullToRefresh() {\n\t\tsuper.onPullToRefresh();\n\n\t\tif (getShowIndicatorInternal()) {\n\t\t\tswitch (getCurrentMode()) {\n\t\t\t\tcase PULL_FROM_END:\n\t\t\t\t\tmIndicatorIvBottom.pullToRefresh();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PULL_FROM_START:\n\t\t\t\t\tmIndicatorIvTop.pullToRefresh();\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t// NO-OP\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected void onRefreshing(boolean doScroll) {\n\t\tsuper.onRefreshing(doScroll);\n\n\t\tif (getShowIndicatorInternal()) {\n\t\t\tupdateIndicatorViewsVisibility();\n\t\t}\n\t}\n\n\t@Override\n\tprotected void onReleaseToRefresh() {\n\t\tsuper.onReleaseToRefresh();\n\n\t\tif (getShowIndicatorInternal()) {\n\t\t\tswitch (getCurrentMode()) {\n\t\t\t\tcase PULL_FROM_END:\n\t\t\t\t\tmIndicatorIvBottom.releaseToRefresh();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PULL_FROM_START:\n\t\t\t\t\tmIndicatorIvTop.releaseToRefresh();\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t// NO-OP\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected void onReset() {\n\t\tsuper.onReset();\n\n\t\tif (getShowIndicatorInternal()) {\n\t\t\tupdateIndicatorViewsVisibility();\n\t\t}\n\t}\n\n\t@Override\n\tprotected void handleStyledAttributes(TypedArray a) {\n\t\t// Set Show Indicator to the XML value, or default value\n\t\tmShowIndicator = a.getBoolean(R.styleable.PullToRefresh_ptrShowIndicator, !isPullToRefreshOverScrollEnabled());\n\t\t\n\t\t// Get IndicatorLayout code\n\t\tString layoutCode = null;\n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrIndicatorStyle)) {\n\t\t\tlayoutCode = a.getString(R.styleable.PullToRefresh_ptrIndicatorStyle);\n\t\t\t \n\t\t} \n\t\t\n\t\t// Convert layoutCode to a class token, and assign the class token into mIndicatorLayoutClazz\n\t\tmIndicatorLayoutClazz = IndicatorLayoutFactory.createIndicatorLayoutClazzByLayoutCode(layoutCode);\n\t\t\t\n\t}\n\n\tprotected boolean isReadyForPullStart() {\n\t\treturn isFirstItemVisible();\n\t}\n\n\tprotected boolean isReadyForPullEnd() {\n\t\treturn isLastItemVisible();\n\t}\n\n\t@Override\n\tprotected void onScrollChanged(int l, int t, int oldl, int oldt) {\n\t\tsuper.onScrollChanged(l, t, oldl, oldt);\n\t\tif (null != mEmptyView && !mScrollEmptyView) {\n\t\t\tmEmptyView.scrollTo(-l, -t);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void onFinishInflate() {\n\t\tsuper.onFinishInflate();\n\t\tif (isInEditMode()) {\n\t\t\t// Only when the preview mode of IDE\n\t\t\tcreateSampleList();\n\t\t}\n\t}\n\t/**\n\t * <pre>\n\t * Create the sample list to be shown on the preview layout of IDE.\n\t * _NOTE_ : This method is used only for the preview mode of IDE.\n\t * </pre>\n\t */\n\tprivate void createSampleList() {\n\t\tList<String> listItems = Arrays.asList(new String[]{\"Item 1\", \"Item 2\", \"Item 3\", \"Item 4\", \"Item 5\", \"Item 6\", \"Item 7\"});\n\t\tListAdapter sampleAdapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_1, listItems);\n\t\tsetAdapter(sampleAdapter);\n\t}\n\n\t@Override\n\tprotected void updateUIForMode() {\n\t\tsuper.updateUIForMode();\n\n\t\t// Check Indicator Views consistent with new Mode\n\t\tif (getShowIndicatorInternal()) {\n\t\t\taddIndicatorViews();\n\t\t} else {\n\t\t\tremoveIndicatorViews();\n\t\t}\n\t}\n\n\tprivate void addIndicatorViews() {\n\t\tMode mode = getMode();\n\t\tFrameLayout refreshableViewWrapper = getRefreshableViewWrapper();\n\n\t\tif (mode.showHeaderLoadingLayout() && null == mIndicatorIvTop) {\n\t\t\t// If the mode can pull down, and we don't have one set already\n\t\t\tmIndicatorIvTop = IndicatorLayoutFactory.createIndicatorLayout(mIndicatorLayoutClazz, getContext(), Mode.PULL_FROM_START);\n\t\t\tViewGroup.LayoutParams params = mIndicatorIvTop.createApplicableHeaderLayoutParams();\n\t\t\trefreshableViewWrapper.addView(mIndicatorIvTop, params);\n\n\t\t} else if (!mode.showHeaderLoadingLayout() && null != mIndicatorIvTop) {\n\t\t\t// If we can't pull down, but have a View then remove it\n\t\t\trefreshableViewWrapper.removeView(mIndicatorIvTop);\n\t\t\tmIndicatorIvTop = null;\n\t\t}\n\n\t\tif (mode.showFooterLoadingLayout() && null == mIndicatorIvBottom) {\n\t\t\t// If the mode can pull down, and we don't have one set already\n\t\t\tmIndicatorIvBottom = IndicatorLayoutFactory.createIndicatorLayout(mIndicatorLayoutClazz, getContext(), Mode.PULL_FROM_END);\n\t\t\tViewGroup.LayoutParams params = mIndicatorIvBottom.createApplicableFooterLayoutParams();\n\t\t\trefreshableViewWrapper.addView(mIndicatorIvBottom, params);\n\n\t\t} else if (!mode.showFooterLoadingLayout() && null != mIndicatorIvBottom) {\n\t\t\t// If we can't pull down, but have a View then remove it\n\t\t\trefreshableViewWrapper.removeView(mIndicatorIvBottom);\n\t\t\tmIndicatorIvBottom = null;\n\t\t}\n\t}\n\n\tprivate boolean getShowIndicatorInternal() {\n\t\treturn mShowIndicator && isPullToRefreshEnabled();\n\t}\n\n\tprivate boolean isFirstItemVisible() {\n\t\tfinal Adapter adapter = mRefreshableView.getAdapter();\n\n\t\tif (null == adapter || adapter.isEmpty()) {\n\t\t\tif (DEBUG) {\n\t\t\t\tLog.d(LOG_TAG, \"isFirstItemVisible. Empty View.\");\n\t\t\t}\n\t\t\treturn true;\n\n\t\t} else {\n\n\t\t\t/**\n\t\t\t * This check should really just be:\n\t\t\t * mRefreshableView.getFirstVisiblePosition() == 0, but PtRListView\n\t\t\t * internally use a HeaderView which messes the positions up. For\n\t\t\t * now we'll just add one to account for it and rely on the inner\n\t\t\t * condition which checks getTop().\n\t\t\t */\n\t\t\tif (mRefreshableView.getFirstVisiblePosition() <= 1) {\n\t\t\t\tfinal View firstVisibleChild = mRefreshableView.getChildAt(0);\n\t\t\t\tif (firstVisibleChild != null) {\n\t\t\t\t\treturn firstVisibleChild.getTop() >= mRefreshableView.getTop();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate boolean isLastItemVisible() {\n\t\tfinal Adapter adapter = mRefreshableView.getAdapter();\n\n\t\tif (null == adapter || adapter.isEmpty()) {\n\t\t\tif (DEBUG) {\n\t\t\t\tLog.d(LOG_TAG, \"isLastItemVisible. Empty View.\");\n\t\t\t}\n\t\t\treturn true;\n\t\t} else {\n\t\t\tfinal int lastItemPosition = mRefreshableView.getCount() - 1;\n\t\t\tfinal int lastVisiblePosition = mRefreshableView.getLastVisiblePosition();\n\n\t\t\tif (DEBUG) {\n\t\t\t\tLog.d(LOG_TAG, \"isLastItemVisible. Last Item Position: \" + lastItemPosition + \" Last Visible Pos: \"\n\t\t\t\t\t\t+ lastVisiblePosition);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * This check should really just be: lastVisiblePosition ==\n\t\t\t * lastItemPosition, but PtRListView internally uses a FooterView\n\t\t\t * which messes the positions up. For me we'll just subtract one to\n\t\t\t * account for it and rely on the inner condition which checks\n\t\t\t * getBottom().\n\t\t\t */\n\t\t\tif (lastVisiblePosition >= lastItemPosition - 1) {\n\t\t\t\tfinal int childIndex = lastVisiblePosition - mRefreshableView.getFirstVisiblePosition();\n\t\t\t\tfinal View lastVisibleChild = mRefreshableView.getChildAt(childIndex);\n\t\t\t\tif (lastVisibleChild != null) {\n\t\t\t\t\treturn lastVisibleChild.getBottom() <= mRefreshableView.getBottom();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate void removeIndicatorViews() {\n\t\tif (null != mIndicatorIvTop) {\n\t\t\tgetRefreshableViewWrapper().removeView(mIndicatorIvTop);\n\t\t\tmIndicatorIvTop = null;\n\t\t}\n\n\t\tif (null != mIndicatorIvBottom) {\n\t\t\tgetRefreshableViewWrapper().removeView(mIndicatorIvBottom);\n\t\t\tmIndicatorIvBottom = null;\n\t\t}\n\t}\n\n\tprivate void updateIndicatorViewsVisibility() {\n\t\tif (null != mIndicatorIvTop) {\n\t\t\tif (!isRefreshing() && isReadyForPullStart()) {\n\t\t\t\tif (!mIndicatorIvTop.isVisible()) {\n\t\t\t\t\tmIndicatorIvTop.show();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (mIndicatorIvTop.isVisible()) {\n\t\t\t\t\tmIndicatorIvTop.hide();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (null != mIndicatorIvBottom) {\n\t\t\tif (!isRefreshing() && isReadyForPullEnd()) {\n\t\t\t\tif (!mIndicatorIvBottom.isVisible()) {\n\t\t\t\t\tmIndicatorIvBottom.show();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (mIndicatorIvBottom.isVisible()) {\n\t\t\t\t\tmIndicatorIvBottom.hide();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshBase.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.drawable.Drawable;\nimport android.os.Build.VERSION;\nimport android.os.Build.VERSION_CODES;\nimport android.os.Bundle;\nimport android.os.Parcelable;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.Gravity;\nimport android.view.MotionEvent;\nimport android.view.View;\nimport android.view.ViewConfiguration;\nimport android.view.ViewGroup;\nimport android.view.animation.AlphaAnimation;\nimport android.view.animation.Animation;\nimport android.view.animation.Animation.AnimationListener;\nimport android.view.animation.AnimationSet;\nimport android.view.animation.DecelerateInterpolator;\nimport android.view.animation.Interpolator;\nimport android.view.animation.TranslateAnimation;\nimport android.widget.FrameLayout;\nimport android.widget.LinearLayout;\nimport android.widget.ProgressBar;\n\nimport com.handmark.pulltorefresh.configuration.xml.PullToRefreshXmlConfiguration;\nimport com.handmark.pulltorefresh.library.internal.LoadingLayout;\nimport com.handmark.pulltorefresh.library.internal.Utils;\nimport com.handmark.pulltorefresh.library.internal.ViewCompat;\n\npublic abstract class PullToRefreshBase<T extends View> extends LinearLayout implements IPullToRefresh<T> {\n\n\t// ===========================================================\n\t// Constants\n\t// ===========================================================\n\n\tstatic final boolean DEBUG = false;\n\n\tstatic final boolean USE_HW_LAYERS = false;\n\n\tstatic final String LOG_TAG = \"PullToRefresh\";\n\n\tpublic static final float DEFAULT_FRICTION = 2.0f;\n\tpublic static final int DEFAULT_SMOOTH_SCROLL_DURATION_MS = 200;\n\tpublic static final int DEFAULT_SMOOTH_SCROLL_LONG_DURATION_MS = 325;\n\n\tstatic final int DEMO_SCROLL_INTERVAL = 225;\n\n\tstatic final String STATE_STATE = \"ptr_state\";\n\tstatic final String STATE_MODE = \"ptr_mode\";\n\tstatic final String STATE_CURRENT_MODE = \"ptr_current_mode\";\n\tstatic final String STATE_SCROLLING_REFRESHING_ENABLED = \"ptr_disable_scrolling\";\n\tstatic final String STATE_SHOW_REFRESHING_VIEW = \"ptr_show_refreshing_view\";\n\tstatic final String STATE_SUPER = \"ptr_super\";\n\n\tstatic final int REFRESHABLEVIEW_REFRESHING_BAR_VIEW_WHILE_REFRESHING_DURATION = 100;\n\tstatic final int REFRESHABLE_VIEW_HIDE_WHILE_REFRESHING_DURATION = 500;\n\tstatic final int GOOGLE_STYLE_VIEW_APPEAREANCE_DURATION = 200;\n\tstatic final int DFEAULT_REFRESHABLEVIEW_REFRESHING_BAR_SIZE = ViewGroup.LayoutParams.WRAP_CONTENT;\n\n\tstatic final int LAYER_TYPE_HARDWARE = 2;\n\tstatic final int LAYER_TYPE_NONE = 0;\n\t// ===========================================================\n\t// Fields\n\t// ===========================================================\n\t\n\tprivate int mTouchSlop;\n\tprivate float mLastMotionX, mLastMotionY;\n\tprivate float mInitialMotionX, mInitialMotionY;\n\t\n\t// needed properties while scrolling\n\tprivate float mFriction;\n\tprivate int mSmoothScrollDurationMs = 200;\n\tprivate int mSmoothScrollLongDurationMs = 325;\n\t\n\tprivate boolean mIsBeingDragged = false;\n\tprivate State mState = State.RESET;\n\tprivate Mode mMode = Mode.getDefault();\n\n\tprivate Mode mCurrentMode;\n\tT mRefreshableView;\n\tprivate FrameLayout mRefreshableViewWrapper;\n\n\tprivate boolean mShowViewWhileRefreshing = true;\n\tprivate boolean mScrollingWhileRefreshingEnabled = false;\n\tprivate boolean mFilterTouchEvents = true;\n\tprivate boolean mOverScrollEnabled = true;\n\tprivate boolean mLayoutVisibilityChangesEnabled = true;\n\n\tprivate Interpolator mScrollAnimationInterpolator;\n\tprivate Class<? extends LoadingLayout> mLoadingLayoutClazz = null;\n\t\n\tprivate LoadingLayout mHeaderLayout;\n\tprivate LoadingLayout mFooterLayout;\n\n\t/**\n\t * Top DecorView for containing google style pull to refresh \n\t */\n\tprivate FrameLayout mTopActionbarLayout;\n\t/**\n\t * Flag whether {@link #onAttachedToWindow()} event has been called\n\t */\t\n\tprivate boolean mWindowAttached = false;\n\t/**\n\t * View Layout being shown over ActionBar\n\t */\t\n\tprivate GoogleStyleViewLayout mGoogleStyleViewLayout;\n\t/**\n\t * Progress Bar being shown over ActionBar\n\t */\n\tprivate GoogleStyleProgressLayout mGoogleStyleProgressLayout;\t\n\t/**\n\t * Progress bar ratating on center while Refreshing\n\t */\t\n\tprivate ProgressBar mRefreshableViewProgressBar;\n\n\tprivate OnRefreshListener<T> mOnRefreshListener;\n\tprivate OnRefreshListener2<T> mOnRefreshListener2;\n\tprivate OnPullEventListener<T> mOnPullEventListener;\n\n\tprivate SmoothScrollRunnable mCurrentSmoothScrollRunnable;\n\n\tprivate int mStatusBarHeight;\n\t/**\n\t * Current actionbar size\n\t */\n\tprivate int mActionBarHeight;\n\t/**\n\t * Flag whether {@link #onRefreshing(boolean)} has been called\n\t */\n\tprivate boolean mRefreshing;\n\t/**\n\t * Flag whether Google style view layout appearance animation will be shown\n\t */\n\tprivate boolean mShowGoogleStyleViewAnimationEnabled = true;\n\t/**\n\t * Duration of Google style view layout appearance animation\n\t */\n\tprivate int mShowGoogleStyleViewAnimationDuration = GOOGLE_STYLE_VIEW_APPEAREANCE_DURATION;\n\t/**\n\t * Flag whether {@code mRefreshaleView} will be hidden while refreshing\n\t */\n\tprivate boolean mRefeshableViewHideWhileRefreshingEnabled = true;\n\t/**\n\t * {@code mRefreshableView}'s fade-out Duration\n\t */\n\tprivate int mRefeshableViewHideWhileRefreshingDuration = REFRESHABLE_VIEW_HIDE_WHILE_REFRESHING_DURATION;\n\t/**\n\t * Flag whether some {@code ProgressBar} will be shown while refreshing\n\t */\n\tprivate boolean mRefeshableViewRefreshingBarViewWhileRefreshingEnabled = true;\n\t/**\n\t * {@code mRefreshableViewRefreshingBar}'s fade-in Duration\n\t */\n\tprivate int mRefeshableViewRefreshingBarViewWhileRefreshingDuration = REFRESHABLEVIEW_REFRESHING_BAR_VIEW_WHILE_REFRESHING_DURATION;\n\t/**\n\t * Width of {@code mRefreshableViewRefreshingBar}\n\t */\n\tprivate int mRefeshableViewRefreshingBarWidth = DFEAULT_REFRESHABLEVIEW_REFRESHING_BAR_SIZE;\n\t/**\n\t * Height of {@code mRefreshableViewRefreshingBar}\n\t */\n\tprivate int mRefeshableViewRefreshingBarHeight = DFEAULT_REFRESHABLEVIEW_REFRESHING_BAR_SIZE;\t\n\t/**\n\t * Flag whether Google style view layout's size is set to ActionBar's size \n\t * (Don't set to false as possible, it's hard to control height if this flag is false)\n\t */\n\tprivate boolean mSetGoogleViewLayoutSizeToActionbarHeight = true;\n\n\tprivate int mYPositionOfGoogleStyleViewLayout;\n\n\tprivate int mYPositionOfGoogleStyleProgressLayout;\n\t// ===========================================================\n\t// Constructors\n\t// ===========================================================\n\tpublic PullToRefreshBase(Context context) {\n\t\tsuper(context);\n\t\tinit(context, null);\n\t}\n\n\tpublic PullToRefreshBase(Context context, AttributeSet attrs) {\n\t\tsuper(context, attrs);\n\t\tinit(context, attrs);\n\t}\n\n\tpublic PullToRefreshBase(Context context, Mode mode) {\n\t\tsuper(context);\n\t\tmMode = mode;\n\t\tinit(context, null);\n\t}\n\n\tpublic PullToRefreshBase(Context context, Mode mode, Class<? extends LoadingLayout> loadingLayoutClazz) {\n\t\tsuper(context);\n\t\tmMode = mode;\n\t\tmLoadingLayoutClazz = loadingLayoutClazz;\n\t\tinit(context, null);\n\t}\n\t\n\t@Override\n\tpublic void addView(View child, int index, ViewGroup.LayoutParams params) {\n\t\tif (DEBUG) {\n\t\t\tLog.d(LOG_TAG, \"addView: \" + child.getClass().getSimpleName());\n\t\t}\n\n\t\tfinal T refreshableView = getRefreshableView();\n\n\t\tif (refreshableView instanceof ViewGroup) {\n\t\t\t((ViewGroup) refreshableView).addView(child, index, params);\n\t\t} else {\n\t\t\tthrow new UnsupportedOperationException(\"Refreshable View is not a ViewGroup so can't addView\");\n\t\t}\n\t}\n\t\n\t@Deprecated\n\t@Override\n\tpublic final boolean demo() {\n\t\tif (mMode.showHeaderLoadingLayout() && isReadyForPullStart()) {\n\t\t\tsmoothScrollToAndBack(-getHeaderSize() * 2);\n\t\t\treturn true;\n\t\t} else if (mMode.showFooterLoadingLayout() && isReadyForPullEnd()) {\n\t\t\tsmoothScrollToAndBack(getFooterSize() * 2);\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic final Mode getCurrentMode() {\n\t\treturn mCurrentMode;\n\t}\n\n\t@Override\n\tpublic final boolean getFilterTouchEvents() {\n\t\treturn mFilterTouchEvents;\n\t}\n\n\t@Override\n\tpublic final ILoadingLayout getLoadingLayoutProxy() {\n\t\treturn getLoadingLayoutProxy(true, true);\n\t}\n\n\t@Override\n\tpublic final ILoadingLayout getLoadingLayoutProxy(boolean includeStart, boolean includeEnd) {\n\t\treturn createLoadingLayoutProxy(includeStart, includeEnd);\n\t}\n\n\t@Override\n\tpublic final Mode getMode() {\n\t\treturn mMode;\n\t}\n\n\t@Override\n\tpublic final T getRefreshableView() {\n\t\treturn mRefreshableView;\n\t}\n\n\t@Override\n\tpublic final boolean getShowViewWhileRefreshing() {\n\t\treturn mShowViewWhileRefreshing;\n\t}\n\n\t@Override\n\tpublic final State getState() {\n\t\treturn mState;\n\t}\n\n\t/**\n\t * @deprecated See {@link #isScrollingWhileRefreshingEnabled()}.\n\t */\n\tpublic final boolean isDisableScrollingWhileRefreshing() {\n\t\treturn !isScrollingWhileRefreshingEnabled();\n\t}\n\n\t@Override\n\tpublic final boolean isPullToRefreshEnabled() {\n\t\treturn mMode.permitsPullToRefresh();\n\t}\n\n\t@Override\n\tpublic final boolean isPullToRefreshOverScrollEnabled() {\n\t\treturn VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD && mOverScrollEnabled\n\t\t\t\t&& OverscrollHelper.isAndroidOverScrollEnabled(mRefreshableView);\n\t}\n\n\t@Override\n\tpublic final boolean isRefreshing() {\n\t\treturn mState == State.REFRESHING || mState == State.MANUAL_REFRESHING;\n\t}\n\n    @Override\n    public final void stopRefreshing() {\n        onRefreshComplete();\n    }\n\n\t@Override\n\tpublic final boolean isScrollingWhileRefreshingEnabled() {\n\t\treturn mScrollingWhileRefreshingEnabled;\n\t}\n\t\n\t@Override\n\tpublic final boolean onInterceptTouchEvent(MotionEvent event) {\n\n\t\tif (!isPullToRefreshEnabled()) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfinal int action = event.getAction();\n\n\t\tif (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {\n\t\t\tmIsBeingDragged = false;\n\t\t\treturn false;\n\t\t}\n\n\t\tif (action != MotionEvent.ACTION_DOWN && mIsBeingDragged) {\n\t\t\treturn true;\n\t\t}\n\n\t\tswitch (action) {\n\t\t\tcase MotionEvent.ACTION_MOVE: {\n\t\t\t\t// If we're refreshing, and the flag is set. Eat all MOVE events\n\t\t\t\tif (!mScrollingWhileRefreshingEnabled && isRefreshing()) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tif (isReadyForPull()) {\n\t\t\t\t\tfinal float y = event.getY(), x = event.getX();\n\t\t\t\t\tfinal float diff, oppositeDiff, absDiff;\n\n\t\t\t\t\t// We need to use the correct values, based on scroll\n\t\t\t\t\t// direction\n\t\t\t\t\tswitch (getFilteredPullToRefreshScrollDirection()) {\n\t\t\t\t\t\tcase HORIZONTAL:\n\t\t\t\t\t\t\tdiff = x - mLastMotionX;\n\t\t\t\t\t\t\toppositeDiff = y - mLastMotionY;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase VERTICAL:\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tdiff = y - mLastMotionY;\n\t\t\t\t\t\t\toppositeDiff = x - mLastMotionX;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tabsDiff = Math.abs(diff);\n\n\t\t\t\t\tif (absDiff > mTouchSlop && (!mFilterTouchEvents || absDiff > Math.abs(oppositeDiff))) {\n\t\t\t\t\t\tif ((mMode.showHeaderLoadingLayout() || mMode.showGoogleStyle()) && diff >= 1f && isReadyForPullStart()) {\n\t\t\t\t\t\t\tmLastMotionY = y;\n\t\t\t\t\t\t\tmLastMotionX = x;\n\t\t\t\t\t\t\tmIsBeingDragged = true;\n\t\t\t\t\t\t\tif (mMode == Mode.BOTH) {\n\t\t\t\t\t\t\t\tmCurrentMode = Mode.PULL_FROM_START;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (mMode.showFooterLoadingLayout() && diff <= -1f && isReadyForPullEnd()) {\n\t\t\t\t\t\t\tmLastMotionY = y;\n\t\t\t\t\t\t\tmLastMotionX = x;\n\t\t\t\t\t\t\tmIsBeingDragged = true;\n\t\t\t\t\t\t\tif (mMode == Mode.BOTH) {\n\t\t\t\t\t\t\t\tmCurrentMode = Mode.PULL_FROM_END;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase MotionEvent.ACTION_DOWN: {\n\t\t\t\tif (isReadyForPull()) {\n\t\t\t\t\tmLastMotionY = mInitialMotionY = event.getY();\n\t\t\t\t\tmLastMotionX = mInitialMotionX = event.getX();\n\t\t\t\t\tmIsBeingDragged = false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn mIsBeingDragged;\n\t}\n\n\t@Override\n\tpublic final void onRefreshComplete() {\n\t\tif (isRefreshing()) {\n\t\t\tsetState(State.RESET);\n\t\t}\n\t}\n\n\t@Override\n\tpublic final boolean onTouchEvent(MotionEvent event) {\n\n\t\tif (!isPullToRefreshEnabled()) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// If we're refreshing, and the flag is set. Eat the event\n\t\tif (!mScrollingWhileRefreshingEnabled && isRefreshing()) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (event.getAction() == MotionEvent.ACTION_DOWN && event.getEdgeFlags() != 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tswitch (event.getAction()) {\n\t\t\tcase MotionEvent.ACTION_MOVE: {\n\t\t\t\tif (mIsBeingDragged) {\n\t\t\t\t\tmLastMotionY = event.getY();\n\t\t\t\t\tmLastMotionX = event.getX();\n\t\t\t\t\tpullEvent();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MotionEvent.ACTION_DOWN: {\n\t\t\t\tif (isReadyForPull()) {\n\t\t\t\t\tmLastMotionY = mInitialMotionY = event.getY();\n\t\t\t\t\tmLastMotionX = mInitialMotionX = event.getX();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MotionEvent.ACTION_CANCEL:\n\t\t\tcase MotionEvent.ACTION_UP: {\n\t\t\t\tif (mIsBeingDragged) {\n\t\t\t\t\tmIsBeingDragged = false;\n\n\t\t\t\t\tif (mState == State.RELEASE_TO_REFRESH\n\t\t\t\t\t\t\t&& (null != mOnRefreshListener || null != mOnRefreshListener2)) {\n\t\t\t\t\t\tsetState(State.REFRESHING, true);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\t// If we're already refreshing, just scroll back to the top\n\t\t\t\t\tif (isRefreshing()) {\n\t\t\t\t\t\tsmoothScrollTo(0);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\t// If we haven't returned by here, then we're not in a state\n\t\t\t\t\t// to pull, so just reset\n\t\t\t\t\tsetState(State.RESET);\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\t/**\n\t * Set new friction\n\t * @param friction New friction value. Must be float. The default value is {@value #DEFAULT_FRICTION}.\n\t */\n\tpublic final void setFriction(float friction) {\n\t\tthis.mFriction = friction;\n\t}\n\t/**\n\t * Set new smooth scroll duration\n\t * @param smoothScrollDurationMs Milliseconds. The default value is {@value #DEFAULT_SMOOTH_SCROLL_DURATION_MS}.\n\t */\n\tpublic final void setSmoothScrollDuration(int smoothScrollDurationMs) {\n\t\tthis.mSmoothScrollDurationMs = smoothScrollDurationMs;\n\t} \n\t/**\n\t * Set new smooth scroll <b>longer</b> duration. <br /> This duration is only used by calling {@link #smoothScrollToLonger(int)}. \n\t * @param smoothScrollLongDurationMs Milliseconds. The default value is {@value #DEFAULT_SMOOTH_SCROLL_LONG_DURATION_MS}.\n\t */\n\tpublic final void setSmoothScrollLongDuration(int smoothScrollLongDurationMs) {\n\t\tthis.mSmoothScrollLongDurationMs = smoothScrollLongDurationMs;\n\t} \n\t/**\n\t * \n\t */\n\tpublic final void setScrollingWhileRefreshingEnabled(boolean allowScrollingWhileRefreshing) {\n\t\tmScrollingWhileRefreshingEnabled = allowScrollingWhileRefreshing;\n\t}\n\t/**\n\t * @deprecated See {@link #setScrollingWhileRefreshingEnabled(boolean)}\n\t */\n\tpublic void setDisableScrollingWhileRefreshing(boolean disableScrollingWhileRefreshing) {\n\t\tsetScrollingWhileRefreshingEnabled(!disableScrollingWhileRefreshing);\n\t}\n\n\t@Override\n\tpublic final void setFilterTouchEvents(boolean filterEvents) {\n\t\tmFilterTouchEvents = filterEvents;\n\t}\n\n\t/**\n\t * @deprecated You should now call this method on the result of\n\t *             {@link #getLoadingLayoutProxy()}.\n\t */\n\tpublic void setLastUpdatedLabel(CharSequence label) {\n\t\tgetLoadingLayoutProxy().setLastUpdatedLabel(label);\n\t}\n\n\t/**\n\t * @deprecated You should now call this method on the result of\n\t *             {@link #getLoadingLayoutProxy()}.\n\t */\n\tpublic void setLoadingDrawable(Drawable drawable) {\n\t\tgetLoadingLayoutProxy().setLoadingDrawable(drawable);\n\t}\n\n\t/**\n\t * @deprecated You should now call this method on the result of\n\t *             {@link #getLoadingLayoutProxy(boolean, boolean)}.\n\t */\n\tpublic void setLoadingDrawable(Drawable drawable, Mode mode) {\n\t\tgetLoadingLayoutProxy(mode.showHeaderLoadingLayout(), mode.showFooterLoadingLayout()).setLoadingDrawable(\n\t\t\t\tdrawable);\n\t}\n\n\t@Override\n\tpublic void setLongClickable(boolean longClickable) {\n\t\tgetRefreshableView().setLongClickable(longClickable);\n\t}\n\n\t@Override\n\tpublic final void setMode(Mode mode) {\n\t\tif (mode != mMode) {\n\t\t\tif (DEBUG) {\n\t\t\t\tLog.d(LOG_TAG, \"Setting mode to: \" + mode);\n\t\t\t}\n\t\t\tmMode = mode;\n\t\t\tupdateUIForMode();\n\t\t\tupdateUIForGoogleStyleMode();\n\t\t}\n\t}\n\n\tpublic void setOnPullEventListener(OnPullEventListener<T> listener) {\n\t\tmOnPullEventListener = listener;\n\t}\n\n\t@Override\n\tpublic final void setOnRefreshListener(OnRefreshListener<T> listener) {\n\t\tmOnRefreshListener = listener;\n\t\tmOnRefreshListener2 = null;\n\t}\n\n\t@Override\n\tpublic final void setOnRefreshListener(OnRefreshListener2<T> listener) {\n\t\tmOnRefreshListener2 = listener;\n\t\tmOnRefreshListener = null;\n\t}\n\n\t/**\n\t * @deprecated You should now call this method on the result of\n\t *             {@link #getLoadingLayoutProxy()}.\n\t */\n\tpublic void setPullLabel(CharSequence pullLabel) {\n\t\tgetLoadingLayoutProxy().setPullLabel(pullLabel);\n\t}\n\n\t/**\n\t * @deprecated You should now call this method on the result of\n\t *             {@link #getLoadingLayoutProxy(boolean, boolean)}.\n\t */\n\tpublic void setPullLabel(CharSequence pullLabel, Mode mode) {\n\t\tgetLoadingLayoutProxy(mode.showHeaderLoadingLayout(), mode.showFooterLoadingLayout()).setPullLabel(pullLabel);\n\t}\n\n\t/**\n\t * @param enable Whether Pull-To-Refresh should be used\n\t * @deprecated This simple calls setMode with an appropriate mode based on\n\t *             the passed value.\n\t */\n\tpublic final void setPullToRefreshEnabled(boolean enable) {\n\t\tsetMode(enable ? Mode.getDefault() : Mode.DISABLED);\n\t}\n\n\t@Override\n\tpublic final void setPullToRefreshOverScrollEnabled(boolean enabled) {\n\t\tmOverScrollEnabled = enabled;\n\t}\n\n\t@Override\n\tpublic final void setRefreshing() {\n\t\tsetRefreshing(true);\n\t}\n\n\t@Override\n\tpublic final void setRefreshing(boolean doScroll) {\n\t\tif (!isRefreshing()) {\n\t\t\tsetState(State.MANUAL_REFRESHING, doScroll);\n\t\t}\n\t}\n\n\t/**\n\t * @deprecated You should now call this method on the result of\n\t *             {@link #getLoadingLayoutProxy()}.\n\t */\n\tpublic void setRefreshingLabel(CharSequence refreshingLabel) {\n\t\tgetLoadingLayoutProxy().setRefreshingLabel(refreshingLabel);\n\t}\n\n\t/**\n\t * @deprecated You should now call this method on the result of\n\t *             {@link #getLoadingLayoutProxy(boolean, boolean)}.\n\t */\n\tpublic void setRefreshingLabel(CharSequence refreshingLabel, Mode mode) {\n\t\tgetLoadingLayoutProxy(mode.showHeaderLoadingLayout(), mode.showFooterLoadingLayout()).setRefreshingLabel(\n\t\t\t\trefreshingLabel);\n\t}\n\n\t/**\n\t * @deprecated You should now call this method on the result of\n\t *             {@link #getLoadingLayoutProxy()}.\n\t */\n\tpublic void setReleaseLabel(CharSequence releaseLabel) {\n\t\tsetReleaseLabel(releaseLabel, Mode.BOTH);\n\t}\n\n\t/**\n\t * @deprecated You should now call this method on the result of\n\t *             {@link #getLoadingLayoutProxy(boolean, boolean)}.\n\t */\n\tpublic void setReleaseLabel(CharSequence releaseLabel, Mode mode) {\n\t\tgetLoadingLayoutProxy(mode.showHeaderLoadingLayout(), mode.showFooterLoadingLayout()).setReleaseLabel(\n\t\t\t\treleaseLabel);\n\t}\n\n\tpublic void setScrollAnimationInterpolator(Interpolator interpolator) {\n\t\tmScrollAnimationInterpolator = interpolator;\n\t}\n\n\t@Override\n\tpublic final void setShowViewWhileRefreshing(boolean showView) {\n\t\tmShowViewWhileRefreshing = showView;\n\t}\n\n\t/**\n\t * @return Either {@link Orientation#VERTICAL} or\n\t *         {@link Orientation#HORIZONTAL} depending on the scroll direction.\n\t */\n\tpublic abstract Orientation getPullToRefreshScrollDirection();\n\t/**\n\t * <p>\n\t * Wrap {@link #getPullToRefreshScrollDirection()} method <br />\n\t * Other methods Use this method instead of {@link #getPullToRefreshScrollDirection()} method, because an orientation must be VERTICAL when mode is google style\n\t * </p>\n\t * @return Oreintation.VERTICAL if mMode.showGoogleStyle() is true,<br />Return value of {@link #getPullToRefreshScrollDirection()} method if else \n\t */\n\tpublic final Orientation getFilteredPullToRefreshScrollDirection() {\n\t\tOrientation orientation = getPullToRefreshScrollDirection();\n\t\tif (mMode.showGoogleStyle() ) {\n\t\t\torientation = Orientation.VERTICAL;\n\t\t}\n\t\treturn orientation;\n\t}\n\n\tfinal void setState(State state, final boolean... params) {\n\t\tmState = state;\n\t\tif (DEBUG) {\n\t\t\tLog.d(LOG_TAG, \"State: \" + mState.name());\n\t\t}\n\n\t\tswitch (mState) {\n\t\t\tcase RESET:\n\t\t\t\tonReset();\n\t\t\t\tbreak;\n\t\t\tcase PULL_TO_REFRESH:\n\t\t\t\tonPullToRefresh();\n\t\t\t\tbreak;\n\t\t\tcase RELEASE_TO_REFRESH:\n\t\t\t\tonReleaseToRefresh();\n\t\t\t\tbreak;\n\t\t\tcase REFRESHING:\n\t\t\tcase MANUAL_REFRESHING:\n\t\t\t\tonRefreshing(params[0]);\n\t\t\t\tbreak;\n\t\t\tcase OVERSCROLLING:\n\t\t\t\t// NO-OP\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// Call OnPullEventListener\n\t\tif (null != mOnPullEventListener) {\n\t\t\tmOnPullEventListener.onPullEvent(this, mState, mCurrentMode);\n\t\t}\n\t}\n\n\t/**\n\t * Used internally for adding view. Need because we override addView to\n\t * pass-through to the Refreshable View\n\t */\n\tprotected final void addViewInternal(View child, int index, ViewGroup.LayoutParams params) {\n\t\tsuper.addView(child, index, params);\n\t}\n\n\t/**\n\t * Used internally for adding view. Need because we override addView to\n\t * pass-through to the Refreshable View\n\t */\n\tprotected final void addViewInternal(View child, ViewGroup.LayoutParams params) {\n\t\tsuper.addView(child, -1, params);\n\t}\n\n\t/**\n\t * Create a new loading layout instance by using the class token {@link #mLoadingLayoutClazz}\n\t * @param context\n\t * @param mode\n\t * @param attrs\n\t * @return Loading layout instance which was created by using the class token {@link #mLoadingLayoutClazz}\n\t */\n\tprotected LoadingLayout createLoadingLayout(Context context, Mode mode, TypedArray attrs) {\n\t\treturn LoadingLayoutFactory.createLoadingLayout(mLoadingLayoutClazz, context, mode, getFilteredPullToRefreshScrollDirection(), attrs);\n\t}\n\t/**\n\t * Create a new google style view layout instance by using the class token \n\t * @param layoutCode Google style view layout code to be converted to some class token \n\t * @param context\n\t * @param mode\n\t * @param attrs\n\t * @return Google style <b>view</b> layout instance which was created by using the class token\n\t */\n\tprivate GoogleStyleViewLayout createGoogleStyleViewLayout(\n\t\t\tString layoutCode, Context context, TypedArray a) {\n\t\tClass<? extends GoogleStyleViewLayout> clazz = GoogleStyleViewLayoutFactory.createGoogleStyleViewLayoutClazzByLayoutCode(layoutCode);\n\t\treturn GoogleStyleViewLayoutFactory.createGoogleStyleViewLayout(clazz, context, a);\n\t}\t\n\t/**\n\t * Create a new google style progress layout instance by using the class token \n\t * @param layoutCode google style progress layout code  to be converted to some class token \n\t * @param context\n\t * @param mode\n\t * @param attrs\n\t * @return Google style <b>progress</b> layout instance which was created by using the class token\n\t */\n\tprivate GoogleStyleProgressLayout createGoogleStyleProgressLayout(\n\t\t\tString layoutCode, Context context, TypedArray a) {\n\t\tClass<? extends GoogleStyleProgressLayout> clazz = GoogleStyleProgressLayoutFactory.createGoogleStyleProgressLayoutClazzByLayoutCode(layoutCode);\n\t\treturn GoogleStyleProgressLayoutFactory.createGoogleStyleProgressLayout(clazz, context, a);\n\t}\n\t/**\n\t * Used internally for {@link #getLoadingLayoutProxy(boolean, boolean)}.\n\t * Allows derivative classes to include any extra LoadingLayouts.\n\t */\n\tprotected LoadingLayoutProxy createLoadingLayoutProxy(final boolean includeStart, final boolean includeEnd) {\n\t\tLoadingLayoutProxy proxy = new LoadingLayoutProxy();\n\n\t\tif (includeStart && mMode.showHeaderLoadingLayout()) {\n\t\t\tproxy.addLayout(mHeaderLayout);\n\t\t}\n\t\tif (includeEnd && mMode.showFooterLoadingLayout()) {\n\t\t\tproxy.addLayout(mFooterLayout);\n\t\t}\n\n\t\treturn proxy;\n\t}\n\n\t/**\n\t * This is implemented by derived classes to return the created View. If you\n\t * need to use a custom View (such as a custom ListView), override this\n\t * method and return an instance of your custom class.\n\t * <p/>\n\t * Be sure to set the ID of the view in this method, especially if you're\n\t * using a ListActivity or ListFragment.\n\t * \n\t * @param context Context to create view with\n\t * @param attrs AttributeSet from wrapped class. Means that anything you\n\t *            include in the XML layout declaration will be routed to the\n\t *            created View\n\t * @return New instance of the Refreshable View\n\t */\n\tprotected abstract T createRefreshableView(Context context, AttributeSet attrs);\n\n\tprotected final void disableLoadingLayoutVisibilityChanges() {\n\t\tmLayoutVisibilityChangesEnabled = false;\n\t}\n\n\tprotected final LoadingLayout getFooterLayout() {\n\t\treturn mFooterLayout;\n\t}\n\n\tprotected final int getFooterSize() {\n\t\treturn mFooterLayout.getContentSize();\n\t}\n\n\tprotected final LoadingLayout getHeaderLayout() {\n\t\treturn mHeaderLayout;\n\t}\n\n\tprotected final int getHeaderSize() {\n\t\treturn mHeaderLayout.getContentSize();\n\t}\n\n\tprotected final int getGoogleStyleViewSize() {\n\t\treturn mGoogleStyleViewLayout.getContentSize();\n\t}\n\n\tprotected int getPullToRefreshScrollDuration() {\n\t\treturn mSmoothScrollDurationMs;\n\t}\n\n\tprotected int getPullToRefreshScrollDurationLonger() {\n\t\treturn mSmoothScrollLongDurationMs;\n\t}\n\n\tprotected FrameLayout getRefreshableViewWrapper() {\n\t\treturn mRefreshableViewWrapper;\n\t}\n\n\t/**\n\t * Allows Derivative classes to handle the XML Attrs without creating a\n\t * TypedArray themsevles\n\t * \n\t * @param a - TypedArray of PullToRefresh Attributes\n\t */\n\tprotected void handleStyledAttributes(TypedArray a) {\n\t}\n\n\t/**\n\t * Implemented by derived class to return whether the View is in a state\n\t * where the user can Pull to Refresh by scrolling from the end.\n\t * \n\t * @return true if the View is currently in the correct state (for example,\n\t *         bottom of a ListView)\n\t */\n\tprotected abstract boolean isReadyForPullEnd();\n\n\t/**\n\t * Implemented by derived class to return whether the View is in a state\n\t * where the user can Pull to Refresh by scrolling from the start.\n\t * \n\t * @return true if the View is currently the correct state (for example, top\n\t *         of a ListView)\n\t */\n\tprotected abstract boolean isReadyForPullStart();\n\n\t/**\n\t * Called by {@link #onRestoreInstanceState(Parcelable)} so that derivative\n\t * classes can handle their saved instance state.\n\t * \n\t * @param savedInstanceState - Bundle which contains saved instance state.\n\t */\n\tprotected void onPtrRestoreInstanceState(Bundle savedInstanceState) {\n\t}\n\n\t/**\n\t * Called by {@link #onSaveInstanceState()} so that derivative classes can\n\t * save their instance state.\n\t * \n\t * @param saveState - Bundle to be updated with saved state.\n\t */\n\tprotected void onPtrSaveInstanceState(Bundle saveState) {\n\t}\n\n\t/**\n\t * Called when the UI has been to be updated to be in the\n\t * {@link State#PULL_TO_REFRESH} state.\n\t */\n\tprotected void onPullToRefresh() {\n\t\tswitch (mCurrentMode) {\n\t\t\tcase PULL_FROM_END:\n\t\t\t\tmFooterLayout.pullToRefresh();\n\t\t\t\tbreak;\n\t\t\tcase GOOGLE_STYLE:\n\t\t\t\tshowViewTopLayout();\n\t\t\t\tmGoogleStyleViewLayout.pullToRefresh();\n\t\t\t\tmGoogleStyleProgressLayout.pullToRefresh();\n\t\t\t\tbreak;\n\t\t\tcase PULL_FROM_START:\n\t\t\t\tmHeaderLayout.pullToRefresh();\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t// NO-OP\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/**\n\t * Called when the UI has been to be updated to be in the\n\t * {@link State#REFRESHING} or {@link State#MANUAL_REFRESHING} state.\n\t * \n\t * @param doScroll - Whether the UI should scroll for this event.\n\t */\n\tprotected void onRefreshing(final boolean doScroll) {\n\t\t// Set the flag as below for fade-in animation of mRefreshableView when releasing \n\t\tmRefreshing = true;\n\n\t\tif (mMode.showHeaderLoadingLayout()) {\n\t\t\tmHeaderLayout.refreshing();\n\t\t}\n\t\tif (mMode.showFooterLoadingLayout()) {\n\t\t\tmFooterLayout.refreshing();\n\t\t}\n\t\tif (mMode.showGoogleStyle()) {\n\t\t\t// Fade-out mRefreshableView\n\t\t\tif ( mRefeshableViewHideWhileRefreshingEnabled == true ) {\n\t\t\t\tAlphaAnimator.fadeout(mRefreshableView, mRefeshableViewHideWhileRefreshingDuration);\t\n\t\t\t}\n\t\t\t// Fade-in refreshing bar on center\n\t\t\tif (mRefeshableViewRefreshingBarViewWhileRefreshingEnabled == true ) {\n\t\t\t\tmRefreshableViewProgressBar.setVisibility(View.VISIBLE);\n\t\t\t\tAlphaAnimator.fadein(mRefreshableViewProgressBar, mRefeshableViewRefreshingBarViewWhileRefreshingDuration);\n\t\t\t}\n\n\t\t\tmGoogleStyleViewLayout.refreshing();\n\t\t\tmGoogleStyleProgressLayout.refreshing();\n\t\t}\n\n\t\tif (doScroll) {\n\t\t\tif (mShowViewWhileRefreshing) {\n\n\t\t\t\t// Call Refresh Listener when the Scroll has finished\n\t\t\t\tOnSmoothScrollFinishedListener listener = new OnSmoothScrollFinishedListener() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void onSmoothScrollFinished() {\n\t\t\t\t\t\tcallRefreshListener();\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tswitch (mCurrentMode) {\n\t\t\t\t\tcase MANUAL_REFRESH_ONLY:\n\t\t\t\t\tcase PULL_FROM_END:\n\t\t\t\t\t\tsmoothScrollTo(getFooterSize(), listener);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\tcase PULL_FROM_START:\n\t\t\t\t\t\tsmoothScrollTo(-getHeaderSize(), listener);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsmoothScrollTo(0);\n\t\t\t}\n\t\t} else {\n\t\t\t// We're not scrolling, so just call Refresh Listener now\n\t\t\tcallRefreshListener();\n\t\t}\n\t}\n\n\t/**\n\t * Called when the UI has been to be updated to be in the\n\t * {@link State#RELEASE_TO_REFRESH} state.\n\t */\n\tprotected void onReleaseToRefresh() {\n\t\tswitch (mCurrentMode) {\n\t\t\tcase PULL_FROM_END:\n\t\t\t\tmFooterLayout.releaseToRefresh();\n\t\t\t\tbreak;\n\t\t\tcase GOOGLE_STYLE:\n\t\t\t\tmGoogleStyleViewLayout.releaseToRefresh();\n\t\t\t\tmGoogleStyleProgressLayout.releaseToRefresh();\n\t\t\t\tbreak;\n\t\t\tcase PULL_FROM_START:\n\t\t\t\tmHeaderLayout.releaseToRefresh();\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t// NO-OP\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/**\n\t * Called when the UI has been to be updated to be in the\n\t * {@link State#RESET} state.\n\t */\n\tprotected void onReset() {\n\t\tmIsBeingDragged = false;\n\t\tmLayoutVisibilityChangesEnabled = true;\n\n\t\t// Always reset both layouts, just in case...\n\t\tmHeaderLayout.reset();\n\t\tmFooterLayout.reset();\n\t\tif (mMode.showGoogleStyle()) {\n\t\t\tmGoogleStyleViewLayout.reset();\n\t\t\thideViewTopLayout();\n\t\t\tmGoogleStyleProgressLayout.reset();\n\n\t\t\t// Fade-in mRefreshableView\n\t\t\tif ( mRefreshing == true && mRefeshableViewHideWhileRefreshingEnabled == true ) {\n\t\t\t\tmRefreshableView.clearAnimation();\n\t\t\t\tAlphaAnimator.fadein(mRefreshableView, mRefeshableViewHideWhileRefreshingDuration);\n\t\t\t}\n\t\t\t// Fade-out refreshing bar on center\n\t\t\tif (mRefeshableViewRefreshingBarViewWhileRefreshingEnabled == true ) {\n\t\t\t\tAlphaAnimator.fadeout(mRefreshableViewProgressBar, mRefeshableViewRefreshingBarViewWhileRefreshingDuration, new AnimationListener(){\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void onAnimationEnd(Animation animation) {\n\t\t\t\t\t\tmRefreshableViewProgressBar.setVisibility(View.INVISIBLE);\t\t\t\t\t\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void onAnimationRepeat(Animation animation) {\n\t\t\t\t\t\t// do nothing\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void onAnimationStart(Animation animation) {\n\t\t\t\t\t\t// do nothing\n\t\t\t\t\t}});\t\n\t\t\t}\n\t\t}\n\n\t\tmRefreshing = false;\n\t\tsmoothScrollTo(0);\n\t}\n\n\t@Override\n\tprotected final void onRestoreInstanceState(Parcelable state) {\n\t\tif (state instanceof Bundle) {\n\t\t\tBundle bundle = (Bundle) state;\n\n\t\t\tsetMode(Mode.mapIntToValue(bundle.getInt(STATE_MODE, 0)));\n\t\t\tmCurrentMode = Mode.mapIntToValue(bundle.getInt(STATE_CURRENT_MODE, 0));\n\n\t\t\tmScrollingWhileRefreshingEnabled = bundle.getBoolean(STATE_SCROLLING_REFRESHING_ENABLED, false);\n\t\t\tmShowViewWhileRefreshing = bundle.getBoolean(STATE_SHOW_REFRESHING_VIEW, true);\n\n\t\t\t// Let super Restore Itself\n\t\t\tsuper.onRestoreInstanceState(bundle.getParcelable(STATE_SUPER));\n\n\t\t\tState viewState = State.mapIntToValue(bundle.getInt(STATE_STATE, 0));\n\t\t\tif (viewState == State.REFRESHING || viewState == State.MANUAL_REFRESHING) {\n\t\t\t\tsetState(viewState, true);\n\t\t\t}\n\n\t\t\t// Now let derivative classes restore their state\n\t\t\tonPtrRestoreInstanceState(bundle);\n\t\t\treturn;\n\t\t}\n\n\t\tsuper.onRestoreInstanceState(state);\n\t}\n\n\t@Override\n\tprotected final Parcelable onSaveInstanceState() {\n\t\tBundle bundle = new Bundle();\n\n\t\t// Let derivative classes get a chance to save state first, that way we\n\t\t// can make sure they don't overrite any of our values\n\t\tonPtrSaveInstanceState(bundle);\n\n\t\tbundle.putInt(STATE_STATE, mState.getIntValue());\n\t\tbundle.putInt(STATE_MODE, mMode.getIntValue());\n\t\tbundle.putInt(STATE_CURRENT_MODE, mCurrentMode.getIntValue());\n\t\tbundle.putBoolean(STATE_SCROLLING_REFRESHING_ENABLED, mScrollingWhileRefreshingEnabled);\n\t\tbundle.putBoolean(STATE_SHOW_REFRESHING_VIEW, mShowViewWhileRefreshing);\n\t\tbundle.putParcelable(STATE_SUPER, super.onSaveInstanceState());\n\n\t\treturn bundle;\n\t}\n\n\t@Override\n\tprotected final void onSizeChanged(int w, int h, int oldw, int oldh) {\n\t\tif (DEBUG) {\n\t\t\tLog.d(LOG_TAG, String.format(\"onSizeChanged. W: %d, H: %d\", w, h));\n\t\t}\n\n\t\tsuper.onSizeChanged(w, h, oldw, oldh);\n\n\t\t// Skip if this view is loaded from preview mode of IDE\n\t\tif (isInEditMode()) {\n\t\t\treturn;\n\t\t}\n\t\t// We need to update the header/footer when our size changes\n\t\trefreshLoadingViewsSize();\n\n\t\t// Update the Refreshable View layout\n\t\trefreshRefreshableViewSize(w, h);\n\n\t\t/**\n\t\t * As we're currently in a Layout Pass, we need to schedule another one\n\t\t * to layout any changes we've made here\n\t\t */\n\t\tpost(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\trequestLayout();\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Re-measure the Loading Views height, and adjust internal padding as\n\t * necessary\n\t */\n\tprotected final void refreshLoadingViewsSize() {\n\t\tfinal int maximumPullScroll = (int) (getMaximumPullScroll() * 1.2f);\n\n\t\tint pLeft = getPaddingLeft();\n\t\tint pTop = getPaddingTop();\n\t\tint pRight = getPaddingRight();\n\t\tint pBottom = getPaddingBottom();\n\n\t\tswitch (getFilteredPullToRefreshScrollDirection()) {\n\t\t\tcase HORIZONTAL:\n\t\t\t\tif (mMode.showHeaderLoadingLayout()) {\n\t\t\t\t\tmHeaderLayout.setWidth(maximumPullScroll);\n\t\t\t\t\tpLeft = -maximumPullScroll;\n\t\t\t\t} else {\n\t\t\t\t\tpLeft = 0;\n\t\t\t\t}\n\n\t\t\t\tif (mMode.showFooterLoadingLayout()) {\n\t\t\t\t\tmFooterLayout.setWidth(maximumPullScroll);\n\t\t\t\t\tpRight = -maximumPullScroll;\n\t\t\t\t} else {\n\t\t\t\t\tpRight = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase VERTICAL:\n\t\t\t\tif (mMode.showHeaderLoadingLayout()) {\n\t\t\t\t\tmHeaderLayout.setHeight(maximumPullScroll);\n\t\t\t\t\tpTop = -maximumPullScroll;\n\t\t\t\t} else if (mMode.showGoogleStyle() && mWindowAttached == true ) {\n\t\t\t\t\t/**\n\t\t\t\t\t * Set size of {@code GoogleStyleViewLayout} to ActionBar's size if {@code mSetGoogleViewLayoutSizeToActionbarHeight} is true\n\t\t\t\t\t * This code is a default action, but if you want to use custom size of {@code GoogleStyleViewLayout}, set {@code ptrSetGoogleViewLayoutSizeToActionbarHeight} to false in layout xml (but not recommended).\n\t\t\t\t\t */\n\t\t\t\t\tif (mSetGoogleViewLayoutSizeToActionbarHeight == true) {\n\t\t\t\t\t\tmGoogleStyleViewLayout.setHeight(mActionBarHeight);\n\t\t\t\t\t}\n\n\t\t\t\t\tpTop = 0;\n\t\t\t\t} else {\n\t\t\t\t\tpTop = 0;\n\t\t\t\t}\n\n\t\t\t\tif (mMode.showFooterLoadingLayout()) {\n\t\t\t\t\tmFooterLayout.setHeight(maximumPullScroll);\n\t\t\t\t\tpBottom = -maximumPullScroll;\n\t\t\t\t} else {\n\t\t\t\t\tpBottom = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (DEBUG) {\n\t\t\tLog.d(LOG_TAG, String.format(\"Setting Padding. L: %d, T: %d, R: %d, B: %d\", pLeft, pTop, pRight, pBottom));\n\t\t}\n\t\tsetPadding(pLeft, pTop, pRight, pBottom);\n\t}\n\n\tprotected final void refreshRefreshableViewSize(int width, int height) {\n\t\t// We need to set the Height of the Refreshable View to the same as\n\t\t// this layout\n\t\tLinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mRefreshableViewWrapper.getLayoutParams();\n\n\t\tswitch (getFilteredPullToRefreshScrollDirection()) {\n\t\t\tcase HORIZONTAL:\n\t\t\t\tif (lp.width != width) {\n\t\t\t\t\tlp.width = width;\n\t\t\t\t\tmRefreshableViewWrapper.requestLayout();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase VERTICAL:\n\t\t\t\tif (lp.height != height) {\n\t\t\t\t\tlp.height = height;\n\t\t\t\t\tmRefreshableViewWrapper.requestLayout();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/**\n\t * Helper method which just calls scrollTo() in the correct scrolling\n\t * direction.\n\t * \n\t * @param value - New Scroll value\n\t */\n\tprotected final void setHeaderScroll(int value) {\n\t\tif (DEBUG) {\n\t\t\tLog.d(LOG_TAG, \"setHeaderScroll: \" + value);\n\t\t}\n\n\t\t// Clamp value to with pull scroll range\n\t\tfinal int maximumPullScroll = getMaximumPullScroll();\n\t\tvalue = Math.min(maximumPullScroll, Math.max(-maximumPullScroll, value));\n\n\t\tif (mLayoutVisibilityChangesEnabled) {\n\t\t\tif (value < 0) {\n\t\t\t\tswitch (mCurrentMode) {\n\t\t\t\t\tcase GOOGLE_STYLE:\n\t\t\t\t\t\tmGoogleStyleViewLayout.setVisibility(View.VISIBLE);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\t\n\t\t\t\t\tcase PULL_FROM_START:\n\t\t\t\t\t\tmHeaderLayout.setVisibility(View.VISIBLE);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else if (value > 0) {\n\t\t\t\tmFooterLayout.setVisibility(View.VISIBLE);\n\t\t\t} else {\n\t\t\t\tmHeaderLayout.setVisibility(View.INVISIBLE);\n\t\t\t\tmFooterLayout.setVisibility(View.INVISIBLE);\n\t\t\t}\n\t\t}\n\n\t\tif (USE_HW_LAYERS) {\n\t\t\t/**\n\t\t\t * Use a Hardware Layer on the Refreshable View if we've scrolled at\n\t\t\t * all. We don't use them on the Header/Footer Views as they change\n\t\t\t * often, which would negate any HW layer performance boost.\n\t\t\t */\n\t\t\tViewCompat.setLayerType(mRefreshableViewWrapper, value != 0 ? LAYER_TYPE_HARDWARE \n\t\t\t\t\t: LAYER_TYPE_NONE /* View.LAYER_TYPE_NONE */);\n\t\t}\n\n\t\t// skip ScrollTo(...) \n\t\tif (mMode.showGoogleStyle() ) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch (getFilteredPullToRefreshScrollDirection()) {\n\t\t\tcase VERTICAL:\n\t\t\t\tscrollTo(0, value);\n\t\t\t\tbreak;\n\t\t\tcase HORIZONTAL:\n\t\t\t\tscrollTo(value, 0);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/**\n\t * Smooth Scroll to position using the duration of\n\t * {@link #mSmoothScrollDurationMs} ms.\n\t * \n\t * @param scrollValue - Position to scroll to\n\t */\n\tprotected final void smoothScrollTo(int scrollValue) {\n\t\tsmoothScrollTo(scrollValue, getPullToRefreshScrollDuration());\n\t}\n\n\t/**\n\t * Smooth Scroll to position using the the duration of\n\t * {@link #mSmoothScrollDurationMs} ms.\n\t * \n\t * @param scrollValue - Position to scroll to\n\t * @param listener - Listener for scroll\n\t */\n\tprotected final void smoothScrollTo(int scrollValue, OnSmoothScrollFinishedListener listener) {\n\t\tsmoothScrollTo(scrollValue, getPullToRefreshScrollDuration(), 0, listener);\n\t}\n\n\t/**\n\t * Smooth Scroll to position using the longer the duration of\n\t * {@link #mSmoothScrollLongDurationMs} ms.\n\t * \n\t * @param scrollValue - Position to scroll to\n\t */\n\tprotected final void smoothScrollToLonger(int scrollValue) {\n\t\tsmoothScrollTo(scrollValue, getPullToRefreshScrollDurationLonger());\n\t}\n\n\t/**\n\t * Updates the View State when the mode has been set. This does not do any\n\t * checking that the mode is different to current state so always updates.\n\t */\n\tprotected void updateUIForMode() {\n\t\t// We need to use the correct LayoutParam values, based on scroll\n\t\t// direction\n\t\tfinal LinearLayout.LayoutParams lp = getLoadingLayoutLayoutParams();\n\n\t\t// Remove Header, and then add Header Loading View again if needed\n\t\tif (this == mHeaderLayout.getParent()) {\n\t\t\tremoveView(mHeaderLayout);\n\t\t}\n\t\tif (mMode.showHeaderLoadingLayout()) {\n\t\t\taddViewInternal(mHeaderLayout, 0, lp);\n\t\t}\n\n\t\t// Remove Footer, and then add Footer Loading View again if needed\n\t\tif (this == mFooterLayout.getParent()) {\n\t\t\tremoveView(mFooterLayout);\n\t\t}\n\t\tif (mMode.showFooterLoadingLayout()) {\n\t\t\taddViewInternal(mFooterLayout, lp);\n\t\t}\n\n\t\t// Hide Loading Views\n\t\trefreshLoadingViewsSize();\n\n\t\t// If we're not using Mode.BOTH, set mCurrentMode to mMode, otherwise\n\t\t// set it to pull down\n\t\tmCurrentMode = (mMode != Mode.BOTH) ? mMode : Mode.PULL_FROM_START;\n\t}\n\t/**\n\t * Be called separately for google style mode when updating ui\n\t */\n\tprotected void updateUIForGoogleStyleMode() {\n\t    // Skip if this view is loaded from preview mode of IDE\n\t\tif (isInEditMode()) {\n\t\t\treturn;\n\t\t}\n\t\tif ( mWindowAttached == false ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( mMode.showGoogleStyle() == false ) {\n            return;\n        }\n\n\t\t// We need to use the correct LayoutParam values, based on scroll\n\t\t// direction\n\t\t//\n\t\tif ( mTopActionbarLayout == mGoogleStyleViewLayout.getParent()) {\n\t\t\tmTopActionbarLayout.removeView(mGoogleStyleViewLayout);\n\t\t}\n\n\t\tLog.d(LOG_TAG, \"mViewOnTopLayout has been added.\" + mGoogleStyleViewLayout);\n\t\tmTopActionbarLayout.addView(mGoogleStyleViewLayout);\n\t\t/**\n\t\t * Set size of {@code GoogleStyleViewLayout} to ActionBar's size if {@code mSetGoogleViewLayoutSizeToActionbarHeight} is true\n\t\t * This code is a default action, but if you want to use custom size of {@code GoogleStyleViewLayout}, set {@code ptrSetGoogleViewLayoutSizeToActionbarHeight} to false in layout xml (but not recommended).\n\t\t */\n\t\tif (mSetGoogleViewLayoutSizeToActionbarHeight == true) {\n\t\t\t// If it has called setHeight(...) method immediately after {@code view} has been added, the height isn't set correct\n\t\t\tpost(new Runnable(){\n\n\t\t\t\t@Override\n\t\t\t\tpublic void run() {\n\t\t\t\t\tmGoogleStyleViewLayout.setHeight(mActionBarHeight);\n\t\t\t\t}});\t\t\t\n\t\t}\n\t\t// Show Google style view layout to screen\n\t\tmGoogleStyleViewLayout.setVisibility(View.VISIBLE);\n\t\t\n\t\t// Hide Loading Views\n\t\trefreshLoadingViewsSize();\n\n\t\t// If we're not using Mode.BOTH, set mCurrentMode to mMode, otherwise\n\t\t// set it to pull down\n\t\tmCurrentMode = (mMode != Mode.BOTH) ? mMode : Mode.PULL_FROM_START;\n\t}\n\n\tprivate void addRefreshableView(Context context, T refreshableView) {\n\t\tmRefreshableViewWrapper = new FrameLayout(context);\n\t\tmRefreshableViewWrapper.addView(refreshableView, ViewGroup.LayoutParams.MATCH_PARENT,\n\t\t\t\tViewGroup.LayoutParams.MATCH_PARENT);\n\n\t\taddViewInternal(mRefreshableViewWrapper, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,\n\t\t\t\tLayoutParams.MATCH_PARENT));\n\t}\n\n\tprivate void callRefreshListener() {\n\t\tif (null != mOnRefreshListener) {\n\t\t\tmOnRefreshListener.onRefresh(this);\n\t\t} else if (null != mOnRefreshListener2) {\n\t\t\tif (mCurrentMode == Mode.PULL_FROM_START || mCurrentMode == Mode.GOOGLE_STYLE) {\n\t\t\t\tmOnRefreshListener2.onPullDownToRefresh(this);\n\t\t\t} else if (mCurrentMode == Mode.PULL_FROM_END) {\n\t\t\t\tmOnRefreshListener2.onPullUpToRefresh(this);\n\t\t\t}\n\t\t}\n\t}\n\n\t@SuppressWarnings(\"deprecation\")\n\tprivate void init(Context context, AttributeSet attrs) {\n\t\t// Skip if this view is loaded from preview mode of IDE\n\t\tif (isInEditMode()) {\n\t\t\t// Create the refreshable view and finish the initialization\n\t\t\tmRefreshableView = createRefreshableView(context, attrs);\n\t\t\taddRefreshableView(context, mRefreshableView);\n\t\t\treturn;\n\t\t}\n\t\t// PullToRefreshXmlConfiguration must be initialized.\n\t\tPullToRefreshXmlConfiguration.getInstance().init(context);\n\t\t/**\n\t\t *  start initialization\n\t\t */\n\t\t// Styleables from XML\n\n\t\t// Getting mMode is first, because It uses mMode in getFilteredPullToRefreshScrollDirection()\n\t\tTypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PullToRefresh);\n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrMode)) {\n\t\t\tmMode = Mode.mapIntToValue(a.getInteger(R.styleable.PullToRefresh_ptrMode, 0));\n\t\t\tfilterModeForSDKVersion();\n\t\t}\n\n\t\tswitch (getFilteredPullToRefreshScrollDirection()) {\n\t\t\tcase HORIZONTAL:\n\t\t\t\tsetOrientation(LinearLayout.HORIZONTAL);\n\t\t\t\tbreak;\n\t\t\tcase VERTICAL:\n\t\t\tdefault:\n\t\t\t\tsetOrientation(LinearLayout.VERTICAL);\n\t\t\t\tbreak;\n\t\t}\n\n\t\tViewConfiguration config = ViewConfiguration.get(context);\n\t\tmTouchSlop = config.getScaledTouchSlop();\n\n\t\t// Default value of PTR View's gravity is center. So let the value be set center when the gravity is not set yet in XML.\n\t\tif (!Utils.existAttributeValue(attrs, \"gravity\")) {\n\t\t\tsetGravity(Gravity.CENTER);\n\t\t}\n\n\t\t// Get a loading layout class token\n\t\tString loadingLayoutCode = null;\n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrAnimationStyle)) {\n\t\t\tloadingLayoutCode = a.getString(R.styleable.PullToRefresh_ptrAnimationStyle);\n\t\t} \n\t\t\n\t\tmLoadingLayoutClazz = LoadingLayoutFactory.createLoadingLayoutClazzByLayoutCode(loadingLayoutCode);\n\t\t\n\t\t// Refreshable View\n\t\t// By passing the attrs, we can add ListView/GridView params via XML\n\t\tmRefreshableView = createRefreshableView(context, attrs);\n\t\taddRefreshableView(context, mRefreshableView);\n\n\t\t// We need to create now layouts now\n\t\tmHeaderLayout = createLoadingLayout(context, Mode.PULL_FROM_START, a);\n\t\tmFooterLayout = createLoadingLayout(context, Mode.PULL_FROM_END, a);\n\n\t\t/**\n\t\t * Initialization for Google Style mode\n\t\t */\n\t\t// Get a Google style view layout class token\n\t\tString googleStyleViewLayoutCode = null;\n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrGoogleViewStyle)) {\n\t\t\tgoogleStyleViewLayoutCode = a.getString(R.styleable.PullToRefresh_ptrGoogleViewStyle);\n\t\t} \n\t\t// Get a Google style progress layout class token\n\t\tString googleStyleProgressLayoutCode = null;\n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrGoogleViewStyle)) {\n\t\t\tgoogleStyleProgressLayoutCode = a.getString(R.styleable.PullToRefresh_ptrGoogleProgressStyle);\n\t\t} \n\t\t// Get a google style view layout\n\t\tmGoogleStyleViewLayout = createGoogleStyleViewLayout(googleStyleViewLayoutCode, context, a);\n\t\t// Get a google style progress layout \n\t\tmGoogleStyleProgressLayout = createGoogleStyleProgressLayout(googleStyleProgressLayoutCode, context, a);\n\t\t// Get animation options for Google style mode\n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrShowGoogleStyleViewAnimationEnabled)) {\n\t\t\tmShowGoogleStyleViewAnimationEnabled = a.getBoolean(R.styleable.PullToRefresh_ptrShowGoogleStyleViewAnimationEnabled, true);\n\t\t}\n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrHideRefeshableViewWhileRefreshingEnabled)) {\n\t\t\tmRefeshableViewHideWhileRefreshingEnabled = a.getBoolean(R.styleable.PullToRefresh_ptrHideRefeshableViewWhileRefreshingEnabled, true);\n\t\t}\n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrViewRefeshableViewProgressBarOnCenterWhileRefreshingEnabled)) {\n\t\t\tmRefeshableViewRefreshingBarViewWhileRefreshingEnabled = a.getBoolean(R.styleable.PullToRefresh_ptrViewRefeshableViewProgressBarOnCenterWhileRefreshingEnabled, true);\n\t\t}\n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrShowGoogleStyleViewAnimationDuration)) {\n\t\t\tmShowGoogleStyleViewAnimationDuration = a.getInteger(R.styleable.PullToRefresh_ptrShowGoogleStyleViewAnimationDuration, GOOGLE_STYLE_VIEW_APPEAREANCE_DURATION);\n\t\t}\n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrHideRefeshableViewWhileRefreshingDuration)) {\n\t\t\tmRefeshableViewHideWhileRefreshingDuration = a.getInteger(R.styleable.PullToRefresh_ptrHideRefeshableViewWhileRefreshingDuration, REFRESHABLE_VIEW_HIDE_WHILE_REFRESHING_DURATION);\n\t\t}\n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrViewRefeshableViewProgressBarOnCenterWhileRefreshingDuration)) {\n\t\t\tmRefeshableViewRefreshingBarViewWhileRefreshingDuration = a.getInteger(R.styleable.PullToRefresh_ptrViewRefeshableViewProgressBarOnCenterWhileRefreshingDuration, REFRESHABLEVIEW_REFRESHING_BAR_VIEW_WHILE_REFRESHING_DURATION);\n\t\t}\n\n\t\t// Get a flag that decides Google View Layout's size is set to ActionBar's \n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrSetGoogleViewLayoutSizeToActionbarHeight)) {\n\t\t\tmSetGoogleViewLayoutSizeToActionbarHeight = a.getBoolean(R.styleable.PullToRefresh_ptrSetGoogleViewLayoutSizeToActionbarHeight, true);\n\t\t}\n\n\t\t// Get width or height attr of refreshing bar \n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrRefeshableViewProgressBarOnCenterWidth)) {\n\t\t\tmRefeshableViewRefreshingBarWidth = a.getInteger(R.styleable.PullToRefresh_ptrRefeshableViewProgressBarOnCenterWidth, DFEAULT_REFRESHABLEVIEW_REFRESHING_BAR_SIZE);\n\t\t}\n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrRefeshableViewProgressBarOnCenterHeight)) {\n\t\t\tmRefeshableViewRefreshingBarHeight = a.getInteger(R.styleable.PullToRefresh_ptrRefeshableViewProgressBarOnCenterHeight, DFEAULT_REFRESHABLEVIEW_REFRESHING_BAR_SIZE);\n\t\t}\t\t\n\t\t/**\n\t\t * Styleables from XML\n\t\t */\n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrRefreshableViewBackground)) {\n\t\t\tDrawable background = a.getDrawable(R.styleable.PullToRefresh_ptrRefreshableViewBackground);\n\t\t\tif (null != background) {\n\t\t\t\tmRefreshableView.setBackgroundDrawable(background);\n\t\t\t}\n\t\t} else if (a.hasValue(R.styleable.PullToRefresh_ptrAdapterViewBackground)) {\n\t\t\tUtils.warnDeprecation(\"ptrAdapterViewBackground\", \"ptrRefreshableViewBackground\");\n\t\t\tDrawable background = a.getDrawable(R.styleable.PullToRefresh_ptrAdapterViewBackground);\n\t\t\tif (null != background) {\n\t\t\t\tmRefreshableView.setBackgroundDrawable(background);\n\t\t\t}\n\t\t}\n\n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrOverScroll)) {\n\t\t\tmOverScrollEnabled = a.getBoolean(R.styleable.PullToRefresh_ptrOverScroll, true);\n\t\t}\n\n\t\tif (a.hasValue(R.styleable.PullToRefresh_ptrScrollingWhileRefreshingEnabled)) {\n\t\t\tmScrollingWhileRefreshingEnabled = a.getBoolean(\n\t\t\t\t\tR.styleable.PullToRefresh_ptrScrollingWhileRefreshingEnabled, false);\n\t\t}\n\t\t\n\t\t// set scroll properties from attributes \n\t\tfloat friction = a.getFloat(R.styleable.PullToRefresh_ptrFriction, DEFAULT_FRICTION);\n\t\tint smoothScrollDuration = a.getInt(R.styleable.PullToRefresh_ptrSmoothScrollDuration, DEFAULT_SMOOTH_SCROLL_DURATION_MS);\n\t\tint smoothScrollLongDuration = a.getInt(R.styleable.PullToRefresh_ptrSmoothScrollLongDuration, DEFAULT_SMOOTH_SCROLL_LONG_DURATION_MS);\n\t\t\n\t\tsetFriction(friction);\n\t\tsetSmoothScrollDuration(smoothScrollDuration);\n\t\tsetSmoothScrollLongDuration(smoothScrollLongDuration);\n\t\t\n\t\t// Let the derivative classes have a go at handling attributes, then\n\t\t// recycle them...\n\t\thandleStyledAttributes(a);\n\t\ta.recycle();\n\n\t\t// Get action bar height and status bar height \n\t\tinitActionBarSize(context);\n\t\tinitStatusBarSize(context);\n\n\t\tdetermineYPositionOfGoogleStyleViewLayout();\n\t\t\n\t\t// Finally update the UI for the modes\n\t\tupdateUIForMode();\n\t\t// updateUIForGoogleStyleMode() method will be called when onAttachedToWindow() event has been fired.\n\t}\n\n\tprivate void filterModeForSDKVersion() {\n\t\t// If SDK version is 2.x or lower, Let the mode not be google mode. \n\t\t// Because google mode should not be supported in those versions.\n\t\tif ( VERSION.SDK_INT < VERSION_CODES.HONEYCOMB && mMode == Mode.GOOGLE_STYLE ) {\n\t\t\tmMode = Mode.PULL_FROM_START;\n\t\t}\n\t}\n\n\tprivate void determineYPositionOfGoogleStyleViewLayout() {\n\t\tif ( VERSION.SDK_INT < VERSION_CODES.ICE_CREAM_SANDWICH ) { \n\t\t\tmYPositionOfGoogleStyleViewLayout = 0;\n\t\t} else {\n\t\t\tmYPositionOfGoogleStyleViewLayout = mStatusBarHeight;\n\t\t}\n\t}\n\t/**\n\t * NOTE : This method must be called after initStatusBarSize() and initActionBarSize() have already been called. Also, mGoogleStyleProgressLayout should be initialized before calling this method. \n\t */\n\tprivate void determineYPositionOfGoogleStyleProgressLayout() {\n\t\tif ( VERSION.SDK_INT < VERSION_CODES.ICE_CREAM_SANDWICH ) { \n\t\t\tmYPositionOfGoogleStyleProgressLayout = mStatusBarHeight + 1;\n\t\t} else {\n\t\t\tmYPositionOfGoogleStyleProgressLayout = mActionBarHeight + mGoogleStyleProgressLayout.getHeight() + 1;\n\t\t}\t\t\n\t}\n\t/**\n\t * Show google view layout and google progress layout when pulling\n\t */\n\tprivate void showViewTopLayout() {\n    \tif (mMode.showGoogleStyle() == false ) {\n    \t\treturn;\n    \t}\n\n    \t// Initialize Translate and Alpha animation\n    \tif ( mShowGoogleStyleViewAnimationEnabled == true ) {\n        \tAnimationSet set = new AnimationSet(true /* share interpolator */);\n        \tset.setDuration(mShowGoogleStyleViewAnimationDuration);\n        \tset.setFillAfter(true);\n        \tset.setAnimationListener(new AnimationListener(){\n\n    \t\t\t@Override\n    \t\t\tpublic void onAnimationEnd(Animation anim) {\n    \t\t\t}\n\n    \t\t\t@Override\n    \t\t\tpublic void onAnimationRepeat(Animation anim) {\n    \t\t\t}\n\n    \t\t\t@Override\n    \t\t\tpublic void onAnimationStart(Animation anim) {\n    \t\t\t\tmTopActionbarLayout.setVisibility(View.VISIBLE);\n    \t\t\t}});\n        \t\n        \tTranslateAnimation transAnimation = new TranslateAnimation(Animation.ABSOLUTE, 0,Animation.ABSOLUTE, 0, Animation.ABSOLUTE, -mActionBarHeight, Animation.ABSOLUTE, mYPositionOfGoogleStyleViewLayout);\n        \tAlphaAnimation alphaAnimation = new AlphaAnimation(0.0f, 1.0f);\n        \tset.addAnimation(transAnimation);\n        \tset.addAnimation(alphaAnimation);\n        \t// Start animation\n        \tmTopActionbarLayout.startAnimation(set);    \t\t\n    \t} else {\n       \t\t// Show Google style view layout without animation\n    \t\t((FrameLayout.LayoutParams) mTopActionbarLayout.getLayoutParams()).topMargin = mYPositionOfGoogleStyleViewLayout;\n    \t\tmTopActionbarLayout.setVisibility(View.VISIBLE);   \t\t\n    \t}\n\n    \tmGoogleStyleProgressLayout.setVisibility(View.VISIBLE);\n    }\n\n\t/**\n\t * Hide google view layout and google progress layout when releasing\n\t */\n\tprivate void hideViewTopLayout() {\n    \tif (mMode.showGoogleStyle() == false ) {\n    \t\treturn;\n    \t}\n\n    \tif ( mShowGoogleStyleViewAnimationEnabled == true ) {\n        \t// Initialize Translate and Alpha animation\n    \t   \tAnimationSet set = new AnimationSet(true /* share interpolator */);\n        \tset.setDuration(mShowGoogleStyleViewAnimationDuration);\n        \tset.setFillAfter(true);\n        \tset.setAnimationListener(new AnimationListener(){\n\n    \t\t\t@Override\n    \t\t\tpublic void onAnimationEnd(Animation anim) {\n    \t\t\t\tmTopActionbarLayout.setVisibility(View.INVISIBLE);\n    \t\t\t}\n\n    \t\t\t@Override\n    \t\t\tpublic void onAnimationRepeat(Animation anim) {\n    \t\t\t}\n\n    \t\t\t@Override\n    \t\t\tpublic void onAnimationStart(Animation anim) {\n    \t\t\t}});\n        \t\n        \tTranslateAnimation transAnimation = new TranslateAnimation(Animation.ABSOLUTE, 0,Animation.ABSOLUTE, 0, Animation.ABSOLUTE, mTopActionbarLayout.getTop(), Animation.ABSOLUTE, -mStatusBarHeight);\n        \tAlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.0f);\n        \tset.addAnimation(transAnimation);\n        \tset.addAnimation(alphaAnimation);\n        \t// Start animation\n        \tmTopActionbarLayout.startAnimation(set);\n    \t} else {\n      \t\t// Hide Google style view layout without animation\n    \t\t((FrameLayout.LayoutParams) mTopActionbarLayout.getLayoutParams()).topMargin = -mActionBarHeight;\n    \t\tmTopActionbarLayout.setVisibility(View.INVISIBLE);\n    \t}\n\n    \tmGoogleStyleProgressLayout.setVisibility(View.INVISIBLE);\n    }\n    \n\t@Override\n\tprotected void onAttachedToWindow() {\n\t\tsuper.onAttachedToWindow();\n\t\tmWindowAttached = true;\n\t\t\n\t\tinitTopViewGroup();\n\t\tupdateUIForGoogleStyleMode();\n\t}\n\n\t/**\n     * Initialize {@code mTopActionbarLayout} and add that into Top DecorView(this is the root view),\n     * and initialize needed components\n     */   \n\tprivate void initTopViewGroup() {\n\n\t\t// Skip if this view is loaded from preview mode of IDE\n\t\tif (isInEditMode()) {\n\t\t\treturn;\n\t\t}\n        if ( mMode.showGoogleStyle() == false ) {\n            return;\n        }\n\n\t\tView view = this.getRootView();\n\t\tViewGroup topViewGroup = null;\n\t\tContext context = getContext();\n\t\tif (view instanceof ViewGroup == false) {\n\t\t\tLog.w(LOG_TAG, \"Current root view is not ViewGroup type. Google Style Pull To Refresh mode will be disabled.\");\n\t\t\ttopViewGroup = new ViewGroup(context) {\n\t\t\t\t@Override\n\t\t\t\tprotected void onLayout(boolean changed, int l, int t, int r, int b) {\n\t\t\t\t\t// do nothing\n\t\t\t\t}};\n\n\t\t} else {\n\t\t\ttopViewGroup = (ViewGroup) view;\n\t\t}\n\n\t\t// Initialize Top Layout Layout\n\t\tFrameLayout layout = new FrameLayout(context);\n\n\t\t@SuppressWarnings(\"deprecation\")\n\t\tint matchParent = ViewGroup.LayoutParams.FILL_PARENT;\n\t\t\n\t\tViewGroup.LayoutParams params = new ViewGroup.LayoutParams(matchParent, mActionBarHeight);\n\t\t\n\t\ttopViewGroup.addView(layout, params);\n\t\tlayout.setVisibility(View.INVISIBLE);\n\n\t\t// Initialize refreshing bar on center\n        if (mMode.showGoogleStyle()) {\n            mRefreshableViewProgressBar = generateCircleProgressBar(context);\n            FrameLayout.LayoutParams barParams = new FrameLayout.LayoutParams(mRefeshableViewRefreshingBarWidth, mRefeshableViewRefreshingBarHeight);\n            barParams.gravity = Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL;\n            mRefreshableViewProgressBar.setVisibility(View.INVISIBLE);\n            mRefreshableViewWrapper.addView(mRefreshableViewProgressBar, -1, barParams);        \t\n        }\n\t\t// Initialize Google style progress layout\n\t\ttopViewGroup.addView(mGoogleStyleProgressLayout, mGoogleStyleProgressLayout.createLayoutParams());\n\t\tmGoogleStyleProgressLayout.setVisibility(View.INVISIBLE);\n\t\t// Set height of Google style progress layout\n\t\tpost(new Runnable(){\n\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tdetermineYPositionOfGoogleStyleProgressLayout();\n\t\t\t\tmGoogleStyleProgressLayout.setTopMargin(mYPositionOfGoogleStyleProgressLayout);\n\t\t\t\t\n\t\t\t}});\n\n\t\t// Finally assign\n\t\tmTopActionbarLayout = layout;\n\n\t}\n\t/**\n\t * Get an actionBar's size and save into a field\n\t * @param context\n\t */\n\tprivate void initActionBarSize(Context context) {\n\t\tmActionBarHeight = Utils.getActionBarSize(context);\n\t}\n\t/**\n\t * Get an StatusBar's size and save into a field\n\t * @param context\n\t */\n\tprivate void initStatusBarSize(Context context) {\n\t\tmStatusBarHeight = Utils.getStatusBarSize(context);\n\t}\n\t/**\n\t * Generate Progress bar UI Component on center\n\t * @param context\n\t * @return Generated ProgressBar instance\n\t */\n\tprivate ProgressBar generateCircleProgressBar(Context context) {\n        ProgressBar circleProgressBar = new ProgressBar(context);\n        circleProgressBar.setScrollBarStyle(android.R.attr.progressBarStyle);\n        circleProgressBar.setIndeterminate(true);\n\t\t\n\t\treturn circleProgressBar;\n\t}\n\n\tprivate boolean isReadyForPull() {\n\t\tswitch (mMode) {\n\t\t\tcase PULL_FROM_START:\n\t\t\tcase GOOGLE_STYLE:\n\t\t\t\treturn isReadyForPullStart();\n\t\t\tcase PULL_FROM_END:\n\t\t\t\treturn isReadyForPullEnd();\n\t\t\tcase BOTH:\n\t\t\t\treturn isReadyForPullEnd() || isReadyForPullStart();\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Actions a Pull Event\n\t * \n\t * @return true if the Event has been handled, false if there has been no\n\t *         change\n\t */\n\tprivate void pullEvent() {\n\t\tfinal int newScrollValue;\n\t\tfinal int itemDimension;\n\t\tfinal float initialMotionValue, lastMotionValue;\n\n\t\tswitch (getFilteredPullToRefreshScrollDirection()) {\n\t\t\tcase HORIZONTAL:\n\t\t\t\tinitialMotionValue = mInitialMotionX;\n\t\t\t\tlastMotionValue = mLastMotionX;\n\t\t\t\tbreak;\n\t\t\tcase VERTICAL:\n\t\t\tdefault:\n\t\t\t\tinitialMotionValue = mInitialMotionY;\n\t\t\t\tlastMotionValue = mLastMotionY;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tswitch (mCurrentMode) {\n\t\t\tcase PULL_FROM_END:\n\t\t\t\tnewScrollValue = Math.round(Math.max(initialMotionValue - lastMotionValue, 0) / mFriction);\n\t\t\t\titemDimension = getFooterSize();\n\t\t\t\tbreak;\n\t\t\tcase GOOGLE_STYLE:\n\t\t\t\tnewScrollValue = Math.round(Math.min(initialMotionValue - lastMotionValue, 0) / mFriction);\n\t\t\t\titemDimension = getGoogleStyleViewSize();\n\t\t\t\tbreak;\n\t\t\tcase PULL_FROM_START:\n\t\t\tdefault:\n\t\t\t\tnewScrollValue = Math.round(Math.min(initialMotionValue - lastMotionValue, 0) / mFriction);\n\t\t\t\titemDimension = getHeaderSize();\n\t\t\t\tbreak;\n\t\t}\n\n\t\tsetHeaderScroll(newScrollValue);\n\n\t\tif (newScrollValue != 0 && !isRefreshing()) {\n\t\t\tfloat scale = Math.abs(newScrollValue) / (float) itemDimension;\n\t\t\tswitch (mCurrentMode) {\n\t\t\t\tcase PULL_FROM_END:\n\t\t\t\t\tmFooterLayout.onPull(scale);\n\t\t\t\t\tbreak;\n\t\t\t\tcase GOOGLE_STYLE:\n\t\t\t\t\tmGoogleStyleViewLayout.onPull(scale);\n\t\t\t\t\tmGoogleStyleProgressLayout.onPull(scale);\n\t\t\t\t\tbreak;\n\t\t\t\tcase PULL_FROM_START:\n\t\t\t\tdefault:\n\t\t\t\t\tmHeaderLayout.onPull(scale);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (mState != State.PULL_TO_REFRESH && itemDimension >= Math.abs(newScrollValue)) {\n\t\t\t\tsetState(State.PULL_TO_REFRESH);\n\t\t\t} else if (mState == State.PULL_TO_REFRESH && itemDimension < Math.abs(newScrollValue)) {\n\t\t\t\tsetState(State.RELEASE_TO_REFRESH);\n\t\t\t}\n\t\t}\n\t}\n\n\t@SuppressWarnings(\"deprecation\")\n\tprivate LinearLayout.LayoutParams getLoadingLayoutLayoutParams() {\n\t\tswitch (getFilteredPullToRefreshScrollDirection()) {\n\t\t\tcase HORIZONTAL:\n\t\t\t\treturn new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,\n\t\t\t\t\t\tLinearLayout.LayoutParams.FILL_PARENT);\n\t\t\tcase VERTICAL:\n\t\t\tdefault:\n\t\t\t\treturn new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,\n\t\t\t\t\t\tLinearLayout.LayoutParams.WRAP_CONTENT);\n\t\t}\n\t}\n\n\tprivate int getMaximumPullScroll() {\n\t\tswitch (getFilteredPullToRefreshScrollDirection()) {\n\t\t\tcase HORIZONTAL:\n\t\t\t\treturn Math.round(getWidth() / mFriction);\n\t\t\tcase VERTICAL:\n\t\t\tdefault:\n\t\t\t\treturn Math.round(getHeight() / mFriction);\n\t\t}\n\t}\n\n\t/**\n\t * Smooth Scroll to position using the specific duration\n\t * \n\t * @param scrollValue - Position to scroll to\n\t * @param duration - Duration of animation in milliseconds\n\t */\n\tprivate final void smoothScrollTo(int scrollValue, long duration) {\n\t\tsmoothScrollTo(scrollValue, duration, 0, null);\n\t}\n\n\tprivate final void smoothScrollTo(int newScrollValue, long duration, long delayMillis,\n\t\t\tOnSmoothScrollFinishedListener listener) {\n\t\tif (null != mCurrentSmoothScrollRunnable) {\n\t\t\tmCurrentSmoothScrollRunnable.stop();\n\t\t}\n\n\t\tfinal int oldScrollValue;\n\t\tswitch (getFilteredPullToRefreshScrollDirection()) {\n\t\t\tcase HORIZONTAL:\n\t\t\t\toldScrollValue = getScrollX();\n\t\t\t\tbreak;\n\t\t\tcase VERTICAL:\n\t\t\tdefault:\n\t\t\t\toldScrollValue = getScrollY();\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (oldScrollValue != newScrollValue) {\n\t\t\tif (null == mScrollAnimationInterpolator) {\n\t\t\t\t// Default interpolator is a Decelerate Interpolator\n\t\t\t\tmScrollAnimationInterpolator = new DecelerateInterpolator();\n\t\t\t}\n\t\t\tmCurrentSmoothScrollRunnable = new SmoothScrollRunnable(oldScrollValue, newScrollValue, duration, listener);\n\n\t\t\tif (delayMillis > 0) {\n\t\t\t\tpostDelayed(mCurrentSmoothScrollRunnable, delayMillis);\n\t\t\t} else {\n\t\t\t\tpost(mCurrentSmoothScrollRunnable);\n\t\t\t}\n\t\t\t\n\t\t} else if ( listener != null ) { \n\t\t\t// Call listener immediately\n\t\t\tlistener.onSmoothScrollFinished();\n\t\t}\n\t}\n\n\tprivate final void smoothScrollToAndBack(int y) {\n\t\tsmoothScrollTo(y, mSmoothScrollDurationMs, 0, new OnSmoothScrollFinishedListener() {\n\n\t\t\t@Override\n\t\t\tpublic void onSmoothScrollFinished() {\n\t\t\t\tsmoothScrollTo(0, mSmoothScrollDurationMs, DEMO_SCROLL_INTERVAL, null);\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic static enum Mode {\n\n\t\t/**\n\t\t * Disable all Pull-to-Refresh gesture and Refreshing handling\n\t\t */\n\t\tDISABLED(0x0),\n\n\t\t/**\n\t\t * Only allow the user to Pull from the start of the Refreshable View to\n\t\t * refresh. The start is either the Top or Left, depending on the\n\t\t * scrolling direction.\n\t\t */\n\t\tPULL_FROM_START(0x1),\n\n\t\t/**\n\t\t * Only allow the user to Pull from the end of the Refreshable View to\n\t\t * refresh. The start is either the Bottom or Right, depending on the\n\t\t * scrolling direction.\n\t\t */\n\t\tPULL_FROM_END(0x2),\n\n\t\t/**\n\t\t * Allow the user to both Pull from the start, from the end to refresh.\n\t\t */\n\t\tBOTH(0x3),\n\n\t\t/**\n\t\t * Disables Pull-to-Refresh gesture handling, but allows manually\n\t\t * setting the Refresh state via\n\t\t * {@link PullToRefreshBase#setRefreshing() setRefreshing()}.\n\t\t */\n\t\tMANUAL_REFRESH_ONLY(0x4),\n\n\t\t/**\n\t\t * Google style pull-to-refresh mode\n\t\t *\n\t\t */\n\t\tGOOGLE_STYLE(0x5);\n\t\t\n\t\t/**\n\t\t * @deprecated Use {@link #PULL_FROM_START} from now on.\n\t\t */\n\t\tpublic static Mode PULL_DOWN_TO_REFRESH = Mode.PULL_FROM_START;\n\n\t\t/**\n\t\t * @deprecated Use {@link #PULL_FROM_END} from now on.\n\t\t */\n\t\tpublic static Mode PULL_UP_TO_REFRESH = Mode.PULL_FROM_END;\n\n\t\t/**\n\t\t * Maps an int to a specific mode. This is needed when saving state, or\n\t\t * inflating the view from XML where the mode is given through a attr\n\t\t * int.\n\t\t * \n\t\t * @param modeInt - int to map a Mode to\n\t\t * @return Mode that modeInt maps to, or PULL_FROM_START by default.\n\t\t */\n\t\tstatic Mode mapIntToValue(final int modeInt) {\n\t\t\tfor (Mode value : Mode.values()) {\n\t\t\t\tif (modeInt == value.getIntValue()) {\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If not, return default\n\t\t\treturn getDefault();\n\t\t}\n\n\t\tstatic Mode getDefault() {\n\t\t\treturn PULL_FROM_START;\n\t\t}\n\n\t\tprivate int mIntValue;\n\n\t\t// The modeInt values need to match those from attrs.xml\n\t\tMode(int modeInt) {\n\t\t\tmIntValue = modeInt;\n\t\t}\n\n\t\t/**\n\t\t * @return true if the mode permits Pull-to-Refresh\n\t\t */\n\t\tboolean permitsPullToRefresh() {\n\t\t\treturn !(this == DISABLED || this == MANUAL_REFRESH_ONLY);\n\t\t}\n\n\t\t/**\n\t\t * @return true if this mode wants the Loading Layout Header to be shown\n\t\t */\n\t\tpublic boolean showHeaderLoadingLayout() {\n\t\t\treturn this == PULL_FROM_START || this == BOTH;\n\t\t}\n\n\t\t/**\n\t\t * @return true if this mode wants the Loading Layout Footer to be shown\n\t\t */\n\t\tpublic boolean showFooterLoadingLayout() {\n\t\t\treturn this == PULL_FROM_END || this == BOTH || this == MANUAL_REFRESH_ONLY;\n\t\t}\n\n\t\t/**\n\t\t * @return true if this mode wants the Loading Layout to be shown like Google style pull-to-refresh\n\t\t */\n\t\tpublic boolean showGoogleStyle() {\n\t\t\treturn this == GOOGLE_STYLE;\n\t\t}\n\n\t\tint getIntValue() {\n\t\t\treturn mIntValue;\n\t\t}\n\n\t}\n\n\t// ===========================================================\n\t// Inner, Anonymous Classes, and Enumerations\n\t// ===========================================================\n\n\t/**\n\t * Simple Listener that allows you to be notified when the user has scrolled\n\t * to the end of the AdapterView. See (\n\t * {@link PullToRefreshAdapterViewBase#setOnLastItemVisibleListener}.\n\t * \n\t * @author Chris Banes\n\t */\n\tpublic static interface OnLastItemVisibleListener {\n\n\t\t/**\n\t\t * Called when the user has scrolled to the end of the list\n\t\t */\n\t\tpublic void onLastItemVisible();\n\n\t}\n\n\t/**\n\t * Listener that allows you to be notified when the user has started or\n\t * finished a touch event. Useful when you want to append extra UI events\n\t * (such as sounds). See (\n\t * {@link PullToRefreshAdapterViewBase#setOnPullEventListener}.\n\t * \n\t * @author Chris Banes\n\t */\n\tpublic static interface OnPullEventListener<V extends View> {\n\n\t\t/**\n\t\t * Called when the internal state has been changed, usually by the user\n\t\t * pulling.\n\t\t * \n\t\t * @param refreshView - View which has had it's state change.\n\t\t * @param state - The new state of View.\n\t\t * @param direction - One of {@link Mode#PULL_FROM_START} or\n\t\t *            {@link Mode#PULL_FROM_END} depending on which direction\n\t\t *            the user is pulling. Only useful when <var>state</var> is\n\t\t *            {@link State#PULL_TO_REFRESH} or\n\t\t *            {@link State#RELEASE_TO_REFRESH}.\n\t\t */\n\t\tpublic void onPullEvent(final PullToRefreshBase<V> refreshView, State state, Mode direction);\n\n\t}\n\n\t/**\n\t * Simple Listener to listen for any callbacks to Refresh.\n\t * \n\t * @author Chris Banes\n\t */\n\tpublic static interface OnRefreshListener<V extends View> {\n\n\t\t/**\n\t\t * onRefresh will be called for both a Pull from start, and Pull from\n\t\t * end\n\t\t */\n\t\tpublic void onRefresh(final PullToRefreshBase<V> refreshView);\n\n\t}\n\n\t/**\n\t * An advanced version of the Listener to listen for callbacks to Refresh.\n\t * This listener is different as it allows you to differentiate between Pull\n\t * Ups, and Pull Downs.\n\t * \n\t * @author Chris Banes\n\t */\n\tpublic static interface OnRefreshListener2<V extends View> {\n\t\t// TODO These methods need renaming to START/END rather than DOWN/UP\n\n\t\t/**\n\t\t * onPullDownToRefresh will be called only when the user has Pulled from\n\t\t * the start, and released.\n\t\t */\n\t\tpublic void onPullDownToRefresh(final PullToRefreshBase<V> refreshView);\n\n\t\t/**\n\t\t * onPullUpToRefresh will be called only when the user has Pulled from\n\t\t * the end, and released.\n\t\t */\n\t\tpublic void onPullUpToRefresh(final PullToRefreshBase<V> refreshView);\n\n\t}\n\n\tpublic static enum Orientation {\n\t\tVERTICAL, HORIZONTAL;\n\t}\n\n\tpublic static enum State {\n\n\t\t/**\n\t\t * When the UI is in a state which means that user is not interacting\n\t\t * with the Pull-to-Refresh function.\n\t\t */\n\t\tRESET(0x0),\n\n\t\t/**\n\t\t * When the UI is being pulled by the user, but has not been pulled far\n\t\t * enough so that it refreshes when released.\n\t\t */\n\t\tPULL_TO_REFRESH(0x1),\n\n\t\t/**\n\t\t * When the UI is being pulled by the user, and <strong>has</strong>\n\t\t * been pulled far enough so that it will refresh when released.\n\t\t */\n\t\tRELEASE_TO_REFRESH(0x2),\n\n\t\t/**\n\t\t * When the UI is currently refreshing, caused by a pull gesture.\n\t\t */\n\t\tREFRESHING(0x8),\n\n\t\t/**\n\t\t * When the UI is currently refreshing, caused by a call to\n\t\t * {@link PullToRefreshBase#setRefreshing() setRefreshing()}.\n\t\t */\n\t\tMANUAL_REFRESHING(0x9),\n\n\t\t/**\n\t\t * When the UI is currently overscrolling, caused by a fling on the\n\t\t * Refreshable View.\n\t\t */\n\t\tOVERSCROLLING(0x10);\n\n\t\t/**\n\t\t * Maps an int to a specific state. This is needed when saving state.\n\t\t * \n\t\t * @param stateInt - int to map a State to\n\t\t * @return State that stateInt maps to\n\t\t */\n\t\tstatic State mapIntToValue(final int stateInt) {\n\t\t\tfor (State value : State.values()) {\n\t\t\t\tif (stateInt == value.getIntValue()) {\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If not, return default\n\t\t\treturn RESET;\n\t\t}\n\n\t\tprivate int mIntValue;\n\n\t\tState(int intValue) {\n\t\t\tmIntValue = intValue;\n\t\t}\n\n\t\tint getIntValue() {\n\t\t\treturn mIntValue;\n\t\t}\n\t}\n\n\tfinal class SmoothScrollRunnable implements Runnable {\n\t\tprivate final Interpolator mInterpolator;\n\t\tprivate final int mScrollToY;\n\t\tprivate final int mScrollFromY;\n\t\tprivate final long mDuration;\n\t\tprivate OnSmoothScrollFinishedListener mListener;\n\n\t\tprivate boolean mContinueRunning = true;\n\t\tprivate long mStartTime = -1;\n\t\tprivate int mCurrentY = -1;\n\n\t\tpublic SmoothScrollRunnable(int fromY, int toY, long duration, OnSmoothScrollFinishedListener listener) {\n\t\t\tmScrollFromY = fromY;\n\t\t\tmScrollToY = toY;\n\t\t\tmInterpolator = mScrollAnimationInterpolator;\n\t\t\tmDuration = duration;\n\t\t\tmListener = listener;\n\t\t}\n\n\t\t@Override\n\t\tpublic void run() {\n\n\t\t\t/**\n\t\t\t * Only set mStartTime if this is the first time we're starting,\n\t\t\t * else actually calculate the Y delta\n\t\t\t */\n\t\t\tif (mStartTime == -1) {\n\t\t\t\tmStartTime = System.currentTimeMillis();\n\t\t\t} else {\n\n\t\t\t\t/**\n\t\t\t\t * We do do all calculations in long to reduce software float\n\t\t\t\t * calculations. We use 1000 as it gives us good accuracy and\n\t\t\t\t * small rounding errors\n\t\t\t\t */\n\t\t\t\tlong normalizedTime = (1000 * (System.currentTimeMillis() - mStartTime)) / mDuration;\n\t\t\t\tnormalizedTime = Math.max(Math.min(normalizedTime, 1000), 0);\n\n\t\t\t\tfinal int deltaY = Math.round((mScrollFromY - mScrollToY)\n\t\t\t\t\t\t* mInterpolator.getInterpolation(normalizedTime / 1000f));\n\t\t\t\tmCurrentY = mScrollFromY - deltaY;\n\t\t\t\tsetHeaderScroll(mCurrentY);\n\t\t\t}\n\n\t\t\t// If we're not at the target Y, keep going...\n\t\t\tif (mContinueRunning && mScrollToY != mCurrentY) {\n\t\t\t\tViewCompat.postOnAnimation(PullToRefreshBase.this, this);\n\t\t\t} else {\n\t\t\t\tif (null != mListener) {\n\t\t\t\t\tmListener.onSmoothScrollFinished();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpublic void stop() {\n\t\t\tmContinueRunning = false;\n\t\t\tremoveCallbacks(this);\n\t\t}\n\t}\n\n\tstatic interface OnSmoothScrollFinishedListener {\n\t\tvoid onSmoothScrollFinished();\n\t}\n\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshExpandableListView.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.os.Build.VERSION;\nimport android.os.Build.VERSION_CODES;\nimport android.util.AttributeSet;\nimport android.view.View;\nimport android.widget.ExpandableListView;\n\nimport com.handmark.pulltorefresh.library.internal.EmptyViewMethodAccessor;\nimport com.handmark.pulltorefresh.library.internal.LoadingLayout;\n\npublic class PullToRefreshExpandableListView extends PullToRefreshAdapterViewBase<ExpandableListView> {\n\n\tpublic PullToRefreshExpandableListView(Context context) {\n\t\tsuper(context);\n\t}\n\n\tpublic PullToRefreshExpandableListView(Context context, AttributeSet attrs) {\n\t\tsuper(context, attrs);\n\t}\n\n\tpublic PullToRefreshExpandableListView(Context context, Mode mode) {\n\t\tsuper(context, mode);\n\t}\n\n\tpublic PullToRefreshExpandableListView(Context context, Mode mode, Class<? extends LoadingLayout> loadingLayoutClazz) {\n\t\tsuper(context, mode, loadingLayoutClazz);\n\t}\n\n\t@Override\n\tpublic final Orientation getPullToRefreshScrollDirection() {\n\t\treturn Orientation.VERTICAL;\n\t}\n\n\t@Override\n\tprotected ExpandableListView createRefreshableView(Context context, AttributeSet attrs) {\n\t\tfinal ExpandableListView lv;\n\t\tif (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {\n\t\t\tlv = new InternalExpandableListViewSDK9(context, attrs);\n\t\t} else {\n\t\t\tlv = new InternalExpandableListView(context, attrs);\n\t\t}\n\n\t\t// Set it to this so it can be used in ListActivity/ListFragment\n\t\tlv.setId(android.R.id.list);\n\t\treturn lv;\n\t}\n\n\tclass InternalExpandableListView extends ExpandableListView implements EmptyViewMethodAccessor {\n\n\t\tpublic InternalExpandableListView(Context context, AttributeSet attrs) {\n\t\t\tsuper(context, attrs);\n\t\t}\n\n\t\t@Override\n\t\tpublic void setEmptyView(View emptyView) {\n\t\t\tPullToRefreshExpandableListView.this.setEmptyView(emptyView);\n\t\t}\n\n\t\t@Override\n\t\tpublic void setEmptyViewInternal(View emptyView) {\n\t\t\tsuper.setEmptyView(emptyView);\n\t\t}\n\t}\n\n\t@TargetApi(9)\n\tfinal class InternalExpandableListViewSDK9 extends InternalExpandableListView {\n\n\t\tpublic InternalExpandableListViewSDK9(Context context, AttributeSet attrs) {\n\t\t\tsuper(context, attrs);\n\t\t}\n\n\t\t@Override\n\t\tprotected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX,\n\t\t\t\tint scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {\n\n\t\t\tfinal boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,\n\t\t\t\t\tscrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);\n\n\t\t\t// Does all of the hard work...\n\t\t\tOverscrollHelper.overScrollBy(PullToRefreshExpandableListView.this, deltaX, scrollX, deltaY, scrollY,\n\t\t\t\t\tisTouchEvent);\n\n\t\t\treturn returnValue;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshGridView.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.os.Build.VERSION;\nimport android.os.Build.VERSION_CODES;\nimport android.util.AttributeSet;\nimport android.view.View;\nimport android.widget.GridView;\n\nimport com.handmark.pulltorefresh.library.internal.EmptyViewMethodAccessor;\nimport com.handmark.pulltorefresh.library.internal.LoadingLayout;\n\npublic class PullToRefreshGridView extends PullToRefreshAdapterViewBase<GridView> {\n\n\tpublic PullToRefreshGridView(Context context) {\n\t\tsuper(context);\n\t}\n\n\tpublic PullToRefreshGridView(Context context, AttributeSet attrs) {\n\t\tsuper(context, attrs);\n\t}\n\n\tpublic PullToRefreshGridView(Context context, Mode mode) {\n\t\tsuper(context, mode);\n\t}\n\n\tpublic PullToRefreshGridView(Context context, Mode mode, Class<? extends LoadingLayout> loadingLayoutClazz) {\n\t\tsuper(context, mode, loadingLayoutClazz);\n\t}\n\n\t@Override\n\tpublic final Orientation getPullToRefreshScrollDirection() {\n\t\treturn Orientation.VERTICAL;\n\t}\n\n\t@Override\n\tprotected final GridView createRefreshableView(Context context, AttributeSet attrs) {\n\t\tfinal GridView gv;\n\t\tif (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {\n\t\t\tgv = new InternalGridViewSDK9(context, attrs);\n\t\t} else {\n\t\t\tgv = new InternalGridView(context, attrs);\n\t\t}\n\n\t\t// Use Generated ID (from res/values/ids.xml)\n\t\tgv.setId(R.id.gridview);\n\t\treturn gv;\n\t}\n\n\tclass InternalGridView extends GridView implements EmptyViewMethodAccessor {\n\n\t\tpublic InternalGridView(Context context, AttributeSet attrs) {\n\t\t\tsuper(context, attrs);\n\t\t}\n\n\t\t@Override\n\t\tpublic void setEmptyView(View emptyView) {\n\t\t\tPullToRefreshGridView.this.setEmptyView(emptyView);\n\t\t}\n\n\t\t@Override\n\t\tpublic void setEmptyViewInternal(View emptyView) {\n\t\t\tsuper.setEmptyView(emptyView);\n\t\t}\n\t}\n\n\t@TargetApi(9)\n\tfinal class InternalGridViewSDK9 extends InternalGridView {\n\n\t\tpublic InternalGridViewSDK9(Context context, AttributeSet attrs) {\n\t\t\tsuper(context, attrs);\n\t\t}\n\n\t\t@Override\n\t\tprotected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX,\n\t\t\t\tint scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {\n\n\t\t\tfinal boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,\n\t\t\t\t\tscrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);\n\n\t\t\t// Does all of the hard work...\n\t\t\tOverscrollHelper.overScrollBy(PullToRefreshGridView.this, deltaX, scrollX, deltaY, scrollY, isTouchEvent);\n\n\t\t\treturn returnValue;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshHorizontalScrollView.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport com.handmark.pulltorefresh.library.internal.LoadingLayout;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.os.Build.VERSION;\nimport android.os.Build.VERSION_CODES;\nimport android.util.AttributeSet;\nimport android.view.View;\nimport android.widget.HorizontalScrollView;\n\npublic class PullToRefreshHorizontalScrollView extends PullToRefreshBase<HorizontalScrollView> {\n\n\tpublic PullToRefreshHorizontalScrollView(Context context) {\n\t\tsuper(context);\n\t}\n\n\tpublic PullToRefreshHorizontalScrollView(Context context, AttributeSet attrs) {\n\t\tsuper(context, attrs);\n\t}\n\n\tpublic PullToRefreshHorizontalScrollView(Context context, Mode mode) {\n\t\tsuper(context, mode);\n\t}\n\n\tpublic PullToRefreshHorizontalScrollView(Context context, Mode mode, Class<? extends LoadingLayout> loadingLayoutClazz) {\n\t\tsuper(context, mode, loadingLayoutClazz);\n\t}\n\n\t@Override\n\tpublic final Orientation getPullToRefreshScrollDirection() {\n\t\treturn Orientation.HORIZONTAL;\n\t}\n\n\t@Override\n\tprotected HorizontalScrollView createRefreshableView(Context context, AttributeSet attrs) {\n\t\tHorizontalScrollView scrollView;\n\n\t\tif (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {\n\t\t\tscrollView = new InternalHorizontalScrollViewSDK9(context, attrs);\n\t\t} else {\n\t\t\tscrollView = new HorizontalScrollView(context, attrs);\n\t\t}\n\n\t\tscrollView.setId(R.id.scrollview);\n\t\treturn scrollView;\n\t}\n\n\t@Override\n\tprotected boolean isReadyForPullStart() {\n\t\treturn mRefreshableView.getScrollX() == 0;\n\t}\n\n\t@Override\n\tprotected boolean isReadyForPullEnd() {\n\t\tView scrollViewChild = mRefreshableView.getChildAt(0);\n\t\tif (null != scrollViewChild) {\n\t\t\treturn mRefreshableView.getScrollX() >= (scrollViewChild.getWidth() - getWidth());\n\t\t}\n\t\treturn false;\n\t}\n\n\t@TargetApi(9)\n\tfinal class InternalHorizontalScrollViewSDK9 extends HorizontalScrollView {\n\n\t\tpublic InternalHorizontalScrollViewSDK9(Context context, AttributeSet attrs) {\n\t\t\tsuper(context, attrs);\n\t\t}\n\n\t\t@Override\n\t\tprotected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX,\n\t\t\t\tint scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {\n\n\t\t\tfinal boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,\n\t\t\t\t\tscrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);\n\n\t\t\t// Does all of the hard work...\n\t\t\tOverscrollHelper.overScrollBy(PullToRefreshHorizontalScrollView.this, deltaX, scrollX, deltaY, scrollY,\n\t\t\t\t\tgetScrollRange(), isTouchEvent);\n\n\t\t\treturn returnValue;\n\t\t}\n\n\t\t/**\n\t\t * Taken from the AOSP ScrollView source\n\t\t */\n\t\tprivate int getScrollRange() {\n\t\t\tint scrollRange = 0;\n\t\t\tif (getChildCount() > 0) {\n\t\t\t\tView child = getChildAt(0);\n\t\t\t\tscrollRange = Math.max(0, child.getWidth() - (getWidth() - getPaddingLeft() - getPaddingRight()));\n\t\t\t}\n\t\t\treturn scrollRange;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshListView.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Canvas;\nimport android.os.Build.VERSION;\nimport android.os.Build.VERSION_CODES;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.Gravity;\nimport android.view.MotionEvent;\nimport android.view.View;\nimport android.widget.FrameLayout;\nimport android.widget.ListAdapter;\nimport android.widget.ListView;\n\nimport com.handmark.pulltorefresh.library.internal.EmptyViewMethodAccessor;\nimport com.handmark.pulltorefresh.library.internal.LoadingLayout;\n\npublic class PullToRefreshListView extends PullToRefreshAdapterViewBase<ListView> {\n\n\tprivate LoadingLayout mHeaderLoadingView;\n\tprivate LoadingLayout mFooterLoadingView;\n\n\tprivate FrameLayout mLvFooterLoadingFrame;\n\n\tprivate boolean mListViewExtrasEnabled;\n\n\tpublic PullToRefreshListView(Context context) {\n\t\tsuper(context);\n\t}\n\n\tpublic PullToRefreshListView(Context context, AttributeSet attrs) {\n\t\tsuper(context, attrs);\n\t}\n\n\tpublic PullToRefreshListView(Context context, Mode mode) {\n\t\tsuper(context, mode);\n\t}\n\n\tpublic PullToRefreshListView(Context context, Mode mode, Class<? extends LoadingLayout> loadingLayoutClazz) {\n\t\tsuper(context, mode, loadingLayoutClazz);\n\t}\n\n\t@Override\n\tpublic final Orientation getPullToRefreshScrollDirection() {\n\t\treturn Orientation.VERTICAL;\n\t}\n\n\t@Override\n\tprotected void onRefreshing(final boolean doScroll) {\n\t\tListAdapter adapter = mRefreshableView.getAdapter();\n\t\t/**\n\t\t * Don't let ptrListView do refreshing if adapter is null.\n\t\t */\n\t\tif (null == adapter) {\n\t\t\tLog.d(PullToRefreshListView.class.getSimpleName(), \"Please set an adapter for PullToRefreshListView\");\n\t\t\treturn;\n\t\t}\n\t\t/**\n\t\t * If we're not showing the Refreshing view, the\n\t\t * the header/footer views won't show so we use the normal method.\n\t\t */\n\t\tif (!mListViewExtrasEnabled || !getShowViewWhileRefreshing() || getCurrentMode() == Mode.GOOGLE_STYLE) {\n\t\t\tsuper.onRefreshing(doScroll);\n\t\t\treturn;\n\t\t}\n\n\t\tsuper.onRefreshing(false);\n\n\t\tfinal LoadingLayout origLoadingView, listViewLoadingView, oppositeListViewLoadingView;\n\t\tfinal int selection, scrollToY;\n\n\t\tswitch (getCurrentMode()) {\n\t\t\tcase MANUAL_REFRESH_ONLY:\n\t\t\tcase PULL_FROM_END:\n\t\t\t\torigLoadingView = getFooterLayout();\n\t\t\t\tlistViewLoadingView = mFooterLoadingView;\n\t\t\t\toppositeListViewLoadingView = mHeaderLoadingView;\n\t\t\t\tselection = mRefreshableView.getCount() - 1;\n\t\t\t\tscrollToY = getScrollY() - getFooterSize();\n\t\t\t\tbreak;\n\t\t\tcase PULL_FROM_START:\n\t\t\tdefault:\n\t\t\t\torigLoadingView = getHeaderLayout();\n\t\t\t\tlistViewLoadingView = mHeaderLoadingView;\n\t\t\t\toppositeListViewLoadingView = mFooterLoadingView;\n\t\t\t\tselection = 0;\n\t\t\t\tscrollToY = getScrollY() + getHeaderSize();\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// Hide our original Loading View\n\t\torigLoadingView.reset();\n\t\torigLoadingView.hideAllViews();\n\n\t\t// Make sure the opposite end is hidden too\n\t\toppositeListViewLoadingView.setVisibility(View.GONE);\n\n\t\t// Show the ListView Loading View and set it to refresh.\n\t\tlistViewLoadingView.setVisibility(View.VISIBLE);\n\t\tlistViewLoadingView.refreshing();\n\n\t\tif (doScroll) {\n\t\t\t// We need to disable the automatic visibility changes for now\n\t\t\tdisableLoadingLayoutVisibilityChanges();\n\n\t\t\t// We scroll slightly so that the ListView's header/footer is at the\n\t\t\t// same Y position as our normal header/footer\n\t\t\tsetHeaderScroll(scrollToY);\n\n\t\t\t// Make sure the ListView is scrolled to show the loading\n\t\t\t// header/footer\n\t\t\tmRefreshableView.setSelection(selection);\n\n\t\t\t// Smooth scroll as normal\n\t\t\tsmoothScrollTo(0);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void onReset() {\n\t\t/**\n\t\t * If the extras are not enabled, just call up to super and return.\n\t\t */\n\t\tif (!mListViewExtrasEnabled || getCurrentMode() == Mode.GOOGLE_STYLE) {\n\t\t\tsuper.onReset();\n\t\t\treturn;\n\t\t}\n\n\t\tfinal LoadingLayout originalLoadingLayout, listViewLoadingLayout;\n\t\tfinal int scrollToHeight, selection;\n\t\tfinal boolean scrollLvToEdge;\n\n\t\tswitch (getCurrentMode()) {\n\t\t\tcase MANUAL_REFRESH_ONLY:\n\t\t\tcase PULL_FROM_END:\n\t\t\t\toriginalLoadingLayout = getFooterLayout();\n\t\t\t\tlistViewLoadingLayout = mFooterLoadingView;\n\t\t\t\tselection = mRefreshableView.getCount() - 1;\n\t\t\t\tscrollToHeight = getFooterSize();\n\t\t\t\tscrollLvToEdge = Math.abs(mRefreshableView.getLastVisiblePosition() - selection) <= 1;\n\t\t\t\tbreak;\n\t\t\tcase PULL_FROM_START:\n\t\t\tdefault:\n\t\t\t\toriginalLoadingLayout = getHeaderLayout();\n\t\t\t\tlistViewLoadingLayout = mHeaderLoadingView;\n\t\t\t\tscrollToHeight = -getHeaderSize();\n\t\t\t\tselection = 0;\n\t\t\t\tscrollLvToEdge = Math.abs(mRefreshableView.getFirstVisiblePosition() - selection) <= 1;\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// If the ListView header loading layout is showing, then we need to\n\t\t// flip so that the original one is showing instead\n\t\tif (listViewLoadingLayout.getVisibility() == View.VISIBLE) {\n\n\t\t\t// Set our Original View to Visible\n\t\t\toriginalLoadingLayout.showInvisibleViews();\n\n\t\t\t// Hide the ListView Header/Footer\n\t\t\tlistViewLoadingLayout.setVisibility(View.GONE);\n\n\t\t\t/**\n\t\t\t * Scroll so the View is at the same Y as the ListView\n\t\t\t * header/footer, but only scroll if: we've pulled to refresh, it's\n\t\t\t * positioned correctly\n\t\t\t */\n\t\t\tif (scrollLvToEdge && getState() != State.MANUAL_REFRESHING) {\n\t\t\t\tmRefreshableView.setSelection(selection);\n\t\t\t\tsetHeaderScroll(scrollToHeight);\n\t\t\t}\n\t\t}\n\n\t\t// Finally, call up to super\n\t\tsuper.onReset();\n\t}\n\n\t@Override\n\tprotected LoadingLayoutProxy createLoadingLayoutProxy(final boolean includeStart, final boolean includeEnd) {\n\t\tLoadingLayoutProxy proxy = super.createLoadingLayoutProxy(includeStart, includeEnd);\n\n\t\tif (mListViewExtrasEnabled) {\n\t\t\tfinal Mode mode = getMode();\n\n\t\t\tif (includeStart && mode.showHeaderLoadingLayout()) {\n\t\t\t\tproxy.addLayout(mHeaderLoadingView);\n\t\t\t}\n\t\t\tif (includeEnd && mode.showFooterLoadingLayout()) {\n\t\t\t\tproxy.addLayout(mFooterLoadingView);\n\t\t\t}\n\t\t}\n\n\t\treturn proxy;\n\t}\n\n\tprotected ListView createListView(Context context, AttributeSet attrs) {\n\t\tfinal ListView lv;\n\t\tif (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {\n\t\t\tlv = new InternalListViewSDK9(context, attrs);\n\t\t} else {\n\t\t\tlv = new InternalListView(context, attrs);\n\t\t}\n\t\treturn lv;\n\t}\n\n\t@Override\n\tprotected ListView createRefreshableView(Context context, AttributeSet attrs) {\n\t\tListView lv = createListView(context, attrs);\n\n\t\t// Set it to this so it can be used in ListActivity/ListFragment\n\t\tlv.setId(android.R.id.list);\n\t\treturn lv;\n\t}\n\n\t@Override\n\tprotected void handleStyledAttributes(TypedArray a) {\n\t\tsuper.handleStyledAttributes(a);\n\n\t\tmListViewExtrasEnabled = a.getBoolean(R.styleable.PullToRefresh_ptrListViewExtrasEnabled, true);\n\t\tif ( getMode() == Mode.GOOGLE_STYLE) {\n\t\t\tmListViewExtrasEnabled = false;\n\t\t}\n\t\t\n\t\tif (mListViewExtrasEnabled) {\n\t\t\tfinal FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,\n\t\t\t\t\tFrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL);\n\n\t\t\t// Create Loading Views ready for use later\n\t\t\tFrameLayout frame = new FrameLayout(getContext());\n\t\t\tmHeaderLoadingView = createLoadingLayout(getContext(), Mode.PULL_FROM_START, a);\n\t\t\tmHeaderLoadingView.setVisibility(View.GONE);\n\t\t\tframe.addView(mHeaderLoadingView, lp);\n\t\t\tmRefreshableView.addHeaderView(frame, null, false);\n\n\t\t\tmLvFooterLoadingFrame = new FrameLayout(getContext());\n\t\t\tmFooterLoadingView = createLoadingLayout(getContext(), Mode.PULL_FROM_END, a);\n\t\t\tmFooterLoadingView.setVisibility(View.GONE);\n\t\t\tmLvFooterLoadingFrame.addView(mFooterLoadingView, lp);\n\n\t\t\t/**\n\t\t\t * If the value for Scrolling While Refreshing hasn't been\n\t\t\t * explicitly set via XML, enable Scrolling While Refreshing.\n\t\t\t */\n\t\t\tif (!a.hasValue(R.styleable.PullToRefresh_ptrScrollingWhileRefreshingEnabled)) {\n\t\t\t\tsetScrollingWhileRefreshingEnabled(true);\n\t\t\t}\n\t\t}\n\t}\n\n\t@TargetApi(9)\n\tfinal class InternalListViewSDK9 extends InternalListView {\n\n\t\tpublic InternalListViewSDK9(Context context, AttributeSet attrs) {\n\t\t\tsuper(context, attrs);\n\t\t}\n\n\t\t@Override\n\t\tprotected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX,\n\t\t\t\tint scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {\n\n\t\t\tfinal boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,\n\t\t\t\t\tscrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);\n\n\t\t\t// Does all of the hard work...\n\t\t\tOverscrollHelper.overScrollBy(PullToRefreshListView.this, deltaX, scrollX, deltaY, scrollY, isTouchEvent);\n\n\t\t\treturn returnValue;\n\t\t}\n\t}\n\n\tprotected class InternalListView extends ListView implements EmptyViewMethodAccessor {\n\n\t\tprivate boolean mAddedLvFooter = false;\n\n\t\tpublic InternalListView(Context context, AttributeSet attrs) {\n\t\t\tsuper(context, attrs);\n\t\t}\n\n\t\t@Override\n\t\tprotected void dispatchDraw(Canvas canvas) {\n\t\t\t/**\n\t\t\t * This is a bit hacky, but Samsung's ListView has got a bug in it\n\t\t\t * when using Header/Footer Views and the list is empty. This masks\n\t\t\t * the issue so that it doesn't cause an FC. See Issue #66.\n\t\t\t */\n\t\t\ttry {\n\t\t\t\tsuper.dispatchDraw(canvas);\n\t\t\t} catch (IndexOutOfBoundsException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean dispatchTouchEvent(MotionEvent ev) {\n\t\t\t/**\n\t\t\t * This is a bit hacky, but Samsung's ListView has got a bug in it\n\t\t\t * when using Header/Footer Views and the list is empty. This masks\n\t\t\t * the issue so that it doesn't cause an FC. See Issue #66.\n\t\t\t */\n\t\t\ttry {\n\t\t\t\treturn super.dispatchTouchEvent(ev);\n\t\t\t} catch (IndexOutOfBoundsException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void setAdapter(ListAdapter adapter) {\n\t\t\t// Add the Footer View at the last possible moment\n\t\t\tif (null != mLvFooterLoadingFrame && !mAddedLvFooter) {\n\t\t\t\taddFooterView(mLvFooterLoadingFrame, null, false);\n\t\t\t\tmAddedLvFooter = true;\n\t\t\t}\n\n\t\t\tsuper.setAdapter(adapter);\n\t\t}\n\n\t\t@Override\n\t\tpublic void setEmptyView(View emptyView) {\n\t\t\tPullToRefreshListView.this.setEmptyView(emptyView);\n\t\t}\n\n\t\t@Override\n\t\tpublic void setEmptyViewInternal(View emptyView) {\n\t\t\tsuper.setEmptyView(emptyView);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshScrollView.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport com.handmark.pulltorefresh.library.internal.LoadingLayout;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.os.Build.VERSION;\nimport android.os.Build.VERSION_CODES;\nimport android.util.AttributeSet;\nimport android.view.View;\nimport android.widget.ScrollView;\n\npublic class PullToRefreshScrollView extends PullToRefreshBase<ScrollView> {\n\n\tpublic PullToRefreshScrollView(Context context) {\n\t\tsuper(context);\n\t}\n\n\tpublic PullToRefreshScrollView(Context context, AttributeSet attrs) {\n\t\tsuper(context, attrs);\n\t}\n\n\tpublic PullToRefreshScrollView(Context context, Mode mode) {\n\t\tsuper(context, mode);\n\t}\n\n\tpublic PullToRefreshScrollView(Context context, Mode mode, Class<? extends LoadingLayout> loadingLayoutClazz) {\n\t\tsuper(context, mode, loadingLayoutClazz);\n\t}\n\n\t@Override\n\tpublic final Orientation getPullToRefreshScrollDirection() {\n\t\treturn Orientation.VERTICAL;\n\t}\n\n\t@Override\n\tprotected ScrollView createRefreshableView(Context context, AttributeSet attrs) {\n\t\tScrollView scrollView;\n\t\tif (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {\n\t\t\tscrollView = new InternalScrollViewSDK9(context, attrs);\n\t\t} else {\n\t\t\tscrollView = new ScrollView(context, attrs);\n\t\t}\n\n\t\tscrollView.setId(R.id.scrollview);\n\t\treturn scrollView;\n\t}\n\n\t@Override\n\tprotected boolean isReadyForPullStart() {\n\t\treturn mRefreshableView.getScrollY() == 0;\n\t}\n\n\t@Override\n\tprotected boolean isReadyForPullEnd() {\n\t\tView scrollViewChild = mRefreshableView.getChildAt(0);\n\t\tif (null != scrollViewChild) {\n\t\t\treturn mRefreshableView.getScrollY() >= (scrollViewChild.getHeight() - getHeight());\n\t\t}\n\t\treturn false;\n\t}\n\n\t@TargetApi(9)\n\tfinal class InternalScrollViewSDK9 extends ScrollView {\n\n\t\tpublic InternalScrollViewSDK9(Context context, AttributeSet attrs) {\n\t\t\tsuper(context, attrs);\n\t\t}\n\n\t\t@Override\n\t\tprotected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX,\n\t\t\t\tint scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {\n\n\t\t\tfinal boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,\n\t\t\t\t\tscrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);\n\n\t\t\t// Does all of the hard work...\n\t\t\tOverscrollHelper.overScrollBy(PullToRefreshScrollView.this, deltaX, scrollX, deltaY, scrollY,\n\t\t\t\t\tgetScrollRange(), isTouchEvent);\n\n\t\t\treturn returnValue;\n\t\t}\n\n\t\t/**\n\t\t * Taken from the AOSP ScrollView source\n\t\t */\n\t\tprivate int getScrollRange() {\n\t\t\tint scrollRange = 0;\n\t\t\tif (getChildCount() > 0) {\n\t\t\t\tView child = getChildAt(0);\n\t\t\t\tscrollRange = Math.max(0, child.getHeight() - (getHeight() - getPaddingBottom() - getPaddingTop()));\n\t\t\t}\n\t\t\treturn scrollRange;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshWebView.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library;\n\nimport com.handmark.pulltorefresh.library.internal.LoadingLayout;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.os.Build.VERSION;\nimport android.os.Build.VERSION_CODES;\nimport android.os.Bundle;\nimport android.util.AttributeSet;\nimport android.util.FloatMath;\nimport android.webkit.WebChromeClient;\nimport android.webkit.WebView;\n\npublic class PullToRefreshWebView extends PullToRefreshBase<WebView> {\n\n\tprivate static final OnRefreshListener<WebView> defaultOnRefreshListener = new OnRefreshListener<WebView>() {\n\n\t\t@Override\n\t\tpublic void onRefresh(PullToRefreshBase<WebView> refreshView) {\n\t\t\trefreshView.getRefreshableView().reload();\n\t\t}\n\n\t};\n\n\tprivate final WebChromeClient defaultWebChromeClient = new WebChromeClient() {\n\n\t\t@Override\n\t\tpublic void onProgressChanged(WebView view, int newProgress) {\n\t\t\tif (newProgress == 100) {\n\t\t\t\tonRefreshComplete();\n\t\t\t}\n\t\t}\n\n\t};\n\n\tpublic PullToRefreshWebView(Context context) {\n\t\tsuper(context);\n\n\t\t/**\n\t\t * Added so that by default, Pull-to-Refresh refreshes the page\n\t\t */\n\t\tsetOnRefreshListener(defaultOnRefreshListener);\n\t\tmRefreshableView.setWebChromeClient(defaultWebChromeClient);\n\t}\n\n\tpublic PullToRefreshWebView(Context context, AttributeSet attrs) {\n\t\tsuper(context, attrs);\n\n\t\t/**\n\t\t * Added so that by default, Pull-to-Refresh refreshes the page\n\t\t */\n\t\tsetOnRefreshListener(defaultOnRefreshListener);\n\t\tmRefreshableView.setWebChromeClient(defaultWebChromeClient);\n\t}\n\n\tpublic PullToRefreshWebView(Context context, Mode mode) {\n\t\tsuper(context, mode);\n\n\t\t/**\n\t\t * Added so that by default, Pull-to-Refresh refreshes the page\n\t\t */\n\t\tsetOnRefreshListener(defaultOnRefreshListener);\n\t\tmRefreshableView.setWebChromeClient(defaultWebChromeClient);\n\t}\n\n\tpublic PullToRefreshWebView(Context context, Mode mode, Class<? extends LoadingLayout> loadingLayoutClazz) {\n\t\tsuper(context, mode, loadingLayoutClazz);\n\n\t\t/**\n\t\t * Added so that by default, Pull-to-Refresh refreshes the page\n\t\t */\n\t\tsetOnRefreshListener(defaultOnRefreshListener);\n\t\tmRefreshableView.setWebChromeClient(defaultWebChromeClient);\n\t}\n\n\t@Override\n\tpublic final Orientation getPullToRefreshScrollDirection() {\n\t\treturn Orientation.VERTICAL;\n\t}\n\n\t@Override\n\tprotected WebView createRefreshableView(Context context, AttributeSet attrs) {\n\t\tWebView webView;\n\t\tif (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {\n\t\t\twebView = new InternalWebViewSDK9(context, attrs);\n\t\t} else {\n\t\t\twebView = new WebView(context, attrs);\n\t\t}\n\n\t\twebView.setId(R.id.webview);\n\t\treturn webView;\n\t}\n\n\t@Override\n\tprotected boolean isReadyForPullStart() {\n\t\treturn mRefreshableView.getScrollY() == 0;\n\t}\n\n\t@Override\n\tprotected boolean isReadyForPullEnd() {\n\t\tfloat exactContentHeight = FloatMath.floor(mRefreshableView.getContentHeight() * mRefreshableView.getScale());\n\t\treturn mRefreshableView.getScrollY() >= (exactContentHeight - mRefreshableView.getHeight());\n\t}\n\n\t@Override\n\tprotected void onPtrRestoreInstanceState(Bundle savedInstanceState) {\n\t\tsuper.onPtrRestoreInstanceState(savedInstanceState);\n\t\tmRefreshableView.restoreState(savedInstanceState);\n\t}\n\n\t@Override\n\tprotected void onPtrSaveInstanceState(Bundle saveState) {\n\t\tsuper.onPtrSaveInstanceState(saveState);\n\t\tmRefreshableView.saveState(saveState);\n\t}\n\n\t@TargetApi(9)\n\tfinal class InternalWebViewSDK9 extends WebView {\n\n\t\t// WebView doesn't always scroll back to it's edge so we add some\n\t\t// fuzziness\n\t\tstatic final int OVERSCROLL_FUZZY_THRESHOLD = 2;\n\n\t\t// WebView seems quite reluctant to overscroll so we use the scale\n\t\t// factor to scale it's value\n\t\tstatic final float OVERSCROLL_SCALE_FACTOR = 1.5f;\n\n\t\tpublic InternalWebViewSDK9(Context context, AttributeSet attrs) {\n\t\t\tsuper(context, attrs);\n\t\t}\n\n\t\t@Override\n\t\tprotected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX,\n\t\t\t\tint scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {\n\n\t\t\tfinal boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,\n\t\t\t\t\tscrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);\n\n\t\t\t// Does all of the hard work...\n\t\t\tOverscrollHelper.overScrollBy(PullToRefreshWebView.this, deltaX, scrollX, deltaY, scrollY,\n\t\t\t\t\tgetScrollRange(), OVERSCROLL_FUZZY_THRESHOLD, OVERSCROLL_SCALE_FACTOR, isTouchEvent);\n\n\t\t\treturn returnValue;\n\t\t}\n\n\t\tprivate int getScrollRange() {\n\t\t\treturn (int) Math.max(0, FloatMath.floor(mRefreshableView.getContentHeight() * mRefreshableView.getScale())\n\t\t\t\t\t- (getHeight() - getPaddingBottom() - getPaddingTop()));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/extras/PullToRefreshWebView2.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library.extras;\n\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport android.webkit.WebView;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshWebView;\n\n/**\n * An advanced version of {@link PullToRefreshWebView} which delegates the\n * triggering of the PullToRefresh gesture to the Javascript running within the\n * WebView. This means that you should only use this class if:\n * <p/>\n * <ul>\n * <li>{@link PullToRefreshWebView} doesn't work correctly because you're using\n * <code>overflow:scroll</code> or something else which means\n * {@link WebView#getScrollY()} doesn't return correct values.</li>\n * <li>You control the web content being displayed, as you need to write some\n * Javascript callbacks.</li>\n * </ul>\n * <p/>\n * <p/>\n * The way this call works is that when a PullToRefresh gesture is in action,\n * the following Javascript methods will be called:\n * <code>isReadyForPullDown()</code> and <code>isReadyForPullUp()</code>, it is\n * your job to calculate whether the view is in a state where a PullToRefresh\n * can happen, and return the result via the callback mechanism. An example can\n * be seen below:\n * <p/>\n * \n * <pre>\n * function isReadyForPullDown() {\n *   var result = ...  // Probably using the .scrollTop DOM attribute\n *   ptr.isReadyForPullDownResponse(result);\n * }\n * \n * function isReadyForPullUp() {\n *   var result = ...  // Probably using the .scrollBottom DOM attribute\n *   ptr.isReadyForPullUpResponse(result);\n * }\n * </pre>\n * \n * @author Chris Banes\n */\npublic class PullToRefreshWebView2 extends PullToRefreshWebView {\n\n\tstatic final String JS_INTERFACE_PKG = \"ptr\";\n\tstatic final String DEF_JS_READY_PULL_DOWN_CALL = \"javascript:isReadyForPullDown();\";\n\tstatic final String DEF_JS_READY_PULL_UP_CALL = \"javascript:isReadyForPullUp();\";\n\n\tpublic PullToRefreshWebView2(Context context) {\n\t\tsuper(context);\n\t}\n\n\tpublic PullToRefreshWebView2(Context context, AttributeSet attrs) {\n\t\tsuper(context, attrs);\n\t}\n\n\tpublic PullToRefreshWebView2(Context context, Mode mode) {\n\t\tsuper(context, mode);\n\t}\n\n\tprivate JsValueCallback mJsCallback;\n\tprivate final AtomicBoolean mIsReadyForPullDown = new AtomicBoolean(false);\n\tprivate final AtomicBoolean mIsReadyForPullUp = new AtomicBoolean(false);\n\n\t@Override\n\tprotected WebView createRefreshableView(Context context, AttributeSet attrs) {\n\t\tWebView webView = super.createRefreshableView(context, attrs);\n\n\t\t// Need to add JS Interface so we can get the response back\n\t\tmJsCallback = new JsValueCallback();\n\t\twebView.addJavascriptInterface(mJsCallback, JS_INTERFACE_PKG);\n\n\t\treturn webView;\n\t}\n\n\t@Override\n\tprotected boolean isReadyForPullStart() {\n\t\t// Call Javascript...\n\t\tgetRefreshableView().loadUrl(DEF_JS_READY_PULL_DOWN_CALL);\n\n\t\t// Response will be given to JsValueCallback, which will update\n\t\t// mIsReadyForPullDown\n\n\t\treturn mIsReadyForPullDown.get();\n\t}\n\n\t@Override\n\tprotected boolean isReadyForPullEnd() {\n\t\t// Call Javascript...\n\t\tgetRefreshableView().loadUrl(DEF_JS_READY_PULL_UP_CALL);\n\n\t\t// Response will be given to JsValueCallback, which will update\n\t\t// mIsReadyForPullUp\n\n\t\treturn mIsReadyForPullUp.get();\n\t}\n\n\t/**\n\t * Used for response from Javascript\n\t * \n\t * @author Chris Banes\n\t */\n\tfinal class JsValueCallback {\n\n\t\tpublic void isReadyForPullUpResponse(boolean response) {\n\t\t\tmIsReadyForPullUp.set(response);\n\t\t}\n\n\t\tpublic void isReadyForPullDownResponse(boolean response) {\n\t\t\tmIsReadyForPullDown.set(response);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/extras/SoundPullEventListener.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library.extras;\n\nimport java.util.HashMap;\n\nimport android.content.Context;\nimport android.media.MediaPlayer;\nimport android.view.View;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshBase;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.State;\n\npublic class SoundPullEventListener<V extends View> implements PullToRefreshBase.OnPullEventListener<V> {\n\n\tprivate final Context mContext;\n\tprivate final HashMap<State, Integer> mSoundMap;\n\n\tprivate MediaPlayer mCurrentMediaPlayer;\n\n\t/**\n\t * Constructor\n\t * \n\t * @param context - Context\n\t */\n\tpublic SoundPullEventListener(Context context) {\n\t\tmContext = context;\n\t\tmSoundMap = new HashMap<State, Integer>();\n\t}\n\n\t@Override\n\tpublic final void onPullEvent(PullToRefreshBase<V> refreshView, State event, Mode direction) {\n\t\tInteger soundResIdObj = mSoundMap.get(event);\n\t\tif (null != soundResIdObj) {\n\t\t\tplaySound(soundResIdObj.intValue());\n\t\t}\n\t}\n\n\t/**\n\t * Set the Sounds to be played when a Pull Event happens. You specify which\n\t * sound plays for which events by calling this method multiple times for\n\t * each event.\n\t * <p/>\n\t * If you've already set a sound for a certain event, and add another sound\n\t * for that event, only the new sound will be played.\n\t * \n\t * @param event - The event for which the sound will be played.\n\t * @param resId - Resource Id of the sound file to be played (e.g.\n\t *            <var>R.raw.pull_sound</var>)\n\t */\n\tpublic void addSoundEvent(State event, int resId) {\n\t\tmSoundMap.put(event, resId);\n\t}\n\n\t/**\n\t * Clears all of the previously set sounds and events.\n\t */\n\tpublic void clearSounds() {\n\t\tmSoundMap.clear();\n\t}\n\n\t/**\n\t * Gets the current (or last) MediaPlayer instance.\n\t */\n\tpublic MediaPlayer getCurrentMediaPlayer() {\n\t\treturn mCurrentMediaPlayer;\n\t}\n\n\tprivate void playSound(int resId) {\n\t\t// Stop current player, if there's one playing\n\t\tif (null != mCurrentMediaPlayer) {\n\t\t\tmCurrentMediaPlayer.stop();\n\t\t\tmCurrentMediaPlayer.release();\n\t\t}\n\n\t\tmCurrentMediaPlayer = MediaPlayer.create(mContext, resId);\n\t\tif (null != mCurrentMediaPlayer) {\n\t\t\tmCurrentMediaPlayer.start();\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/internal/AbstractDefaultGoogleStyleViewLayout.java",
    "content": "/*******************************************************************************\n * Copyright 2014 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library.internal;\n\nimport android.content.Context;\nimport android.content.res.ColorStateList;\nimport android.content.res.TypedArray;\nimport android.graphics.Color;\nimport android.graphics.Typeface;\nimport android.graphics.drawable.Drawable;\nimport android.text.TextUtils;\nimport android.util.TypedValue;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.FrameLayout;\nimport android.widget.TextView;\n\nimport com.handmark.pulltorefresh.library.GoogleStyleViewLayout;\nimport com.handmark.pulltorefresh.library.R;\n/**\n * Abstract class of Default Google style view layout <br />\n * Instance of UI Components are been getting as abstract method, if you override this method, abstract get...() methods must be implemented. These will be assigned to UI instance fields. \n * @author Wonjun Kim\n *\n */\npublic abstract class AbstractDefaultGoogleStyleViewLayout extends GoogleStyleViewLayout {\n\n\tprivate FrameLayout mInnerLayout;\n\tprivate TextView mHeaderText;\n\tprivate TextView mSubHeaderText;\n\t\n\tprivate CharSequence mPullLabel;\n\tprivate CharSequence mRefreshingLabel;\n\tprivate CharSequence mReleaseLabel;\n\t\n\tpublic AbstractDefaultGoogleStyleViewLayout(Context context, TypedArray attrs) {\n\t\tsuper(context, attrs);\n\n\t\tinitImpl(context, attrs);\n\t\tinitComponents(context, attrs);\n\t\tinitProperties(context, attrs);\n\t\treset();\n\t}\n\n\tprotected abstract void initImpl(Context context, TypedArray attrs);\n\t/**\n\t * Assign get..() methods to fields\n\t * @param context\n\t * @param attrs\n\t */\n\tprivate void initComponents(Context context, TypedArray attrs) {\n\t\tmInnerLayout = getInnerLayout(context, attrs);\n\t\tmHeaderText = getHeaderText(context, attrs);\n\t\tmSubHeaderText = geSubHeaderTextLayout(context, attrs);\n\t}\n\t/**\n\t * Returns SubHeaderText Layout instance to be displayed\n\t * @param context\n\t * @param attrs\n\t * @return\n\t */\n\tprotected abstract TextView geSubHeaderTextLayout(Context context, TypedArray attrs);\n\t/**\n\t * Returns Inner Layout instance to be displayed\n\t * @param context\n\t * @param attrs\n\t * @return\n\t */\n\tprotected abstract TextView getHeaderText(Context context, TypedArray attrs);\n\t/**\n\t * Returns HeaderText Layout instance to be displayed\n\t * @param context\n\t * @param attrs\n\t * @return\n\t */\n\tprotected abstract FrameLayout getInnerLayout(Context context, TypedArray attrs);\n\n\t@Override\n\tpublic final void setHeight(int height) {\n\t\t// set Inner layout's height too\n\t\tViewGroup.LayoutParams lp = mInnerLayout.getLayoutParams();\n\t\tlp.height = height;\n\t\tViewGroup.LayoutParams thisLp = getLayoutParams();\n\t\tif ( thisLp != null ) {\n\t\t\tthisLp.height = height;\n\t\t}\n\t\n\t\trequestLayout();\n\t}\n\t/**\n\t * Initialize text color, sub text color , and text appearance. <br />\n\t * If text color is not set, set default color by calling {@link #getDefaultTextColor(Context, TypedArray)}, or {@link #getDefaultSubTextColor(Context, TypedArray)}.<br />\n\t * Also, if background color is not set, set default color by calling {@link #getDefaultBackgroundColor(Context, TypedArray)}\n\t * @param context\n\t * @param attrs\n\t */\n\tprotected void initProperties(Context context, TypedArray attrs) {\n\t\t// Load Loading Layout Labels\n\t\tloadLoadingLayoutLabels(context, attrs);\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderBackground)) {\n\t\t\tDrawable background = attrs.getDrawable(R.styleable.PullToRefresh_ptrHeaderBackground);\n\t\t\tif ( null != background ) {\n\t\t\t\tViewCompat.setBackground(this, background);\t\t\n\t\t\t}\n\t\t} else {\n\t\t\t// Set background to white as default\n\t\t\tsetBackgroundColor(getDefaultBackgroundColor(context, attrs));\n\t\t}\n\t\t\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderTextAppearance)) {\n\t\t\tTypedValue styleID = new TypedValue();\n\t\t\tattrs.getValue(R.styleable.PullToRefresh_ptrHeaderTextAppearance, styleID);\n\t\t\tsetTextAppearance(styleID.data);\n\t\t}\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrSubHeaderTextAppearance)) {\n\t\t\tTypedValue styleID = new TypedValue();\n\t\t\tattrs.getValue(R.styleable.PullToRefresh_ptrSubHeaderTextAppearance, styleID);\n\t\t\tsetSubTextAppearance(styleID.data);\n\t\t}\n\n\t\t// Text Color attrs need to be set after TextAppearance attrs\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderTextColor)) {\n\t\t\tColorStateList colors = attrs.getColorStateList(R.styleable.PullToRefresh_ptrHeaderTextColor);\n\t\t\tif (null != colors) {\n\t\t\t\tsetTextColor(colors);\n\t\t\t}\n\t\t} else {\n\t\t\t// Set Text color to black as default \n\t\t\tsetTextColor(getDefaultTextColor(context, attrs));\n\t\t}\n\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderSubTextColor)) {\n\t\t\tColorStateList colors = attrs.getColorStateList(R.styleable.PullToRefresh_ptrHeaderSubTextColor);\n\t\t\tif (null != colors) {\n\t\t\t\tsetSubTextColor(colors);\n\t\t\t}\n\t\t} else {\n\t\t\t// Set Text color to black as default \n\t\t\tsetSubTextColor(getDefaultSubTextColor(context, attrs));\n\t\t}\n\t\t\n\t\tinitPropertiesImpl(context, attrs);\n\n\t}\n\n\tprotected abstract void initPropertiesImpl(Context context, TypedArray attrs);\n\t/**\n\t * Use {@code Color.White} color as default to set background color. <br />\n\t * If you want to change this default, override this method. \n\t * @param context\n\t * @param attrs\n\t * @return Color value\n\t */\n\tprotected int getDefaultBackgroundColor(Context context, TypedArray attrs) {\n\t\treturn Color.WHITE;\n\t}\n\t/**\n\t * Use {@code Color.Black} color as default to set text color. <br />\n\t * If you want to change this default, override this method. \n\t * @param context\n\t * @param attrs\n\t * @return Color value\n\t */\n\tprotected int getDefaultTextColor(Context context, TypedArray attrs) {\n\t\treturn Color.BLACK;\n\t}\n\t/**\n\t * Use {@code Color.Black} color as default to set sub text color. <br />\n\t * If you want to change this default, override this method. \n\t * @param context\n\t * @param attrs\n\t * @return Color value\n\t */\n\tprotected int getDefaultSubTextColor(Context context, TypedArray attrs) {\n\t\treturn Color.BLACK;\n\t}\n\n\t/**\n\t * Load labels of pull, refresh, release, and assign into fields\n\t * <br />Convert an each attribute value such as {@code ptrPullLabel}, {@code ptrRefreshLabel} or {@code ptrReleaseLabel} to each label field if each value exists.\n\t * <br />Or if not, then the each label is assigned some string as default\n\t * <br />\n\t * NOTE : This method <b>Must</b> be modified if kinds of {@code Mode} are increased.\n\t * @param attrs \n\t */\n\tprivate void loadLoadingLayoutLabels(Context context, TypedArray attrs) {\n\t\tmPullLabel = loadPullLabel(context, attrs);\n\t\tmRefreshingLabel = loadRefreshingLabel(context, attrs);\n\t\tmReleaseLabel = loadReleaseLabel(context, attrs);\n\t}\n\t/**\n\t * Load labels of pull\n\t * <br />Convert an {@code ptrPullLabel} attribute value to {@code mPullLabel} field if each value exists.\n\t * <br />Or if not, then the pull label is assigned some string as default\n\t * <br />If you want to set some custom pull label at sub class, you have to override this method and implement.\n\t * NOTE : This method <b>Must</b> be modified if kinds of {@code Mode} are increased.\n\t * @param context\n\t * @param attrs\n\t * @param mode\n\t * @return String to be a pull label  \n\t */\n\tprotected String loadPullLabel(Context context, TypedArray attrs) {\n\t\t// Pull Label\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrPullLabel)) {\n\t\t\treturn attrs.getString(R.styleable.PullToRefresh_ptrPullLabel);\n\t\t} \n\t\t\n\t\tint stringId = R.string.pull_to_refresh_pull_label;\n\t\treturn context.getString(stringId);\n\t}\t\n\t/**\n\t * Load labels of refreshing\n\t * <br />Convert an {@code ptrRefreshLabel} attribute value to {@code mRefreshingLabel} field if each value exists.\n\t * <br />Or if not, then the refreshing label is assigned some string as default\n\t * <br />If you want to set some custom refreshing label at sub class, you have to override this method and implement.\n\t * NOTE : This method <b>Must</b> be modified if kinds of {@code Mode} are increased.\n\t * @param context\n\t * @param attrs\n\t * @return String to be a refreshing label  \n\t */\n\tprotected String loadRefreshingLabel(Context context, TypedArray attrs) {\n\t\t// Refresh Label\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrRefreshLabel)) {\n\t\t\treturn attrs.getString(R.styleable.PullToRefresh_ptrRefreshLabel);\n\t\t} \n\t\t\n\t\tint stringId = R.string.pull_to_refresh_refreshing_label;\n\t\treturn context.getString(stringId);\n\t}\t\n\t/**\n\t * Load labels of release\n\t * <br />Convert an {@code ptrReleaseLabel} attribute value to {@code mReleaseLabel} field if each value exists.\n\t * <br />Or if not, then the release label is assigned some string as default\n\t * <br />If you want to set some custom release label at sub class, you have to override this method and implement.\n\t * NOTE : This method <b>Must</b> be modified if kinds of {@code Mode} are increased.\n\t * @param context\n\t * @param attrs\n\t * @return String to be a refreshing label  \n\t */\n\tprotected String loadReleaseLabel(Context context, TypedArray attrs) {\n\t\t// Release Label\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrReleaseLabel)) {\n\t\t\treturn attrs.getString(R.styleable.PullToRefresh_ptrReleaseLabel);\n\t\t} \n\t\t\n\t\tint stringId = R.string.pull_to_refresh_release_label;\n\t\treturn context.getString(stringId);\n\t\t\n\t}\n\n\t@Override\n\tpublic final void setWidth(int width) {\n\t\tViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) getLayoutParams();\n\t\tlp.width = width;\n\t\trequestLayout();\n\t}\n\n\t@Override\n\tpublic final int getContentSize() {\n\t\treturn mInnerLayout.getHeight();\n\t}\n\n\tpublic final void hideAllViews() {\n\t\thideHeaderText();\n\t\thideSubHeaderText();\n\t}\n\n\tprivate void hideHeaderText() {\n\t\tif (null != mHeaderText && View.VISIBLE == mHeaderText.getVisibility()) {\n\t\t\tmHeaderText.setVisibility(View.INVISIBLE);\n\t\t}\n\t}\n\n\tprivate void hideSubHeaderText() {\n\t\tif (null != mHeaderText && View.VISIBLE == mSubHeaderText.getVisibility()) {\n\t\t\tmSubHeaderText.setVisibility(View.INVISIBLE);\n\t\t}\n\t}\n\n\tprotected abstract void pullToRefreshImpl();\n\tprotected abstract void releaseToRefreshImpl();\n\tprotected abstract void refreshingImpl();\n\tprotected abstract void resetImpl();\n\tprotected abstract void onPullImpl(float scale);\n\t\n\t@Override\n\tpublic final void pullToRefresh() {\n\t\tif (null != mHeaderText) {\n\t\t\tmHeaderText.setText(mPullLabel);\n\t\t}\n\t\tpullToRefreshImpl();\n\t}\n\t\n\t@Override\n\tpublic final void refreshing() {\n\t\tif (null != mHeaderText) {\n\t\t\tmHeaderText.setText(mRefreshingLabel);\n\t\t}\n\n\t\tif (null != mSubHeaderText) {\n\t\t\tmSubHeaderText.setVisibility(View.GONE);\n\t\t}\n\t\t\n\t\trefreshingImpl();\n\t}\n\n\t@Override\n\tpublic final void releaseToRefresh() {\n\t\tif (null != mHeaderText) {\n\t\t\tmHeaderText.setText(mReleaseLabel);\n\t\t}\n\t\t\n\t\treleaseToRefreshImpl();\n\t}\n\n\t@Override\n\tpublic final void reset() {\n\t\tif (null != mHeaderText) {\n\t\t\tmHeaderText.setText(mPullLabel);\n\t\t}\n\n\t\tif (null != mSubHeaderText) {\n\t\t\tif (TextUtils.isEmpty(mSubHeaderText.getText())) {\n\t\t\t\tmSubHeaderText.setVisibility(View.GONE);\n\t\t\t} else {\n\t\t\t\tmSubHeaderText.setVisibility(View.VISIBLE);\n\t\t\t}\n\t\t}\n\t\tresetImpl();\n\t}\n\n\tpublic void setLastUpdatedLabel(CharSequence label) {\n\t\tsetSubHeaderText(label);\n\t}\n\n\tpublic void setPullLabel(CharSequence pullLabel) {\n\t\tmPullLabel = pullLabel;\n\t}\n\n\tpublic void setRefreshingLabel(CharSequence refreshingLabel) {\n\t\tmRefreshingLabel = refreshingLabel;\n\t}\n\n\tpublic void setReleaseLabel(CharSequence releaseLabel) {\n\t\tmReleaseLabel = releaseLabel;\n\t}\n\n\tpublic void setTextTypeface(Typeface tf) {\n\t\tif (null != mHeaderText) {\n\t\t\tmHeaderText.setTypeface(tf);\t\t\t\n\t\t}\n\t}\n\n\tpublic final void showInvisibleViews() {\n\t\tshowHeaderText();\n\t\tshowSubHeaderText();\n\t}\n\n\tprivate void showSubHeaderText() {\n\t\tif (null != mSubHeaderText && View.INVISIBLE == mSubHeaderText.getVisibility()) {\n\t\t\tmSubHeaderText.setVisibility(View.VISIBLE);\n\t\t}\n\t}\n\n\tprivate void showHeaderText() {\n\t\tif (null != mHeaderText && View.INVISIBLE == mHeaderText.getVisibility()) {\n\t\t\tmHeaderText.setVisibility(View.VISIBLE);\n\t\t}\n\t}\n\n\tprivate void setSubHeaderText(CharSequence label) {\n\t\tif (null != mSubHeaderText) {\n\t\t\tif (TextUtils.isEmpty(label)) {\n\t\t\t\tmSubHeaderText.setVisibility(View.GONE);\n\t\t\t} else {\n\t\t\t\tmSubHeaderText.setText(label);\n\n\t\t\t\t// Only set it to Visible if we're GONE, otherwise VISIBLE will\n\t\t\t\t// be set soon\n\t\t\t\tif (View.GONE == mSubHeaderText.getVisibility()) {\n\t\t\t\t\tmSubHeaderText.setVisibility(View.VISIBLE);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void setSubTextAppearance(int value) {\n\t\tif (null != mSubHeaderText) {\n\t\t\tmSubHeaderText.setTextAppearance(getContext(), value);\n\t\t}\n\t}\n\n\tprivate void setSubTextColor(ColorStateList color) {\n\t\tif (null != mSubHeaderText) {\n\t\t\tmSubHeaderText.setTextColor(color);\n\t\t}\n\t}\n\n\tprivate void setSubTextColor(int color) {\n\t\tif (null != mSubHeaderText) {\n\t\t\tmSubHeaderText.setTextColor(color);\n\t\t}\n\t}\n\n\tprivate void setTextAppearance(int value) {\n\t\tif (null != mHeaderText) {\n\t\t\tmHeaderText.setTextAppearance(getContext(), value);\n\t\t}\n\t\tif (null != mSubHeaderText) {\n\t\t\tmSubHeaderText.setTextAppearance(getContext(), value);\n\t\t}\n\t}\n\n\tprivate void setTextColor(ColorStateList color) {\n\t\tif (null != mHeaderText) {\n\t\t\tmHeaderText.setTextColor(color);\n\t\t}\n\t\tif (null != mSubHeaderText) {\n\t\t\tmSubHeaderText.setTextColor(color);\n\t\t}\n\t}\n\n\tprivate void setTextColor(int color) {\n\t\tif (null != mHeaderText) {\n\t\t\tmHeaderText.setTextColor(color);\n\t\t}\n\t\tif (null != mSubHeaderText) {\n\t\t\tmSubHeaderText.setTextColor(color);\n\t\t}\n\t}\n\t\n\t@Override\n\tpublic void onPull(float scale) {\n\t\tonPullImpl(scale);\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/internal/Assert.java",
    "content": "/*******************************************************************************\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library.internal;\n\npublic class Assert {\n\tprivate static final String MESSAGE_FORMAT = \"\\\"%s\\\" argument must be not null.\";\n\n\tpublic static void notNull(Object object, String argName) {\n\t\tif (object == null) {\n\t\t\t// When a parameter is null,\n\t\t\t// it throws a NullPointerException instead of an IllegalArgumentException.\n\t\t\t// This rule is recommended by the item 62 on Effective Java 2nd edition as follows.\n\t\t\t// \"If a caller passes null in some parameter for which null values are prohibited, \n\t\t\t// convention dictates that NullPointerException be thrown rather than IllegalArgumentException.\"\n\t\t\tthrow new NullPointerException(String.format(MESSAGE_FORMAT, argName));\n\t\t}\n\t}\n}"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/internal/DefaultGoogleStyleProgressLayout.java",
    "content": "/*******************************************************************************\n * Copyright 2014 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library.internal;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.widget.ProgressBar;\n\nimport com.handmark.pulltorefresh.library.GoogleStyleProgressLayout;\nimport com.handmark.pulltorefresh.library.R;\n/**\n * Specific implemented layout of Google style progress layout<br />\n * NOTE : This class doesn't have abstract default class because of no extend points in this class. \n * @author Wonjun Kim\n *\n */\npublic class DefaultGoogleStyleProgressLayout extends GoogleStyleProgressLayout {\n\n\tprivate PullingProgressLayout mActionBarHeaderPullingProgressLayout;\n\tprivate ProgressBar mActionBarHeaderRefreshingProgressBar;\n\n\tpublic DefaultGoogleStyleProgressLayout(Context context, TypedArray attrs) {\n\t\tsuper(context, attrs);\n\t\tinitInflate(context, R.layout.pull_to_refresh_progress_google_style);\n\t\tinitProperties();\n\t\treset();\n\t}\n\t/**\n\t * Inflate layout by {@code inflateId}\n\t * @param context\n\t * @param inflateId inflate id value like {@code R.layout...} \n\t */\n\tprivate void initInflate(Context context, int inflateId) {\n\t\tLayoutInflater.from(context).inflate(inflateId, this);\t\t\n\t}\n\t/**\n\t * Assign UI Components to fields\n\t */\n\tprivate void initProperties() {\n\t\tmActionBarHeaderPullingProgressLayout = (PullingProgressLayout) findViewById(R.id.pulling_progress);\n\t\tmActionBarHeaderRefreshingProgressBar = (ProgressBar) findViewById(R.id.refreshing_progress);\n\t}\n\t/**\n\t * Show pulling bar and hide refreshing bar\n\t */\n\t@Override\n\tpublic void reset() {\n\t\tmActionBarHeaderPullingProgressLayout.setVisibility(View.VISIBLE);\n\t\tmActionBarHeaderRefreshingProgressBar.setVisibility(View.INVISIBLE);\n\t\tmActionBarHeaderPullingProgressLayout.setPercent(0);\n\t}\n\t/**\n\t * Hide pulling bar and show refreshing bar\n\t */\n\t@Override\n\tpublic void refreshing() {\n\t\tmActionBarHeaderPullingProgressLayout.setVisibility(View.INVISIBLE);\n\t\tmActionBarHeaderRefreshingProgressBar.setVisibility(View.VISIBLE);\n\t}\n\n\t@Override\n\tpublic void releaseToRefresh() {\n\t}\n\n\t@Override\n\tpublic void pullToRefresh() {\n\t}\n\t/**\n\t * Set progress of pulling bar\n\t */\n\t@Override\n\tpublic void onPull(float scale) {\n\t\tint percent = (int) (scale * 100);\n\t\tmActionBarHeaderPullingProgressLayout.setPercent(percent);\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/internal/DefaultGoogleStyleViewLayout.java",
    "content": "/*******************************************************************************\n * Copyright 2014 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library.internal;\n\nimport com.handmark.pulltorefresh.library.R;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.view.LayoutInflater;\nimport android.widget.FrameLayout;\nimport android.widget.TextView;\n/**\n * Specific implemented layout of Google style view layout<br />\n * @author Wonjun Kim\n */\npublic class DefaultGoogleStyleViewLayout extends AbstractDefaultGoogleStyleViewLayout {\n\n\tpublic DefaultGoogleStyleViewLayout(Context context, TypedArray attrs) {\n\t\tsuper(context, attrs);\n\t}\n\t/**\n\t * Inflate layout by {@code inflateId}\n\t * @param context\n\t * @param inflateId inflate id value like {@code R.layout...} \n\t */\n\tprivate void initInflate(Context context, int inflateId) {\n\t\tLayoutInflater.from(context).inflate(inflateId, this);\n\t}\n\t/**\n\t * Initialize layout\n\t */\n\t@Override\n\tprotected void initImpl(Context context, TypedArray attrs) {\n\t\tinitInflate(context, getLayoutInflateId());\n\t}\n\t/**\n\t * Returns inflate id to be used when inflating\n\t * If you want to change layout xml, you have to override this method and change a return value\n\t * @return Inflate id\n\t */\n\tprotected int getLayoutInflateId() {\n\t\treturn R.layout.pull_to_refresh_header_google_style;\n\t}\n\t/**\n\t * Bind SubHeaderText layout Component to some field\n\t */\n\t@Override\n\tprotected TextView geSubHeaderTextLayout(Context context, TypedArray attrs) {\n\t\treturn (TextView) findViewById(R.id.pull_to_refresh_sub_text);\n\t}\n\t/**\n\t * Bind HeaderText layout Component to some field\n\t */\n\t@Override\n\tprotected TextView getHeaderText(Context context, TypedArray attrs) {\n\t\treturn (TextView) findViewById(R.id.pull_to_refresh_text);\n\t}\n\t/**\n\t * Bind Inner layout Component to some field\n\t */\n\t@Override\n\tprotected FrameLayout getInnerLayout(Context context, TypedArray attrs) {\n\t\treturn (FrameLayout) findViewById(R.id.fl_inner_for_google_style);\n\t}\n\n\t@Override\n\tprotected void initPropertiesImpl(Context context, TypedArray attrs) {\n\t\t// do nothing\n\t}\n\n\t@Override\n\tprotected void pullToRefreshImpl() {\n\t\t// do nothing\n\t}\n\n\t@Override\n\tprotected void releaseToRefreshImpl() {\n\t\t// do nothing\t\t\n\t}\n\n\t@Override\n\tprotected void refreshingImpl() {\n\t\t// do nothing\t\t\n\t}\n\n\t@Override\n\tprotected void resetImpl() {\n\t\t// do nothing\t\t\n\t}\n\n\t@Override\n\tprotected void onPullImpl(float scale) {\n\t\t// do nothing\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/internal/DefaultIndicatorLayout.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library.internal;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.graphics.Matrix;\nimport android.graphics.drawable.Drawable;\nimport android.view.Gravity;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.animation.Animation;\nimport android.view.animation.Animation.AnimationListener;\nimport android.view.animation.AnimationUtils;\nimport android.view.animation.Interpolator;\nimport android.view.animation.LinearInterpolator;\nimport android.view.animation.RotateAnimation;\nimport android.widget.FrameLayout;\nimport android.widget.ImageView;\nimport android.widget.ImageView.ScaleType;\n\nimport com.handmark.pulltorefresh.library.IIndicatorLayout;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase;\nimport com.handmark.pulltorefresh.library.R;\n\n@SuppressLint(\"ViewConstructor\")\npublic class DefaultIndicatorLayout extends IndicatorLayout implements IIndicatorLayout, AnimationListener {\n\n\tstatic final int DEFAULT_ROTATION_ANIMATION_DURATION = 150;\n\n\tprivate Animation mInAnim, mOutAnim;\n\tprivate ImageView mArrowImageView;\n\n\tprivate final Animation mRotateAnimation, mResetRotateAnimation;\n\n\tpublic DefaultIndicatorLayout(Context context, PullToRefreshBase.Mode mode) {\n\t\tsuper(context);\n\t\tmArrowImageView = new ImageView(context);\n\n\t\tDrawable arrowD = getIconDrawable(context, mode);\n\t\tmArrowImageView.setImageDrawable(arrowD);\n\t\t\n\t\tfinal int padding = getResources().getDimensionPixelSize(R.dimen.indicator_internal_padding);\n\t\tmArrowImageView.setPadding(padding, padding, padding, padding);\n\t\taddView(mArrowImageView);\n\n\t\tint inAnimResId, outAnimResId;\n\t\tswitch (mode) {\n\t\t\tcase PULL_FROM_END:\n\t\t\t\tinAnimResId = R.anim.slide_in_from_bottom;\n\t\t\t\toutAnimResId = R.anim.slide_out_to_bottom;\n\t\t\t\tsetBackgroundResource(R.drawable.indicator_bg_bottom);\n\n\t\t\t\t// Rotate Arrow so it's pointing the correct way\n\t\t\t\tmArrowImageView.setScaleType(ScaleType.MATRIX);\n\t\t\t\tMatrix matrix = new Matrix();\n\t\t\t\tmatrix.setRotate(180f, arrowD.getIntrinsicWidth() / 2f, arrowD.getIntrinsicHeight() / 2f);\n\t\t\t\tmArrowImageView.setImageMatrix(matrix);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\tcase PULL_FROM_START:\n\t\t\t\tinAnimResId = R.anim.slide_in_from_top;\n\t\t\t\toutAnimResId = R.anim.slide_out_to_top;\n\t\t\t\tsetBackgroundResource(R.drawable.indicator_bg_top);\n\t\t\t\tbreak;\n\t\t}\n\n\t\tmInAnim = AnimationUtils.loadAnimation(context, inAnimResId);\n\t\tmInAnim.setAnimationListener(this);\n\n\t\tmOutAnim = AnimationUtils.loadAnimation(context, outAnimResId);\n\t\tmOutAnim.setAnimationListener(this);\n\n\t\tfinal Interpolator interpolator = new LinearInterpolator();\n\t\tmRotateAnimation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,\n\t\t\t\t0.5f);\n\t\tmRotateAnimation.setInterpolator(interpolator);\n\t\tmRotateAnimation.setDuration(DEFAULT_ROTATION_ANIMATION_DURATION);\n\t\tmRotateAnimation.setFillAfter(true);\n\n\t\tmResetRotateAnimation = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF, 0.5f,\n\t\t\t\tAnimation.RELATIVE_TO_SELF, 0.5f);\n\t\tmResetRotateAnimation.setInterpolator(interpolator);\n\t\tmResetRotateAnimation.setDuration(DEFAULT_ROTATION_ANIMATION_DURATION);\n\t\tmResetRotateAnimation.setFillAfter(true);\n\n\t}\n\t/**\n\t * Create an icon that default indicator layout will use \n\t * @param context\n\t * @param mode\n\t * @return Indicator icon\n\t */\n\tprotected Drawable getIconDrawable(Context context, PullToRefreshBase.Mode mode) {\n\t\treturn getResources().getDrawable(R.drawable.indicator_arrow);\n\t}\n\t/**\n\t * {@inheritDoc}\n\t */\n\tpublic final boolean isVisible() {\n\t\tAnimation currentAnim = getAnimation();\n\t\tif (null != currentAnim) {\n\t\t\treturn mInAnim == currentAnim;\n\t\t}\n\n\t\treturn getVisibility() == View.VISIBLE;\n\t}\n\t/**\n\t * {@inheritDoc}\n\t */\n\tpublic void hide() {\n\t\tstartAnimation(mOutAnim);\n\t}\n\t/**\n\t * {@inheritDoc}\n\t */\n\tpublic void show() {\n\t\tmArrowImageView.clearAnimation();\n\t\tstartAnimation(mInAnim);\n\t}\n\n\t@Override\n\tpublic void onAnimationEnd(Animation animation) {\n\t\tif (animation == mOutAnim) {\n\t\t\tmArrowImageView.clearAnimation();\n\t\t\tsetVisibility(View.GONE);\n\t\t} else if (animation == mInAnim) {\n\t\t\tsetVisibility(View.VISIBLE);\n\t\t}\n\n\t\tclearAnimation();\n\t}\n\n\t@Override\n\tpublic void onAnimationRepeat(Animation animation) {\n\t\t// NO-OP\n\t}\n\n\t@Override\n\tpublic void onAnimationStart(Animation animation) {\n\t\tsetVisibility(View.VISIBLE);\n\t}\n\t/**\n\t * {@inheritDoc}\n\t */\t\n\t@Override\n\tpublic void releaseToRefresh() {\n\t\tmArrowImageView.startAnimation(mRotateAnimation);\n\t}\n\t/**\n\t * {@inheritDoc}\n\t */\t\n\t@Override\n\tpublic void pullToRefresh() {\n\t\tmArrowImageView.startAnimation(mResetRotateAnimation);\n\t}\n\n\t/**\n\t * {@inheritDoc}\n\t */\n\tpublic LayoutParams createApplicableHeaderLayoutParams() {\n\t\tFrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,\n\t\t\t\tViewGroup.LayoutParams.WRAP_CONTENT);\n\t\tparams.rightMargin = getResources().getDimensionPixelSize(R.dimen.indicator_right_padding);\n\t\tparams.gravity = Gravity.TOP | Gravity.RIGHT;\n\t\treturn params;\n\t}\n\t/**\n\t * {@inheritDoc}\n\t */\n\tpublic LayoutParams createApplicableFooterLayoutParams() {\n\t\tFrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,\n\t\t\t\tViewGroup.LayoutParams.WRAP_CONTENT);\n\t\tparams.rightMargin = getResources().getDimensionPixelSize(R.dimen.indicator_right_padding);\n\t\tparams.gravity = Gravity.BOTTOM | Gravity.RIGHT;\n\t\treturn params;\n\t}\t\n}"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/internal/EmptyViewMethodAccessor.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library.internal;\n\nimport android.view.View;\n\n/**\n * Interface that allows PullToRefreshBase to hijack the call to\n * AdapterView.setEmptyView()\n * \n * @author chris\n */\npublic interface EmptyViewMethodAccessor {\n\n\t/**\n\t * Calls upto AdapterView.setEmptyView()\n\t * \n\t * @param emptyView - to set as Empty View\n\t */\n\tpublic void setEmptyViewInternal(View emptyView);\n\n\t/**\n\t * Should call PullToRefreshBase.setEmptyView() which will then\n\t * automatically call through to setEmptyViewInternal()\n\t * \n\t * @param emptyView - to set as Empty View\n\t */\n\tpublic void setEmptyView(View emptyView);\n\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/internal/FlipLoadingLayout.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library.internal;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Matrix;\nimport android.graphics.drawable.Drawable;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.animation.Animation;\nimport android.view.animation.RotateAnimation;\nimport android.widget.ImageView.ScaleType;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Orientation;\nimport com.handmark.pulltorefresh.library.R;\n\n@SuppressLint(\"ViewConstructor\")\npublic class FlipLoadingLayout extends LoadingLayout {\n\n\tstatic final int FLIP_ANIMATION_DURATION = 150;\n\n\tprivate final Animation mRotateAnimation, mResetRotateAnimation;\n\n\tpublic FlipLoadingLayout(Context context, final Mode mode, final Orientation scrollDirection, TypedArray attrs) {\n\t\tsuper(context, mode, scrollDirection, attrs);\n\n\t\tfinal int rotateAngle = mode == Mode.PULL_FROM_START ? -180 : 180;\n\n\t\tmRotateAnimation = new RotateAnimation(0, rotateAngle, Animation.RELATIVE_TO_SELF, 0.5f,\n\t\t\t\tAnimation.RELATIVE_TO_SELF, 0.5f);\n\t\tmRotateAnimation.setInterpolator(ANIMATION_INTERPOLATOR);\n\t\tmRotateAnimation.setDuration(FLIP_ANIMATION_DURATION);\n\t\tmRotateAnimation.setFillAfter(true);\n\n\t\tmResetRotateAnimation = new RotateAnimation(rotateAngle, 0, Animation.RELATIVE_TO_SELF, 0.5f,\n\t\t\t\tAnimation.RELATIVE_TO_SELF, 0.5f);\n\t\tmResetRotateAnimation.setInterpolator(ANIMATION_INTERPOLATOR);\n\t\tmResetRotateAnimation.setDuration(FLIP_ANIMATION_DURATION);\n\t\tmResetRotateAnimation.setFillAfter(true);\n\t}\n\n\t@Override\n\tprotected void onLoadingDrawableSet(Drawable imageDrawable) {\n\t\tif (null != imageDrawable) {\n\t\t\tfinal int dHeight = imageDrawable.getIntrinsicHeight();\n\t\t\tfinal int dWidth = imageDrawable.getIntrinsicWidth();\n\n\t\t\t/**\n\t\t\t * We need to set the width/height of the ImageView so that it is\n\t\t\t * square with each side the size of the largest drawable dimension.\n\t\t\t * This is so that it doesn't clip when rotated.\n\t\t\t */\n\t\t\tViewGroup.LayoutParams lp = mHeaderImage.getLayoutParams();\n\t\t\tlp.width = lp.height = Math.max(dHeight, dWidth);\n\t\t\tmHeaderImage.requestLayout();\n\n\t\t\t/**\n\t\t\t * We now rotate the Drawable so that is at the correct rotation,\n\t\t\t * and is centered.\n\t\t\t */\n\t\t\tmHeaderImage.setScaleType(ScaleType.MATRIX);\n\t\t\tMatrix matrix = new Matrix();\n\t\t\tmatrix.postTranslate((lp.width - dWidth) / 2f, (lp.height - dHeight) / 2f);\n\t\t\tmatrix.postRotate(getDrawableRotationAngle(), lp.width / 2f, lp.height / 2f);\n\t\t\tmHeaderImage.setImageMatrix(matrix);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void onPullImpl(float scaleOfLayout) {\n\t\t// NO-OP\n\t}\n\n\t@Override\n\tprotected void pullToRefreshImpl() {\n\t\t// Only start reset Animation, we've previously show the rotate anim\n\t\tif (mRotateAnimation == mHeaderImage.getAnimation()) {\n\t\t\tmHeaderImage.startAnimation(mResetRotateAnimation);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void refreshingImpl() {\n\t\tmHeaderImage.clearAnimation();\n\t\tmHeaderImage.setVisibility(View.INVISIBLE);\n\t\tmHeaderProgress.setVisibility(View.VISIBLE);\n\t}\n\n\t@Override\n\tprotected void releaseToRefreshImpl() {\n\t\tmHeaderImage.startAnimation(mRotateAnimation);\n\t}\n\n\t@Override\n\tprotected void resetImpl() {\n\t\tmHeaderImage.clearAnimation();\n\t\tmHeaderProgress.setVisibility(View.GONE);\n\t\tmHeaderImage.setVisibility(View.VISIBLE);\n\t}\n\n\t@Override\n\tprotected int getDefaultDrawableResId() {\n\t\treturn R.drawable.default_ptr_flip;\n\t}\n\n\tprivate float getDrawableRotationAngle() {\n\t\tfloat angle = 0f;\n\t\tswitch (mMode) {\n\t\t\tcase PULL_FROM_END:\n\t\t\t\tif (mScrollDirection == Orientation.HORIZONTAL) {\n\t\t\t\t\tangle = 90f;\n\t\t\t\t} else {\n\t\t\t\t\tangle = 180f;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase PULL_FROM_START:\n\t\t\t\tif (mScrollDirection == Orientation.HORIZONTAL) {\n\t\t\t\t\tangle = 270f;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn angle;\n\t}\n\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/internal/FlippedProgressBar.java",
    "content": "/*******************************************************************************\n * Copyright 2014 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library.internal;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.util.AttributeSet;\nimport android.widget.ProgressBar;\n/**\n * Right to left ProgressBar\n * @author Wonjun Kim\n *\n */\npublic class FlippedProgressBar extends ProgressBar {\n\tpublic FlippedProgressBar(Context context) {\n\t\tsuper(context);\n\t}\n\n\tpublic FlippedProgressBar(Context context, AttributeSet attrs) {\n\t\tsuper(context, attrs);\n\t}\n\n\tpublic FlippedProgressBar(Context context, AttributeSet attrs, int defStyle) {\n\t\tsuper(context, attrs, defStyle);\n\t}\n\t\n\t@Override\n\tprotected void onDraw(Canvas canvas) {\n\t\tcanvas.save();\n\t\tfloat centerX = this.getWidth() / 2.0f;\n\t\tfloat centerY = this.getHeight() / 2.0f;\n\t\tcanvas.scale(-1, 1, centerX /* center of x */, centerY /* center of y */);\n\t\tsuper.onDraw(canvas);\n\t\tcanvas.restore();\n\t}\n\t\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/internal/IndicatorLayout.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library.internal;\n\nimport com.handmark.pulltorefresh.library.IIndicatorLayout;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport android.widget.FrameLayout;\n/**\n * @see IIndicatorLayout\n * @author Wonjun Kim\n */\npublic abstract class IndicatorLayout extends FrameLayout implements IIndicatorLayout {\n\t\n\tpublic IndicatorLayout(Context context) {\n\t\tsuper(context);\n\t}\n\n\tpublic IndicatorLayout(Context context, AttributeSet attrs) {\n\t\tsuper(context, attrs);\n\t}\n\n\tpublic IndicatorLayout(Context context, AttributeSet attrs, int defStyle) {\n\t\tsuper(context, attrs, defStyle);\n\t}\n\t/**\n\t * Create a specific {@code LayoutParams}.<br /> \n\t * Pull To Refresh will add this layout with applying this {@code LayoutParams} to the layout     \n\t * @return {@code LayoutParams} which is applied if this indicator layout is a header of Pull To Refresh\n\t */\n\tpublic abstract LayoutParams createApplicableHeaderLayoutParams();\n\t/**\n\t * Create a specific {@code LayoutParams}.<br /> \n\t * Pull To Refresh will add this layout with applying this {@code LayoutParams} to the layout     \n\t * @return {@code LayoutParams} which is applied if this indicator layout is a footer of Pull To Refresh \n\t */\n\tpublic abstract LayoutParams createApplicableFooterLayoutParams();\n\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/internal/LoadingLayout.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library.internal;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.content.res.ColorStateList;\nimport android.content.res.TypedArray;\nimport android.graphics.Typeface;\nimport android.graphics.drawable.AnimationDrawable;\nimport android.graphics.drawable.Drawable;\nimport android.text.TextUtils;\nimport android.util.TypedValue;\nimport android.view.Gravity;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.animation.Interpolator;\nimport android.view.animation.LinearInterpolator;\nimport android.widget.FrameLayout;\nimport android.widget.ImageView;\nimport android.widget.ProgressBar;\nimport android.widget.TextView;\n\nimport com.handmark.pulltorefresh.library.ILoadingLayout;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Orientation;\nimport com.handmark.pulltorefresh.library.R;\n\n@SuppressLint(\"ViewConstructor\")\npublic abstract class LoadingLayout extends FrameLayout implements ILoadingLayout {\n\n\tstatic final String LOG_TAG = \"PullToRefresh-LoadingLayout\";\n\n\tstatic final Interpolator ANIMATION_INTERPOLATOR = new LinearInterpolator();\n\n\tprotected FrameLayout mInnerLayout;\n\n\tprotected ImageView mHeaderImage;\n\tprotected ProgressBar mHeaderProgress;\n\n\tprivate boolean mUseIntrinsicAnimation;\n\n\tprotected TextView mHeaderText;\n\tprotected TextView mSubHeaderText;\n\n\tprotected final Mode mMode;\n\tprotected final Orientation mScrollDirection;\n\n\tprivate CharSequence mPullLabel;\n\tprivate CharSequence mRefreshingLabel;\n\tprivate CharSequence mReleaseLabel;\n\n\tprivate Drawable mImageDrawable;\n\t\n\t/**\n\t * The constructor to customize layout, not public scope now.\n\t * @param context\n\t * @param mode\n\t * @param scrollDirection\n\t */\n\tprotected LoadingLayout(Context context, final Mode mode, final Orientation scrollDirection, TypedArray attrs, int inflateId) {\n\t\tsuper(context);\n\t\tmMode = mode;\n\t\tmScrollDirection = scrollDirection;\n\n\t\tinitInflate(context, inflateId);\n\t\tinitComponents();\n\t\tinitProperties(context, mode, attrs);\n\n\t\tif (null != mImageDrawable) {\n\t\t\tsetLoadingDrawable(mImageDrawable);\n\t\t\tmImageDrawable = null;\n\t\t}\n\n\t\treset();\t\n\t\t\n\t}\n\t\n\tpublic LoadingLayout(Context context, final Mode mode, final Orientation scrollDirection, TypedArray attrs) {\n\t\tsuper(context);\n\t\tmMode = mode;\n\t\tmScrollDirection = scrollDirection;\n\n\t\tswitch (scrollDirection) {\n\t\t\tcase HORIZONTAL:\n\t\t\t\tinitInflate(context, R.layout.pull_to_refresh_header_horizontal);\n\t\t\t\tbreak;\n\t\t\tcase VERTICAL:\n\t\t\tdefault:\n\t\t\t\tinitInflate(context, R.layout.pull_to_refresh_header_vertical);\n\t\t\t\tbreak;\n\t\t}\n\n\t\tinitComponents();\n\n\t\tif (null != mInnerLayout) {\n\t\t\tFrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mInnerLayout.getLayoutParams();\n\n\t\t\tswitch (mode) {\n\t\t\t\tcase PULL_FROM_END:\n\t\t\t\t\tlp.gravity = scrollDirection == Orientation.VERTICAL ? Gravity.TOP : Gravity.LEFT;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase PULL_FROM_START:\n\t\t\t\tdefault:\n\t\t\t\t\tlp.gravity = scrollDirection == Orientation.VERTICAL ? Gravity.BOTTOM : Gravity.RIGHT;\n\t\t\t\t\tbreak;\n\t\t\t}\t\t\t\n\t\t}\n\n\t\tinitProperties(context, mode, attrs);\n\n\t\t// If we don't have a user defined drawable, load the default\n\t\tif (null == mImageDrawable) {\n\t\t\tmImageDrawable = context.getResources().getDrawable(getDefaultDrawableResId());\n\t\t}\n\n\t\t// Set Drawable, and save width/height\n\t\tsetLoadingDrawable(mImageDrawable);\n\t\tmImageDrawable = null;\n\n\t\treset();\n\t}\n\n\tprotected void initComponents() {\n\t\tmInnerLayout = (FrameLayout) findViewById(R.id.fl_inner);\n\t\tmHeaderText = (TextView) mInnerLayout.findViewById(R.id.pull_to_refresh_text);\n\t\tmHeaderProgress = (ProgressBar) mInnerLayout.findViewById(R.id.pull_to_refresh_progress);\n\t\tmSubHeaderText = (TextView) mInnerLayout.findViewById(R.id.pull_to_refresh_sub_text);\n\t\tmHeaderImage = (ImageView) mInnerLayout.findViewById(R.id.pull_to_refresh_image);\n\t}\n\n\tprivate void initInflate(Context context, int inflateId) {\n\t\tLayoutInflater.from(context).inflate(inflateId, this);\n\t}\n\n\tprotected void initProperties(Context context, final Mode mode,\n\t\t\tTypedArray attrs) {\n\t\t// Load Loading Layout Labels\n\t\tloadLoadingLayoutLabels(context, attrs, mode);\n\t\t\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderBackground)) {\n\t\t\tDrawable background = attrs.getDrawable(R.styleable.PullToRefresh_ptrHeaderBackground);\n\t\t\tif (null != background) {\n\t\t\t\tViewCompat.setBackground(this, background);\n\t\t\t}\n\t\t}\n\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderTextAppearance)) {\n\t\t\tTypedValue styleID = new TypedValue();\n\t\t\tattrs.getValue(R.styleable.PullToRefresh_ptrHeaderTextAppearance, styleID);\n\t\t\tsetTextAppearance(styleID.data);\n\t\t}\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrSubHeaderTextAppearance)) {\n\t\t\tTypedValue styleID = new TypedValue();\n\t\t\tattrs.getValue(R.styleable.PullToRefresh_ptrSubHeaderTextAppearance, styleID);\n\t\t\tsetSubTextAppearance(styleID.data);\n\t\t}\n\n\t\t// Text Color attrs need to be set after TextAppearance attrs\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderTextColor)) {\n\t\t\tColorStateList colors = attrs.getColorStateList(R.styleable.PullToRefresh_ptrHeaderTextColor);\n\t\t\tif (null != colors) {\n\t\t\t\tsetTextColor(colors);\n\t\t\t}\n\t\t}\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderSubTextColor)) {\n\t\t\tColorStateList colors = attrs.getColorStateList(R.styleable.PullToRefresh_ptrHeaderSubTextColor);\n\t\t\tif (null != colors) {\n\t\t\t\tsetSubTextColor(colors);\n\t\t\t}\n\t\t}\n\n\t\t// Try and get defined drawable from Attrs\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawable)) {\n\t\t\tmImageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawable);\n\t\t}\n\n\t\t// Check Specific Drawable from Attrs, these overrite the generic\n\t\t// drawable attr above\n\t\tswitch (mode) {\n\t\t\tcase PULL_FROM_START:\n\t\t\tdefault:\n\t\t\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableStart)) {\n\t\t\t\t\tmImageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableStart);\n\t\t\t\t} else if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableTop)) {\n\t\t\t\t\tUtils.warnDeprecation(\"ptrDrawableTop\", \"ptrDrawableStart\");\n\t\t\t\t\tmImageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableTop);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase PULL_FROM_END:\n\t\t\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableEnd)) {\n\t\t\t\t\tmImageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableEnd);\n\t\t\t\t} else if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableBottom)) {\n\t\t\t\t\tUtils.warnDeprecation(\"ptrDrawableBottom\", \"ptrDrawableEnd\");\n\t\t\t\t\tmImageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableBottom);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t}\n\t\n\t/**\n\t * Load labels of pull, refresh, release, and assign into fields\n\t * <br />Convert an each attribute value such as {@code ptrPullLabel}, {@code ptrRefreshLabel} or {@code ptrReleaseLabel} to each label field if each value exists.\n\t * <br />Or if not, then the each label is assigned some string as default\n\t * <br />\n\t * NOTE : This method <b>Must</b> be modified if kinds of {@code Mode} are increased.\n\t * @param attrs \n\t * @param mode Current mode\n\t */\n\tprivate void loadLoadingLayoutLabels(Context context, TypedArray attrs, Mode mode) {\n\t\tmPullLabel = loadPullLabel(context, attrs, mode);\n\t\tmRefreshingLabel = loadRefreshingLabel(context, attrs, mode);\n\t\tmReleaseLabel = loadReleaseLabel(context, attrs, mode);\n\t}\n\t/**\n\t * Load labels of pull\n\t * <br />Convert an {@code ptrPullLabel} attribute value to {@code mPullLabel} field if each value exists.\n\t * <br />Or if not, then the pull label is assigned some string as default\n\t * <br />If you want to set some custom pull label at sub class, you have to override this method and implement.\n\t * NOTE : This method <b>Must</b> be modified if kinds of {@code Mode} are increased.\n\t * @param context\n\t * @param attrs\n\t * @param mode\n\t * @return String to be a pull label  \n\t */\n\tprotected String loadPullLabel(Context context, TypedArray attrs, Mode mode) {\n\t\t// Pull Label\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrPullLabel)) {\n\t\t\treturn attrs.getString(R.styleable.PullToRefresh_ptrPullLabel);\n\t\t} \n\t\t\n\t\tint stringId = (mode == Mode.PULL_FROM_END) ? R.string.pull_to_refresh_from_bottom_pull_label : R.string.pull_to_refresh_pull_label;\n\t\treturn context.getString(stringId);\n\t}\t\n\t/**\n\t * Load labels of refreshing\n\t * <br />Convert an {@code ptrRefreshLabel} attribute value to {@code mRefreshingLabel} field if each value exists.\n\t * <br />Or if not, then the refreshing label is assigned some string as default\n\t * <br />If you want to set some custom refreshing label at sub class, you have to override this method and implement.\n\t * NOTE : This method <b>Must</b> be modified if kinds of {@code Mode} are increased.\n\t * @param context\n\t * @param attrs\n\t * @param mode\n\t * @return String to be a refreshing label  \n\t */\n\tprotected String loadRefreshingLabel(Context context, TypedArray attrs,\n\t\t\tMode mode) {\n\t\t// Refresh Label\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrRefreshLabel)) {\n\t\t\treturn attrs.getString(R.styleable.PullToRefresh_ptrRefreshLabel);\n\t\t} \n\t\t\n\t\tint stringId = (mode == Mode.PULL_FROM_END) ? R.string.pull_to_refresh_from_bottom_refreshing_label : R.string.pull_to_refresh_refreshing_label;\n\t\treturn context.getString(stringId);\n\t}\t\n\t/**\n\t * Load labels of release\n\t * <br />Convert an {@code ptrReleaseLabel} attribute value to {@code mReleaseLabel} field if each value exists.\n\t * <br />Or if not, then the release label is assigned some string as default\n\t * <br />If you want to set some custom release label at sub class, you have to override this method and implement.\n\t * NOTE : This method <b>Must</b> be modified if kinds of {@code Mode} are increased.\n\t * @param context\n\t * @param attrs\n\t * @param mode\n\t * @return String to be a refreshing label  \n\t */\n\tprotected String loadReleaseLabel(Context context, TypedArray attrs, Mode mode) {\n\t\t// Release Label\n\t\tif (attrs.hasValue(R.styleable.PullToRefresh_ptrReleaseLabel)) {\n\t\t\treturn attrs.getString(R.styleable.PullToRefresh_ptrReleaseLabel);\n\t\t} \n\t\t\n\t\tint stringId = (mode == Mode.PULL_FROM_END) ? R.string.pull_to_refresh_from_bottom_release_label : R.string.pull_to_refresh_release_label;\n\t\treturn context.getString(stringId);\n\t\t\n\t}\n\n\tpublic void setHeight(int height) {\n\t\tViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) getLayoutParams();\n\t\tlp.height = height;\n\t\trequestLayout();\n\t}\n\n\tpublic final void setWidth(int width) {\n\t\tViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) getLayoutParams();\n\t\tlp.width = width;\n\t\trequestLayout();\n\t}\n\n\tpublic final int getContentSize() {\n\t\tswitch (mScrollDirection) {\n\t\t\tcase HORIZONTAL:\n\t\t\t\treturn mInnerLayout.getWidth();\n\t\t\tcase VERTICAL:\n\t\t\tdefault:\n\t\t\t\treturn mInnerLayout.getHeight();\n\t\t}\n\t}\n\n\tpublic final void hideAllViews() {\n\t\thideHeaderText();\n\t\thideHeaderProgress();\n\t\thideHeaderImage();\n\t\thideSubHeaderText();\n\t}\n\n\tprivate void hideHeaderText() {\n\t\tif (null != mHeaderText && View.VISIBLE == mHeaderText.getVisibility()) {\n\t\t\tmHeaderText.setVisibility(View.INVISIBLE);\n\t\t}\n\t}\n\n\tprivate void hideHeaderProgress() {\n\t\tif (null != mHeaderProgress && View.VISIBLE == mHeaderProgress.getVisibility()) {\n\t\t\tmHeaderProgress.setVisibility(View.INVISIBLE);\n\t\t}\n\t}\n\n\tprivate void hideSubHeaderText() {\n\t\tif (null != mHeaderText && View.VISIBLE == mSubHeaderText.getVisibility()) {\n\t\t\tmSubHeaderText.setVisibility(View.INVISIBLE);\n\t\t}\n\t}\n\n\tpublic final void onPull(float scaleOfLayout) {\n\t\tif (!mUseIntrinsicAnimation) {\n\t\t\tonPullImpl(scaleOfLayout);\n\t\t}\n\t}\n\n\tpublic final void pullToRefresh() {\n\t\tif (null != mHeaderText) {\n\t\t\tmHeaderText.setText(mPullLabel);\n\t\t}\n\n\t\t// Now call the callback\n\t\tpullToRefreshImpl();\n\t}\n\n\tpublic final void refreshing() {\n\t\tif (null != mHeaderText) {\n\t\t\tmHeaderText.setText(mRefreshingLabel);\n\t\t}\n\n\t\tif (null != mHeaderImage && mUseIntrinsicAnimation) {\n\t\t\t((AnimationDrawable) mHeaderImage.getDrawable()).start();\n\t\t} else {\n\t\t\t// Now call the callback\n\t\t\trefreshingImpl();\n\t\t}\n\n\t\tif (null != mSubHeaderText) {\n\t\t\tmSubHeaderText.setVisibility(View.GONE);\n\t\t}\n\t}\n\n\tpublic final void releaseToRefresh() {\n\t\tif (null != mHeaderText) {\n\t\t\tmHeaderText.setText(mReleaseLabel);\n\t\t}\n\n\t\t// Now call the callback\n\t\treleaseToRefreshImpl();\n\t}\n\n\tpublic final void reset() {\n\t\tif (null != mHeaderText) {\n\t\t\tmHeaderText.setText(mPullLabel);\n\t\t}\n\n\t\tshowHeaderImage();\n\n\t\tif (null != mHeaderImage && mUseIntrinsicAnimation) {\n\t\t\t((AnimationDrawable) mHeaderImage.getDrawable()).stop();\n\t\t} else {\n\t\t\t// Now call the callback\n\t\t\tresetImpl();\n\t\t}\t\t\n\n\t\tif (null != mSubHeaderText) {\n\t\t\tif (TextUtils.isEmpty(mSubHeaderText.getText())) {\n\t\t\t\tmSubHeaderText.setVisibility(View.GONE);\n\t\t\t} else {\n\t\t\t\tmSubHeaderText.setVisibility(View.VISIBLE);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void showHeaderImage() {\n\t\tif (null != mHeaderImage && View.INVISIBLE == mHeaderImage.getVisibility()) {\n\t\t\tmHeaderImage.setVisibility(View.VISIBLE);\t\n\t\t}\n\t}\n\t\n\tprivate void hideHeaderImage() {\n\t\tif (null != mHeaderImage && View.VISIBLE == mHeaderImage.getVisibility() ) {\n\t\t\tmHeaderImage.setVisibility(View.INVISIBLE);\t\n\t\t}\t\t\n\t}\n\n\t@Override\n\tpublic void setLastUpdatedLabel(CharSequence label) {\n\t\tsetSubHeaderText(label);\n\t}\n\n\tpublic final void setLoadingDrawable(Drawable imageDrawable) {\n\t\t// Set Drawable\n\t\tif ( null != mHeaderImage ) {\n\t\t\tmHeaderImage.setImageDrawable(imageDrawable);\n\t\t}\n\t\t\n\t\tmUseIntrinsicAnimation = (imageDrawable instanceof AnimationDrawable);\n\t\t// Now call the callback\n\t\tonLoadingDrawableSet(imageDrawable);\n\t}\n\n\tpublic void setPullLabel(CharSequence pullLabel) {\n\t\tmPullLabel = pullLabel;\n\t}\n\n\tpublic void setRefreshingLabel(CharSequence refreshingLabel) {\n\t\tmRefreshingLabel = refreshingLabel;\n\t}\n\n\tpublic void setReleaseLabel(CharSequence releaseLabel) {\n\t\tmReleaseLabel = releaseLabel;\n\t}\n\n\t@Override\n\tpublic void setTextTypeface(Typeface tf) {\n\t\tif (null != mHeaderText) {\n\t\t\tmHeaderText.setTypeface(tf);\t\t\t\n\t\t}\n\t}\n\n\tpublic final void showInvisibleViews() {\n\t\tshowHeaderText();\n\t\tshowHeaderProgress();\n\t\tshowHeaderImage();\n\t\tshowSubHeaderText();\n\t}\n\n\tprivate void showSubHeaderText() {\n\t\tif (null != mSubHeaderText && View.INVISIBLE == mSubHeaderText.getVisibility()) {\n\t\t\tmSubHeaderText.setVisibility(View.VISIBLE);\n\t\t}\n\t}\n\n\tprivate void showHeaderProgress() {\n\t\tif (null != mHeaderProgress && View.INVISIBLE == mHeaderProgress.getVisibility()) {\n\t\t\tmHeaderProgress.setVisibility(View.VISIBLE);\n\t\t}\n\t}\n\n\tprivate void showHeaderText() {\n\t\tif (null != mHeaderText && View.INVISIBLE == mHeaderText.getVisibility()) {\n\t\t\tmHeaderText.setVisibility(View.VISIBLE);\n\t\t}\n\t}\n\n\t/**\n\t * Callbacks for derivative Layouts\n\t */\n\n\tprotected abstract int getDefaultDrawableResId();\n\n\tprotected abstract void onLoadingDrawableSet(Drawable imageDrawable);\n\n\tprotected abstract void onPullImpl(float scaleOfLayout);\n\n\tprotected abstract void pullToRefreshImpl();\n\n\tprotected abstract void refreshingImpl();\n\n\tprotected abstract void releaseToRefreshImpl();\n\n\tprotected abstract void resetImpl();\n\n\tprivate void setSubHeaderText(CharSequence label) {\n\t\tif (null != mSubHeaderText) {\n\t\t\tif (TextUtils.isEmpty(label)) {\n\t\t\t\tmSubHeaderText.setVisibility(View.GONE);\n\t\t\t} else {\n\t\t\t\tmSubHeaderText.setText(label);\n\n\t\t\t\t// Only set it to Visible if we're GONE, otherwise VISIBLE will\n\t\t\t\t// be set soon\n\t\t\t\tif (View.GONE == mSubHeaderText.getVisibility()) {\n\t\t\t\t\tmSubHeaderText.setVisibility(View.VISIBLE);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void setSubTextAppearance(int value) {\n\t\tif (null != mSubHeaderText) {\n\t\t\tmSubHeaderText.setTextAppearance(getContext(), value);\n\t\t}\n\t}\n\n\tprivate void setSubTextColor(ColorStateList color) {\n\t\tif (null != mSubHeaderText) {\n\t\t\tmSubHeaderText.setTextColor(color);\n\t\t}\n\t}\n\n\tprivate void setTextAppearance(int value) {\n\t\tif (null != mHeaderText) {\n\t\t\tmHeaderText.setTextAppearance(getContext(), value);\n\t\t}\n\t\tif (null != mSubHeaderText) {\n\t\t\tmSubHeaderText.setTextAppearance(getContext(), value);\n\t\t}\n\t}\n\n\tprivate void setTextColor(ColorStateList color) {\n\t\tif (null != mHeaderText) {\n\t\t\tmHeaderText.setTextColor(color);\n\t\t}\n\t\tif (null != mSubHeaderText) {\n\t\t\tmSubHeaderText.setTextColor(color);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/internal/PullingProgressLayout.java",
    "content": "/*******************************************************************************\n * Copyright 2014 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library.internal;\n\nimport com.handmark.pulltorefresh.library.R;\n\nimport android.content.Context;\nimport android.content.res.Resources;\nimport android.graphics.Canvas;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.Gravity;\nimport android.view.LayoutInflater;\nimport android.widget.LinearLayout;\nimport android.widget.ProgressBar;\n/**\n * Layout Class displaying specialized progress bar whose progress starts from center,\n * @author Wonjun Kim\n *\n */\npublic class PullingProgressLayout extends LinearLayout {\n\n\tprivate ProgressBar mPullingLeftBar;\n\tprivate ProgressBar mPullingRightBar;\n\n\tpublic PullingProgressLayout(Context context) {\n\t\tsuper(context);\n\t\tinitializeLayout(context);\n\t\t\n\t}\n\n\tpublic PullingProgressLayout(Context context, AttributeSet attrs) {\n\t\tsuper(context, attrs);\n\t\tinitializeLayout(context);\n\t}\n\n\tprivate void initializeLayout(Context context) {\n\t\tResources res = context.getResources();\n\t\t\n\t\tLayoutInflater.from(context).inflate(R.layout.pulling_progress_layout, this);\n\t\t\n\t\tmPullingLeftBar = (ProgressBar) findViewById(R.id.pulling_left_progressbar);\n\t\tmPullingRightBar = (ProgressBar) findViewById(R.id.pulling_right_progressbar);\n\t\t\n\t\tmPullingLeftBar.setProgressDrawable(res.getDrawable(R.drawable.progress_horizontal_holo_light));\n\t\tmPullingRightBar.setProgressDrawable(res.getDrawable(R.drawable.progress_horizontal_holo_light));\n\t\t\n\t\tmPullingLeftBar.setMax(100);\n\t\tmPullingRightBar.setMax(100);\n\t\t\n\t\tmPullingLeftBar.setProgress(40);\n\t\tmPullingRightBar.setProgress(40);\n\t}\n\t/**\n\t * Route percent value to internal bars \n\t * @param percent Positive integer value. max is 100. \n\t */\n\tpublic void setPercent(int percent) {\n\t\tif ( percent > 100 ) {\n\t\t\tpercent = 100;\n\t\t}\n\t\t\n\t\tif ( percent < 0 ) {\n\t\t\tpercent = 0;\n\t\t}\n\t\t\n\t\tmPullingLeftBar.setProgress(percent);\n\t\tmPullingRightBar.setProgress(percent);\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/internal/RotateLoadingLayout.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library.internal;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Matrix;\nimport android.graphics.drawable.Drawable;\nimport android.view.animation.Animation;\nimport android.view.animation.RotateAnimation;\nimport android.widget.ImageView.ScaleType;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Orientation;\nimport com.handmark.pulltorefresh.library.R;\n\npublic class RotateLoadingLayout extends LoadingLayout {\n\n\tstatic final int ROTATION_ANIMATION_DURATION = 1200;\n\n\tprivate final Animation mRotateAnimation;\n\tprivate final Matrix mHeaderImageMatrix;\n\n\tprivate float mRotationPivotX, mRotationPivotY;\n\n\tprivate final boolean mRotateDrawableWhilePulling;\n\n\tpublic RotateLoadingLayout(Context context, Mode mode, Orientation scrollDirection, TypedArray attrs) {\n\t\tsuper(context, mode, scrollDirection, attrs);\n\n\t\tmRotateDrawableWhilePulling = attrs.getBoolean(R.styleable.PullToRefresh_ptrRotateDrawableWhilePulling, true);\n\n\t\tmHeaderImage.setScaleType(ScaleType.MATRIX);\n\t\tmHeaderImageMatrix = new Matrix();\n\t\tmHeaderImage.setImageMatrix(mHeaderImageMatrix);\n\n\t\tmRotateAnimation = new RotateAnimation(0, 720, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,\n\t\t\t\t0.5f);\n\t\tmRotateAnimation.setInterpolator(ANIMATION_INTERPOLATOR);\n\t\tmRotateAnimation.setDuration(ROTATION_ANIMATION_DURATION);\n\t\tmRotateAnimation.setRepeatCount(Animation.INFINITE);\n\t\tmRotateAnimation.setRepeatMode(Animation.RESTART);\n\t}\n\n\tpublic void onLoadingDrawableSet(Drawable imageDrawable) {\n\t\tif (null != imageDrawable) {\n\t\t\tmRotationPivotX = Math.round(imageDrawable.getIntrinsicWidth() / 2f);\n\t\t\tmRotationPivotY = Math.round(imageDrawable.getIntrinsicHeight() / 2f);\n\t\t}\n\t}\n\n\tprotected void onPullImpl(float scaleOfLayout) {\n\t\tfloat angle;\n\t\tif (mRotateDrawableWhilePulling) {\n\t\t\tangle = scaleOfLayout * 90f;\n\t\t} else {\n\t\t\tangle = Math.max(0f, Math.min(180f, scaleOfLayout * 360f - 180f));\n\t\t}\n\n\t\tmHeaderImageMatrix.setRotate(angle, mRotationPivotX, mRotationPivotY);\n\t\tmHeaderImage.setImageMatrix(mHeaderImageMatrix);\n\t}\n\n\t@Override\n\tprotected void refreshingImpl() {\n\t\tmHeaderImage.startAnimation(mRotateAnimation);\n\t}\n\n\t@Override\n\tprotected void resetImpl() {\n\t\tmHeaderImage.clearAnimation();\n\t\tresetImageRotation();\n\t}\n\n\tprivate void resetImageRotation() {\n\t\tif (null != mHeaderImageMatrix) {\n\t\t\tmHeaderImageMatrix.reset();\n\t\t\tmHeaderImage.setImageMatrix(mHeaderImageMatrix);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void pullToRefreshImpl() {\n\t\t// NO-OP\n\t}\n\n\t@Override\n\tprotected void releaseToRefreshImpl() {\n\t\t// NO-OP\n\t}\n\n\t@Override\n\tprotected int getDefaultDrawableResId() {\n\t\treturn R.drawable.default_ptr_rotate;\n\t}\n\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/internal/Utils.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library.internal;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.Reader;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.util.TypedValue;\n\npublic class Utils {\n\n\tstatic final String LOG_TAG = \"PullToRefresh\";\n\t/**\n\t * Android namespace for Android attributes'-related util methods\n\t */\n\tstatic final String ANDROID_NAMESPACE = \"http://schemas.android.com/apk/res/android\";\n\t/**\n\t *  Invalid android attribute (temporarily defined, to check android attributes' values)\n\t */\n\tstatic final int INVALID_INT_VALUE = -1;\n\t/**\n\t * Delegate warn logs at where some deprecated method has been called\n\t * @param depreacted Deprecated method name\n\t * @param replacement Method name to be able to switch\n\t */\n\tpublic static void warnDeprecation(String depreacted, String replacement) {\n\t\tLog.w(LOG_TAG, \"You're using the deprecated \" + depreacted + \" attr, please switch over to \" + replacement);\n\t}\n\t/**\n\t * Try to close {@code InputStream} without any exceptions, and ignore if some exception occurs\n\t * @param is {@code InputStream} instance to close\n\t */\n\tpublic static void closeSilently(InputStream is) {\n\t\t// If the instance is null, do nothing and return\n\t\tif (is == null) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\ttry {\n\t\t\t// try to close\n\t\t\tis.close();\n\t\t} catch (IOException e) {\n\t\t\t// try to close once more\n\t\t\ttry {\n\t\t\t\tis.close();\n\t\t\t} catch (IOException e1) {\n\t\t\t\t// do nothing\n\t\t\t}\n\t\t}\n\t}\n\t/**\n\t * Try to close {@code Reader} without any exceptions, and ignore if some exception occurs\n\t * @param br {@code Reader} instance to close\n\t */\n\tpublic static void closeSilently(Reader br) {\n\t\t// If the instance is null, do nothing and return\n\t\tif (br == null) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\t// try to close\n\t\t\tbr.close();\n\t\t} catch (IOException e) {\n\t\t\ttry {\n\t\t\t\t// try to close once more\n\t\t\t\tbr.close();\n\t\t\t} catch (IOException e1) {\n\t\t\t\t// do nothing\n\t\t\t}\n\t\t}\t\t\n\t}\n\t/**\n\t * Check whether android {@code attribute} exists and is set in {@code attributeSet} \n\t * @param attrs {@code AttributeSet} where the {@code attribute} is included (if that is set)\n\t * @return true if the {@code attribute} exists\n\t */\n\t@Deprecated\n\tpublic static boolean existAttributeIntValue(AttributeSet attrs, String attribute) {\n\t\treturn existAttributeIntValue(attrs, ANDROID_NAMESPACE, attribute);\n\t}\n\t/**\n\t * Check whether android {@code attribute} exists and is set in {@code attributeSet} \n\t * @param attrs {@code AttributeSet} where the {@code attribute} is included (if that is set)\n\t * @param namespace Namespace where the {@code attribute} is defined \n\t * @param attribute Attribute to be checked\n\t * @return true if the {@code attribute} exists\n\t */\n\t@Deprecated\n\tpublic static boolean existAttributeIntValue(AttributeSet attrs, String namespace, String attribute) {\n\t\treturn existAttributeIntValue(attrs, namespace, attribute, INVALID_INT_VALUE);\n\t}\n\t/**\n\t * Check whether android {@code attribute} exists and is set in {@code attributeSet} \n\t * @param attrs {@code AttributeSet} where the {@code attribute} is included (if that is set)\n\t * @param namespace Namespace where the {@code attribute} is defined \n\t * @param attribute Attribute to be checked\n\t * @param invalidValue The flag to check that the {@code attribute} is set \n\t * @return true if the {@code attribute} exists\n\t */\n\t@Deprecated\n\tpublic static boolean existAttributeIntValue(AttributeSet attrs, String namespace, String attribute, int invalidValue) {\n\t\t// If attrs is null, assume the attribute is not set.\n\t\tif ( attrs == null ) {\n\t\t\treturn false;\n\t\t}\n\t\tAssert.notNull(attrs, \"namespace\");\n\t\tAssert.notNull(attrs, \"attribute\");\n\t\t\n\t\tboolean isExist = true;\n\t\tint value = attrs.getAttributeIntValue(namespace, attribute, invalidValue);\n\t\tif ( value == invalidValue ) {\n\t\t\tisExist = false;\n\t\t}\n\t\treturn isExist;\n\t}\n\t/**\n\t * Check whether android {@code attribute} exists and is set in {@code attributeSet} \n\t * @param attrs {@code AttributeSet} where the {@code attribute} is included (if that is set)\n\t * @param attribute Attribute to be checked\n\t * @return true if the {@code attribute} exists\n\t */\n\tpublic static boolean existAttributeValue(AttributeSet attrs, String attribute) {\n\t\treturn existAttributeValue(attrs, ANDROID_NAMESPACE, attribute);\n\t}\t\n\t/**\n\t * Check whether android {@code attribute} exists and is set in {@code attributeSet} \n\t * @param attrs {@code AttributeSet} where the {@code attribute} is included (if that is set)\n\t * @param namespace Namespace where the {@code attribute} is defined \n\t * @param attribute Attribute to be checked\n\t * @return true if the {@code attribute} exists\n\t */\n\tpublic static boolean existAttributeValue(AttributeSet attrs, String namespace, String attribute) {\n\t\t// If attrs is null, assume the attribute is not set.\n\t\tif ( attrs == null ) {\n\t\t\treturn false;\n\t\t}\n\t\tAssert.notNull(attrs, \"namespace\");\n\t\tAssert.notNull(attrs, \"attribute\");\n\t\t\n\t\tboolean isExist = true;\n\t\tString value = attrs.getAttributeValue(namespace, attribute);\n\t\t// Assume that it doesn't exist only when value is null.\n\t\t// An empty value can be skipped.\n\t\tif ( value == null ) {\n\t\t\tisExist = false;\n\t\t}\n\t\treturn isExist;\n\t}\t\n\t/**\n\t * Get an action bar size <br />\n\t * {@link //stackoverflow.com/questions/7165830/what-is-the-size-of-actionbar-in-pixels}\n\t * @param context\n\t */\t\n\tpublic static int getActionBarSize(Context context) {\n\t\t// Calculate ActionBar height\n\t\tint actionBarHeight = 0;\n\t\tTypedValue tv = new TypedValue();\n\t\tif (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {\n\t\t    actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,context.getResources().getDisplayMetrics());\n\t\t}\n\t\t\n\t\treturn actionBarHeight;\n\t}\n\t/**\n\t * Get a status bar size <br />\n\t * @param context\n\t */\t\n\tpublic static int getStatusBarSize(Context context) {\n\t      int result = 0;\n\t      int resourceId = context.getResources().getIdentifier(\"status_bar_height\", \"dimen\", \"android\");\n\t      if (resourceId > 0) {\n\t          result = context.getResources().getDimensionPixelSize(resourceId);\n\t      } \n\t      \n\t     return result;\n\t}\n}\n"
  },
  {
    "path": "library/src/main/java/com/handmark/pulltorefresh/library/internal/ViewCompat.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n * Copyright 2013 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.library.internal;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\n\nimport com.handmark.pulltorefresh.configuration.xml.PullToRefreshXmlConfiguration;\n\nimport android.annotation.TargetApi;\nimport android.graphics.Paint;\nimport android.graphics.drawable.Drawable;\nimport android.os.Build.VERSION;\nimport android.util.Log;\nimport android.view.View;\n\n@SuppressWarnings(\"deprecation\")\npublic class ViewCompat {\n\t/**\n\t * @author Wonjun Kim\n\t */\n\tprivate static class Methods {\n\t\tprivate static final String LOG_TAG = Methods.class.getName();\n\t\t\n\t\tprivate static Method setLayerTypeMethod;\n\t\tprivate static Method postOnAnimationMethod;\n\t\tprivate static Method setBackgroundMethod;\n\t\t\n\t\tstatic {\n\t\t\tinitializeMethods();\n\t\t}\n\t\t\n\t\t@SuppressWarnings(\"unchecked\")\n\t\tprivate static void initializeMethods() {\n\t\t\t\n\t\t\tClass<? extends View> viewClazz = null;\n\t\t\t\n\t\t\t// Initialize android.view.View class token\n\t\t\ttry {\n\t\t\t\tviewClazz = (Class<? extends View>) Class.forName(\"android.view.View\");\n\t\t\t} catch (ClassNotFoundException e) {\n\t\t\t\tLog.e(LOG_TAG, \"android.view.View class has not been found. Maybe Pull To Refresh might work not correctly.\", e);\n\t\t\t} \n\t\t\t\n\t\t\t// If viewClazz fails to initialize, skip creating methods\n\t\t\tif ( viewClazz == null ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t// Initialize setLayerType()\n\t\t\ttry {\n\t\t\t\tsetLayerTypeMethod = viewClazz.getMethod(\"setLayerType\", int.class, Paint.class);\n\t\t\t} catch (NoSuchMethodException e) {\n\t\t\t\tLog.e(LOG_TAG, \"android.view.View.setLayerType() method has not been found. Maybe Pull To Refresh might work not correctly.\", e);\n\t\t\t}\n\t\t\t\n\t\t\t// Initialize postOnAnimation()\n\t\t\ttry {\n\t\t\t\tpostOnAnimationMethod = viewClazz.getMethod(\"postOnAnimation\", Runnable.class);\n\t\t\t} catch (NoSuchMethodException e) {\n\t\t\t\tLog.e(LOG_TAG, \"android.view.View.postOnAnimation() method has not been found. Maybe Pull To Refresh might work not correctly.\", e);\n\t\t\t}\n\t\t\t\n\t\t\t// Initialize setBackground() \n\t\t\ttry {\n\t\t\t\tsetBackgroundMethod = viewClazz.getMethod(\"setBackground\", Drawable.class);\n\t\t\t} catch (NoSuchMethodException e) {\n\t\t\t\tLog.e(LOG_TAG, \"android.view.View.setBackground() method has not been found. Maybe Pull To Refresh might work not correctly.\", e);\n\t\t\t}\t\t\t\n\t\t\t\n\t\t}\t\t\n\t\tprivate static void setLayerType(View view, int layerType) {\n\t\t\tAssert.notNull(view, \"view\");\n\t\t\t\n\t\t\tif ( setLayerTypeMethod == null ) {\n\t\t\t\tLog.e(LOG_TAG, \"android.view.View.setLayerType() method token has not been initialized.\");\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tsetLayerTypeMethod.invoke(view, layerType, null /* android.graphics.Paint */);\n\t\t\t} catch (IllegalArgumentException e) {\n\t\t\t\tLog.e(LOG_TAG, \"Some argument is illegal to call android.view.View.setLayerType().\", e);\n\t\t\t} catch (IllegalAccessException e) {\n\t\t\t\tLog.e(LOG_TAG, \"It has failed to call android.view.View.setLayerType().\", e);\n\t\t\t} catch (InvocationTargetException e) {\n\t\t\t\tLog.e(LOG_TAG, \"It has failed to call android.view.View.setLayerType().\", e);\n\t\t\t}\n\t\t}\n\t\t\n\t\tprivate static void postOnAnimation(View view, Runnable runnable) {\n\t\t\tAssert.notNull(view, \"view\");\n\t\t\t\n\t\t\tif ( postOnAnimationMethod == null ) {\n\t\t\t\tLog.e(LOG_TAG, \"android.view.View.postOnAnimation() method token has not been initialized.\");\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tpostOnAnimationMethod.invoke(view, runnable);\n\t\t\t} catch (IllegalArgumentException e) {\n\t\t\t\tLog.e(LOG_TAG, \"Some argument is illegal to call android.view.View.postOnAnimation().\", e);\n\t\t\t} catch (IllegalAccessException e) {\n\t\t\t\tLog.e(LOG_TAG, \"It has failed to call android.view.View.postOnAnimation().\", e);\n\t\t\t} catch (InvocationTargetException e) {\n\t\t\t\tLog.e(LOG_TAG, \"It has failed to call android.view.View.postOnAnimation().\", e);\n\t\t\t}\n\t\t}\n\t\t\n\t\tprivate static void setBackground(View view, Drawable background) {\n\t\t\tAssert.notNull(view, \"view\");\n\t\t\t\n\t\t\tif ( setBackgroundMethod == null ) {\n\t\t\t\tLog.e(LOG_TAG, \"android.view.View.setBackground() method token has not been initialized.\");\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tsetBackgroundMethod.invoke(view, background);\n\t\t\t} catch (IllegalArgumentException e) {\n\t\t\t\tLog.e(LOG_TAG, \"Some argument is illegal to call android.view.View.setBackground().\", e);\n\t\t\t} catch (IllegalAccessException e) {\n\t\t\t\tLog.e(LOG_TAG, \"It has failed to call android.view.View.setBackground().\", e);\n\t\t\t} catch (InvocationTargetException e) {\n\t\t\t\tLog.e(LOG_TAG, \"It has failed to call android.view.View.setBackground().\", e);\n\t\t\t}\n\t\t}\n\t} \n\t/*\n\t * Copied from android.os.Build.VERSION_CODES \n\t */\n\tpublic static class VERSION_CODES {\n\t\tpublic static final int CUR_DEVELOPMENT = 10000;\n\t\tpublic static final int BASE = 1;\n\t\tpublic static final int BASE_1_1 = 2;\n\t\tpublic static final int CUPCAKE = 3;\n\t\tpublic static final int DONUT = 4;\n\t\tpublic static final int ECLAIR = 5;\n\t\tpublic static final int ECLAIR_0_1 = 6;\n\t\tpublic static final int ECLAIR_MR1 = 7;\n\t\tpublic static final int FROYO = 8;\n\t\tpublic static final int GINGERBREAD = 9;\n\t\tpublic static final int GINGERBREAD_MR1 = 10;\n\t\tpublic static final int HONEYCOMB = 11;\n\t\tpublic static final int HONEYCOMB_MR1 = 12;\n\t\tpublic static final int HONEYCOMB_MR2 = 13;\n\t\tpublic static final int ICE_CREAM_SANDWICH = 14;\n\t\tpublic static final int ICE_CREAM_SANDWICH_MR1 = 15;\n\t\tpublic static final int JELLY_BEAN = 16;\n\t\tpublic static final int JELLY_BEAN_MR1 = 17;\n\t\tpublic static final int JELLY_BEAN_MR2 = 18;\n\t\tpublic static final int KITKAT = 19;\n\t}\n\n\tpublic static void postOnAnimation(View view, Runnable runnable) {\n\t\tif (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {\n\t\t\tSDK16.postOnAnimation(view, runnable);\n\t\t} else {\n\t\t\tview.postDelayed(runnable, 16);\n\t\t}\n\t}\n\n\tpublic static void setBackground(View view, Drawable background) {\n\t\tif (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {\n\t\t\tSDK16.setBackground(view, background);\n\t\t} else {\n\t\t\tview.setBackgroundDrawable(background);\n\t\t}\n\t}\n\n\tpublic static void setLayerType(View view, int layerType) {\n\t\tif (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {\n\t\t\tSDK11.setLayerType(view, layerType);\n\t\t}\n\t}\n\n\t@TargetApi(11)\n\tstatic class SDK11 {\n\n\t\tpublic static void setLayerType(View view, int layerType) {\n\t\t\tMethods.setLayerType(view, layerType);\n\t\t}\n\t}\n\n\t@TargetApi(16)\n\tstatic class SDK16 {\n\n\t\tpublic static void postOnAnimation(View view, Runnable runnable) {\n\t\t\tMethods.postOnAnimation(view, runnable);\n\t\t}\n\n\t\tpublic static void setBackground(View view, Drawable background) {\n\t\t\tMethods.setBackground(view, background);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t<groupId>com.navercorp.pulltorefresh</groupId>\n\t<artifactId>parent</artifactId>\n\t<packaging>pom</packaging>\n\t<version>3.3.0-SNAPSHOT</version>\n\t<name>Android-PullToRefresh Project</name>\n\t<description>Implementation of the Pull-to-Refresh UI Pattern for Android.</description>\n\t<url>https://github.com/naver/android-pull-to-refresh</url>\n\t<parent>\n\t\t<groupId>org.sonatype.oss</groupId>\n\t\t<artifactId>oss-parent</artifactId>\n\t\t<version>7</version>\n\t</parent>\n\t<licenses>\n\t\t<license>\n\t\t\t<name>Apache License Version 2.0</name>\n\t\t\t<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>\n\t\t\t<distribution>repo</distribution>\n\t\t</license>\n\t</licenses>\n\t<scm>\n\t\t<url>https://github.com/naver/android-pull-to-refresh</url>\n\t\t<connection>scm:git:git://github.com/naver/android-pull-to-refresh.git</connection>\n\t\t<developerConnection>scm:git:git@github.com:naver/android-pull-to-refresh.git</developerConnection>\n\t  <tag>HEAD</tag>\n  </scm>\n\t<developers>\n\t\t<developer>\n\t\t\t<name>Chris Banes</name>\n\t\t\t<url>http://about.me/chrisbanes</url>\n\t\t\t<id>chrisbanes</id>\n\t\t</developer>\n\t\t<developer>\n\t\t\t<name>Wonjun Kim</name>\n\t\t\t<id>ncoolz</id>\n\t\t</developer>\t\t\n\t</developers>\n\t<modules>\n\t\t<module>library</module>\n\t\t<module>sample</module>\n\t\t<module>extras</module>\n\t</modules>\n\t<properties>\n\t\t<!-- build settings -->\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>\n\t\t<java.version>1.6</java.version>\n\t\t<android.version>4.1.1.4</android.version>\n\t\t<android.platform>16</android.platform>\n\t\t<android-maven.version>3.2.0</android-maven.version>\n\t</properties>\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>com.google.android</groupId>\n\t\t\t\t<artifactId>android</artifactId>\n\t\t\t\t<version>${android.version}</version>\n\t\t\t\t<scope>provided</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\t<build>\n\t\t<pluginManagement>\n\t\t\t<plugins>\n\t\t\t\t<!-- compiler settings -->\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-compiler-plugin</artifactId>\n\t\t\t\t\t<version>3.1</version>\n\t\t\t\t\t<configuration>\n           \t\t\t\t<source>${java.version}</source>\n            \t\t\t<target>${java.version}</target>\n    \t\t\t\t</configuration>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-release-plugin</artifactId>\n\t\t\t\t\t<version>2.5</version>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<mavenExecutorId>forked-path</mavenExecutorId>\n\t\t\t\t\t\t<tagNameFormat>v@{project.version}</tagNameFormat>\n\t\t\t\t\t</configuration>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>com.jayway.maven.plugins.android.generation2</groupId>\n\t\t\t\t\t<artifactId>android-maven-plugin</artifactId>\n\t\t\t\t\t<version>3.7.0</version>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<sdk>\n\t\t\t\t\t\t\t<platform>${android.platform}</platform>\n\t\t\t\t\t\t</sdk>\n\t\t\t\t\t\t<undeployBeforeDeploy>true</undeployBeforeDeploy>\n\t\t\t\t\t\t<source>${sourceCompatibility}</source>\n\t\t\t\t\t\t<target>${sourceCompatibility}</target>\n\t\t\t\t\t</configuration>\n\t\t\t\t\t<extensions>true</extensions>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.codehaus.mojo</groupId>\n\t\t\t\t\t<artifactId>build-helper-maven-plugin</artifactId>\n\t\t\t\t\t<version>1.8</version>\n\t\t\t\t</plugin>\n\t\t\t\t<!-- extracted from actionbarsherlock's pom -->\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.codehaus.mojo</groupId>\n\t\t\t\t\t<artifactId>exec-maven-plugin</artifactId>\n\t\t\t\t\t<version>1.2.1</version>\n\t\t\t\t\t<inherited>false</inherited>\n\t\t\t\t\t<executions>\n\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t<phase>package</phase>\n\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t<goal>exec</goal>\n\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t<configuration>\n\t\t\t\t\t\t\t\t<executable>gradle</executable>\n\t\t\t\t\t\t\t\t<arguments>\n\t\t\t\t\t\t\t\t\t<argument>clean</argument>\n\t\t\t\t\t\t\t\t\t<argument>assemble</argument>\n\t\t\t\t\t\t\t\t</arguments>\n\t\t\t\t\t\t\t</configuration>\n\t\t\t\t\t\t</execution>\n\t\t\t\t\t</executions>\n\t\t\t\t</plugin>\n\t\t\t\t<plugin>\n\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t<artifactId>maven-eclipse-plugin</artifactId>\n\t\t\t\t\t<version>2.8</version>\n\t\t\t\t\t<configuration>\n\t\t\t\t\t\t<excludes>\n\t\t\t\t\t\t\t<exclude>com.google.android:android</exclude>\n\t\t\t\t\t\t</excludes>\n\t\t\t\t\t\t<buildOutputDirectory>bin</buildOutputDirectory>\n\t\t\t\t\t\t<classpathContainers>\n\t\t\t\t\t\t\t<classpathContainer>com.android.ide.eclipse.adt.ANDROID_FRAMEWORK</classpathContainer>\n\t\t\t\t\t\t</classpathContainers>\n\t\t\t\t\t\t<additionalProjectnatures>\n\t\t\t\t\t\t\t<projectnature>com.android.ide.eclipse.adt.AndroidNature</projectnature>\n\t\t\t\t\t\t</additionalProjectnatures>\n\t\t\t\t\t\t<additionalBuildcommands>\n\t\t\t\t\t\t\t<buildcommand>com.android.ide.eclipse.adt.ResourceManagerBuilder</buildcommand>\n\t\t\t\t\t\t\t<buildcommand>com.android.ide.eclipse.adt.PreCompilerBuilder</buildcommand>\n\t\t\t\t\t\t\t<buildcommand>com.android.ide.eclipse.adt.ApkBuilder</buildcommand>\n\t\t\t\t\t\t</additionalBuildcommands>\n\t\t\t\t\t</configuration>\n\t\t\t\t</plugin>\n\t\t\t</plugins>\n\t\t</pluginManagement>\n\t\t<sourceDirectory>src</sourceDirectory>\n\t</build>\n\t<profiles>\n\t\t<profile>\n\t\t\t<id>release-sign-artifacts</id>\n\t\t\t<activation>\n\t\t\t\t<property>\n\t\t\t\t\t<name>performRelease</name>\n\t\t\t\t\t<value>true</value>\n\t\t\t\t</property>\n\t\t\t</activation>\n\t\t\t<build>\n\t\t\t\t<plugins>\n\t\t\t\t\t<plugin>\n\t\t\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t\t\t<artifactId>maven-gpg-plugin</artifactId>\n\t\t\t\t\t\t<version>1.4</version>\n\t\t\t\t\t\t<executions>\n\t\t\t\t\t\t\t<execution>\n\t\t\t\t\t\t\t\t<id>sign-artifacts</id>\n\t\t\t\t\t\t\t\t<phase>verify</phase>\n\t\t\t\t\t\t\t\t<goals>\n\t\t\t\t\t\t\t\t\t<goal>sign</goal>\n\t\t\t\t\t\t\t\t</goals>\n\t\t\t\t\t\t\t</execution>\n\t\t\t\t\t\t</executions>\n\t\t\t\t\t</plugin>\n\t\t\t\t</plugins>\n\t\t\t</build>\n\t\t</profile>\n\t</profiles>\n</project>\n"
  },
  {
    "path": "sample/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.handmark.pulltorefresh.samples\"\n    android:versionCode=\"2110\"\n    android:versionName=\"2.1.1\" >\n\n    <uses-sdk\n        android:minSdkVersion=\"4\"\n        android:targetSdkVersion=\"15\" />\n\n    <application\n        android:hardwareAccelerated=\"true\"\n        android:icon=\"@drawable/icon\"\n        android:label=\"@string/app_name\" >\n        <activity\n            android:name=\".LauncherActivity\"\n            android:label=\"PullToRefresh Samples\" >\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n        <activity\n            android:name=\".PullToRefreshListActivity\"\n            android:label=\"PtR ListView\" >\n        </activity>\n        <activity\n            android:name=\".PullToRefreshListFragmentActivity\"\n            android:label=\"PtR ListView Fragment\" >\n        </activity>\n        <activity\n            android:name=\".PullToRefreshListInViewPagerActivity\"\n            android:label=\"PtR ListView in ViewPager\" >\n        </activity>\n        <activity\n            android:name=\".PullToRefreshGridActivity\"\n            android:label=\"PtR GridView\" >\n        </activity>\n        <activity\n            android:name=\".PullToRefreshExpandableListActivity\"\n            android:label=\"PtR ExpandableListView\" >\n        </activity>\n        <activity\n            android:name=\".PullToRefreshWebViewActivity\"\n            android:label=\"PtR WebView\" >\n        </activity>\n        <activity\n            android:name=\".PullToRefreshScrollViewActivity\"\n            android:label=\"PtR ScrollView\" >\n        </activity>\n        <activity\n            android:name=\".PullToRefreshHorizontalScrollViewActivity\"\n            android:label=\"PtR HorizontalScrollView\" >\n        </activity>\n        <activity\n            android:name=\".PullToRefreshViewPagerActivity\"\n            android:label=\"PtR ViewPager\" >\n        </activity>\n        <activity\n            android:name=\".PullToRefreshWebView2Activity\"\n            android:label=\"PtR WebView Advanced\" >\n        </activity>\n        <activity\n            android:name=\".PullToRefreshCustomLoadingLayoutActivity\"\n            android:label=\"PtR Custom LoadingLayout\"></activity>\n    </application>\n\n    <!-- For WebView Sample -->\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n\n    <supports-screens android:anyDensity=\"true\" />\n\n</manifest>"
  },
  {
    "path": "sample/LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "sample/assets/ptr_webview2_sample.html",
    "content": "<html>\n<head>\n<title>PullToRefreshWebView2 Sample</title>\n\n<script language=\"javascript\" type=\"text/javascript\">\n function isReadyForPullDown() {\n   var result = document.body.scrollTop == 0;\n   ptr.isReadyForPullDownResponse(result);\n }\n \n function isReadyForPullUp() {\n   var result = document.body.scrollTop + document.body.clientHeight >= document.body.scrollHeight;\n   ptr.isReadyForPullUpResponse(result);\n }\n</script>\n\n</head>\n\n<body>\n<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sollicitudin mauris varius lacus porttitor eget blandit massa facilisis. Nulla pellentesque odio sed purus fermentum vitae viverra orci faucibus. Sed ullamcorper condimentum vulputate. Curabitur sit amet convallis velit. Vestibulum posuere eleifend risus ac adipiscing. Nam pulvinar nulla a velit faucibus imperdiet. Praesent eget nisi ac justo blandit sagittis. Maecenas at leo nisi, nec varius nisl.</p>\n<p>In hac habitasse platea dictumst. Morbi neque tortor, vestibulum sed viverra a, luctus vel lorem. Nunc turpis eros, varius eget commodo et, euismod at eros. Sed tincidunt mi purus, vel posuere dui. Vestibulum ante lectus, porta sed mattis bibendum, scelerisque cursus sapien. Cras ultrices imperdiet fermentum. Aenean nisi nulla, euismod non blandit ac, dictum quis libero. Morbi consectetur tempor mollis. Suspendisse eget nunc arcu, vel ullamcorper augue. Integer malesuada, diam nec faucibus mollis, nisl velit euismod enim, ac mattis justo neque sit amet mauris. Vivamus pretium imperdiet pharetra.</p>\n<p>Integer sagittis augue sit amet lectus pulvinar sit amet commodo tortor mattis. Maecenas quis tellus eget ante eleifend sollicitudin non et nibh. Maecenas luctus euismod tristique. Fusce in odio nec diam blandit facilisis. Sed nec arcu eros. Vivamus quis tortor a metus tempus aliquam eget volutpat magna. Pellentesque id ultrices dolor. Sed blandit aliquet quam. Phasellus dapibus euismod vulputate. Aenean blandit, elit vitae vestibulum tincidunt, metus dui accumsan nulla, sit amet vehicula mauris lacus in est. Etiam dignissim pellentesque nulla vel malesuada. Cras vel lorem justo.</p>\n<p>Sed condimentum nisl sit amet libero vestibulum hendrerit. Duis auctor tempus placerat. Proin velit ante, ornare nec dictum nec, hendrerit eu arcu. Etiam ut diam ornare quam venenatis pulvinar vitae vel leo. Vivamus consectetur, ante id interdum rhoncus, magna eros pulvinar lacus, a gravida nibh arcu vitae eros. Nulla scelerisque laoreet feugiat. Mauris sit amet gravida felis.</p>\n<p>Nulla ac dolor sapien, vestibulum venenatis justo. Cras placerat velit vitae nibh pellentesque ultricies. Suspendisse adipiscing enim eu justo iaculis eu pretium urna fermentum. Duis porttitor nunc non nunc mattis vestibulum. Etiam elit tellus, feugiat in bibendum eget, adipiscing nec metus. Ut ut sem lacus, quis faucibus diam. Curabitur a nulla fermentum tortor dignissim posuere. Fusce faucibus ante ut sem imperdiet imperdiet eget vitae lorem. Etiam fringilla ornare ipsum, in sagittis quam ornare vitae. Nullam venenatis orci sit amet sapien adipiscing gravida. Proin turpis lectus, hendrerit vitae vehicula ut, auctor ac lectus. Pellentesque sollicitudin blandit ligula quis commodo. Mauris vulputate lectus in velit luctus aliquam. Quisque eget tincidunt elit. Quisque et augue quam, sed scelerisque eros.</p>\n</body>\n\n</html>\n\n"
  },
  {
    "path": "sample/assets/pulltorefresh.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<PullToRefresh>\n    <LoadingLayouts>\n     <layout name=\"my_custom\">com.handmark.pulltorefresh.samples.loadinglayout.CustomLoadingLayout</layout>\n    </LoadingLayouts>\n</PullToRefresh>"
  },
  {
    "path": "sample/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\t\n\t<groupId>com.navercorp.pulltorefresh</groupId>\n\t<artifactId>sample</artifactId>\n\t<packaging>apk</packaging>\n\t<name>Android-PullToRefresh Sample</name>\n\t\n\t<parent>\n\t\t<groupId>com.navercorp.pulltorefresh</groupId>\n\t\t<artifactId>parent</artifactId>\n\t\t<version>3.3.0-SNAPSHOT</version>\n\t</parent>\n\n\t<dependencies>\n\t\t<dependency>\n\t\t\t<groupId>com.google.android</groupId>\n\t\t\t<artifactId>android</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>${project.groupId}</groupId>\n\t\t\t<artifactId>library</artifactId>\n\t\t\t<type>apklib</type>\n\t\t\t<version>${project.version}</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>${project.groupId}</groupId>\n\t\t\t<artifactId>extra-listfragment</artifactId>\n\t\t\t<type>apklib</type>\n\t\t\t<version>${project.version}</version>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>${project.groupId}</groupId>\n\t\t\t<artifactId>extra-viewpager</artifactId>\n\t\t\t<type>apklib</type>\n\t\t\t<version>${project.version}</version>\n\t\t</dependency>\n\t</dependencies>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>com.jayway.maven.plugins.android.generation2</groupId>\n\t\t\t\t<artifactId>android-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.apache.maven.plugins</groupId>\n\t\t\t\t<artifactId>maven-eclipse-plugin</artifactId>\n\t\t\t\t<configuration>\n\t\t\t\t\t<excludes>\n\t\t\t\t\t\t<exclude>com.google.android:android</exclude>\n\t\t\t\t\t\t<exclude>commons-logging:commons-logging</exclude>\n\t\t\t\t\t\t<exclude>xerces:xmlParserAPIs</exclude>\n\t\t\t\t\t\t<exclude>xpp3:xpp3</exclude>\n\t\t\t\t\t</excludes>\n\t\t\t\t</configuration>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n</project>\n"
  },
  {
    "path": "sample/project.properties",
    "content": "# This file is automatically generated by Android Tools.\n# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n#\n# This file must be checked in Version Control Systems.\n#\n# To customize properties used by the Ant build system use,\n# \"ant.properties\", and override values to adapt the script to your\n# project structure.\n\n# Project target.\ntarget=android-16\nandroid.library.reference.1=../library\nandroid.library.reference.2=../extras/PullToRefreshListFragment\nandroid.library.reference.3=../extras/PullToRefreshViewPager\n"
  },
  {
    "path": "sample/res/layout/activity_ptr_custom_loadinglayout.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\" >\n    <com.handmark.pulltorefresh.library.PullToRefreshListView\n        xmlns:ptr=\"http://schemas.android.com/apk/res-auto\"\n        android:id=\"@+id/ptrListView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        ptr:ptrSmoothScrollDuration=\"400\"\n        ptr:ptrShowIndicator=\"false\"\n        ptr:ptrAnimationStyle=\"my_custom\"\n        ptr:ptrOverScroll=\"true\"\n        />\n</LinearLayout>\n"
  },
  {
    "path": "sample/res/layout/activity_ptr_expandable_list.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"fill_parent\"\n    android:orientation=\"vertical\" >\n\n    <!-- The PullToRefreshExpandableListView replaces a standard ExpandableListView widget. -->\n\n    <com.handmark.pulltorefresh.library.PullToRefreshExpandableListView\n        xmlns:ptr=\"http://schemas.android.com/apk/res-auto\"\n        android:id=\"@+id/pull_refresh_expandable_list\"\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"fill_parent\"\n        ptr:ptrHeaderBackground=\"@android:color/darker_gray\"\n        ptr:ptrHeaderTextColor=\"@android:color/white\"\n        ptr:ptrMode=\"pullUpFromBottom\" />\n\n</LinearLayout>"
  },
  {
    "path": "sample/res/layout/activity_ptr_grid.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:orientation=\"vertical\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"fill_parent\" >\n\n<!-- The PullToRefreshGridView replaces a standard GridView widget. -->\n    <com.handmark.pulltorefresh.library.PullToRefreshGridView\n        xmlns:ptr=\"http://schemas.android.com/apk/res-auto\"\n        android:id=\"@+id/pull_refresh_grid\"\n        android:layout_height=\"fill_parent\"\n        android:layout_width=\"fill_parent\"\n        android:numColumns=\"auto_fit\"\n        android:verticalSpacing=\"1dp\"\n        android:horizontalSpacing=\"1dp\"\n        android:columnWidth=\"100dp\"\n        android:stretchMode=\"columnWidth\"\n        android:gravity=\"fill\"\n        ptr:ptrMode=\"both\"\n        ptr:ptrDrawable=\"@drawable/android\" />\n\n</LinearLayout>"
  },
  {
    "path": "sample/res/layout/activity_ptr_horizontalscrollview.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"fill_parent\"\n    android:orientation=\"vertical\" >\n\n    <!-- The PullToRefreshScrollView replaces a standard PullToRefreshScrollView widget. -->\n\n    <com.handmark.pulltorefresh.library.PullToRefreshHorizontalScrollView\n        xmlns:ptr=\"http://schemas.android.com/apk/res-auto\"\n        android:id=\"@+id/pull_refresh_horizontalscrollview\"\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"fill_parent\"\n        ptr:ptrAnimationStyle=\"flip\"\n        ptr:ptrMode=\"both\" >\n\n        <LinearLayout\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"fill_parent\"\n            android:orientation=\"horizontal\" >\n\n            <TextView\n                style=\"@style/HorizScrollViewItem\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"fill_parent\"\n                android:background=\"#ff99cc00\" />\n\n            <TextView\n                style=\"@style/HorizScrollViewItem\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"fill_parent\"\n                android:background=\"#ffff4444\" />\n\n            <TextView\n                style=\"@style/HorizScrollViewItem\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"fill_parent\"\n                android:background=\"#ff33b5e5\" />\n\n            <TextView\n                style=\"@style/HorizScrollViewItem\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"fill_parent\"\n                android:background=\"#ffcc0000\" />\n\n            <TextView\n                style=\"@style/HorizScrollViewItem\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"fill_parent\"\n                android:background=\"#ffffbb33\" />\n\n            <TextView\n                style=\"@style/HorizScrollViewItem\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"fill_parent\"\n                android:background=\"#ff00ddff\" />\n\n            <TextView\n                style=\"@style/HorizScrollViewItem\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"fill_parent\"\n                android:background=\"#ff669900\" />\n        </LinearLayout>\n        \n    </com.handmark.pulltorefresh.library.PullToRefreshHorizontalScrollView>\n\n</LinearLayout>"
  },
  {
    "path": "sample/res/layout/activity_ptr_list.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"fill_parent\"\n    android:orientation=\"vertical\" >\n\n<!--     The PullToRefreshListView replaces a standard ListView widget. -->\n\n    <com.handmark.pulltorefresh.library.PullToRefreshListView\n        android:id=\"@+id/pull_refresh_list\"\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"fill_parent\"\n        android:cacheColorHint=\"#00000000\"\n        android:divider=\"#19000000\"\n        android:dividerHeight=\"4dp\"\n        android:fadingEdge=\"none\"\n        android:fastScrollEnabled=\"false\"\n        android:footerDividersEnabled=\"false\"\n        android:headerDividersEnabled=\"false\"\n        android:smoothScrollbar=\"true\" />\n\n</LinearLayout>"
  },
  {
    "path": "sample/res/layout/activity_ptr_list_fragment.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\" >\n\n    <fragment\n        android:id=\"@+id/frag_ptr_list\"\n        android:name=\"com.handmark.pulltorefresh.extras.listfragment.PullToRefreshListFragment\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" />\n\n</FrameLayout>"
  },
  {
    "path": "sample/res/layout/activity_ptr_list_in_vp.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"fill_parent\"\n    android:orientation=\"vertical\" >\n\n    <!-- The PullToRefreshListView replaces a standard ListView widget. -->\n\n    <android.support.v4.view.ViewPager\n        android:id=\"@+id/vp_list\"\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"fill_parent\" />\n\n</LinearLayout>"
  },
  {
    "path": "sample/res/layout/activity_ptr_scrollview.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"fill_parent\"\n    android:orientation=\"vertical\" >\n\n    <!-- The PullToRefreshScrollView replaces a standard PullToRefreshScrollView widget. -->\n\n    <com.handmark.pulltorefresh.library.PullToRefreshScrollView\n        xmlns:ptr=\"http://schemas.android.com/apk/res-auto\"\n        android:id=\"@+id/pull_refresh_scrollview\"\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"fill_parent\"\n        ptr:ptrAnimationStyle=\"flip\"\n        ptr:ptrMode=\"both\" >\n\n        <TextView\n            android:layout_width=\"fill_parent\"\n            android:layout_height=\"fill_parent\"\n            android:padding=\"8dp\"\n            android:text=\"@string/filler_text\"\n            android:textSize=\"16sp\" />\n    </com.handmark.pulltorefresh.library.PullToRefreshScrollView>\n\n</LinearLayout>"
  },
  {
    "path": "sample/res/layout/activity_ptr_viewpager.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"fill_parent\" >\n\n    <!-- The PullToRefreshScrollView replaces a standard PullToRefreshScrollView widget. -->\n\n    <com.handmark.pulltorefresh.extras.viewpager.PullToRefreshViewPager\n        xmlns:ptr=\"http://schemas.android.com/apk/res-auto\"\n        android:id=\"@+id/pull_refresh_viewpager\"\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"fill_parent\"\n        ptr:ptrAnimationStyle=\"flip\"\n        ptr:ptrHeaderBackground=\"@android:color/darker_gray\"\n        ptr:ptrMode=\"both\" />\n\n</FrameLayout>"
  },
  {
    "path": "sample/res/layout/activity_ptr_webview.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:orientation=\"vertical\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"fill_parent\" >\n\n<!--     The PullToRefreshWebView replaces a standard WebView widget. -->\n\n    <com.handmark.pulltorefresh.library.PullToRefreshWebView\n        xmlns:ptr=\"http://schemas.android.com/apk/res-auto\"\n        android:id=\"@+id/pull_refresh_webview\"\n        android:layout_height=\"fill_parent\"\n        android:layout_width=\"fill_parent\"\n        ptr:ptrMode=\"both\" />\n\n</LinearLayout>"
  },
  {
    "path": "sample/res/layout/activity_ptr_webview2.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:orientation=\"vertical\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"fill_parent\" >\n\n<!--     The PullToRefreshWebView replaces a standard WebView widget. -->\n\n    <com.handmark.pulltorefresh.library.extras.PullToRefreshWebView2\n        xmlns:ptr=\"http://schemas.android.com/apk/res-auto\"\n        android:id=\"@+id/pull_refresh_webview2\"\n        android:layout_height=\"fill_parent\"\n        android:layout_width=\"fill_parent\"\n        ptr:ptrMode=\"both\" />\n\n</LinearLayout>"
  },
  {
    "path": "sample/res/layout/layout_listview_in_viewpager.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.handmark.pulltorefresh.library.PullToRefreshListView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:ptr=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"fill_parent\"\n    ptr:ptrHeaderBackground=\"@android:color/darker_gray\" />\n"
  },
  {
    "path": "sample/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <string name=\"hello\">Hello World, PullToRefreshActivity!</string>\n    <string name=\"app_name\">pulltorefreshexample</string>\n    <string name=\"filler_text\">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sollicitudin mauris varius lacus porttitor eget blandit massa facilisis. Nulla pellentesque odio sed purus fermentum vitae viverra orci faucibus. Sed ullamcorper condimentum vulputate. Curabitur sit amet convallis velit. Vestibulum posuere eleifend risus ac adipiscing. Nam pulvinar nulla a velit faucibus imperdiet. Praesent eget nisi ac justo blandit sagittis. Maecenas at leo nisi, nec varius nisl.\\nIn hac habitasse platea dictumst. Morbi neque tortor, vestibulum sed viverra a, luctus vel lorem. Nunc turpis eros, varius eget commodo et, euismod at eros. Sed tincidunt mi purus, vel posuere dui. Vestibulum ante lectus, porta sed mattis bibendum, scelerisque cursus sapien. Cras ultrices imperdiet fermentum. Aenean nisi nulla, euismod non blandit ac, dictum quis libero. Morbi consectetur tempor mollis. Suspendisse eget nunc arcu, vel ullamcorper augue. Integer malesuada, diam nec faucibus mollis, nisl velit euismod enim, ac mattis justo neque sit amet mauris. Vivamus pretium imperdiet pharetra.\\nInteger sagittis augue sit amet lectus pulvinar sit amet commodo tortor mattis. Maecenas quis tellus eget ante eleifend sollicitudin non et nibh. Maecenas luctus euismod tristique. Fusce in odio nec diam blandit facilisis. Sed nec arcu eros. Vivamus quis tortor a metus tempus aliquam eget volutpat magna. Pellentesque id ultrices dolor. Sed blandit aliquet quam. Phasellus dapibus euismod vulputate. Aenean blandit, elit vitae vestibulum tincidunt, metus dui accumsan nulla, sit amet vehicula mauris lacus in est. Etiam dignissim pellentesque nulla vel malesuada. Cras vel lorem justo.\\nSed condimentum nisl sit amet libero vestibulum hendrerit. Duis auctor tempus placerat. Proin velit ante, ornare nec dictum nec, hendrerit eu arcu. Etiam ut diam ornare quam venenatis pulvinar vitae vel leo. Vivamus consectetur, ante id interdum rhoncus, magna eros pulvinar lacus, a gravida nibh arcu vitae eros. Nulla scelerisque laoreet feugiat. Mauris sit amet gravida felis.\\nNulla ac dolor sapien, vestibulum venenatis justo. Cras placerat velit vitae nibh pellentesque ultricies. Suspendisse adipiscing enim eu justo iaculis eu pretium urna fermentum. Duis porttitor nunc non nunc mattis vestibulum. Etiam elit tellus, feugiat in bibendum eget, adipiscing nec metus. Ut ut sem lacus, quis faucibus diam. Curabitur a nulla fermentum tortor dignissim posuere. Fusce faucibus ante ut sem imperdiet imperdiet eget vitae lorem. Etiam fringilla ornare ipsum, in sagittis quam ornare vitae. Nullam venenatis orci sit amet sapien adipiscing gravida. Proin turpis lectus, hendrerit vitae vehicula ut, auctor ac lectus. Pellentesque sollicitudin blandit ligula quis commodo. Mauris vulputate lectus in velit luctus aliquam. Quisque eget tincidunt elit. Quisque et augue quam, sed scelerisque eros.</string>\n\n</resources>"
  },
  {
    "path": "sample/res/values/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <style name=\"HorizScrollViewItem\">\n        <item name=\"android:paddingRight\">50dp</item>\n        <item name=\"android:paddingLeft\">50dp</item>\n        <item name=\"android:gravity\">center</item>\n        <item name=\"android:textAppearance\">?android:attr/textAppearanceMedium</item>\n        <item name=\"android:text\">Sample Item</item>\n    </style>\n\n</resources>"
  },
  {
    "path": "sample/src/com/handmark/pulltorefresh/samples/LauncherActivity.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.samples;\n\nimport android.app.ListActivity;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.view.View;\nimport android.widget.ArrayAdapter;\nimport android.widget.ListView;\n\npublic class LauncherActivity extends ListActivity {\n\n\tpublic static final String[] options = { \"ListView\", \"ExpandableListView\", \"GridView\", \"WebView\", \"ScrollView\",\n\t\t\t\"Horizontal ScrollView\", \"ViewPager\", \"ListView Fragment\", \"WebView Advanced\", \"ListView in ViewPager\", \"Custom LoadingLayout\" };\n\n\t@Override\n\tprotected void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n\t\tsetListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, options));\n\t}\n\n\t@Override\n\tprotected void onListItemClick(ListView l, View v, int position, long id) {\n\t\tIntent intent;\n\n\t\tswitch (position) {\n\t\t\tdefault:\n\t\t\tcase 0:\n\t\t\t\tintent = new Intent(this, PullToRefreshListActivity.class);\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tintent = new Intent(this, PullToRefreshExpandableListActivity.class);\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tintent = new Intent(this, PullToRefreshGridActivity.class);\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tintent = new Intent(this, PullToRefreshWebViewActivity.class);\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tintent = new Intent(this, PullToRefreshScrollViewActivity.class);\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\t\tintent = new Intent(this, PullToRefreshHorizontalScrollViewActivity.class);\n\t\t\t\tbreak;\n\t\t\tcase 6:\n\t\t\t\tintent = new Intent(this, PullToRefreshViewPagerActivity.class);\n\t\t\t\tbreak;\n\t\t\tcase 7:\n\t\t\t\tintent = new Intent(this, PullToRefreshListFragmentActivity.class);\n\t\t\t\tbreak;\n\t\t\tcase 8:\n\t\t\t\tintent = new Intent(this, PullToRefreshWebView2Activity.class);\n\t\t\t\tbreak;\n\t\t\tcase 9:\n\t\t\t\tintent = new Intent(this, PullToRefreshListInViewPagerActivity.class);\n\t\t\t\tbreak;\n\t\t\tcase 10:\n\t\t\t\tintent = new Intent(this, PullToRefreshCustomLoadingLayoutActivity.class);\n\t\t\t\tbreak;\t\t\t\t\n\t\t}\n\n\t\tstartActivity(intent);\n\t}\n\n}\n"
  },
  {
    "path": "sample/src/com/handmark/pulltorefresh/samples/PullToRefreshCustomLoadingLayoutActivity.java",
    "content": "/*\n * Copyright (C) 2014 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.handmark.pulltorefresh.samples;\n\nimport java.util.Arrays;\nimport java.util.LinkedList;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshBase;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;\nimport com.handmark.pulltorefresh.library.PullToRefreshListView;\n\nimport android.app.Activity;\nimport android.os.AsyncTask;\nimport android.os.Bundle;\nimport android.text.format.DateUtils;\nimport android.util.Log;\nimport android.widget.ArrayAdapter;\nimport android.widget.ListView;\n\npublic class PullToRefreshCustomLoadingLayoutActivity extends Activity {\n\tprivate static final String[] mStrings = { \"Abbaye de Belloc\", \"Abbaye du Mont des Cats\", \"Abertam\", \"Abondance\",\n\t\t\"Ackawi\", \"Acorn\", \"Adelost\", \"Affidelice au Chablis\", \"Afuega'l Pitu\", \"Airag\", \"Airedale\", \"Aisy Cendre\",\n\t\t\"Allgauer Emmentaler\", \"Abbaye de Belloc\", \"Abbaye du Mont des Cats\", \"Abertam\", \"Abondance\", \"Ackawi\",\n\t\t\"Acorn\", \"Adelost\", \"Affidelice au Chablis\", \"Afuega'l Pitu\", \"Airag\", \"Airedale\", \"Aisy Cendre\",\n\t\t\"Allgauer Emmentaler\" };\n\n\tprivate PullToRefreshListView mPullRefreshListView;\n\tprivate LinkedList<String> mListItems;\n\tprivate ArrayAdapter<String> mAdapter;\n\n\t@Override\n\tprotected void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n\t\tsetContentView(R.layout.activity_ptr_custom_loadinglayout);\n\t\tinitPullToRefresh();\n\t}\n\n\tprivate void initPullToRefresh() {\n\t\tmPullRefreshListView = (PullToRefreshListView) findViewById(R.id.ptrListView);\n\t\t// Set a listener to be invoked when the list should be refreshed.\n\t\tmPullRefreshListView.setOnRefreshListener(new OnRefreshListener<ListView>() {\n\t\t\t@Override\n\t\t\tpublic void onRefresh(PullToRefreshBase<ListView> refreshView) {\n\t\t\t\tString label = DateUtils.formatDateTime(getApplicationContext(), System.currentTimeMillis(),\n\t\t\t\t\t\tDateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL);\n\t\t\t\tLog.d(PullToRefreshCustomLoadingLayoutActivity.class.getCanonicalName(), \"onRefreshing...\" + label);\n\n\t\t\t\t// Do work to refresh the list here.\n\t\t\t\tnew GetDataTask().execute();\n\t\t\t}\n\t\t});\n\n\t\tfinal ListView actualListView = mPullRefreshListView.getRefreshableView();\n\n\t\tmListItems = new LinkedList<String>();\n\t\tmListItems.addAll(Arrays.asList(mStrings));\n\n\t\tmAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mListItems);\n\t\tactualListView.setAdapter(mAdapter);\n\t}\n\n\tprivate class GetDataTask extends AsyncTask<Void, Void, String[]> {   \n\n\t\t@Override\n\t\tprotected String[] doInBackground(Void... params) {\n\t\t\t// Simulates a background job.\n\t\t\ttry {\n\t\t\t\tLog.d(PullToRefreshCustomLoadingLayoutActivity.class.getCanonicalName(), \"GetDataTask.doInBackground\");\n\t\t\t\tThread.sleep(1000);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t}\n\t\t\treturn mStrings;\n\t\t}\n\n\t\t@Override\n\t\tprotected void onPostExecute(String[] result) {\n\n\t\t\tmListItems.addFirst(\"New Item\");\n\t\t\tmAdapter.notifyDataSetChanged();\n\n\t\t\t// Call onRefreshComplete when the list has been refreshed.\n\t\t\tLog.d(PullToRefreshCustomLoadingLayoutActivity.class.getCanonicalName(), \"onRefreshComplete\");\n\t\t\tmPullRefreshListView.onRefreshComplete();\n\t\t\tsuper.onPostExecute(result);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "sample/src/com/handmark/pulltorefresh/samples/PullToRefreshExpandableListActivity.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.samples;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport android.app.ExpandableListActivity;\nimport android.os.AsyncTask;\nimport android.os.Bundle;\nimport android.widget.ExpandableListView;\nimport android.widget.SimpleExpandableListAdapter;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshBase;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;\nimport com.handmark.pulltorefresh.library.PullToRefreshExpandableListView;\n\npublic final class PullToRefreshExpandableListActivity extends ExpandableListActivity {\n\tprivate static final String KEY = \"key\";\n\n\tprivate List<Map<String, String>> groupData = new ArrayList<Map<String, String>>();\n\tprivate List<List<Map<String, String>>> childData = new ArrayList<List<Map<String, String>>>();\n\n\tprivate PullToRefreshExpandableListView mPullRefreshListView;\n\tprivate SimpleExpandableListAdapter mAdapter;\n\n\t/** Called when the activity is first created. */\n\t@Override\n\tpublic void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n\t\tsetContentView(R.layout.activity_ptr_expandable_list);\n\n\t\tmPullRefreshListView = (PullToRefreshExpandableListView) findViewById(R.id.pull_refresh_expandable_list);\n\n\t\t// Set a listener to be invoked when the list should be refreshed.\n\t\tmPullRefreshListView.setOnRefreshListener(new OnRefreshListener<ExpandableListView>() {\n\t\t\t@Override\n\t\t\tpublic void onRefresh(PullToRefreshBase<ExpandableListView> refreshView) {\n\t\t\t\t// Do work to refresh the list here.\n\t\t\t\tnew GetDataTask().execute();\n\t\t\t}\n\t\t});\n\n\t\tfor (String group : mGroupStrings) {\n\t\t\tMap<String, String> groupMap1 = new HashMap<String, String>();\n\t\t\tgroupData.add(groupMap1);\n\t\t\tgroupMap1.put(KEY, group);\n\n\t\t\tList<Map<String, String>> childList = new ArrayList<Map<String, String>>();\n\t\t\tfor (String string : mChildStrings) {\n\t\t\t\tMap<String, String> childMap = new HashMap<String, String>();\n\t\t\t\tchildList.add(childMap);\n\t\t\t\tchildMap.put(KEY, string);\n\t\t\t}\n\t\t\tchildData.add(childList);\n\t\t}\n\n\t\tmAdapter = new SimpleExpandableListAdapter(this, groupData, android.R.layout.simple_expandable_list_item_1,\n\t\t\t\tnew String[] { KEY }, new int[] { android.R.id.text1 }, childData,\n\t\t\t\tandroid.R.layout.simple_expandable_list_item_2, new String[] { KEY }, new int[] { android.R.id.text1 });\n\t\tsetListAdapter(mAdapter);\n\t}\n\n\tprivate class GetDataTask extends AsyncTask<Void, Void, String[]> {\n\n\t\t@Override\n\t\tprotected String[] doInBackground(Void... params) {\n\t\t\t// Simulates a background job.\n\t\t\ttry {\n\t\t\t\tThread.sleep(2000);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t}\n\t\t\treturn mChildStrings;\n\t\t}\n\n\t\t@Override\n\t\tprotected void onPostExecute(String[] result) {\n\t\t\tMap<String, String> newMap = new HashMap<String, String>();\n\t\t\tnewMap.put(KEY, \"Added after refresh...\");\n\t\t\tgroupData.add(newMap);\n\n\t\t\tList<Map<String, String>> childList = new ArrayList<Map<String, String>>();\n\t\t\tfor (String string : mChildStrings) {\n\t\t\t\tMap<String, String> childMap = new HashMap<String, String>();\n\t\t\t\tchildMap.put(KEY, string);\n\t\t\t\tchildList.add(childMap);\n\t\t\t}\n\t\t\tchildData.add(childList);\n\n\t\t\tmAdapter.notifyDataSetChanged();\n\n\t\t\t// Call onRefreshComplete when the list has been refreshed.\n\t\t\tmPullRefreshListView.onRefreshComplete();\n\n\t\t\tsuper.onPostExecute(result);\n\t\t}\n\t}\n\n\tprivate String[] mChildStrings = { \"Child One\", \"Child Two\", \"Child Three\", \"Child Four\", \"Child Five\", \"Child Six\" };\n\n\tprivate String[] mGroupStrings = { \"Group One\", \"Group Two\", \"Group Three\" };\n}\n"
  },
  {
    "path": "sample/src/com/handmark/pulltorefresh/samples/PullToRefreshGridActivity.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.samples;\n\nimport java.util.Arrays;\nimport java.util.LinkedList;\n\nimport android.app.Activity;\nimport android.os.AsyncTask;\nimport android.os.Bundle;\nimport android.view.Gravity;\nimport android.view.Menu;\nimport android.view.MenuItem;\nimport android.widget.ArrayAdapter;\nimport android.widget.GridView;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshBase;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener2;\nimport com.handmark.pulltorefresh.library.PullToRefreshGridView;\n\npublic final class PullToRefreshGridActivity extends Activity {\n\n\tstatic final int MENU_SET_MODE = 0;\n\n\tprivate LinkedList<String> mListItems;\n\tprivate PullToRefreshGridView mPullRefreshGridView;\n\tprivate GridView mGridView;\n\tprivate ArrayAdapter<String> mAdapter;\n\n\t/** Called when the activity is first created. */\n\t@Override\n\tpublic void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n\t\tsetContentView(R.layout.activity_ptr_grid);\n\n\t\tmPullRefreshGridView = (PullToRefreshGridView) findViewById(R.id.pull_refresh_grid);\n\t\tmGridView = mPullRefreshGridView.getRefreshableView();\n\n\t\t// Set a listener to be invoked when the list should be refreshed.\n\t\tmPullRefreshGridView.setOnRefreshListener(new OnRefreshListener2<GridView>() {\n\n\t\t\t@Override\n\t\t\tpublic void onPullDownToRefresh(PullToRefreshBase<GridView> refreshView) {\n\t\t\t\tToast.makeText(PullToRefreshGridActivity.this, \"Pull Down!\", Toast.LENGTH_SHORT).show();\n\t\t\t\tnew GetDataTask().execute();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void onPullUpToRefresh(PullToRefreshBase<GridView> refreshView) {\n\t\t\t\tToast.makeText(PullToRefreshGridActivity.this, \"Pull Up!\", Toast.LENGTH_SHORT).show();\n\t\t\t\tnew GetDataTask().execute();\n\t\t\t}\n\n\t\t});\n\n\t\tmListItems = new LinkedList<String>();\n\n\t\tTextView tv = new TextView(this);\n\t\ttv.setGravity(Gravity.CENTER);\n\t\ttv.setText(\"Empty View, Pull Down/Up to Add Items\");\n\t\tmPullRefreshGridView.setEmptyView(tv);\n\n\t\tmAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mListItems);\n\t\tmGridView.setAdapter(mAdapter);\n\t}\n\n\tprivate class GetDataTask extends AsyncTask<Void, Void, String[]> {\n\n\t\t@Override\n\t\tprotected String[] doInBackground(Void... params) {\n\t\t\t// Simulates a background job.\n\t\t\ttry {\n\t\t\t\tThread.sleep(2000);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t}\n\t\t\treturn mStrings;\n\t\t}\n\n\t\t@Override\n\t\tprotected void onPostExecute(String[] result) {\n\t\t\tmListItems.addFirst(\"Added after refresh...\");\n\t\t\tmListItems.addAll(Arrays.asList(result));\n\t\t\tmAdapter.notifyDataSetChanged();\n\n\t\t\t// Call onRefreshComplete when the list has been refreshed.\n\t\t\tmPullRefreshGridView.onRefreshComplete();\n\n\t\t\tsuper.onPostExecute(result);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean onCreateOptionsMenu(Menu menu) {\n\t\tmenu.add(0, MENU_SET_MODE, 0,\n\t\t\t\tmPullRefreshGridView.getMode() == Mode.BOTH ? \"Change to MODE_PULL_DOWN\"\n\t\t\t\t\t\t: \"Change to MODE_PULL_BOTH\");\n\t\treturn super.onCreateOptionsMenu(menu);\n\t}\n\n\t@Override\n\tpublic boolean onPrepareOptionsMenu(Menu menu) {\n\t\tMenuItem setModeItem = menu.findItem(MENU_SET_MODE);\n\t\tsetModeItem.setTitle(mPullRefreshGridView.getMode() == Mode.BOTH ? \"Change to MODE_PULL_FROM_START\"\n\t\t\t\t: \"Change to MODE_PULL_BOTH\");\n\n\t\treturn super.onPrepareOptionsMenu(menu);\n\t}\n\n\t@Override\n\tpublic boolean onOptionsItemSelected(MenuItem item) {\n\t\tswitch (item.getItemId()) {\n\t\t\tcase MENU_SET_MODE:\n\t\t\t\tmPullRefreshGridView\n\t\t\t\t\t\t.setMode(mPullRefreshGridView.getMode() == Mode.BOTH ? Mode.PULL_FROM_START\n\t\t\t\t\t\t\t\t: Mode.BOTH);\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn super.onOptionsItemSelected(item);\n\t}\n\n\tprivate String[] mStrings = { \"Abbaye de Belloc\", \"Abbaye du Mont des Cats\", \"Abertam\", \"Abondance\", \"Ackawi\",\n\t\t\t\"Acorn\", \"Adelost\", \"Affidelice au Chablis\", \"Afuega'l Pitu\", \"Airag\", \"Airedale\", \"Aisy Cendre\",\n\t\t\t\"Allgauer Emmentaler\" };\n}\n"
  },
  {
    "path": "sample/src/com/handmark/pulltorefresh/samples/PullToRefreshHorizontalScrollViewActivity.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.samples;\n\nimport android.app.Activity;\nimport android.os.AsyncTask;\nimport android.os.Bundle;\nimport android.widget.HorizontalScrollView;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshBase;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;\nimport com.handmark.pulltorefresh.library.PullToRefreshHorizontalScrollView;\n\npublic final class PullToRefreshHorizontalScrollViewActivity extends Activity {\n\n\tPullToRefreshHorizontalScrollView mPullRefreshScrollView;\n\tHorizontalScrollView mScrollView;\n\n\t/** Called when the activity is first created. */\n\t@Override\n\tpublic void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n\t\tsetContentView(R.layout.activity_ptr_horizontalscrollview);\n\n\t\tmPullRefreshScrollView = (PullToRefreshHorizontalScrollView) findViewById(R.id.pull_refresh_horizontalscrollview);\n\t\tmPullRefreshScrollView.setOnRefreshListener(new OnRefreshListener<HorizontalScrollView>() {\n\n\t\t\t@Override\n\t\t\tpublic void onRefresh(PullToRefreshBase<HorizontalScrollView> refreshView) {\n\t\t\t\tnew GetDataTask().execute();\n\t\t\t}\n\t\t});\n\n\t\tmScrollView = mPullRefreshScrollView.getRefreshableView();\n\t}\n\n\tprivate class GetDataTask extends AsyncTask<Void, Void, String[]> {\n\n\t\t@Override\n\t\tprotected String[] doInBackground(Void... params) {\n\t\t\t// Simulates a background job.\n\t\t\ttry {\n\t\t\t\tThread.sleep(4000);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tprotected void onPostExecute(String[] result) {\n\t\t\t// Do some stuff here\n\n\t\t\t// Call onRefreshComplete when the list has been refreshed.\n\t\t\tmPullRefreshScrollView.onRefreshComplete();\n\n\t\t\tsuper.onPostExecute(result);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListActivity.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.samples;\n\nimport java.util.Arrays;\nimport java.util.LinkedList;\n\nimport android.app.ListActivity;\nimport android.os.AsyncTask;\nimport android.os.Bundle;\nimport android.text.format.DateUtils;\nimport android.view.ContextMenu;\nimport android.view.ContextMenu.ContextMenuInfo;\nimport android.view.Menu;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.widget.AdapterView.AdapterContextMenuInfo;\nimport android.widget.ArrayAdapter;\nimport android.widget.ListView;\nimport android.widget.Toast;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshBase;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.OnLastItemVisibleListener;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.State;\nimport com.handmark.pulltorefresh.library.PullToRefreshListView;\nimport com.handmark.pulltorefresh.library.extras.SoundPullEventListener;\n\npublic final class PullToRefreshListActivity extends ListActivity {\n\n\tstatic final int MENU_MANUAL_REFRESH = 0;\n\tstatic final int MENU_DISABLE_SCROLL = 1;\n\tstatic final int MENU_SET_MODE = 2;\n\tstatic final int MENU_DEMO = 3;\n\n\tprivate LinkedList<String> mListItems;\n\tprivate PullToRefreshListView mPullRefreshListView;\n\tprivate ArrayAdapter<String> mAdapter;\n\n\t/** Called when the activity is first created. */\n\t@Override\n\tpublic void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n\t\tsetContentView(R.layout.activity_ptr_list);\n\n\t\tmPullRefreshListView = (PullToRefreshListView) findViewById(R.id.pull_refresh_list);\n\n\t\t// Set a listener to be invoked when the list should be refreshed.\n\t\tmPullRefreshListView.setOnRefreshListener(new OnRefreshListener<ListView>() {\n\t\t\t@Override\n\t\t\tpublic void onRefresh(PullToRefreshBase<ListView> refreshView) {\n\t\t\t\tString label = DateUtils.formatDateTime(getApplicationContext(), System.currentTimeMillis(),\n\t\t\t\t\t\tDateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL);\n\n\t\t\t\t// Update the LastUpdatedLabel\n\t\t\t\trefreshView.getLoadingLayoutProxy().setLastUpdatedLabel(label);\n\n\t\t\t\t// Do work to refresh the list here.\n\t\t\t\tnew GetDataTask().execute();\n\t\t\t}\n\t\t});\n\n\t\t// Add an end-of-list listener\n\t\tmPullRefreshListView.setOnLastItemVisibleListener(new OnLastItemVisibleListener() {\n\n\t\t\t@Override\n\t\t\tpublic void onLastItemVisible() {\n\t\t\t\tToast.makeText(PullToRefreshListActivity.this, \"End of List!\", Toast.LENGTH_SHORT).show();\n\t\t\t}\n\t\t});\n\n\t\tListView actualListView = mPullRefreshListView.getRefreshableView();\n\n\t\t// Need to use the Actual ListView when registering for Context Menu\n\t\tregisterForContextMenu(actualListView);\n\n\t\tmListItems = new LinkedList<String>();\n\t\tmListItems.addAll(Arrays.asList(mStrings));\n\n\t\tmAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mListItems);\n\n\t\t/**\n\t\t * Add Sound Event Listener\n\t\t */\n\t\tSoundPullEventListener<ListView> soundListener = new SoundPullEventListener<ListView>(this);\n\t\tsoundListener.addSoundEvent(State.PULL_TO_REFRESH, R.raw.pull_event);\n\t\tsoundListener.addSoundEvent(State.RESET, R.raw.reset_sound);\n\t\tsoundListener.addSoundEvent(State.REFRESHING, R.raw.refreshing_sound);\n\t\tmPullRefreshListView.setOnPullEventListener(soundListener);\n\n\t\t// You can also just use setListAdapter(mAdapter) or\n\t\t// mPullRefreshListView.setAdapter(mAdapter)\n\t\tactualListView.setAdapter(mAdapter);\n\t}\n\n\tprivate class GetDataTask extends AsyncTask<Void, Void, String[]> {\n\n\t\t@Override\n\t\tprotected String[] doInBackground(Void... params) {\n\t\t\t// Simulates a background job.\n\t\t\ttry {\n\t\t\t\tThread.sleep(4000);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t}\n\t\t\treturn mStrings;\n\t\t}\n\n\t\t@Override\n\t\tprotected void onPostExecute(String[] result) {\n\t\t\tmListItems.addFirst(\"Added after refresh...\");\n\t\t\tmAdapter.notifyDataSetChanged();\n\n\t\t\t// Call onRefreshComplete when the list has been refreshed.\n\t\t\tmPullRefreshListView.onRefreshComplete();\n\n\t\t\tsuper.onPostExecute(result);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean onCreateOptionsMenu(Menu menu) {\n\t\tmenu.add(0, MENU_MANUAL_REFRESH, 0, \"Manual Refresh\");\n\t\tmenu.add(0, MENU_DISABLE_SCROLL, 1,\n\t\t\t\tmPullRefreshListView.isScrollingWhileRefreshingEnabled() ? \"Disable Scrolling while Refreshing\"\n\t\t\t\t\t\t: \"Enable Scrolling while Refreshing\");\n\t\tmenu.add(0, MENU_SET_MODE, 0, mPullRefreshListView.getMode() == Mode.BOTH ? \"Change to MODE_PULL_DOWN\"\n\t\t\t\t: \"Change to MODE_PULL_BOTH\");\n\t\tmenu.add(0, MENU_DEMO, 0, \"Demo\");\n\t\treturn super.onCreateOptionsMenu(menu);\n\t}\n\n\t@Override\n\tpublic void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {\n\t\tAdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;\n\n\t\tmenu.setHeaderTitle(\"Item: \" + getListView().getItemAtPosition(info.position));\n\t\tmenu.add(\"Item 1\");\n\t\tmenu.add(\"Item 2\");\n\t\tmenu.add(\"Item 3\");\n\t\tmenu.add(\"Item 4\");\n\n\t\tsuper.onCreateContextMenu(menu, v, menuInfo);\n\t}\n\n\t@Override\n\tpublic boolean onPrepareOptionsMenu(Menu menu) {\n\t\tMenuItem disableItem = menu.findItem(MENU_DISABLE_SCROLL);\n\t\tdisableItem\n\t\t\t\t.setTitle(mPullRefreshListView.isScrollingWhileRefreshingEnabled() ? \"Disable Scrolling while Refreshing\"\n\t\t\t\t\t\t: \"Enable Scrolling while Refreshing\");\n\n\t\tMenuItem setModeItem = menu.findItem(MENU_SET_MODE);\n\t\tsetModeItem.setTitle(mPullRefreshListView.getMode() == Mode.BOTH ? \"Change to MODE_FROM_START\"\n\t\t\t\t: \"Change to MODE_PULL_BOTH\");\n\n\t\treturn super.onPrepareOptionsMenu(menu);\n\t}\n\n\t@Override\n\tpublic boolean onOptionsItemSelected(MenuItem item) {\n\n\t\tswitch (item.getItemId()) {\n\t\t\tcase MENU_MANUAL_REFRESH:\n\t\t\t\tnew GetDataTask().execute();\n\t\t\t\tmPullRefreshListView.setRefreshing(false);\n\t\t\t\tbreak;\n\t\t\tcase MENU_DISABLE_SCROLL:\n\t\t\t\tmPullRefreshListView.setScrollingWhileRefreshingEnabled(!mPullRefreshListView\n\t\t\t\t\t\t.isScrollingWhileRefreshingEnabled());\n\t\t\t\tbreak;\n\t\t\tcase MENU_SET_MODE:\n\t\t\t\tmPullRefreshListView.setMode(mPullRefreshListView.getMode() == Mode.BOTH ? Mode.PULL_FROM_START\n\t\t\t\t\t\t: Mode.BOTH);\n\t\t\t\tbreak;\n\t\t\tcase MENU_DEMO:\n\t\t\t\tmPullRefreshListView.demo();\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn super.onOptionsItemSelected(item);\n\t}\n\n\tprivate String[] mStrings = { \"Abbaye de Belloc\", \"Abbaye du Mont des Cats\", \"Abertam\", \"Abondance\", \"Ackawi\",\n\t\t\t\"Acorn\", \"Adelost\", \"Affidelice au Chablis\", \"Afuega'l Pitu\", \"Airag\", \"Airedale\", \"Aisy Cendre\",\n\t\t\t\"Allgauer Emmentaler\", \"Abbaye de Belloc\", \"Abbaye du Mont des Cats\", \"Abertam\", \"Abondance\", \"Ackawi\",\n\t\t\t\"Acorn\", \"Adelost\", \"Affidelice au Chablis\", \"Afuega'l Pitu\", \"Airag\", \"Airedale\", \"Aisy Cendre\",\n\t\t\t\"Allgauer Emmentaler\" };\n}\n"
  },
  {
    "path": "sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListFragmentActivity.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.samples;\n\nimport java.util.Arrays;\nimport java.util.LinkedList;\n\nimport android.os.AsyncTask;\nimport android.os.Bundle;\nimport android.support.v4.app.FragmentActivity;\nimport android.widget.ArrayAdapter;\nimport android.widget.ListView;\n\nimport com.handmark.pulltorefresh.extras.listfragment.PullToRefreshListFragment;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;\nimport com.handmark.pulltorefresh.library.PullToRefreshListView;\n\npublic final class PullToRefreshListFragmentActivity extends FragmentActivity implements OnRefreshListener<ListView> {\n\n\tprivate LinkedList<String> mListItems;\n\tprivate ArrayAdapter<String> mAdapter;\n\n\tprivate PullToRefreshListFragment mPullRefreshListFragment;\n\tprivate PullToRefreshListView mPullRefreshListView;\n\n\t/** Called when the activity is first created. */\n\t@Override\n\tpublic void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n\t\tsetContentView(R.layout.activity_ptr_list_fragment);\n\n\t\tmPullRefreshListFragment = (PullToRefreshListFragment) getSupportFragmentManager().findFragmentById(\n\t\t\t\tR.id.frag_ptr_list);\n\n\t\t// Get PullToRefreshListView from Fragment\n\t\tmPullRefreshListView = mPullRefreshListFragment.getPullToRefreshListView();\n\n\t\t// Set a listener to be invoked when the list should be refreshed.\n\t\tmPullRefreshListView.setOnRefreshListener(this);\n\n\t\t// You can also just use mPullRefreshListFragment.getListView()\n\t\tListView actualListView = mPullRefreshListView.getRefreshableView();\n\n\t\tmListItems = new LinkedList<String>();\n\t\tmListItems.addAll(Arrays.asList(mStrings));\n\t\tmAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mListItems);\n\n\t\t// You can also just use setListAdapter(mAdapter) or\n\t\t// mPullRefreshListView.setAdapter(mAdapter)\n\t\tactualListView.setAdapter(mAdapter);\n\n\t\tmPullRefreshListFragment.setListShown(true);\n\t}\n\n\t@Override\n\tpublic void onRefresh(PullToRefreshBase<ListView> refreshView) {\n\t\t// Do work to refresh the list here.\n\t\tnew GetDataTask().execute();\n\t}\n\n\tprivate class GetDataTask extends AsyncTask<Void, Void, String[]> {\n\n\t\t@Override\n\t\tprotected String[] doInBackground(Void... params) {\n\t\t\t// Simulates a background job.\n\t\t\ttry {\n\t\t\t\tThread.sleep(4000);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t}\n\t\t\treturn mStrings;\n\t\t}\n\n\t\t@Override\n\t\tprotected void onPostExecute(String[] result) {\n\t\t\tmListItems.addFirst(\"Added after refresh...\");\n\t\t\tmAdapter.notifyDataSetChanged();\n\n\t\t\t// Call onRefreshComplete when the list has been refreshed.\n\t\t\tmPullRefreshListView.onRefreshComplete();\n\n\t\t\tsuper.onPostExecute(result);\n\t\t}\n\t}\n\n\tprivate String[] mStrings = { \"Abbaye de Belloc\", \"Abbaye du Mont des Cats\", \"Abertam\", \"Abondance\", \"Ackawi\",\n\t\t\t\"Acorn\", \"Adelost\", \"Affidelice au Chablis\", \"Afuega'l Pitu\", \"Airag\", \"Airedale\", \"Aisy Cendre\",\n\t\t\t\"Allgauer Emmentaler\", \"Abbaye de Belloc\", \"Abbaye du Mont des Cats\", \"Abertam\", \"Abondance\", \"Ackawi\",\n\t\t\t\"Acorn\", \"Adelost\", \"Affidelice au Chablis\", \"Afuega'l Pitu\", \"Airag\", \"Airedale\", \"Aisy Cendre\",\n\t\t\t\"Allgauer Emmentaler\" };\n}\n"
  },
  {
    "path": "sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListInViewPagerActivity.java",
    "content": "package com.handmark.pulltorefresh.samples;\n\nimport java.util.Arrays;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.os.AsyncTask;\nimport android.os.Bundle;\nimport android.support.v4.view.PagerAdapter;\nimport android.support.v4.view.ViewPager;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.ViewGroup.LayoutParams;\nimport android.widget.ArrayAdapter;\nimport android.widget.ListAdapter;\nimport android.widget.ListView;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshBase;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;\nimport com.handmark.pulltorefresh.library.PullToRefreshListView;\n\npublic class PullToRefreshListInViewPagerActivity extends Activity implements OnRefreshListener<ListView> {\n\n\tprivate static final String[] STRINGS = { \"Abbaye de Belloc\", \"Abbaye du Mont des Cats\", \"Abertam\", \"Abondance\",\n\t\t\t\"Ackawi\", \"Acorn\", \"Adelost\", \"Affidelice au Chablis\", \"Afuega'l Pitu\", \"Airag\", \"Airedale\", \"Aisy Cendre\",\n\t\t\t\"Allgauer Emmentaler\", \"Abbaye de Belloc\", \"Abbaye du Mont des Cats\", \"Abertam\", \"Abondance\", \"Ackawi\",\n\t\t\t\"Acorn\", \"Adelost\", \"Affidelice au Chablis\", \"Afuega'l Pitu\", \"Airag\", \"Airedale\", \"Aisy Cendre\",\n\t\t\t\"Allgauer Emmentaler\" };\n\n\tprivate ViewPager mViewPager;\n\n\t@Override\n\tprotected void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n\t\tsetContentView(R.layout.activity_ptr_list_in_vp);\n\n\t\tmViewPager = (ViewPager) findViewById(R.id.vp_list);\n\t\tmViewPager.setAdapter(new ListViewPagerAdapter());\n\t}\n\n\tprivate class ListViewPagerAdapter extends PagerAdapter {\n\n\t\t@Override\n\t\tpublic View instantiateItem(ViewGroup container, int position) {\n\t\t\tContext context = container.getContext();\n\n\t\t\tPullToRefreshListView plv = (PullToRefreshListView) LayoutInflater.from(context).inflate(\n\t\t\t\t\tR.layout.layout_listview_in_viewpager, container, false);\n\n\t\t\tListAdapter adapter = new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1,\n\t\t\t\t\tArrays.asList(STRINGS));\n\t\t\tplv.setAdapter(adapter);\n\n\t\t\tplv.setOnRefreshListener(PullToRefreshListInViewPagerActivity.this);\n\n\t\t\t// Now just add ListView to ViewPager and return it\n\t\t\tcontainer.addView(plv, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);\n\n\t\t\treturn plv;\n\t\t}\n\n\t\t@Override\n\t\tpublic void destroyItem(ViewGroup container, int position, Object object) {\n\t\t\tcontainer.removeView((View) object);\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isViewFromObject(View view, Object object) {\n\t\t\treturn view == object;\n\t\t}\n\n\t\t@Override\n\t\tpublic int getCount() {\n\t\t\treturn 3;\n\t\t}\n\n\t}\n\n\t@Override\n\tpublic void onRefresh(PullToRefreshBase<ListView> refreshView) {\n\t\tnew GetDataTask(refreshView).execute();\n\t}\n\n\tprivate static class GetDataTask extends AsyncTask<Void, Void, Void> {\n\n\t\tPullToRefreshBase<?> mRefreshedView;\n\n\t\tpublic GetDataTask(PullToRefreshBase<?> refreshedView) {\n\t\t\tmRefreshedView = refreshedView;\n\t\t}\n\n\t\t@Override\n\t\tprotected Void doInBackground(Void... params) {\n\t\t\t// Simulates a background job.\n\t\t\ttry {\n\t\t\t\tThread.sleep(4000);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tprotected void onPostExecute(Void result) {\n\t\t\tmRefreshedView.onRefreshComplete();\n\t\t\tsuper.onPostExecute(result);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "sample/src/com/handmark/pulltorefresh/samples/PullToRefreshScrollViewActivity.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.samples;\n\nimport android.app.Activity;\nimport android.os.AsyncTask;\nimport android.os.Bundle;\nimport android.widget.ScrollView;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshBase;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;\nimport com.handmark.pulltorefresh.library.PullToRefreshScrollView;\n\npublic final class PullToRefreshScrollViewActivity extends Activity {\n\n\tPullToRefreshScrollView mPullRefreshScrollView;\n\tScrollView mScrollView;\n\n\t/** Called when the activity is first created. */\n\t@Override\n\tpublic void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n\t\tsetContentView(R.layout.activity_ptr_scrollview);\n\n\t\tmPullRefreshScrollView = (PullToRefreshScrollView) findViewById(R.id.pull_refresh_scrollview);\n\t\tmPullRefreshScrollView.setOnRefreshListener(new OnRefreshListener<ScrollView>() {\n\n\t\t\t@Override\n\t\t\tpublic void onRefresh(PullToRefreshBase<ScrollView> refreshView) {\n\t\t\t\tnew GetDataTask().execute();\n\t\t\t}\n\t\t});\n\n\t\tmScrollView = mPullRefreshScrollView.getRefreshableView();\n\t}\n\n\tprivate class GetDataTask extends AsyncTask<Void, Void, String[]> {\n\n\t\t@Override\n\t\tprotected String[] doInBackground(Void... params) {\n\t\t\t// Simulates a background job.\n\t\t\ttry {\n\t\t\t\tThread.sleep(4000);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tprotected void onPostExecute(String[] result) {\n\t\t\t// Do some stuff here\n\n\t\t\t// Call onRefreshComplete when the list has been refreshed.\n\t\t\tmPullRefreshScrollView.onRefreshComplete();\n\n\t\t\tsuper.onPostExecute(result);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "sample/src/com/handmark/pulltorefresh/samples/PullToRefreshViewPagerActivity.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.samples;\n\nimport android.app.Activity;\nimport android.os.AsyncTask;\nimport android.os.Bundle;\nimport android.support.v4.view.PagerAdapter;\nimport android.support.v4.view.ViewPager;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.ViewGroup.LayoutParams;\nimport android.widget.ImageView;\n\nimport com.handmark.pulltorefresh.extras.viewpager.PullToRefreshViewPager;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;\n\npublic class PullToRefreshViewPagerActivity extends Activity implements OnRefreshListener<ViewPager> {\n\n\tprivate PullToRefreshViewPager mPullToRefreshViewPager;\n\n\t@Override\n\tpublic void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n\t\tsetContentView(R.layout.activity_ptr_viewpager);\n\n\t\tmPullToRefreshViewPager = (PullToRefreshViewPager) findViewById(R.id.pull_refresh_viewpager);\n\t\tmPullToRefreshViewPager.setOnRefreshListener(this);\n\n\t\tViewPager vp = mPullToRefreshViewPager.getRefreshableView();\n\t\tvp.setAdapter(new SamplePagerAdapter());\n\t}\n\n\t@Override\n\tpublic void onRefresh(PullToRefreshBase<ViewPager> refreshView) {\n\t\tnew GetDataTask().execute();\n\t}\n\n\tstatic class SamplePagerAdapter extends PagerAdapter {\n\n\t\tprivate static int[] sDrawables = { R.drawable.wallpaper, R.drawable.wallpaper, R.drawable.wallpaper,\n\t\t\t\tR.drawable.wallpaper, R.drawable.wallpaper, R.drawable.wallpaper };\n\n\t\t@Override\n\t\tpublic int getCount() {\n\t\t\treturn sDrawables.length;\n\t\t}\n\n\t\t@Override\n\t\tpublic View instantiateItem(ViewGroup container, int position) {\n\t\t\tImageView imageView = new ImageView(container.getContext());\n\t\t\timageView.setImageResource(sDrawables[position]);\n\n\t\t\t// Now just add ImageView to ViewPager and return it\n\t\t\tcontainer.addView(imageView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);\n\n\t\t\treturn imageView;\n\t\t}\n\n\t\t@Override\n\t\tpublic void destroyItem(ViewGroup container, int position, Object object) {\n\t\t\tcontainer.removeView((View) object);\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isViewFromObject(View view, Object object) {\n\t\t\treturn view == object;\n\t\t}\n\t}\n\n\tprivate class GetDataTask extends AsyncTask<Void, Void, Void> {\n\n\t\t@Override\n\t\tprotected Void doInBackground(Void... params) {\n\t\t\t// Simulates a background job.\n\t\t\ttry {\n\t\t\t\tThread.sleep(4000);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tprotected void onPostExecute(Void result) {\n\t\t\tmPullToRefreshViewPager.onRefreshComplete();\n\t\t\tsuper.onPostExecute(result);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "sample/src/com/handmark/pulltorefresh/samples/PullToRefreshWebView2Activity.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.samples;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android.webkit.WebView;\nimport android.webkit.WebViewClient;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshBase;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;\nimport com.handmark.pulltorefresh.library.extras.PullToRefreshWebView2;\n\npublic final class PullToRefreshWebView2Activity extends Activity implements OnRefreshListener<WebView> {\n\n\t/** Called when the activity is first created. */\n\t@Override\n\tpublic void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n\t\tsetContentView(R.layout.activity_ptr_webview2);\n\n\t\tPullToRefreshWebView2 pullRefreshWebView = (PullToRefreshWebView2) findViewById(R.id.pull_refresh_webview2);\n\t\tpullRefreshWebView.setOnRefreshListener(this);\n\n\t\tWebView webView = pullRefreshWebView.getRefreshableView();\n\t\twebView.getSettings().setJavaScriptEnabled(true);\n\t\twebView.setWebViewClient(new SampleWebViewClient());\n\n\t\t// We just load a prepared HTML page from the assets folder for this\n\t\t// sample, see that file for the Javascript implementation\n\t\twebView.loadUrl(\"file:///android_asset/ptr_webview2_sample.html\");\n\t}\n\n\tprivate static class SampleWebViewClient extends WebViewClient {\n\t\t@Override\n\t\tpublic boolean shouldOverrideUrlLoading(WebView view, String url) {\n\t\t\tview.loadUrl(url);\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onRefresh(final PullToRefreshBase<WebView> refreshView) {\n\t\t// This is very contrived example, we just wait 2 seconds, then call\n\t\t// onRefreshComplete()\n\t\trefreshView.postDelayed(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\trefreshView.onRefreshComplete();\n\t\t\t}\n\t\t}, 2 * 1000);\n\t}\n}\n"
  },
  {
    "path": "sample/src/com/handmark/pulltorefresh/samples/PullToRefreshWebViewActivity.java",
    "content": "/*******************************************************************************\n * Copyright 2011, 2012 Chris Banes.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *******************************************************************************/\npackage com.handmark.pulltorefresh.samples;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android.webkit.WebView;\nimport android.webkit.WebViewClient;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshWebView;\n\npublic final class PullToRefreshWebViewActivity extends Activity {\n\n\tPullToRefreshWebView mPullRefreshWebView;\n\tWebView mWebView;\n\n\t/** Called when the activity is first created. */\n\t@Override\n\tpublic void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n\t\tsetContentView(R.layout.activity_ptr_webview);\n\n\t\tmPullRefreshWebView = (PullToRefreshWebView) findViewById(R.id.pull_refresh_webview);\n\t\tmWebView = mPullRefreshWebView.getRefreshableView();\n\n\t\tmWebView.getSettings().setJavaScriptEnabled(true);\n\t\tmWebView.setWebViewClient(new SampleWebViewClient());\n\t\tmWebView.loadUrl(\"http://www.google.com\");\n\n\t}\n\n\tprivate static class SampleWebViewClient extends WebViewClient {\n\t\t@Override\n\t\tpublic boolean shouldOverrideUrlLoading(WebView view, String url) {\n\t\t\tview.loadUrl(url);\n\t\t\treturn true;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "sample/src/com/handmark/pulltorefresh/samples/loadinglayout/CustomLoadingLayout.java",
    "content": "/*\n * Copyright (C) 2014 Naver Business Platform Corp.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.handmark.pulltorefresh.samples.loadinglayout;\n\nimport android.R;\nimport android.content.Context;\nimport android.content.res.TypedArray;\n\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;\nimport com.handmark.pulltorefresh.library.PullToRefreshBase.Orientation;\nimport com.handmark.pulltorefresh.library.internal.FlipLoadingLayout;\n\npublic class CustomLoadingLayout extends FlipLoadingLayout {\n\n\tprivate static final float MAX_SCALE_SIZE = 3f;\n\n\tpublic CustomLoadingLayout(Context context, Mode mode, Orientation scrollDirection, TypedArray attrs) {\n\t\tsuper(context, mode, scrollDirection, attrs);\n\t}\n\n\t@Override\n\tprotected int getDefaultDrawableResId() {\n\t\t// Use the default arrow icon from android R\n\t\treturn R.drawable.arrow_down_float;\n\t}\n\n\t@Override\n\tprotected void onPullImpl(float scaleOfLayout) {\n\t\tsuper.onPullImpl(scaleOfLayout);\n\t\tint color = getHeaderTextColorBy(scaleOfLayout);\n\t\tmHeaderText.setTextColor(color);\n\t}\n\n\tprivate int getHeaderTextColorBy(float scaleOfLayout) {\n\t\t// Limit the scale size\n\t\tif ( scaleOfLayout > MAX_SCALE_SIZE ) {\n\t\t\tscaleOfLayout = MAX_SCALE_SIZE;\n\t\t}\n\t\t// Create the color code\n\t\tint alpha = (int) ((scaleOfLayout / MAX_SCALE_SIZE) * 255);\n\t\tint color = 0x00FFFFFF /* Transparent & White */ | (alpha << 24);\n\t\treturn color;\n\t}\n\n\t@Override\n\tprotected String loadPullLabel(Context context, TypedArray attrs, Mode mode) {\n\t\treturn \"Custom pull label\";\n\t}\n\n\t@Override\n\tprotected String loadRefreshingLabel(Context context, TypedArray attrs, Mode mode) {\n\t\treturn \"Custom refresh label\";\n\t}\n\n\t@Override\n\tprotected String loadReleaseLabel(Context context, TypedArray attrs, Mode mode) {\n\t\treturn \"Custom release label\";\n\t}\n\n}\n"
  },
  {
    "path": "settings.gradle",
    "content": "include 'library'\ninclude 'extras/PullToRefreshListFragment'\ninclude 'extras/PullToRefreshViewPager'\n"
  }
]