[
  {
    "path": ".gitignore",
    "content": "# Built application files\n*.apk\n*.ap_\n\n# Files for the Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated files\nbin/\ngen/\nout/\n\n# Gradle files\n.gradle/\nbuild/\n\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n# Proguard folder generated by Eclipse\nproguard/\n\n# Log Files\n*.log\n\n# Android Studio Navigation editor temp files\n.navigation/\n\n# Android Studio captures folder\ncaptures/\n\n# Intellij\n*.iml\n.idea\n# Keystore files\n*.jks"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright © 2016 ybq\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# Android-SpinKit\n>Android loading animations(I wrote a android edition according [SpinKit](https://tobiasahlin.com/spinkit))\n\n[Demo Apk](https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/spinkit.apk)\n\n## Preview\n\n<img src=\"https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/screen.gif\" width=\"240px\" height=\"240px\"/>\n\n<img src=\"https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/screen2.gif\" width=\"200px\" height=\"200px\"/>\n\n## Gradle Dependency\n\n ``` gradle\ndependencies {\n    implementation 'com.github.ybq:Android-SpinKit:1.4.0'\n }\n ```\n\n\n## Usage\n- Xml\n\n ```xml\n<com.github.ybq.android.spinkit.SpinKitView\n     xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n     android:id=\"@+id/spin_kit\"\n     style=\"@style/SpinKitView.Large.Circle\"\n     android:layout_width=\"wrap_content\"\n     android:layout_height=\"wrap_content\"\n     android:layout_gravity=\"center\"\n     app:SpinKit_Color=\"@color/colorAccent\" />         \n```\n \n- ProgressBar\n\n ```java\nProgressBar progressBar = (ProgressBar)findViewById(R.id.progress);\nSprite doubleBounce = new DoubleBounce();\nprogressBar.setIndeterminateDrawable(doubleBounce);\n```\n\n## Style\n> \n ```xml\n@style/SpinKitView\n@style/SpinKitView.Circle\n@style/SpinKitView.Large\n@style/SpinKitView.Small\n@style/SpinKitView.Small.DoubleBounce   \n ```\n\nStyle | Preview\n------------     |   -------------\nRotatingPlane    | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/RotatingPlane.gif' alt='RotatingPlane' width=\"90px\" height=\"90px\"/>\nDoubleBounce     | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/DoubleBounce.gif' alt='DoubleBounce' width=\"90px\" height=\"90px\"/>\nWave             | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/Wave.gif' alt='Wave' width=\"90px\" height=\"90px\"/>\nWanderingCubes   | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/WanderingCubes.gif' alt='WanderingCubes' width=\"90px\" height=\"90px\"/>\nPulse            | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/Pulse.gif' alt='Pulse' width=\"90px\" height=\"90px\"/>\nChasingDots      | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/ChasingDots.gif' alt='ChasingDots' width=\"90px\" height=\"90px\"/>\nThreeBounce      | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/ThreeBounce.gif' alt='ThreeBounce' width=\"90px\" height=\"90px\"/>\nCircle           | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/Circle.gif' alt='Circle' width=\"90px\" height=\"90px\"/>\nCubeGrid         | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/CubeGrid.gif' alt='CubeGrid' width=\"90px\" height=\"90px\"/>\nFadingCircle     | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/FadingCircle.gif' alt='FadingCircle' width=\"90px\" height=\"90px\"/>\nFoldingCube      | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/FoldingCube.gif' alt='FoldingCube' width=\"90px\" height=\"90px\"/>\nRotatingCircle   | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/RotatingCircle.gif' alt='RotatingCircle' width=\"90px\" height=\"90px\"/>\n\n\n\n\n\n\n\n## Acknowledgements\n- [SpinKit](https://github.com/tobiasahlin/SpinKit).\n\n\n\n"
  },
  {
    "path": "README_zh-CN.md",
    "content": "\n# Android-SpinKit\n \n> Android 加载动画([SpinKit](https://tobiasahlin.com/spinkit)的Android版本实现)\n\n[Demo Apk](https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/spinkit.apk)\n\n## 效果\n\n<img src=\"https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/screen.gif\" width=\"240px\" height=\"240px\"/>\n \n\n<img src=\"https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/screen2.gif\" width=\"200px\" height=\"200px\"/>\n\n## Gradle 依赖\n\n\n ``` gradle\ndependencies {\n    implementation 'com.github.ybq:Android-SpinKit:1.4.0'\n }\n ```\n\n\n## 使用\n- Xml\n\n ```xml\n<com.github.ybq.android.spinkit.SpinKitView\n     xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n     android:id=\"@+id/spin_kit\"\n     style=\"@style/SpinKitView.Large.Circle\"\n     android:layout_width=\"wrap_content\"\n     android:layout_height=\"wrap_content\"\n     android:layout_gravity=\"center\"\n     app:SpinKit_Color=\"@color/colorAccent\" />         \n ```\n \n \n- ProgressBar\n\n ```java\nProgressBar progressBar = (ProgressBar)findViewById(R.id.progress);\nDoubleBounce doubleBounce = new DoubleBounce();\nprogressBar.setIndeterminateDrawable(doubleBounce);\n```\n\n###样式:\n\n样式 | 预览\n------------     |   -------------\nRotatingPlane    | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/RotatingPlane.gif' alt='RotatingPlane' width=\"90px\" height=\"90px\"/>\nDoubleBounce     | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/DoubleBounce.gif' alt='DoubleBounce' width=\"90px\" height=\"90px\"/>\nWave             | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/Wave.gif' alt='Wave' width=\"90px\" height=\"90px\"/>\nWanderingCubes   | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/WanderingCubes.gif' alt='WanderingCubes' width=\"90px\" height=\"90px\"/>\nPulse            | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/Pulse.gif' alt='Pulse' width=\"90px\" height=\"90px\"/>\nChasingDots      | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/ChasingDots.gif' alt='ChasingDots' width=\"90px\" height=\"90px\"/>\nThreeBounce      | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/ThreeBounce.gif' alt='ThreeBounce' width=\"90px\" height=\"90px\"/>\nCircle           | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/Circle.gif' alt='Circle' width=\"90px\" height=\"90px\"/>\nCubeGrid         | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/CubeGrid.gif' alt='CubeGrid' width=\"90px\" height=\"90px\"/>\nFadingCircle     | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/FadingCircle.gif' alt='FadingCircle' width=\"90px\" height=\"90px\"/>\nFoldingCube      | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/FoldingCube.gif' alt='FoldingCube' width=\"90px\" height=\"90px\"/>\nRotatingCircle   | <img src='https://raw.githubusercontent.com/ybq/AndroidSpinKit/master/art/RotatingCircle.gif' alt='RotatingCircle' width=\"90px\" height=\"90px\"/>\n\n\n\n\n\n\n\n##感谢\n- [SpinKit](https://github.com/tobiasahlin/SpinKit).\n\n\n\n"
  },
  {
    "path": "build.gradle",
    "content": "buildscript {\n    repositories {\n        google()\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:3.2.1'\n        classpath 'com.novoda:bintray-release:0.8.1'\n    }\n}\n\nallprojects {\n    repositories {\n        google()\n        jcenter()\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Tue Nov 14 15:17:22 WET 2017\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-4.6-all.zip\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\n# Default value: -Xmx10248m -XX:MaxPermSize=256m\n# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\nandroid.enableJetifier=true\nandroid.useAndroidX=true"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "library/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "library/build.gradle",
    "content": "apply plugin: 'com.android.library'\napply plugin: 'com.novoda.bintray-release'\n\nandroid {\n\n    compileSdkVersion 28\n    buildToolsVersion '28.0.3'\n\n    defaultConfig {\n        minSdkVersion 14\n        targetSdkVersion 28\n    }\n\n    lintOptions {\n        abortOnError false\n    }\n}\n\n\npublish {\n    userOrg = 'ybq'\n    groupId = 'com.github.ybq'\n    artifactId = 'Android-SpinKit'\n    publishVersion = '1.4.0'\n    desc = 'Android loading animations'\n    website = 'https://github.com/ybq/Android-SpinKit'\n    licences = ['MIT']\n}"
  },
  {
    "path": "library/gradle.properties",
    "content": ""
  },
  {
    "path": "library/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /Users/ybq/Library/Android/sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\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": "library/src/main/AndroidManifest.xml",
    "content": "<manifest package=\"com.github.ybq.android.spinkit\" />\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/SpinKitView.java",
    "content": "package com.github.ybq.android.spinkit;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Color;\nimport android.graphics.drawable.Drawable;\nimport android.os.Build;\nimport android.util.AttributeSet;\nimport android.view.View;\nimport android.widget.ProgressBar;\n\nimport com.github.ybq.android.spinkit.sprite.Sprite;\n\n/**\n * Created by ybq.\n */\npublic class SpinKitView extends ProgressBar {\n\n    private Style mStyle;\n    private int mColor;\n    private Sprite mSprite;\n\n    public SpinKitView(Context context) {\n        this(context, null);\n    }\n\n    public SpinKitView(Context context, AttributeSet attrs) {\n        this(context, attrs, R.attr.SpinKitViewStyle);\n    }\n\n    public SpinKitView(Context context, AttributeSet attrs, int defStyleAttr) {\n        this(context, attrs, defStyleAttr, R.style.SpinKitView);\n    }\n\n    @TargetApi(Build.VERSION_CODES.LOLLIPOP)\n    public SpinKitView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {\n        super(context, attrs, defStyleAttr, defStyleRes);\n        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SpinKitView, defStyleAttr,\n                defStyleRes);\n        mStyle = Style.values()[a.getInt(R.styleable.SpinKitView_SpinKit_Style, 0)];\n        mColor = a.getColor(R.styleable.SpinKitView_SpinKit_Color, Color.WHITE);\n        a.recycle();\n        init();\n        setIndeterminate(true);\n    }\n\n    private void init() {\n        Sprite sprite = SpriteFactory.create(mStyle);\n        sprite.setColor(mColor);\n        setIndeterminateDrawable(sprite);\n    }\n\n    @Override\n    public void setIndeterminateDrawable(Drawable d) {\n        if (!(d instanceof Sprite)) {\n            throw new IllegalArgumentException(\"this d must be instanceof Sprite\");\n        }\n        setIndeterminateDrawable((Sprite) d);\n    }\n\n    public void setIndeterminateDrawable(Sprite d) {\n        super.setIndeterminateDrawable(d);\n        mSprite = d;\n        if (mSprite.getColor() == 0) {\n\n            mSprite.setColor(mColor);\n        }\n        onSizeChanged(getWidth(), getHeight(), getWidth(), getHeight());\n        if (getVisibility() == VISIBLE) {\n\n            mSprite.start();\n        }\n    }\n\n    @Override\n    public Sprite getIndeterminateDrawable() {\n        return mSprite;\n    }\n\n    public void setColor(int color) {\n        this.mColor = color;\n        if (mSprite != null) {\n\n            mSprite.setColor(color);\n        }\n        invalidate();\n    }\n\n    @Override\n    public void unscheduleDrawable(Drawable who) {\n        super.unscheduleDrawable(who);\n        if (who instanceof Sprite) {\n\n            ((Sprite) who).stop();\n        }\n    }\n\n    @Override\n    public void onWindowFocusChanged(boolean hasWindowFocus) {\n        super.onWindowFocusChanged(hasWindowFocus);\n        if (hasWindowFocus) {\n            if (mSprite != null && getVisibility() == VISIBLE) {\n\n                mSprite.start();\n            }\n        }\n    }\n\n    @Override\n    public void onScreenStateChanged(int screenState) {\n        super.onScreenStateChanged(screenState);\n        if (screenState == View.SCREEN_STATE_OFF) {\n\n            if (mSprite != null) {\n\n                mSprite.stop();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/SpriteFactory.java",
    "content": "package com.github.ybq.android.spinkit;\n\nimport com.github.ybq.android.spinkit.sprite.Sprite;\nimport com.github.ybq.android.spinkit.style.ChasingDots;\nimport com.github.ybq.android.spinkit.style.Circle;\nimport com.github.ybq.android.spinkit.style.CubeGrid;\nimport com.github.ybq.android.spinkit.style.DoubleBounce;\nimport com.github.ybq.android.spinkit.style.FadingCircle;\nimport com.github.ybq.android.spinkit.style.FoldingCube;\nimport com.github.ybq.android.spinkit.style.MultiplePulse;\nimport com.github.ybq.android.spinkit.style.MultiplePulseRing;\nimport com.github.ybq.android.spinkit.style.Pulse;\nimport com.github.ybq.android.spinkit.style.PulseRing;\nimport com.github.ybq.android.spinkit.style.RotatingCircle;\nimport com.github.ybq.android.spinkit.style.RotatingPlane;\nimport com.github.ybq.android.spinkit.style.ThreeBounce;\nimport com.github.ybq.android.spinkit.style.WanderingCubes;\nimport com.github.ybq.android.spinkit.style.Wave;\n\n/**\n * Created by ybq.\n */\npublic class SpriteFactory {\n\n    public static Sprite create(Style style) {\n        Sprite sprite = null;\n        switch (style) {\n            case ROTATING_PLANE:\n                sprite = new RotatingPlane();\n                break;\n            case DOUBLE_BOUNCE:\n                sprite = new DoubleBounce();\n                break;\n            case WAVE:\n                sprite = new Wave();\n                break;\n            case WANDERING_CUBES:\n                sprite = new WanderingCubes();\n                break;\n            case PULSE:\n                sprite = new Pulse();\n                break;\n            case CHASING_DOTS:\n                sprite = new ChasingDots();\n                break;\n            case THREE_BOUNCE:\n                sprite = new ThreeBounce();\n                break;\n            case CIRCLE:\n                sprite = new Circle();\n                break;\n            case CUBE_GRID:\n                sprite = new CubeGrid();\n                break;\n            case FADING_CIRCLE:\n                sprite = new FadingCircle();\n                break;\n            case FOLDING_CUBE:\n                sprite = new FoldingCube();\n                break;\n            case ROTATING_CIRCLE:\n                sprite = new RotatingCircle();\n                break;\n            case MULTIPLE_PULSE:\n                sprite = new MultiplePulse();\n                break;\n            case PULSE_RING:\n                sprite = new PulseRing();\n                break;\n            case MULTIPLE_PULSE_RING:\n                sprite = new MultiplePulseRing();\n                break;\n            default:\n                break;\n        }\n        return sprite;\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/Style.java",
    "content": "package com.github.ybq.android.spinkit;\n\n/**\n * Created by ybq.\n */\npublic enum Style {\n\n    ROTATING_PLANE(0),\n    DOUBLE_BOUNCE(1),\n    WAVE(2),\n    WANDERING_CUBES(3),\n    PULSE(4),\n    CHASING_DOTS(5),\n    THREE_BOUNCE(6),\n    CIRCLE(7),\n    CUBE_GRID(8),\n    FADING_CIRCLE(9),\n    FOLDING_CUBE(10),\n    ROTATING_CIRCLE(11),\n    MULTIPLE_PULSE(12),\n    PULSE_RING(13),\n    MULTIPLE_PULSE_RING(14);\n\n    @SuppressWarnings({\"FieldCanBeLocal\", \"unused\"})\n    private int value;\n\n    Style(int value) {\n        this.value = value;\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/animation/AnimationUtils.java",
    "content": "package com.github.ybq.android.spinkit.animation;\n\nimport android.animation.Animator;\nimport android.animation.ValueAnimator;\n\nimport com.github.ybq.android.spinkit.sprite.Sprite;\n\n/**\n * Created by ybq.\n */\npublic class AnimationUtils {\n\n    public static void start(Animator animator) {\n        if (animator != null && !animator.isStarted()) {\n            animator.start();\n        }\n    }\n\n    public static void stop(Animator animator) {\n        if (animator != null && !animator.isRunning()) {\n            animator.end();\n        }\n    }\n\n    public static void start(Sprite... sprites) {\n        for (Sprite sprite : sprites) {\n            sprite.start();\n        }\n    }\n\n    public static void stop(Sprite... sprites) {\n        for (Sprite sprite : sprites) {\n            sprite.stop();\n        }\n    }\n\n    public static boolean isRunning(Sprite... sprites) {\n        for (Sprite sprite : sprites) {\n            if (sprite.isRunning()) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    public static boolean isRunning(ValueAnimator animator) {\n        return animator != null && animator.isRunning();\n    }\n\n    public static boolean isStarted(ValueAnimator animator) {\n        return animator != null && animator.isStarted();\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/animation/FloatProperty.java",
    "content": "/*\n * Copyright (C) 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 */\npackage com.github.ybq.android.spinkit.animation;\n\nimport android.util.Property;\n\n/**\n * An implementation of {@link android.util.Property} to be used specifically with fields of type\n * <code>float</code>. This type-specific subclass enables performance benefit by allowing\n * calls to a {@link #set(Object, Float) set()} function that takes the primitive\n * <code>float</code> type and avoids autoboxing and other overhead associated with the\n * <code>Float</code> class.\n *\n * @param <T> The class on which the Property is declared.\n */\npublic abstract class FloatProperty<T> extends Property<T, Float> {\n\n    public FloatProperty(String name) {\n        super(Float.class, name);\n    }\n\n    /**\n     * A type-specific override of the {@link #set(Object, Float)} that is faster when dealing\n     * with fields of type <code>float</code>.\n     */\n    public abstract void setValue(T object, float value);\n\n    @Override\n    final public void set(T object, Float value) {\n        setValue(object, value);\n    }\n\n}"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/animation/IntProperty.java",
    "content": "/*\n * Copyright (C) 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 */\npackage com.github.ybq.android.spinkit.animation;\n\nimport android.util.Property;\n\n/**\n * An implementation of {@link android.util.Property} to be used specifically with fields of type\n * <code>int</code>. This type-specific subclass enables performance benefit by allowing\n * calls to a {@link #set(Object, Integer) set()} function that takes the primitive\n * <code>int</code> type and avoids autoboxing and other overhead associated with the\n * <code>Integer</code> class.\n *\n * @param <T> The class on which the Property is declared.\n */\npublic abstract class IntProperty<T> extends Property<T, Integer> {\n\n    public IntProperty(String name) {\n        super(Integer.class, name);\n    }\n\n    /**\n     * A type-specific override of the {@link #set(Object, Integer)} that is faster when dealing\n     * with fields of type <code>int</code>.\n     */\n    public abstract void setValue(T object, int value);\n\n    @Override\n    final public void set(T object, Integer value) {\n        setValue(object, value);\n    }\n\n}"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/animation/SpriteAnimatorBuilder.java",
    "content": "package com.github.ybq.android.spinkit.animation;\n\nimport android.animation.Keyframe;\nimport android.animation.ObjectAnimator;\nimport android.animation.PropertyValuesHolder;\nimport android.util.Log;\nimport android.util.Property;\nimport android.view.animation.Animation;\nimport android.view.animation.Interpolator;\n\nimport com.github.ybq.android.spinkit.animation.interpolator.KeyFrameInterpolator;\nimport com.github.ybq.android.spinkit.sprite.Sprite;\n\nimport java.util.HashMap;\nimport java.util.Locale;\nimport java.util.Map;\n\n/**\n * Created by ybq.\n */\npublic class SpriteAnimatorBuilder {\n\n    private static final String TAG = \"SpriteAnimatorBuilder\";\n    private Sprite sprite;\n    private Interpolator interpolator;\n    private int repeatCount = Animation.INFINITE;\n    private long duration = 2000;\n    private int startFrame = 0;\n    private Map<String, FrameData> fds = new HashMap<>();\n\n\n    class FrameData<T> {\n        public FrameData(float[] fractions, Property property, T[] values) {\n            this.fractions = fractions;\n            this.property = property;\n            this.values = values;\n        }\n\n        float[] fractions;\n        Property property;\n        T[] values;\n    }\n\n    class IntFrameData extends FrameData<Integer> {\n\n        public IntFrameData(float[] fractions, Property property, Integer[] values) {\n            super(fractions, property, values);\n        }\n    }\n\n    class FloatFrameData extends FrameData<Float> {\n\n        public FloatFrameData(float[] fractions, Property property, Float[] values) {\n            super(fractions, property, values);\n        }\n    }\n\n    public SpriteAnimatorBuilder(Sprite sprite) {\n        this.sprite = sprite;\n    }\n\n    public SpriteAnimatorBuilder scale(float fractions[], Float... scale) {\n        holder(fractions, Sprite.SCALE, scale);\n        return this;\n    }\n\n    public SpriteAnimatorBuilder alpha(float fractions[], Integer... alpha) {\n        holder(fractions, Sprite.ALPHA, alpha);\n        return this;\n    }\n\n    @SuppressWarnings(\"unused\")\n    public SpriteAnimatorBuilder scaleX(float fractions[], Float... scaleX) {\n        holder(fractions, Sprite.SCALE, scaleX);\n        return this;\n    }\n\n    public SpriteAnimatorBuilder scaleY(float fractions[], Float... scaleY) {\n        holder(fractions, Sprite.SCALE_Y, scaleY);\n        return this;\n    }\n\n    public SpriteAnimatorBuilder rotateX(float fractions[], Integer... rotateX) {\n        holder(fractions, Sprite.ROTATE_X, rotateX);\n        return this;\n    }\n\n    public SpriteAnimatorBuilder rotateY(float fractions[], Integer... rotateY) {\n        holder(fractions, Sprite.ROTATE_Y, rotateY);\n        return this;\n    }\n\n    @SuppressWarnings(\"unused\")\n    public SpriteAnimatorBuilder translateX(float fractions[], Integer... translateX) {\n        holder(fractions, Sprite.TRANSLATE_X, translateX);\n        return this;\n    }\n\n\n    @SuppressWarnings(\"unused\")\n    public SpriteAnimatorBuilder translateY(float fractions[], Integer... translateY) {\n        holder(fractions, Sprite.TRANSLATE_Y, translateY);\n        return this;\n    }\n\n\n    public SpriteAnimatorBuilder rotate(float fractions[], Integer... rotate) {\n        holder(fractions, Sprite.ROTATE, rotate);\n        return this;\n    }\n\n    public SpriteAnimatorBuilder translateXPercentage(float fractions[], Float... translateXPercentage) {\n        holder(fractions, Sprite.TRANSLATE_X_PERCENTAGE, translateXPercentage);\n        return this;\n    }\n\n    public SpriteAnimatorBuilder translateYPercentage(float[] fractions, Float... translateYPercentage) {\n        holder(fractions, Sprite.TRANSLATE_Y_PERCENTAGE, translateYPercentage);\n        return this;\n    }\n\n    private void holder(float[] fractions, Property property, Float[] values) {\n        ensurePair(fractions.length, values.length);\n        fds.put(property.getName(), new FloatFrameData(fractions, property, values));\n    }\n\n\n    private void holder(float[] fractions, Property property, Integer[] values) {\n        ensurePair(fractions.length, values.length);\n        fds.put(property.getName(), new IntFrameData(fractions, property, values));\n    }\n\n    private void ensurePair(int fractionsLength, int valuesLength) {\n        if (fractionsLength != valuesLength) {\n            throw new IllegalStateException(String.format(\n                    Locale.getDefault(),\n                    \"The fractions.length must equal values.length, \" +\n                            \"fraction.length[%d], values.length[%d]\",\n                    fractionsLength,\n                    valuesLength));\n        }\n    }\n\n\n    public SpriteAnimatorBuilder interpolator(Interpolator interpolator) {\n        this.interpolator = interpolator;\n        return this;\n    }\n\n    public SpriteAnimatorBuilder easeInOut(float... fractions) {\n        interpolator(KeyFrameInterpolator.easeInOut(\n                fractions\n        ));\n        return this;\n    }\n\n\n    public SpriteAnimatorBuilder duration(long duration) {\n        this.duration = duration;\n        return this;\n    }\n\n    @SuppressWarnings(\"unused\")\n    public SpriteAnimatorBuilder repeatCount(int repeatCount) {\n        this.repeatCount = repeatCount;\n        return this;\n    }\n\n    public SpriteAnimatorBuilder startFrame(int startFrame) {\n        if (startFrame < 0) {\n            Log.w(TAG, \"startFrame should always be non-negative\");\n            startFrame = 0;\n        }\n        this.startFrame = startFrame;\n        return this;\n    }\n\n    public ObjectAnimator build() {\n\n        PropertyValuesHolder[] holders = new PropertyValuesHolder[fds.size()];\n        int i = 0;\n        for (Map.Entry<String, FrameData> fd : fds.entrySet()) {\n            FrameData data = fd.getValue();\n            Keyframe[] keyframes = new Keyframe[data.fractions.length];\n            float[] fractions = data.fractions;\n            float startF = fractions[startFrame];\n            for (int j = startFrame; j < (startFrame + data.values.length); j++) {\n                int key = j - startFrame;\n                int vk = j % data.values.length;\n                float fraction = fractions[vk] - startF;\n                if (fraction < 0) {\n                    fraction = fractions[fractions.length - 1] + fraction;\n                }\n                if (data instanceof IntFrameData) {\n                    keyframes[key] = Keyframe.ofInt(fraction, (Integer) data.values[vk]);\n                } else if (data instanceof FloatFrameData) {\n                    keyframes[key] = Keyframe.ofFloat(fraction, (Float) data.values[vk]);\n                } else {\n                    keyframes[key] = Keyframe.ofObject(fraction, data.values[vk]);\n                }\n            }\n            holders[i] = PropertyValuesHolder.ofKeyframe(data.property, keyframes);\n            i++;\n        }\n\n        ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(sprite,\n                holders);\n        animator.setDuration(duration);\n        animator.setRepeatCount(repeatCount);\n        animator.setInterpolator(interpolator);\n        return animator;\n    }\n\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/animation/interpolator/Ease.java",
    "content": "package com.github.ybq.android.spinkit.animation.interpolator;\n\nimport android.view.animation.Interpolator;\n\n/**\n * Created by ybq.\n */\npublic class Ease {\n    public static Interpolator inOut() {\n        return PathInterpolatorCompat.create(0.42f, 0f, 0.58f, 1f);\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/animation/interpolator/KeyFrameInterpolator.java",
    "content": "package com.github.ybq.android.spinkit.animation.interpolator;\n\nimport android.animation.TimeInterpolator;\nimport android.view.animation.Interpolator;\n\n/**\n * Created by ybq.\n */\npublic class KeyFrameInterpolator implements Interpolator {\n\n    private TimeInterpolator interpolator;\n    private float[] fractions;\n\n\n    public static KeyFrameInterpolator easeInOut(float... fractions) {\n        KeyFrameInterpolator interpolator = new KeyFrameInterpolator(Ease.inOut());\n        interpolator.setFractions(fractions);\n        return interpolator;\n    }\n\n    public static KeyFrameInterpolator pathInterpolator(float controlX1, float controlY1,\n                                                        float controlX2, float controlY2,\n                                                        float... fractions) {\n        KeyFrameInterpolator interpolator = new KeyFrameInterpolator(PathInterpolatorCompat.create(controlX1, controlY1, controlX2, controlY2));\n        interpolator.setFractions(fractions);\n        return interpolator;\n    }\n\n    public KeyFrameInterpolator(TimeInterpolator interpolator, float... fractions) {\n        this.interpolator = interpolator;\n        this.fractions = fractions;\n    }\n\n    public void setFractions(float... fractions) {\n        this.fractions = fractions;\n    }\n\n    @Override\n    public float getInterpolation(float input) {\n        if (fractions.length > 1) {\n            for (int i = 0; i < fractions.length - 1; i++) {\n                float start = fractions[i];\n                float end = fractions[i + 1];\n                float duration = end - start;\n                if (input >= start && input <= end) {\n                    input = (input - start) / duration;\n                    return start + (interpolator.getInterpolation(input)\n                            * duration);\n                }\n            }\n        }\n        return interpolator.getInterpolation(input);\n    }\n}"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/animation/interpolator/PathInterpolatorCompat.java",
    "content": "/*\n * Copyright (C) 2015 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\npackage com.github.ybq.android.spinkit.animation.interpolator;\n\nimport android.graphics.Path;\nimport android.os.Build;\nimport android.view.animation.Interpolator;\n\n/**\n * Helper for creating path-based {@link Interpolator} instances. On API 21 or newer, the\n * platform implementation will be used and on older platforms a compatible alternative\n * implementation will be used.\n */\npublic class PathInterpolatorCompat {\n\n    private PathInterpolatorCompat() {\n        // prevent instantiation\n    }\n\n    /**\n     * Create an {@link Interpolator} for an arbitrary {@link Path}. The {@link Path}\n     * must begin at {@code (0, 0)} and end at {@code (1, 1)}. The x-coordinate along the\n     * {@link Path} is the input value and the output is the y coordinate of the line at that\n     * point. This means that the Path must conform to a function {@code y = f(x)}.\n     * <p>\n     * The {@link Path} must not have gaps in the x direction and must not\n     * loop back on itself such that there can be two points sharing the same x coordinate.\n     *\n     * @param path the {@link Path} to use to make the line representing the {@link Interpolator}\n     * @return the {@link Interpolator} representing the {@link Path}\n     */\n    @SuppressWarnings(\"unused\")\n    public static Interpolator create(Path path) {\n        if (Build.VERSION.SDK_INT >= 21) {\n            return PathInterpolatorCompatApi21.create(path);\n        }\n        return PathInterpolatorCompatBase.create(path);\n    }\n\n    /**\n     * Create an {@link Interpolator} for a quadratic Bezier curve. The end points\n     * {@code (0, 0)} and {@code (1, 1)} are assumed.\n     *\n     * @param controlX the x coordinate of the quadratic Bezier control point\n     * @param controlY the y coordinate of the quadratic Bezier control point\n     * @return the {@link Interpolator} representing the quadratic Bezier curve\n     */\n    @SuppressWarnings(\"unused\")\n    public static Interpolator create(float controlX, float controlY) {\n        if (Build.VERSION.SDK_INT >= 21) {\n            return PathInterpolatorCompatApi21.create(controlX, controlY);\n        }\n        return PathInterpolatorCompatBase.create(controlX, controlY);\n    }\n\n    /**\n     * Create an {@link Interpolator} for a cubic Bezier curve.  The end points\n     * {@code (0, 0)} and {@code (1, 1)} are assumed.\n     *\n     * @param controlX1 the x coordinate of the first control point of the cubic Bezier\n     * @param controlY1 the y coordinate of the first control point of the cubic Bezier\n     * @param controlX2 the x coordinate of the second control point of the cubic Bezier\n     * @param controlY2 the y coordinate of the second control point of the cubic Bezier\n     * @return the {@link Interpolator} representing the cubic Bezier curve\n     */\n    public static Interpolator create(float controlX1, float controlY1,\n                                      float controlX2, float controlY2) {\n        if (Build.VERSION.SDK_INT >= 21) {\n            return PathInterpolatorCompatApi21.create(controlX1, controlY1, controlX2, controlY2);\n        }\n        return PathInterpolatorCompatBase.create(controlX1, controlY1, controlX2, controlY2);\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/animation/interpolator/PathInterpolatorCompatApi21.java",
    "content": "/*\n * Copyright (C) 2015 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\npackage com.github.ybq.android.spinkit.animation.interpolator;\n\nimport android.annotation.TargetApi;\nimport android.graphics.Path;\nimport android.os.Build;\nimport android.view.animation.Interpolator;\nimport android.view.animation.PathInterpolator;\n\n/**\n * API 21+ implementation for path interpolator compatibility.\n */\nclass PathInterpolatorCompatApi21 {\n\n    private PathInterpolatorCompatApi21() {\n        // prevent instantiation\n    }\n\n    @TargetApi(Build.VERSION_CODES.LOLLIPOP)\n    public static Interpolator create(Path path) {\n        return new PathInterpolator(path);\n    }\n\n    @TargetApi(Build.VERSION_CODES.LOLLIPOP)\n    public static Interpolator create(float controlX, float controlY) {\n        return new PathInterpolator(controlX, controlY);\n    }\n\n    @TargetApi(Build.VERSION_CODES.LOLLIPOP)\n    public static Interpolator create(float controlX1, float controlY1,\n                                      float controlX2, float controlY2) {\n        return new PathInterpolator(controlX1, controlY1, controlX2, controlY2);\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/animation/interpolator/PathInterpolatorCompatBase.java",
    "content": "/*\n * Copyright (C) 2015 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\npackage com.github.ybq.android.spinkit.animation.interpolator;\n\nimport android.graphics.Path;\nimport android.view.animation.Interpolator;\n\n/**\n * Base implementation for path interpolator compatibility.\n */\nclass PathInterpolatorCompatBase {\n\n    private PathInterpolatorCompatBase() {\n        // prevent instantiation\n    }\n\n    public static Interpolator create(Path path) {\n        return new PathInterpolatorDonut(path);\n    }\n\n    public static Interpolator create(float controlX, float controlY) {\n        return new PathInterpolatorDonut(controlX, controlY);\n    }\n\n    public static Interpolator create(float controlX1, float controlY1,\n                                      float controlX2, float controlY2) {\n        return new PathInterpolatorDonut(controlX1, controlY1, controlX2, controlY2);\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/animation/interpolator/PathInterpolatorDonut.java",
    "content": "/*\n * Copyright (C) 2015 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 */\npackage com.github.ybq.android.spinkit.animation.interpolator;\n\nimport android.graphics.Path;\nimport android.graphics.PathMeasure;\nimport android.view.animation.Interpolator;\n\n/**\n * A path interpolator implementation compatible with API 4+.\n */\nclass PathInterpolatorDonut implements Interpolator {\n\n    /**\n     * Governs the accuracy of the approximation of the {@link Path}.\n     */\n    private static final float PRECISION = 0.002f;\n\n    private final float[] mX;\n    private final float[] mY;\n\n    public PathInterpolatorDonut(Path path) {\n        final PathMeasure pathMeasure = new PathMeasure(path, false /* forceClosed */);\n\n        final float pathLength = pathMeasure.getLength();\n        final int numPoints = (int) (pathLength / PRECISION) + 1;\n\n        mX = new float[numPoints];\n        mY = new float[numPoints];\n\n        final float[] position = new float[2];\n        for (int i = 0; i < numPoints; ++i) {\n            final float distance = (i * pathLength) / (numPoints - 1);\n            pathMeasure.getPosTan(distance, position, null /* tangent */);\n\n            mX[i] = position[0];\n            mY[i] = position[1];\n        }\n    }\n\n    public PathInterpolatorDonut(float controlX, float controlY) {\n        this(createQuad(controlX, controlY));\n    }\n\n    public PathInterpolatorDonut(float controlX1, float controlY1,\n                                 float controlX2, float controlY2) {\n        this(createCubic(controlX1, controlY1, controlX2, controlY2));\n    }\n\n    @Override\n    public float getInterpolation(float t) {\n        if (t <= 0.0f) {\n            return 0.0f;\n        } else if (t >= 1.0f) {\n            return 1.0f;\n        }\n\n        // Do a binary search for the correct x to interpolate between.\n        int startIndex = 0;\n        int endIndex = mX.length - 1;\n        while (endIndex - startIndex > 1) {\n            int midIndex = (startIndex + endIndex) / 2;\n            if (t < mX[midIndex]) {\n                endIndex = midIndex;\n            } else {\n                startIndex = midIndex;\n            }\n        }\n\n        final float xRange = mX[endIndex] - mX[startIndex];\n        if (xRange == 0) {\n            return mY[startIndex];\n        }\n\n        final float tInRange = t - mX[startIndex];\n        final float fraction = tInRange / xRange;\n\n        final float startY = mY[startIndex];\n        final float endY = mY[endIndex];\n\n        return startY + (fraction * (endY - startY));\n    }\n\n    private static Path createQuad(float controlX, float controlY) {\n        final Path path = new Path();\n        path.moveTo(0.0f, 0.0f);\n        path.quadTo(controlX, controlY, 1.0f, 1.0f);\n        return path;\n    }\n\n    private static Path createCubic(float controlX1, float controlY1,\n                                    float controlX2, float controlY2) {\n        final Path path = new Path();\n        path.moveTo(0.0f, 0.0f);\n        path.cubicTo(controlX1, controlY1, controlX2, controlY2, 1.0f, 1.0f);\n        return path;\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/sprite/CircleLayoutContainer.java",
    "content": "package com.github.ybq.android.spinkit.sprite;\n\nimport android.graphics.Canvas;\nimport android.graphics.Rect;\n\n/**\n * Created by ybq.\n */\npublic abstract class CircleLayoutContainer extends SpriteContainer {\n\n    @Override\n    public void drawChild(Canvas canvas) {\n        for (int i = 0; i < getChildCount(); i++) {\n            Sprite sprite = getChildAt(i);\n            int count = canvas.save();\n            canvas.rotate(i * 360 / getChildCount(),\n                    getBounds().centerX(),\n                    getBounds().centerY());\n            sprite.draw(canvas);\n            canvas.restoreToCount(count);\n        }\n    }\n\n    @Override\n    protected void onBoundsChange(Rect bounds) {\n        super.onBoundsChange(bounds);\n        bounds = clipSquare(bounds);\n        int radius = (int) (bounds.width() * Math.PI / 3.6f / getChildCount());\n        int left = bounds.centerX() - radius;\n        int right = bounds.centerX() + radius;\n        for (int i = 0; i < getChildCount(); i++) {\n            Sprite sprite = getChildAt(i);\n            sprite.setDrawBounds(left, bounds.top, right, bounds.top + radius * 2);\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/sprite/CircleSprite.java",
    "content": "package com.github.ybq.android.spinkit.sprite;\n\nimport android.animation.ValueAnimator;\nimport android.graphics.Canvas;\nimport android.graphics.Paint;\n\n/**\n * Created by ybq.\n */\npublic class CircleSprite extends ShapeSprite {\n\n    @Override\n    public ValueAnimator onCreateAnimation() {\n        return null;\n    }\n\n    @Override\n    public void drawShape(Canvas canvas, Paint paint) {\n        if (getDrawBounds() != null) {\n            int radius = Math.min(getDrawBounds().width(), getDrawBounds().height()) / 2;\n            canvas.drawCircle(getDrawBounds().centerX(),\n                    getDrawBounds().centerY(),\n                    radius, paint);\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/sprite/RectSprite.java",
    "content": "package com.github.ybq.android.spinkit.sprite;\n\nimport android.animation.ValueAnimator;\nimport android.graphics.Canvas;\nimport android.graphics.Paint;\n\n/**\n * Created by ybq.\n */\npublic class RectSprite extends ShapeSprite {\n    @Override\n    public ValueAnimator onCreateAnimation() {\n        return null;\n    }\n\n    @Override\n    public void drawShape(Canvas canvas, Paint paint) {\n        if (getDrawBounds() != null) {\n            canvas.drawRect(getDrawBounds(), paint);\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/sprite/RingSprite.java",
    "content": "package com.github.ybq.android.spinkit.sprite;\n\nimport android.animation.ValueAnimator;\nimport android.graphics.Canvas;\nimport android.graphics.Paint;\n\n/**\n * Created by ybq.\n */\npublic class RingSprite extends ShapeSprite {\n\n\n    @Override\n    public void drawShape(Canvas canvas, Paint paint) {\n        if (getDrawBounds() != null) {\n            paint.setStyle(Paint.Style.STROKE);\n            int radius = Math.min(getDrawBounds().width(), getDrawBounds().height()) / 2;\n            paint.setStrokeWidth(radius / 12);\n            canvas.drawCircle(getDrawBounds().centerX(),\n                    getDrawBounds().centerY(),\n                    radius, paint);\n        }\n    }\n\n    @Override\n    public ValueAnimator onCreateAnimation() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/sprite/ShapeSprite.java",
    "content": "package com.github.ybq.android.spinkit.sprite;\n\nimport android.graphics.Canvas;\nimport android.graphics.Color;\nimport android.graphics.ColorFilter;\nimport android.graphics.Paint;\n\n/**\n * Created by ybq.\n */\npublic abstract class ShapeSprite extends Sprite {\n\n    private Paint mPaint;\n    private int mUseColor;\n    private int mBaseColor;\n\n    public ShapeSprite() {\n        setColor(Color.WHITE);\n        mPaint = new Paint();\n        mPaint.setAntiAlias(true);\n        mPaint.setColor(mUseColor);\n    }\n\n    @Override\n    public void setColor(int color) {\n        mBaseColor = color;\n        updateUseColor();\n    }\n\n    @Override\n    public int getColor() {\n        return mBaseColor;\n    }\n\n    @SuppressWarnings(\"unused\")\n    public int getUseColor() {\n        return mUseColor;\n    }\n\n    @Override\n    public void setAlpha(int alpha) {\n        super.setAlpha(alpha);\n        updateUseColor();\n    }\n\n    private void updateUseColor() {\n        int alpha = getAlpha();\n        alpha += alpha >> 7;\n        final int baseAlpha = mBaseColor >>> 24;\n        final int useAlpha = baseAlpha * alpha >> 8;\n        mUseColor = (mBaseColor << 8 >>> 8) | (useAlpha << 24);\n    }\n\n    @Override\n    public void setColorFilter(ColorFilter colorFilter) {\n        mPaint.setColorFilter(colorFilter);\n    }\n\n    @Override\n    protected final void drawSelf(Canvas canvas) {\n        mPaint.setColor(mUseColor);\n        drawShape(canvas, mPaint);\n    }\n\n    public abstract void drawShape(Canvas canvas, Paint paint);\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/sprite/Sprite.java",
    "content": "package com.github.ybq.android.spinkit.sprite;\n\nimport android.animation.ValueAnimator;\nimport android.graphics.Camera;\nimport android.graphics.Canvas;\nimport android.graphics.ColorFilter;\nimport android.graphics.Matrix;\nimport android.graphics.PixelFormat;\nimport android.graphics.Rect;\nimport android.graphics.drawable.Animatable;\nimport android.graphics.drawable.Drawable;\nimport android.util.Property;\n\nimport com.github.ybq.android.spinkit.animation.AnimationUtils;\nimport com.github.ybq.android.spinkit.animation.FloatProperty;\nimport com.github.ybq.android.spinkit.animation.IntProperty;\n\n/**\n * Created by ybq.\n */\npublic abstract class Sprite extends Drawable implements\n        ValueAnimator.AnimatorUpdateListener\n        , Animatable\n        , Drawable.Callback {\n\n    private float scale = 1;\n    private float scaleX = 1;\n    private float scaleY = 1;\n    private float pivotX;\n    private float pivotY;\n    private int animationDelay;\n    private int rotateX;\n    private int rotateY;\n    private int translateX;\n    private int translateY;\n    private int rotate;\n    private float translateXPercentage;\n    private float translateYPercentage;\n    private ValueAnimator animator;\n    private int alpha = 255;\n    private static final Rect ZERO_BOUNDS_RECT = new Rect();\n    protected Rect drawBounds = ZERO_BOUNDS_RECT;\n    private Camera mCamera;\n    private Matrix mMatrix;\n\n    public Sprite() {\n        mCamera = new Camera();\n        mMatrix = new Matrix();\n    }\n\n    public abstract int getColor();\n\n    public abstract void setColor(int color);\n\n    @Override\n    public void setAlpha(int alpha) {\n        this.alpha = alpha;\n    }\n\n    @Override\n    public int getAlpha() {\n        return alpha;\n    }\n\n    @Override\n    public int getOpacity() {\n        return PixelFormat.TRANSLUCENT;\n    }\n\n    public float getTranslateXPercentage() {\n        return translateXPercentage;\n    }\n\n    public void setTranslateXPercentage(float translateXPercentage) {\n        this.translateXPercentage = translateXPercentage;\n    }\n\n    public float getTranslateYPercentage() {\n        return translateYPercentage;\n    }\n\n    public void setTranslateYPercentage(float translateYPercentage) {\n        this.translateYPercentage = translateYPercentage;\n    }\n\n    public int getTranslateX() {\n        return translateX;\n    }\n\n    public void setTranslateX(int translateX) {\n        this.translateX = translateX;\n    }\n\n    public int getTranslateY() {\n        return translateY;\n    }\n\n    public void setTranslateY(int translateY) {\n        this.translateY = translateY;\n    }\n\n    public int getRotate() {\n        return rotate;\n    }\n\n    public void setRotate(int rotate) {\n        this.rotate = rotate;\n    }\n\n    public float getScale() {\n        return scale;\n    }\n\n    public void setScale(float scale) {\n        this.scale = scale;\n        setScaleX(scale);\n        setScaleY(scale);\n    }\n\n    public float getScaleX() {\n        return scaleX;\n    }\n\n    public void setScaleX(float scaleX) {\n        this.scaleX = scaleX;\n    }\n\n    public float getScaleY() {\n        return scaleY;\n    }\n\n    public void setScaleY(float scaleY) {\n        this.scaleY = scaleY;\n    }\n\n    public int getRotateX() {\n        return rotateX;\n    }\n\n    public void setRotateX(int rotateX) {\n        this.rotateX = rotateX;\n    }\n\n    public int getRotateY() {\n        return rotateY;\n    }\n\n    public void setRotateY(int rotateY) {\n        this.rotateY = rotateY;\n    }\n\n    public float getPivotX() {\n        return pivotX;\n    }\n\n    public void setPivotX(float pivotX) {\n        this.pivotX = pivotX;\n    }\n\n    public float getPivotY() {\n        return pivotY;\n    }\n\n    public void setPivotY(float pivotY) {\n        this.pivotY = pivotY;\n    }\n\n    @SuppressWarnings(\"unused\")\n    public int getAnimationDelay() {\n        return animationDelay;\n    }\n\n    public Sprite setAnimationDelay(int animationDelay) {\n        this.animationDelay = animationDelay;\n        return this;\n    }\n\n    @Override\n    public void setColorFilter(ColorFilter colorFilter) {\n\n    }\n\n    public abstract ValueAnimator onCreateAnimation();\n\n    @Override\n    public void start() {\n        if (AnimationUtils.isStarted(animator)) {\n            return;\n        }\n\n        animator = obtainAnimation();\n        if (animator == null) {\n            return;\n        }\n\n        AnimationUtils.start(animator);\n        invalidateSelf();\n    }\n\n    public ValueAnimator obtainAnimation() {\n        if (animator == null) {\n            animator = onCreateAnimation();\n        }\n        if (animator != null) {\n            animator.addUpdateListener(this);\n            animator.setStartDelay(animationDelay);\n        }\n        return animator;\n    }\n\n    @Override\n    public void stop() {\n        if (AnimationUtils.isStarted(animator)) {\n            animator.removeAllUpdateListeners();\n            animator.end();\n            reset();\n        }\n    }\n\n    protected abstract void drawSelf(Canvas canvas);\n\n    public void reset() {\n        scale = 1;\n        rotateX = 0;\n        rotateY = 0;\n        translateX = 0;\n        translateY = 0;\n        rotate = 0;\n        translateXPercentage = 0f;\n        translateYPercentage = 0f;\n    }\n\n    @Override\n    public boolean isRunning() {\n        return AnimationUtils.isRunning(animator);\n    }\n\n    @Override\n    protected void onBoundsChange(Rect bounds) {\n        super.onBoundsChange(bounds);\n        setDrawBounds(bounds);\n    }\n\n    public void setDrawBounds(Rect drawBounds) {\n        setDrawBounds(drawBounds.left, drawBounds.top, drawBounds.right, drawBounds.bottom);\n    }\n\n    public void setDrawBounds(int left, int top, int right, int bottom) {\n        this.drawBounds = new Rect(left, top, right, bottom);\n        setPivotX(getDrawBounds().centerX());\n        setPivotY(getDrawBounds().centerY());\n    }\n\n    @Override\n    public void invalidateDrawable(Drawable who) {\n        invalidateSelf();\n    }\n\n    @Override\n    public void scheduleDrawable(Drawable who, Runnable what, long when) {\n\n    }\n\n    @Override\n    public void unscheduleDrawable(Drawable who, Runnable what) {\n\n    }\n\n    @Override\n    public void onAnimationUpdate(ValueAnimator animation) {\n        final Callback callback = getCallback();\n        if (callback != null) {\n            callback.invalidateDrawable(this);\n        }\n    }\n\n    public Rect getDrawBounds() {\n        return drawBounds;\n    }\n\n    @Override\n    public void draw(Canvas canvas) {\n        int tx = getTranslateX();\n        tx = tx == 0 ? (int) (getBounds().width() * getTranslateXPercentage()) : tx;\n        int ty = getTranslateY();\n        ty = ty == 0 ? (int) (getBounds().height() * getTranslateYPercentage()) : ty;\n        canvas.translate(tx, ty);\n        canvas.scale(getScaleX(), getScaleY(), getPivotX(), getPivotY());\n        canvas.rotate(getRotate(), getPivotX(), getPivotY());\n\n        if (getRotateX() != 0 || getRotateY() != 0) {\n            mCamera.save();\n            mCamera.rotateX(getRotateX());\n            mCamera.rotateY(getRotateY());\n            mCamera.getMatrix(mMatrix);\n            mMatrix.preTranslate(-getPivotX(), -getPivotY());\n            mMatrix.postTranslate(getPivotX(), getPivotY());\n            mCamera.restore();\n            canvas.concat(mMatrix);\n        }\n        drawSelf(canvas);\n    }\n\n    public Rect clipSquare(Rect rect) {\n        int w = rect.width();\n        int h = rect.height();\n        int min = Math.min(w, h);\n        int cx = rect.centerX();\n        int cy = rect.centerY();\n        int r = min / 2;\n        return new Rect(\n                cx - r,\n                cy - r,\n                cx + r,\n                cy + r\n        );\n    }\n\n    public static final Property<Sprite, Integer> ROTATE_X = new IntProperty<Sprite>(\"rotateX\") {\n        @Override\n        public void setValue(Sprite object, int value) {\n            object.setRotateX(value);\n        }\n\n        @Override\n        public Integer get(Sprite object) {\n            return object.getRotateX();\n        }\n    };\n\n    public static final Property<Sprite, Integer> ROTATE = new IntProperty<Sprite>(\"rotate\") {\n        @Override\n        public void setValue(Sprite object, int value) {\n            object.setRotate(value);\n        }\n\n        @Override\n        public Integer get(Sprite object) {\n            return object.getRotate();\n        }\n    };\n\n    public static final Property<Sprite, Integer> ROTATE_Y = new IntProperty<Sprite>(\"rotateY\") {\n        @Override\n        public void setValue(Sprite object, int value) {\n            object.setRotateY(value);\n        }\n\n        @Override\n        public Integer get(Sprite object) {\n            return object.getRotateY();\n        }\n    };\n\n    @SuppressWarnings(\"unused\")\n    public static final Property<Sprite, Integer> TRANSLATE_X = new IntProperty<Sprite>(\"translateX\") {\n        @Override\n        public void setValue(Sprite object, int value) {\n            object.setTranslateX(value);\n        }\n\n        @Override\n        public Integer get(Sprite object) {\n            return object.getTranslateX();\n        }\n    };\n\n    @SuppressWarnings(\"unused\")\n    public static final Property<Sprite, Integer> TRANSLATE_Y = new IntProperty<Sprite>(\"translateY\") {\n        @Override\n        public void setValue(Sprite object, int value) {\n            object.setTranslateY(value);\n        }\n\n        @Override\n        public Integer get(Sprite object) {\n            return object.getTranslateY();\n        }\n    };\n\n    public static final Property<Sprite, Float> TRANSLATE_X_PERCENTAGE = new FloatProperty<Sprite>(\"translateXPercentage\") {\n        @Override\n        public void setValue(Sprite object, float value) {\n            object.setTranslateXPercentage(value);\n        }\n\n        @Override\n        public Float get(Sprite object) {\n            return object.getTranslateXPercentage();\n        }\n    };\n\n    public static final Property<Sprite, Float> TRANSLATE_Y_PERCENTAGE = new FloatProperty<Sprite>(\"translateYPercentage\") {\n        @Override\n        public void setValue(Sprite object, float value) {\n            object.setTranslateYPercentage(value);\n        }\n\n        @Override\n        public Float get(Sprite object) {\n            return object.getTranslateYPercentage();\n        }\n    };\n\n    @SuppressWarnings(\"unused\")\n    public static final Property<Sprite, Float> SCALE_X = new FloatProperty<Sprite>(\"scaleX\") {\n        @Override\n        public void setValue(Sprite object, float value) {\n            object.setScaleX(value);\n        }\n\n        @Override\n        public Float get(Sprite object) {\n            return object.getScaleX();\n        }\n    };\n\n    public static final Property<Sprite, Float> SCALE_Y = new FloatProperty<Sprite>(\"scaleY\") {\n        @Override\n        public void setValue(Sprite object, float value) {\n            object.setScaleY(value);\n        }\n\n        @Override\n        public Float get(Sprite object) {\n            return object.getScaleY();\n        }\n    };\n\n    public static final Property<Sprite, Float> SCALE = new FloatProperty<Sprite>(\"scale\") {\n        @Override\n        public void setValue(Sprite object, float value) {\n            object.setScale(value);\n        }\n\n        @Override\n        public Float get(Sprite object) {\n            return object.getScale();\n        }\n    };\n\n    public static final Property<Sprite, Integer> ALPHA = new IntProperty<Sprite>(\"alpha\") {\n        @Override\n        public void setValue(Sprite object, int value) {\n            object.setAlpha(value);\n        }\n\n        @Override\n        public Integer get(Sprite object) {\n            return object.getAlpha();\n        }\n    };\n\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/sprite/SpriteContainer.java",
    "content": "package com.github.ybq.android.spinkit.sprite;\n\nimport android.animation.ValueAnimator;\nimport android.graphics.Canvas;\nimport android.graphics.Rect;\n\nimport com.github.ybq.android.spinkit.animation.AnimationUtils;\n\n/**\n * Created by ybq.\n */\npublic abstract class SpriteContainer extends Sprite {\n\n    private Sprite[] sprites;\n\n    private int color;\n\n    public SpriteContainer() {\n        sprites = onCreateChild();\n        initCallBack();\n        onChildCreated(sprites);\n    }\n\n    private void initCallBack() {\n        if (sprites != null) {\n            for (Sprite sprite : sprites) {\n                sprite.setCallback(this);\n            }\n        }\n    }\n\n    public void onChildCreated(Sprite... sprites) {\n\n    }\n\n    public int getChildCount() {\n        return sprites == null ? 0 : sprites.length;\n    }\n\n    public Sprite getChildAt(int index) {\n        return sprites == null ? null : sprites[index];\n    }\n\n    @Override\n    public void setColor(int color) {\n        this.color = color;\n        for (int i = 0; i < getChildCount(); i++) {\n            getChildAt(i).setColor(color);\n        }\n    }\n\n    @Override\n    public int getColor() {\n        return color;\n    }\n\n    @Override\n    public void draw(Canvas canvas) {\n        super.draw(canvas);\n        drawChild(canvas);\n    }\n\n    public void drawChild(Canvas canvas) {\n        if (sprites != null) {\n            for (Sprite sprite : sprites) {\n                int count = canvas.save();\n                sprite.draw(canvas);\n                canvas.restoreToCount(count);\n            }\n        }\n    }\n\n    @Override\n    protected void drawSelf(Canvas canvas) {\n    }\n\n    @Override\n    protected void onBoundsChange(Rect bounds) {\n        super.onBoundsChange(bounds);\n        for (Sprite sprite : sprites) {\n            sprite.setBounds(bounds);\n        }\n    }\n\n    @Override\n    public void start() {\n        super.start();\n        AnimationUtils.start(sprites);\n    }\n\n    @Override\n    public void stop() {\n        super.stop();\n        AnimationUtils.stop(sprites);\n    }\n\n    @Override\n    public boolean isRunning() {\n        return AnimationUtils.isRunning(sprites) || super.isRunning();\n    }\n\n    public abstract Sprite[] onCreateChild();\n\n    @Override\n    public ValueAnimator onCreateAnimation() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/style/ChasingDots.java",
    "content": "package com.github.ybq.android.spinkit.style;\n\nimport android.animation.ValueAnimator;\nimport android.graphics.Rect;\nimport android.os.Build;\nimport android.view.animation.LinearInterpolator;\n\nimport com.github.ybq.android.spinkit.animation.SpriteAnimatorBuilder;\nimport com.github.ybq.android.spinkit.sprite.CircleSprite;\nimport com.github.ybq.android.spinkit.sprite.Sprite;\nimport com.github.ybq.android.spinkit.sprite.SpriteContainer;\n\n/**\n * Created by ybq.\n */\npublic class ChasingDots extends SpriteContainer {\n\n    @Override\n    public Sprite[] onCreateChild() {\n        return new Sprite[]{\n                new Dot(),\n                new Dot()\n        };\n    }\n\n    @Override\n    public void onChildCreated(Sprite... sprites) {\n        super.onChildCreated(sprites);\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {\n            sprites[1].setAnimationDelay(1000);\n        } else {\n            sprites[1].setAnimationDelay(-1000);\n        }\n    }\n\n    @Override\n    public ValueAnimator onCreateAnimation() {\n        float fractions[] = new float[]{0f, 1f};\n        return new SpriteAnimatorBuilder(this).\n                rotate(fractions, 0, 360).\n                duration(2000).\n                interpolator(new LinearInterpolator()).\n                build();\n    }\n\n    @Override\n    protected void onBoundsChange(Rect bounds) {\n        super.onBoundsChange(bounds);\n        bounds = clipSquare(bounds);\n        int drawW = (int) (bounds.width() * 0.6f);\n        getChildAt(0).setDrawBounds(\n                bounds.right - drawW,\n                bounds.top,\n                bounds.right\n                , bounds.top + drawW\n        );\n        getChildAt(1).setDrawBounds(\n                bounds.right - drawW,\n                bounds.bottom - drawW,\n                bounds.right,\n                bounds.bottom\n        );\n    }\n\n    private class Dot extends CircleSprite {\n\n        Dot() {\n            setScale(0f);\n        }\n\n        @Override\n        public ValueAnimator onCreateAnimation() {\n            float fractions[] = new float[]{0f, 0.5f, 1f};\n            return new SpriteAnimatorBuilder(this).\n                    scale(fractions, 0f, 1f, 0f).\n                    duration(2000).\n                    easeInOut(fractions)\n                    .build();\n        }\n    }\n\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/style/Circle.java",
    "content": "package com.github.ybq.android.spinkit.style;\n\nimport android.animation.ValueAnimator;\nimport android.os.Build;\n\nimport com.github.ybq.android.spinkit.animation.SpriteAnimatorBuilder;\nimport com.github.ybq.android.spinkit.sprite.CircleLayoutContainer;\nimport com.github.ybq.android.spinkit.sprite.CircleSprite;\nimport com.github.ybq.android.spinkit.sprite.Sprite;\n\n/**\n * Created by ybq.\n */\npublic class Circle extends CircleLayoutContainer {\n\n    @Override\n    public Sprite[] onCreateChild() {\n        Dot[] dots = new Dot[12];\n        for (int i = 0; i < dots.length; i++) {\n            dots[i] = new Dot();\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {\n                dots[i].setAnimationDelay(1200 / 12 * i);\n            } else {\n                dots[i].setAnimationDelay(1200 / 12 * i + -1200);\n            }\n        }\n        return dots;\n    }\n\n    private class Dot extends CircleSprite {\n\n        Dot() {\n            setScale(0f);\n        }\n\n        @Override\n        public ValueAnimator onCreateAnimation() {\n            float fractions[] = new float[]{0f, 0.5f, 1f};\n            return new SpriteAnimatorBuilder(this).\n                    scale(fractions, 0f, 1f, 0f).\n                    duration(1200).\n                    easeInOut(fractions)\n                    .build();\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/style/CubeGrid.java",
    "content": "package com.github.ybq.android.spinkit.style;\n\nimport android.animation.ValueAnimator;\nimport android.graphics.Rect;\n\nimport com.github.ybq.android.spinkit.animation.SpriteAnimatorBuilder;\nimport com.github.ybq.android.spinkit.sprite.RectSprite;\nimport com.github.ybq.android.spinkit.sprite.Sprite;\nimport com.github.ybq.android.spinkit.sprite.SpriteContainer;\n\n/**\n * Created by ybq.\n */\npublic class CubeGrid extends SpriteContainer {\n\n    @Override\n    public Sprite[] onCreateChild() {\n        int delays[] = new int[]{\n                200, 300, 400\n                , 100, 200, 300\n                , 0, 100, 200\n        };\n        GridItem[] gridItems = new GridItem[9];\n        for (int i = 0; i < gridItems.length; i++) {\n            gridItems[i] = new GridItem();\n            gridItems[i].setAnimationDelay(delays[i]);\n        }\n        return gridItems;\n    }\n\n    @Override\n    protected void onBoundsChange(Rect bounds) {\n        super.onBoundsChange(bounds);\n        bounds = clipSquare(bounds);\n        int width = (int) (bounds.width() * 0.33f);\n        int height = (int) (bounds.height() * 0.33f);\n        for (int i = 0; i < getChildCount(); i++) {\n            int x = i % 3;\n            int y = i / 3;\n            int l = bounds.left + x * width;\n            int t = bounds.top + y * height;\n            Sprite sprite = getChildAt(i);\n            sprite.setDrawBounds(l, t, l + width, t + height);\n        }\n    }\n\n    private class GridItem extends RectSprite {\n        @Override\n        public ValueAnimator onCreateAnimation() {\n            float fractions[] = new float[]{0f, 0.35f, 0.7f, 1f};\n            return new SpriteAnimatorBuilder(this).\n                    scale(fractions, 1f, 0f, 1f, 1f).\n                    duration(1300).\n                    easeInOut(fractions)\n                    .build();\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/style/DoubleBounce.java",
    "content": "package com.github.ybq.android.spinkit.style;\n\nimport android.animation.ValueAnimator;\nimport android.os.Build;\n\nimport com.github.ybq.android.spinkit.animation.SpriteAnimatorBuilder;\nimport com.github.ybq.android.spinkit.sprite.CircleSprite;\nimport com.github.ybq.android.spinkit.sprite.Sprite;\nimport com.github.ybq.android.spinkit.sprite.SpriteContainer;\n\n/**\n * Created by ybq.\n */\npublic class DoubleBounce extends SpriteContainer {\n\n    @Override\n    public Sprite[] onCreateChild() {\n        return new Sprite[]{\n                new Bounce(), new Bounce()\n        };\n    }\n\n    @Override\n    public void onChildCreated(Sprite... sprites) {\n        super.onChildCreated(sprites);\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {\n            sprites[1].setAnimationDelay(1000);\n        } else {\n            sprites[1].setAnimationDelay(-1000);\n        }\n    }\n\n    private class Bounce extends CircleSprite {\n\n        Bounce() {\n            setAlpha(153);\n            setScale(0f);\n        }\n\n        @Override\n        public ValueAnimator onCreateAnimation() {\n            float fractions[] = new float[]{0f, 0.5f, 1f};\n            return new SpriteAnimatorBuilder(this).scale(fractions, 0f, 1f, 0f).\n                    duration(2000).\n                    easeInOut(fractions)\n                    .build();\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/style/FadingCircle.java",
    "content": "package com.github.ybq.android.spinkit.style;\n\nimport android.animation.ValueAnimator;\nimport android.os.Build;\n\nimport com.github.ybq.android.spinkit.animation.SpriteAnimatorBuilder;\nimport com.github.ybq.android.spinkit.sprite.CircleLayoutContainer;\nimport com.github.ybq.android.spinkit.sprite.CircleSprite;\nimport com.github.ybq.android.spinkit.sprite.Sprite;\n\n/**\n * Created by ybq.\n */\npublic class FadingCircle extends CircleLayoutContainer {\n\n    @Override\n    public Sprite[] onCreateChild() {\n        Dot[] dots = new Dot[12];\n        for (int i = 0; i < dots.length; i++) {\n            dots[i] = new Dot();\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {\n                dots[i].setAnimationDelay(1200 / 12 * i);\n            } else {\n                dots[i].setAnimationDelay(1200 / 12 * i + -1200);\n            }\n        }\n        return dots;\n    }\n\n    private class Dot extends CircleSprite {\n\n        Dot() {\n            setAlpha(0);\n        }\n\n        @Override\n        public ValueAnimator onCreateAnimation() {\n            float fractions[] = new float[]{0f, 0.39f, 0.4f, 1f};\n            return new SpriteAnimatorBuilder(this).\n                    alpha(fractions, 0, 0, 255, 0).\n                    duration(1200).\n                    easeInOut(fractions).build();\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/style/FoldingCube.java",
    "content": "package com.github.ybq.android.spinkit.style;\n\nimport android.animation.ValueAnimator;\nimport android.graphics.Canvas;\nimport android.graphics.Rect;\nimport android.os.Build;\nimport android.view.animation.LinearInterpolator;\n\nimport com.github.ybq.android.spinkit.animation.SpriteAnimatorBuilder;\nimport com.github.ybq.android.spinkit.sprite.RectSprite;\nimport com.github.ybq.android.spinkit.sprite.Sprite;\nimport com.github.ybq.android.spinkit.sprite.SpriteContainer;\n\n/**\n * Created by ybq.\n */\npublic class FoldingCube extends SpriteContainer {\n\n    @SuppressWarnings(\"FieldCanBeLocal\")\n    private boolean wrapContent = false;\n\n    @Override\n    public Sprite[] onCreateChild() {\n        Cube[] cubes\n                = new Cube[4];\n        for (int i = 0; i < cubes.length; i++) {\n            cubes[i] = new Cube();\n\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {\n                cubes[i].setAnimationDelay(300 * i);\n            } else {\n                cubes[i].setAnimationDelay(300 * i - 1200);\n            }\n        }\n        return cubes;\n    }\n\n    @Override\n    protected void onBoundsChange(Rect bounds) {\n        super.onBoundsChange(bounds);\n        bounds = clipSquare(bounds);\n        int size = Math.min(bounds.width(), bounds.height());\n        if (wrapContent) {\n            size = (int) Math.sqrt(\n                    (size\n                            * size) / 2);\n            int oW = (bounds.width() - size) / 2;\n            int oH = (bounds.height() - size) / 2;\n            bounds = new Rect(\n                    bounds.left + oW,\n                    bounds.top + oH,\n                    bounds.right - oW,\n                    bounds.bottom - oH\n            );\n        }\n\n        int px = bounds.left + size / 2 + 1;\n        int py = bounds.top + size / 2 + 1;\n        for (int i = 0; i < getChildCount(); i++) {\n            Sprite sprite = getChildAt(i);\n            sprite.setDrawBounds(\n                    bounds.left,\n                    bounds.top,\n                    px,\n                    py\n            );\n            sprite.setPivotX(sprite.getDrawBounds().right);\n            sprite.setPivotY(sprite.getDrawBounds().bottom);\n        }\n    }\n\n    @Override\n    public void drawChild(Canvas canvas) {\n\n        Rect bounds = clipSquare(getBounds());\n        for (int i = 0; i < getChildCount(); i++) {\n            int count = canvas.save();\n            canvas.rotate(45 + i * 90, bounds.centerX(), bounds.centerY());\n            Sprite sprite = getChildAt(i);\n            sprite.draw(canvas);\n            canvas.restoreToCount(count);\n        }\n    }\n\n    private class Cube extends RectSprite {\n\n        Cube() {\n            setAlpha(0);\n            setRotateX(-180);\n        }\n\n        @Override\n        public ValueAnimator onCreateAnimation() {\n            float fractions[] = new float[]{0f, 0.1f, 0.25f, 0.75f, 0.9f, 1f};\n            return new SpriteAnimatorBuilder(this).\n                    alpha(fractions, 0, 0, 255, 255, 0, 0).\n                    rotateX(fractions, -180, -180, 0, 0, 0, 0).\n                    rotateY(fractions, 0, 0, 0, 0, 180, 180).\n                    duration(2400).\n                    interpolator(new LinearInterpolator())\n                    .build();\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/style/MultiplePulse.java",
    "content": "package com.github.ybq.android.spinkit.style;\n\nimport com.github.ybq.android.spinkit.sprite.Sprite;\nimport com.github.ybq.android.spinkit.sprite.SpriteContainer;\n\n/**\n * Created by ybq.\n */\npublic class MultiplePulse extends SpriteContainer {\n    @Override\n    public Sprite[] onCreateChild() {\n        return new Sprite[]{\n                new Pulse(),\n                new Pulse(),\n                new Pulse(),\n        };\n    }\n\n    @Override\n    public void onChildCreated(Sprite... sprites) {\n        for (int i = 0; i < sprites.length; i++) {\n            sprites[i].setAnimationDelay(200 * (i + 1));\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/style/MultiplePulseRing.java",
    "content": "package com.github.ybq.android.spinkit.style;\n\nimport com.github.ybq.android.spinkit.sprite.Sprite;\nimport com.github.ybq.android.spinkit.sprite.SpriteContainer;\n\n/**\n * Created by ybq.\n */\npublic class MultiplePulseRing extends SpriteContainer {\n\n    @Override\n    public Sprite[] onCreateChild() {\n        return new Sprite[]{\n                new PulseRing(),\n                new PulseRing(),\n                new PulseRing(),\n        };\n    }\n\n    @Override\n    public void onChildCreated(Sprite... sprites) {\n        for (int i = 0; i < sprites.length; i++) {\n            sprites[i].setAnimationDelay(200 * (i + 1));\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/style/Pulse.java",
    "content": "package com.github.ybq.android.spinkit.style;\n\nimport android.animation.ValueAnimator;\n\nimport com.github.ybq.android.spinkit.animation.SpriteAnimatorBuilder;\nimport com.github.ybq.android.spinkit.sprite.CircleSprite;\n\n/**\n * Created by ybq.\n */\npublic class Pulse extends CircleSprite {\n\n    public Pulse() {\n        setScale(0f);\n    }\n\n    @Override\n    public ValueAnimator onCreateAnimation() {\n        float fractions[] = new float[]{0f, 1f};\n        return new SpriteAnimatorBuilder(this).\n                scale(fractions, 0f, 1f).\n                alpha(fractions, 255, 0).\n                duration(1000).\n                easeInOut(fractions)\n                .build();\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/style/PulseRing.java",
    "content": "package com.github.ybq.android.spinkit.style;\n\nimport android.animation.ValueAnimator;\n\nimport com.github.ybq.android.spinkit.animation.SpriteAnimatorBuilder;\nimport com.github.ybq.android.spinkit.animation.interpolator.KeyFrameInterpolator;\nimport com.github.ybq.android.spinkit.sprite.RingSprite;\n\n/**\n * Created by ybq.\n */\npublic class PulseRing extends RingSprite {\n\n    public PulseRing() {\n        setScale(0f);\n    }\n\n    @Override\n    public ValueAnimator onCreateAnimation() {\n        float fractions[] = new float[]{0f, 0.7f, 1f};\n        return new SpriteAnimatorBuilder(this).\n                scale(fractions, 0f, 1f, 1f).\n                alpha(fractions, 255, (int) (255 * 0.7), 0).\n                duration(1000).\n                interpolator(KeyFrameInterpolator.pathInterpolator(0.21f, 0.53f, 0.56f, 0.8f, fractions)).\n                build();\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/style/RotatingCircle.java",
    "content": "package com.github.ybq.android.spinkit.style;\n\nimport android.animation.ValueAnimator;\n\nimport com.github.ybq.android.spinkit.animation.SpriteAnimatorBuilder;\nimport com.github.ybq.android.spinkit.sprite.CircleSprite;\n\npublic class RotatingCircle extends CircleSprite {\n\n    @Override\n    public ValueAnimator onCreateAnimation() {\n        float fractions[] = new float[]{0f, 0.5f, 1f};\n        return new SpriteAnimatorBuilder(this).\n                rotateX(fractions, 0, -180, -180).\n                rotateY(fractions, 0, 0, -180).\n                duration(1200).\n                easeInOut(fractions)\n                .build();\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/style/RotatingPlane.java",
    "content": "package com.github.ybq.android.spinkit.style;\n\nimport android.animation.ValueAnimator;\nimport android.graphics.Rect;\n\nimport com.github.ybq.android.spinkit.animation.SpriteAnimatorBuilder;\nimport com.github.ybq.android.spinkit.sprite.RectSprite;\n\n/**\n * Created by ybq.\n */\npublic class RotatingPlane extends RectSprite {\n    @Override\n    protected void onBoundsChange(Rect bounds) {\n        setDrawBounds(clipSquare(bounds));\n    }\n\n    @Override\n    public ValueAnimator onCreateAnimation() {\n        float fractions[] = new float[]{0f, 0.5f, 1f};\n        return new SpriteAnimatorBuilder(this).\n                rotateX(fractions, 0, -180, -180).\n                rotateY(fractions, 0, 0, -180).\n                duration(1200).\n                easeInOut(fractions)\n                .build();\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/style/ThreeBounce.java",
    "content": "package com.github.ybq.android.spinkit.style;\n\nimport android.animation.ValueAnimator;\nimport android.graphics.Rect;\n\nimport com.github.ybq.android.spinkit.animation.SpriteAnimatorBuilder;\nimport com.github.ybq.android.spinkit.sprite.CircleSprite;\nimport com.github.ybq.android.spinkit.sprite.Sprite;\nimport com.github.ybq.android.spinkit.sprite.SpriteContainer;\n\n/**\n * Created by ybq.\n */\npublic class ThreeBounce extends SpriteContainer {\n\n    @Override\n    public Sprite[] onCreateChild() {\n        return new Sprite[]{\n                new Bounce(),\n                new Bounce(),\n                new Bounce()\n        };\n    }\n\n    @Override\n    public void onChildCreated(Sprite... sprites) {\n        super.onChildCreated(sprites);\n        sprites[1].setAnimationDelay(160);\n        sprites[2].setAnimationDelay(320);\n    }\n\n    @Override\n    protected void onBoundsChange(Rect bounds) {\n        super.onBoundsChange(bounds);\n        bounds = clipSquare(bounds);\n        int radius = bounds.width() / 8;\n        int top = bounds.centerY() - radius;\n        int bottom = bounds.centerY() + radius;\n\n        for (int i = 0; i < getChildCount(); i++) {\n            int left = bounds.width() * i / 3\n                    + bounds.left;\n            getChildAt(i).setDrawBounds(\n                    left, top, left + radius * 2, bottom\n            );\n        }\n    }\n\n    private class Bounce extends CircleSprite {\n\n        Bounce() {\n            setScale(0f);\n        }\n\n        @Override\n        public ValueAnimator onCreateAnimation() {\n            float fractions[] = new float[]{0f, 0.4f, 0.8f, 1f};\n            return new SpriteAnimatorBuilder(this).scale(fractions, 0f, 1f, 0f, 0f).\n                    duration(1400).\n                    easeInOut(fractions)\n                    .build();\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/style/WanderingCubes.java",
    "content": "package com.github.ybq.android.spinkit.style;\n\nimport android.animation.ValueAnimator;\nimport android.graphics.Rect;\nimport android.os.Build;\n\nimport com.github.ybq.android.spinkit.animation.SpriteAnimatorBuilder;\nimport com.github.ybq.android.spinkit.sprite.RectSprite;\nimport com.github.ybq.android.spinkit.sprite.Sprite;\nimport com.github.ybq.android.spinkit.sprite.SpriteContainer;\n\n/**\n * Created by ybq.\n */\npublic class WanderingCubes extends SpriteContainer {\n\n    @Override\n    public Sprite[] onCreateChild() {\n        return new Sprite[]{\n                new Cube(0),\n                new Cube(3)\n        };\n    }\n\n    @Override\n    public void onChildCreated(Sprite... sprites) {\n        super.onChildCreated(sprites);\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {\n            sprites[1].setAnimationDelay(-900);\n        }\n    }\n\n    @Override\n    protected void onBoundsChange(Rect bounds) {\n        bounds = clipSquare(bounds);\n        super.onBoundsChange(bounds);\n        for (int i = 0; i < getChildCount(); i++) {\n            Sprite sprite = getChildAt(i);\n            sprite.setDrawBounds(\n                    bounds.left,\n                    bounds.top,\n                    bounds.left + bounds.width() / 4,\n                    bounds.top + bounds.height() / 4\n            );\n        }\n    }\n\n    private class Cube extends RectSprite {\n        int startFrame;\n\n        public Cube(int startFrame) {\n            this.startFrame = startFrame;\n        }\n\n        @Override\n        public ValueAnimator onCreateAnimation() {\n            float fractions[] = new float[]{0f, 0.25f, 0.5f, 0.51f, 0.75f, 1f};\n            SpriteAnimatorBuilder builder = new SpriteAnimatorBuilder(this).\n                    rotate(fractions, 0, -90, -179, -180, -270, -360).\n                    translateXPercentage(fractions, 0f, 0.75f, 0.75f, 0.75f, 0f, 0f).\n                    translateYPercentage(fractions, 0f, 0f, 0.75f, 0.75f, 0.75f, 0f).\n                    scale(fractions, 1f, 0.5f, 1f, 1f, 0.5f, 1f).\n                    duration(1800).\n                    easeInOut(fractions);\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {\n                builder.\n                        startFrame(startFrame);\n            }\n            return builder.build();\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/java/com/github/ybq/android/spinkit/style/Wave.java",
    "content": "package com.github.ybq.android.spinkit.style;\n\nimport android.animation.ValueAnimator;\nimport android.graphics.Rect;\nimport android.os.Build;\n\nimport com.github.ybq.android.spinkit.animation.SpriteAnimatorBuilder;\nimport com.github.ybq.android.spinkit.sprite.RectSprite;\nimport com.github.ybq.android.spinkit.sprite.Sprite;\nimport com.github.ybq.android.spinkit.sprite.SpriteContainer;\n\n/**\n * Created by ybq.\n */\npublic class Wave extends SpriteContainer {\n\n    @Override\n    public Sprite[] onCreateChild() {\n        WaveItem[] waveItems = new WaveItem[5];\n        for (int i = 0; i < waveItems.length; i++) {\n            waveItems[i] = new WaveItem();\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {\n                waveItems[i].setAnimationDelay(600 + i * 100);\n            } else {\n                waveItems[i].setAnimationDelay(-1200 + i * 100);\n            }\n\n        }\n        return waveItems;\n    }\n\n    @Override\n    protected void onBoundsChange(Rect bounds) {\n        super.onBoundsChange(bounds);\n        bounds = clipSquare(bounds);\n        int rw = bounds.width() / getChildCount();\n        int width = bounds.width() / 5 * 3 / 5;\n        for (int i = 0; i < getChildCount(); i++) {\n            Sprite sprite = getChildAt(i);\n            int l = bounds.left + i * rw + rw / 5;\n            int r = l + width;\n            sprite.setDrawBounds(l, bounds.top, r, bounds.bottom);\n        }\n    }\n\n    private class WaveItem extends RectSprite {\n\n        WaveItem() {\n            setScaleY(0.4f);\n        }\n\n        @Override\n        public ValueAnimator onCreateAnimation() {\n            float fractions[] = new float[]{0f, 0.2f, 0.4f, 1f};\n            return new SpriteAnimatorBuilder(this).scaleY(fractions, 0.4f, 1f, 0.4f, 0.4f).\n                    duration(1200).\n                    easeInOut(fractions)\n                    .build();\n        }\n    }\n}\n"
  },
  {
    "path": "library/src/main/res/values/attrs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <attr name=\"SpinKitViewStyle\" format=\"reference\" />\n\n    <declare-styleable name=\"SpinKitView\">\n        <attr name=\"SpinKit_Style\">\n            <enum name=\"RotatingPlane\" value=\"0\" />\n            <enum name=\"DoubleBounce\" value=\"1\" />\n            <enum name=\"Wave\" value=\"2\" />\n            <enum name=\"WanderingCubes\" value=\"3\" />\n            <enum name=\"Pulse\" value=\"4\" />\n            <enum name=\"ChasingDots\" value=\"5\" />\n            <enum name=\"ThreeBounce\" value=\"6\" />\n            <enum name=\"Circle\" value=\"7\" />\n            <enum name=\"CubeGrid\" value=\"8\" />\n            <enum name=\"FadingCircle\" value=\"9\" />\n            <enum name=\"FoldingCube\" value=\"10\" />\n            <enum name=\"RotatingCircle\" value=\"11\" />\n            <enum name=\"MultiplePulse\" value=\"12\" />\n            <enum name=\"PulseRing\" value=\"13\" />\n            <enum name=\"MultiplePulseRing\" value=\"14\" />\n        </attr>\n        <attr name=\"SpinKit_Color\" format=\"color\" />\n    </declare-styleable>\n\n</resources>"
  },
  {
    "path": "library/src/main/res/values/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <style name=\"SpinKitView\">\n        <item name=\"android:indeterminateOnly\">true</item>\n        <item name=\"android:minWidth\">48dip</item>\n        <item name=\"android:maxWidth\">48dip</item>\n        <item name=\"android:minHeight\">48dip</item>\n        <item name=\"android:maxHeight\">48dip</item>\n    </style>\n\n    <style name=\"SpinKitView.ChasingDots\">\n        <item name=\"SpinKit_Style\">ChasingDots</item>\n    </style>\n\n    <style name=\"SpinKitView.Circle\">\n        <item name=\"SpinKit_Style\">Circle</item>\n    </style>\n\n    <style name=\"SpinKitView.CubeGrid\">\n        <item name=\"SpinKit_Style\">CubeGrid</item>\n    </style>\n\n    <style name=\"SpinKitView.DoubleBounce\">\n        <item name=\"SpinKit_Style\">DoubleBounce</item>\n    </style>\n\n    <style name=\"SpinKitView.FadingCircle\">\n        <item name=\"SpinKit_Style\">FadingCircle</item>\n    </style>\n\n    <style name=\"SpinKitView.FoldingCube\">\n        <item name=\"SpinKit_Style\">FoldingCube</item>\n    </style>\n\n    <style name=\"SpinKitView.Pulse\">\n        <item name=\"SpinKit_Style\">Pulse</item>\n    </style>\n\n    <style name=\"SpinKitView.RotatingPlane\">\n        <item name=\"SpinKit_Style\">RotatingPlane</item>\n    </style>\n\n    <style name=\"SpinKitView.RotatingCircle\">\n        <item name=\"SpinKit_Style\">RotatingCircle</item>\n    </style>\n\n    <style name=\"SpinKitView.ThreeBounce\">\n        <item name=\"SpinKit_Style\">ThreeBounce</item>\n    </style>\n\n    <style name=\"SpinKitView.WanderingCubes\">\n        <item name=\"SpinKit_Style\">WanderingCubes</item>\n    </style>\n\n    <style name=\"SpinKitView.Wave\">\n        <item name=\"SpinKit_Style\">Wave</item>\n    </style>\n\n    <style name=\"SpinKitView.MultiplePulse\">\n        <item name=\"SpinKit_Style\">MultiplePulse</item>\n    </style>\n\n    <style name=\"SpinKitView.PulseRing\">\n        <item name=\"SpinKit_Style\">PulseRing</item>\n    </style>\n\n    <style name=\"SpinKitView.MultiplePulseRing\">\n        <item name=\"SpinKit_Style\">MultiplePulseRing</item>\n    </style>\n\n    <style name=\"SpinKitView.Large\">\n        <item name=\"android:minWidth\">76dip</item>\n        <item name=\"android:maxWidth\">76dip</item>\n        <item name=\"android:minHeight\">76dip</item>\n        <item name=\"android:maxHeight\">76dip</item>\n    </style>\n\n    <style name=\"SpinKitView.Large.ChasingDots\">\n        <item name=\"SpinKit_Style\">ChasingDots</item>\n    </style>\n\n    <style name=\"SpinKitView.Large.Circle\">\n        <item name=\"SpinKit_Style\">Circle</item>\n    </style>\n\n    <style name=\"SpinKitView.Large.CubeGrid\">\n        <item name=\"SpinKit_Style\">CubeGrid</item>\n    </style>\n\n    <style name=\"SpinKitView.Large.DoubleBounce\">\n        <item name=\"SpinKit_Style\">DoubleBounce</item>\n    </style>\n\n    <style name=\"SpinKitView.Large.FadingCircle\">\n        <item name=\"SpinKit_Style\">FadingCircle</item>\n    </style>\n\n    <style name=\"SpinKitView.Large.FoldingCube\">\n        <item name=\"SpinKit_Style\">FoldingCube</item>\n    </style>\n\n    <style name=\"SpinKitView.Large.Pulse\">\n        <item name=\"SpinKit_Style\">Pulse</item>\n    </style>\n\n    <style name=\"SpinKitView.Large.RotatingPlane\">\n        <item name=\"SpinKit_Style\">RotatingPlane</item>\n    </style>\n\n    <style name=\"SpinKitView.Large.RotatingCircle\">\n        <item name=\"SpinKit_Style\">RotatingCircle</item>\n    </style>\n\n    <style name=\"SpinKitView.Large.ThreeBounce\">\n        <item name=\"SpinKit_Style\">ThreeBounce</item>\n    </style>\n\n    <style name=\"SpinKitView.Large.WanderingCubes\">\n        <item name=\"SpinKit_Style\">WanderingCubes</item>\n    </style>\n\n    <style name=\"SpinKitView.Large.Wave\">\n        <item name=\"SpinKit_Style\">Wave</item>\n    </style>\n\n    <style name=\"SpinKitView.Large.MultiplePulse\">\n        <item name=\"SpinKit_Style\">MultiplePulse</item>\n    </style>\n\n    <style name=\"SpinKitView.Large.PulseRing\">\n        <item name=\"SpinKit_Style\">PulseRing</item>\n    </style>\n\n    <style name=\"SpinKitView.Large.MultiplePulseRing\">\n        <item name=\"SpinKit_Style\">MultiplePulseRing</item>\n    </style>\n\n    <style name=\"SpinKitView.Small\">\n        <item name=\"android:minWidth\">16dip</item>\n        <item name=\"android:maxWidth\">16dip</item>\n        <item name=\"android:minHeight\">16dip</item>\n        <item name=\"android:maxHeight\">16dip</item>\n    </style>\n\n    <style name=\"SpinKitView.Small.ChasingDots\">\n        <item name=\"SpinKit_Style\">ChasingDots</item>\n    </style>\n\n    <style name=\"SpinKitView.Small.Circle\">\n        <item name=\"SpinKit_Style\">Circle</item>\n    </style>\n\n    <style name=\"SpinKitView.Small.CubeGrid\">\n        <item name=\"SpinKit_Style\">CubeGrid</item>\n    </style>\n\n    <style name=\"SpinKitView.Small.DoubleBounce\">\n        <item name=\"SpinKit_Style\">DoubleBounce</item>\n    </style>\n\n    <style name=\"SpinKitView.Small.FadingCircle\">\n        <item name=\"SpinKit_Style\">FadingCircle</item>\n    </style>\n\n    <style name=\"SpinKitView.Small.FoldingCube\">\n        <item name=\"SpinKit_Style\">FoldingCube</item>\n    </style>\n\n    <style name=\"SpinKitView.Small.Pulse\">\n        <item name=\"SpinKit_Style\">Pulse</item>\n    </style>\n\n    <style name=\"SpinKitView.Small.RotatingPlane\">\n        <item name=\"SpinKit_Style\">RotatingPlane</item>\n    </style>\n\n    <style name=\"SpinKitView.Small.RotatingCircle\">\n        <item name=\"SpinKit_Style\">RotatingCircle</item>\n    </style>\n\n    <style name=\"SpinKitView.Small.ThreeBounce\">\n        <item name=\"SpinKit_Style\">ThreeBounce</item>\n    </style>\n\n    <style name=\"SpinKitView.Small.WanderingCubes\">\n        <item name=\"SpinKit_Style\">WanderingCubes</item>\n    </style>\n\n    <style name=\"SpinKitView.Small.Wave\">\n        <item name=\"SpinKit_Style\">Wave</item>\n    </style>\n\n    <style name=\"SpinKitView.Small.MultiplePulse\">\n        <item name=\"SpinKit_Style\">MultiplePulse</item>\n    </style>\n\n    <style name=\"SpinKitView.Small.PulseRing\">\n        <item name=\"SpinKit_Style\">PulseRing</item>\n    </style>\n\n    <style name=\"SpinKitView.Small.MultiplePulseRing\">\n        <item name=\"SpinKit_Style\">MultiplePulseRing</item>\n    </style>\n</resources>"
  },
  {
    "path": "sample/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "sample/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n\n    compileSdkVersion 28\n    buildToolsVersion '28.0.3'\n\n    defaultConfig {\n        applicationId \"com.github.ybq.android.spinkit\"\n        minSdkVersion 14\n        targetSdkVersion 28\n        versionCode 1\n        versionName \"1.0\"\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\ndependencies {\n    implementation fileTree(include: ['*.jar'], dir: 'libs')\n    implementation 'androidx.appcompat:appcompat:1.0.0'\n    implementation 'com.google.android.material:material:1.0.0'\n    implementation project(':library')\n}\n"
  },
  {
    "path": "sample/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /Users/ybq/Library/Android/sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\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": "sample/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.github.ybq.android.loading\">\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:testOnly=\"false\"\n        android:theme=\"@style/AppTheme\">\n        <activity\n            android:name=\"com.github.ybq.android.loading.MainActivity\"\n            android:label=\"@string/app_name\"\n            android:theme=\"@style/AppTheme.NoActionBar\">\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=\"com.github.ybq.android.loading.DetailActivity\"\n            android:label=\"@string/app_name\"\n            android:theme=\"@style/AppTheme.NoActionBar\" />\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "sample/src/main/java/com/github/ybq/android/loading/ArgbEvaluator.java",
    "content": "\n/*\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\npackage com.github.ybq.android.loading;\n\nimport android.animation.TypeEvaluator;\n\n/**\n * This evaluator can be used to perform type interpolation between integer\n * values that represent ARGB colors.\n */\npublic class ArgbEvaluator implements TypeEvaluator {\n    private static final ArgbEvaluator sInstance = new ArgbEvaluator();\n\n    /**\n     * Returns an instance of <code>ArgbEvaluator</code> that may be used in\n     * {@link android.animation.ValueAnimator#setEvaluator(TypeEvaluator)}. The same instance may\n     * be used in multiple <code>Animator</code>s because it holds no state.\n     *\n     * @return An instance of <code>ArgbEvalutor</code>.\n     */\n    public static ArgbEvaluator getInstance() {\n        return sInstance;\n    }\n\n    /**\n     * This function returns the calculated in-between value for a color\n     * given integers that represent the start and end values in the four\n     * bytes of the 32-bit int. Each channel is separately linearly interpolated\n     * and the resulting calculated values are recombined into the return value.\n     *\n     * @param fraction   The fraction from the starting to the ending values\n     * @param startValue A 32-bit int value representing colors in the\n     *                   separate bytes of the parameter\n     * @param endValue   A 32-bit int value representing colors in the\n     *                   separate bytes of the parameter\n     * @return A value that is calculated to be the linearly interpolated\n     * result, derived by separating the start and end values into separate\n     * color channels and interpolating each one separately, recombining the\n     * resulting values in the same way.\n     */\n    public Object evaluate(float fraction, Object startValue, Object endValue) {\n        int startInt = (Integer) startValue;\n        int startA = (startInt >> 24) & 0xff;\n        int startR = (startInt >> 16) & 0xff;\n        int startG = (startInt >> 8) & 0xff;\n        int startB = startInt & 0xff;\n        int endInt = (Integer) endValue;\n        int endA = (endInt >> 24) & 0xff;\n        int endR = (endInt >> 16) & 0xff;\n        int endG = (endInt >> 8) & 0xff;\n        int endB = endInt & 0xff;\n        return (startA + (int) (fraction * (endA - startA))) << 24 |\n                (startR + (int) (fraction * (endR - startR))) << 16 |\n                (startG + (int) (fraction * (endG - startG))) << 8 |\n                (startB + (int) (fraction * (endB - startB)));\n    }\n}"
  },
  {
    "path": "sample/src/main/java/com/github/ybq/android/loading/Colors.java",
    "content": "package com.github.ybq.android.loading;\n\n/**\n * Created by ybq.\n */\npublic interface Colors {\n    int[] colors = new int[]{\n            0XFFD55400,\n            0XFF2B3E51,\n            0XFF00BD9C,\n            0XFF227FBB,\n            0XFF7F8C8D,\n            0XFFFFCC5C,\n            0XFFD55400,\n            0XFF1AAF5D,\n    };\n}\n"
  },
  {
    "path": "sample/src/main/java/com/github/ybq/android/loading/DetailActivity.java",
    "content": "package com.github.ybq.android.loading;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.TextView;\n\nimport com.github.ybq.android.spinkit.SpinKitView;\nimport com.github.ybq.android.spinkit.SpriteFactory;\nimport com.github.ybq.android.spinkit.Style;\nimport com.github.ybq.android.spinkit.sprite.Sprite;\n\nimport androidx.appcompat.app.AppCompatActivity;\nimport androidx.viewpager.widget.PagerAdapter;\nimport androidx.viewpager.widget.ViewPager;\n\npublic class DetailActivity extends AppCompatActivity implements Colors {\n\n    public static void start(Context context, int position) {\n        Intent intent = new Intent(context, DetailActivity.class);\n        intent.putExtra(\"position\", position);\n        context.startActivity(intent);\n    }\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_detail);\n        ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);\n        viewPager.setOffscreenPageLimit(0);\n        viewPager.setAdapter(new PagerAdapter() {\n            @Override\n            public int getCount() {\n                return Style.values().length;\n            }\n\n            @Override\n            public boolean isViewFromObject(View view, Object object) {\n                return view == object;\n            }\n\n            @Override\n            public Object instantiateItem(ViewGroup container, int position) {\n                @SuppressLint(\"InflateParams\") View view = LayoutInflater.from(container.getContext()).inflate(R.layout.item_pager, null);\n\n                SpinKitView spinKitView = (SpinKitView) view.findViewById(R.id.spin_kit);\n                TextView name = (TextView) view.findViewById(R.id.name);\n                Style style = Style.values()[position];\n                name.setText(style.name().toLowerCase());\n                Sprite drawable = SpriteFactory.create(style);\n                spinKitView.setIndeterminateDrawable(drawable);\n                container.addView(view);\n\n                return view;\n            }\n\n            @Override\n            public void destroyItem(ViewGroup container, int position, Object object) {\n                container.removeView((View) object);\n            }\n        });\n\n        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {\n            @Override\n            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {\n                int color = (int) ArgbEvaluator.getInstance().evaluate(positionOffset,\n                        colors[position % colors.length],\n                        colors[(position + 1) % colors.length]);\n                getWindow().getDecorView().setBackgroundColor(color);\n            }\n\n            @Override\n            public void onPageSelected(int position) {\n                getWindow().getDecorView().setBackgroundColor(colors[position % colors.length]);\n            }\n\n            @Override\n            public void onPageScrollStateChanged(int state) {\n\n            }\n        });\n\n        viewPager.setCurrentItem(getIntent().getIntExtra(\"position\", 0));\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/com/github/ybq/android/loading/MainActivity.java",
    "content": "package com.github.ybq.android.loading;\n\nimport android.os.Bundle;\n\nimport com.google.android.material.tabs.TabLayout;\n\nimport androidx.appcompat.app.AppCompatActivity;\nimport androidx.fragment.app.Fragment;\nimport androidx.fragment.app.FragmentPagerAdapter;\nimport androidx.viewpager.widget.ViewPager;\n\npublic class MainActivity extends AppCompatActivity {\n\n    TabLayout mTabLayout;\n    ViewPager mViewPager;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n        mTabLayout = (TabLayout) findViewById(R.id.tabs);\n        mViewPager = (ViewPager) findViewById(R.id.viewpager);\n\n        mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {\n\n            String[] titles = new String[]{\n                    \"Style\", \"Widget\"\n            };\n\n            @Override\n            public Fragment getItem(int position) {\n                if (position == 0) {\n                    return StyleFragment.newInstance();\n                } else {\n                    return WidgetFragment.newInstance();\n                }\n            }\n\n            @Override\n            public int getCount() {\n                return 2;\n            }\n\n            @Override\n            public CharSequence getPageTitle(int position) {\n                return titles[position];\n            }\n        });\n        mTabLayout.setupWithViewPager(mViewPager);\n    }\n\n}\n"
  },
  {
    "path": "sample/src/main/java/com/github/ybq/android/loading/SquareFrameLayout.java",
    "content": "package com.github.ybq.android.loading;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.os.Build;\nimport android.util.AttributeSet;\nimport android.widget.FrameLayout;\n\n/**\n * Created by ybq.\n */\npublic class SquareFrameLayout extends FrameLayout {\n    public SquareFrameLayout(Context context) {\n        super(context);\n    }\n\n    public SquareFrameLayout(Context context, AttributeSet attrs) {\n        super(context, attrs);\n    }\n\n    public SquareFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n    }\n\n    @SuppressWarnings(\"unused\")\n    @TargetApi(Build.VERSION_CODES.LOLLIPOP)\n    public SquareFrameLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {\n        super(context, attrs, defStyleAttr, defStyleRes);\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        //noinspection SuspiciousNameCombination\n        super.onMeasure(widthMeasureSpec, widthMeasureSpec);\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/com/github/ybq/android/loading/StyleFragment.java",
    "content": "package com.github.ybq.android.loading;\n\nimport android.annotation.SuppressLint;\nimport android.os.Bundle;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\n\nimport com.github.ybq.android.spinkit.SpinKitView;\nimport com.github.ybq.android.spinkit.SpriteFactory;\nimport com.github.ybq.android.spinkit.Style;\nimport com.github.ybq.android.spinkit.sprite.Sprite;\n\nimport androidx.annotation.Nullable;\nimport androidx.fragment.app.Fragment;\nimport androidx.recyclerview.widget.GridLayoutManager;\nimport androidx.recyclerview.widget.RecyclerView;\n\n/**\n * Created by ybq.\n */\npublic class StyleFragment extends Fragment implements Colors {\n\n    public static StyleFragment newInstance() {\n        return new StyleFragment();\n    }\n\n\n    @SuppressLint(\"InflateParams\")\n    @Nullable\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {\n        return inflater.inflate(R.layout.fragment_style, null);\n    }\n\n    @Override\n    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {\n        super.onViewCreated(view, savedInstanceState);\n        RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.list);\n        GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 4);\n        layoutManager.setOrientation(RecyclerView.VERTICAL);\n        recyclerView.setLayoutManager(layoutManager);\n\n        recyclerView.setAdapter(new RecyclerView.Adapter<Holder>() {\n            @Override\n            public Holder onCreateViewHolder(ViewGroup parent, int viewType) {\n                @SuppressLint(\"InflateParams\") View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_style, null);\n                return new Holder(view);\n            }\n\n            @Override\n            public void onBindViewHolder(Holder holder, int position) {\n                holder.bind(position);\n            }\n\n            @Override\n            public int getItemCount() {\n                return Style.values().length;\n            }\n        });\n    }\n\n    class Holder extends RecyclerView.ViewHolder {\n\n        SpinKitView spinKitView;\n\n        public Holder(View itemView) {\n            super(itemView);\n            spinKitView = (SpinKitView) itemView.findViewById(R.id.spin_kit);\n        }\n\n        public void bind(int position) {\n            itemView.setBackgroundColor(colors[position % colors.length]);\n            final int finalPosition = position;\n            itemView.setOnClickListener(new View.OnClickListener() {\n                @Override\n                public void onClick(View v) {\n                    DetailActivity.start(v.getContext(), finalPosition);\n                }\n            });\n            position = position % 15;\n            Style style = Style.values()[position];\n            Sprite drawable = SpriteFactory.create(style);\n            spinKitView.setIndeterminateDrawable(drawable);\n        }\n    }\n\n}\n"
  },
  {
    "path": "sample/src/main/java/com/github/ybq/android/loading/WidgetFragment.java",
    "content": "package com.github.ybq.android.loading;\n\nimport android.graphics.Color;\nimport android.os.Bundle;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.Button;\nimport android.widget.ImageView;\nimport android.widget.ProgressBar;\nimport android.widget.TextView;\n\nimport com.github.ybq.android.spinkit.style.ChasingDots;\nimport com.github.ybq.android.spinkit.style.Circle;\nimport com.github.ybq.android.spinkit.style.DoubleBounce;\nimport com.github.ybq.android.spinkit.style.Wave;\n\nimport androidx.annotation.Nullable;\nimport androidx.fragment.app.Fragment;\n\n/**\n * Created by ybq.\n */\npublic class WidgetFragment extends Fragment implements Colors {\n\n    private Wave mWaveDrawable;\n    private Circle mCircleDrawable;\n    private ChasingDots mChasingDotsDrawable;\n\n    public static WidgetFragment newInstance() {\n        return new WidgetFragment();\n    }\n\n    @Nullable\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {\n        return inflater.inflate(R.layout.fragment_widget, null);\n    }\n\n    @Override\n    public void onViewCreated(View view, Bundle savedInstanceState) {\n        super.onViewCreated(view, savedInstanceState);\n\n        //ProgressBar\n        ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.progress);\n        DoubleBounce doubleBounce = new DoubleBounce();\n        doubleBounce.setBounds(0, 0, 100, 100);\n        doubleBounce.setColor(colors[7]);\n        progressBar.setIndeterminateDrawable(doubleBounce);\n\n        //Button\n        Button button = (Button) view.findViewById(R.id.button);\n        mWaveDrawable = new Wave();\n        mWaveDrawable.setBounds(0, 0, 100, 100);\n        //noinspection deprecation\n        mWaveDrawable.setColor(getResources().getColor(R.color.colorAccent));\n        button.setCompoundDrawables(mWaveDrawable, null, null, null);\n\n        //TextView\n        TextView textView = (TextView) view.findViewById(R.id.text);\n        mCircleDrawable = new Circle();\n        mCircleDrawable.setBounds(0, 0, 100, 100);\n        mCircleDrawable.setColor(Color.WHITE);\n        textView.setCompoundDrawables(null, null, mCircleDrawable, null);\n        textView.setBackgroundColor(colors[2]);\n\n        //ImageView\n        ImageView imageView = (ImageView) view.findViewById(R.id.image);\n        mChasingDotsDrawable = new ChasingDots();\n        mChasingDotsDrawable.setColor(Color.WHITE);\n        imageView.setImageDrawable(mChasingDotsDrawable);\n        imageView.setBackgroundColor(colors[0]);\n    }\n\n    @Override\n    public void onResume() {\n        super.onResume();\n        mWaveDrawable.start();\n        mCircleDrawable.start();\n        mChasingDotsDrawable.start();\n    }\n\n    @Override\n    public void onStop() {\n        super.onStop();\n        mWaveDrawable.stop();\n        mCircleDrawable.stop();\n        mChasingDotsDrawable.stop();\n    }\n}\n"
  },
  {
    "path": "sample/src/main/res/layout/activity_detail.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    android:clipChildren=\"false\"\n    android:fitsSystemWindows=\"true\">\n\n    <androidx.viewpager.widget.ViewPager\n        android:id=\"@+id/view_pager\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:clipChildren=\"false\"\n        android:fitsSystemWindows=\"true\" />\n</FrameLayout>\n"
  },
  {
    "path": "sample/src/main/res/layout/activity_main.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:clipChildren=\"false\"\n    android:fitsSystemWindows=\"true\"\n    android:orientation=\"vertical\">\n\n    <com.google.android.material.tabs.TabLayout\n        android:id=\"@+id/tabs\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\" />\n\n    <androidx.viewpager.widget.ViewPager\n        android:id=\"@+id/viewpager\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" />\n</LinearLayout>\n"
  },
  {
    "path": "sample/src/main/res/layout/fragment_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=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:clipChildren=\"false\"\n    android:fitsSystemWindows=\"true\">\n\n    <androidx.recyclerview.widget.RecyclerView\n        android:id=\"@+id/list\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" />\n</FrameLayout>\n"
  },
  {
    "path": "sample/src/main/res/layout/fragment_widget.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    android:clipChildren=\"false\"\n    android:fitsSystemWindows=\"true\">\n\n    <ScrollView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\">\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:orientation=\"vertical\"\n            android:padding=\"16dp\">\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:gravity=\"center_vertical\"\n                android:orientation=\"horizontal\">\n\n                <TextView\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:text=\"ProgressBar\" />\n\n                <ProgressBar\n                    android:id=\"@+id/progress\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"2\"\n                    android:indeterminate=\"true\" />\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginTop=\"20dp\"\n                android:gravity=\"center_vertical\"\n                android:orientation=\"horizontal\">\n\n                <TextView\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:text=\"Button\" />\n\n                <Button\n                    android:id=\"@+id/button\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"2\"\n                    android:drawablePadding=\"10dp\"\n                    android:text=\"button\" />\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginTop=\"20dp\"\n                android:gravity=\"center_vertical\"\n                android:orientation=\"horizontal\">\n\n                <TextView\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:text=\"TextView\" />\n\n                <TextView\n                    android:id=\"@+id/text\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"2\"\n                    android:drawablePadding=\"10dp\"\n                    android:gravity=\"center\"\n                    android:padding=\"10dp\"\n                    android:text=\"TextView\" />\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:layout_marginTop=\"20dp\"\n                android:gravity=\"center_vertical\"\n                android:orientation=\"horizontal\">\n\n                <TextView\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:text=\"ImageView\" />\n\n                <ImageView\n                    android:id=\"@+id/image\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"100dp\"\n                    android:layout_marginTop=\"10dp\"\n                    android:layout_weight=\"2\"\n                    android:gravity=\"center\"\n                    android:padding=\"10dp\" />\n\n            </LinearLayout>\n\n        </LinearLayout>\n\n    </ScrollView>\n\n</FrameLayout>\n"
  },
  {
    "path": "sample/src/main/res/layout/item_pager.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    android:clipChildren=\"false\"\n    android:fitsSystemWindows=\"true\"\n    android:orientation=\"vertical\">\n\n    <com.github.ybq.android.spinkit.SpinKitView\n        android:id=\"@+id/spin_kit\"\n        style=\"@style/SpinKitView.Large\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:fitsSystemWindows=\"true\"\n        android:indeterminate=\"true\" />\n\n    <TextView\n        android:id=\"@+id/name\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"bottom|center_horizontal\"\n        android:layout_marginBottom=\"20dp\"\n        android:textColor=\"@android:color/white\"\n        android:textSize=\"24sp\" />\n</FrameLayout>"
  },
  {
    "path": "sample/src/main/res/layout/item_style.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.github.ybq.android.loading.SquareFrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:clipChildren=\"false\"\n    android:orientation=\"vertical\">\n\n    <com.github.ybq.android.spinkit.SpinKitView\n        android:id=\"@+id/spin_kit\"\n        style=\"@style/SpinKitView\"\n        android:background=\"?selectableItemBackgroundBorderless\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:padding=\"10dp\" />\n\n</com.github.ybq.android.loading.SquareFrameLayout>"
  },
  {
    "path": "sample/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#00000000</color>\n    <color name=\"colorPrimaryDark\">#00000000</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "sample/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n    <dimen name=\"fab_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "sample/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">SpinKit</string>\n</resources>\n"
  },
  {
    "path": "sample/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n    <style name=\"AppTheme.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n    </style>\n\n    <style name=\"AppTheme.AppBarOverlay\" parent=\"ThemeOverlay.AppCompat.Dark.ActionBar\" />\n\n    <style name=\"AppTheme.PopupOverlay\" parent=\"ThemeOverlay.AppCompat.Light\" />\n\n</resources>\n"
  },
  {
    "path": "sample/src/main/res/values-v21/styles.xml",
    "content": "<resources>>\n\n    <style name=\"AppTheme.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n        <item name=\"android:windowTranslucentStatus\">true</item>\n        <item name=\"android:windowTranslucentNavigation\">true</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':sample', ':library'\n\n"
  }
]