├── .idea ├── .name ├── vcs.xml ├── modules.xml ├── runConfigurations.xml ├── compiler.xml ├── gradle.xml └── misc.xml ├── sample ├── .gitignore ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── src │ └── main │ │ ├── res │ │ ├── drawable-hdpi │ │ │ ├── stark_icon.png │ │ │ ├── house_stark.png │ │ │ ├── barratheon_icon.png │ │ │ ├── house_lannister.png │ │ │ ├── lannister_icon.png │ │ │ ├── house_barratheon.png │ │ │ ├── ic_create_white_18dp.png │ │ │ ├── ic_link_white_18dp.png │ │ │ ├── ic_reply_white_18dp.png │ │ │ └── ic_android_white_18dp.png │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ ├── drawable-mdpi │ │ │ ├── ic_create_white_18dp.png │ │ │ ├── ic_link_white_18dp.png │ │ │ ├── ic_reply_white_18dp.png │ │ │ └── ic_android_white_18dp.png │ │ ├── drawable-xhdpi │ │ │ ├── ic_link_white_18dp.png │ │ │ ├── ic_reply_white_18dp.png │ │ │ ├── ic_android_white_18dp.png │ │ │ └── ic_create_white_18dp.png │ │ ├── drawable-xxhdpi │ │ │ ├── ic_link_white_18dp.png │ │ │ ├── ic_create_white_18dp.png │ │ │ ├── ic_reply_white_18dp.png │ │ │ └── ic_android_white_18dp.png │ │ ├── values │ │ │ ├── dimens.xml │ │ │ ├── styles.xml │ │ │ └── strings.xml │ │ ├── menu │ │ │ └── menu_main.xml │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ └── layout │ │ │ └── activity_main.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── snow │ │ └── skittlessample │ │ ├── SkittleSample.java │ │ └── MainActivity3.java ├── proguard-rules.pro ├── build.gradle ├── gradlew.bat └── gradlew ├── package-list ├── skittles ├── .gitignore ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── src │ └── main │ │ ├── res │ │ ├── drawable-hdpi │ │ │ └── ic_add_white_18dp.png │ │ ├── drawable-mdpi │ │ │ └── ic_add_white_18dp.png │ │ ├── drawable-xhdpi │ │ │ └── ic_add_white_18dp.png │ │ ├── values │ │ │ ├── public.xml │ │ │ ├── attrs.xml │ │ │ ├── styles.xml │ │ │ └── dimens.xml │ │ ├── drawable-xxhdpi │ │ │ └── ic_add_white_18dp.png │ │ ├── values-v21 │ │ │ └── dimens.xml │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ └── layout │ │ │ ├── skittle_container.xml │ │ │ ├── main_skittle.xml │ │ │ ├── skittle.xml │ │ │ └── text_skittle.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── snow │ │ └── skittles │ │ ├── Constants.java │ │ ├── SkittleType.java │ │ ├── BaseSkittle.java │ │ ├── Skittle.java │ │ ├── SkittleBuilder_Factory.java │ │ ├── TextSkittle.java │ │ ├── SkittleBuilder.java │ │ ├── ItemAnimator.java │ │ ├── SkittleLayout.java │ │ ├── SkittleContainer.java │ │ └── SkittleAdapter.java ├── proguard-rules.pro ├── build.gradle ├── gradlew.bat └── gradlew ├── settings.gradle ├── art ├── Sample1.png ├── Sample2.png ├── Sample3.png ├── Skittle.gif ├── Snackbar.gif ├── TextSkittle.gif ├── SnackbarDismiss.gif └── Taste the rainbow.jpg ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── .travis.yml ├── gradle.properties ├── LICENSE ├── gradlew.bat ├── Readme.md └── gradlew /.idea/.name: -------------------------------------------------------------------------------- 1 | Skittles -------------------------------------------------------------------------------- /sample/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /package-list: -------------------------------------------------------------------------------- 1 | snow.skittles 2 | -------------------------------------------------------------------------------- /skittles/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':skittles', ':sample' 2 | -------------------------------------------------------------------------------- /art/Sample1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/art/Sample1.png -------------------------------------------------------------------------------- /art/Sample2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/art/Sample2.png -------------------------------------------------------------------------------- /art/Sample3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/art/Sample3.png -------------------------------------------------------------------------------- /art/Skittle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/art/Skittle.gif -------------------------------------------------------------------------------- /art/Snackbar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/art/Snackbar.gif -------------------------------------------------------------------------------- /art/TextSkittle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/art/TextSkittle.gif -------------------------------------------------------------------------------- /art/SnackbarDismiss.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/art/SnackbarDismiss.gif -------------------------------------------------------------------------------- /art/Taste the rainbow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/art/Taste the rainbow.jpg -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /sample/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /skittles/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/skittles/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/stark_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-hdpi/stark_icon.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/house_stark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-hdpi/house_stark.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/barratheon_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-hdpi/barratheon_icon.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/house_lannister.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-hdpi/house_lannister.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/lannister_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-hdpi/lannister_icon.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/house_barratheon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-hdpi/house_barratheon.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/ic_create_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-hdpi/ic_create_white_18dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/ic_link_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-hdpi/ic_link_white_18dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/ic_reply_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-hdpi/ic_reply_white_18dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-mdpi/ic_create_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-mdpi/ic_create_white_18dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-mdpi/ic_link_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-mdpi/ic_link_white_18dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-mdpi/ic_reply_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-mdpi/ic_reply_white_18dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_link_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-xhdpi/ic_link_white_18dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_reply_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-xhdpi/ic_reply_white_18dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxhdpi/ic_link_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-xxhdpi/ic_link_white_18dp.png -------------------------------------------------------------------------------- /skittles/src/main/res/drawable-hdpi/ic_add_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/skittles/src/main/res/drawable-hdpi/ic_add_white_18dp.png -------------------------------------------------------------------------------- /skittles/src/main/res/drawable-mdpi/ic_add_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/skittles/src/main/res/drawable-mdpi/ic_add_white_18dp.png -------------------------------------------------------------------------------- /skittles/src/main/res/drawable-xhdpi/ic_add_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/skittles/src/main/res/drawable-xhdpi/ic_add_white_18dp.png -------------------------------------------------------------------------------- /skittles/src/main/res/values/public.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/ic_android_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-hdpi/ic_android_white_18dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-mdpi/ic_android_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-mdpi/ic_android_white_18dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_android_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-xhdpi/ic_android_white_18dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_create_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-xhdpi/ic_create_white_18dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxhdpi/ic_create_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-xxhdpi/ic_create_white_18dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxhdpi/ic_reply_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-xxhdpi/ic_reply_white_18dp.png -------------------------------------------------------------------------------- /skittles/src/main/res/drawable-xxhdpi/ic_add_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/skittles/src/main/res/drawable-xxhdpi/ic_add_white_18dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxhdpi/ic_android_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aashrai/Skittles/HEAD/sample/src/main/res/drawable-xxhdpi/ic_android_white_18dp.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .gradle/ 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | *.iml 10 | 11 | generateJavadocs.sh 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /skittles/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Jan 19 09:21:50 IST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip 7 | -------------------------------------------------------------------------------- /sample/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Jul 25 20:23:33 IST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-bin.zip 7 | -------------------------------------------------------------------------------- /skittles/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Jul 25 20:23:33 IST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-bin.zip 7 | -------------------------------------------------------------------------------- /skittles/src/main/java/snow/skittles/Constants.java: -------------------------------------------------------------------------------- 1 | package snow.skittles; 2 | 3 | /** 4 | * Created by aashrai on 2/2/16. 5 | */ 6 | public class Constants { 7 | 8 | static final int MAIN_SKITTLE = 0; 9 | static final int SKITTLE = 1; 10 | static final int TEXT_SKITTLE = 2; 11 | } 12 | -------------------------------------------------------------------------------- /skittles/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /sample/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | 256dp 7 | 8 | -------------------------------------------------------------------------------- /skittles/src/main/res/values-v21/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | 94dp 7 | 8dp 8 | -------------------------------------------------------------------------------- /skittles/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /sample/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /sample/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /skittles/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /skittles/src/main/java/snow/skittles/SkittleType.java: -------------------------------------------------------------------------------- 1 | package snow.skittles; 2 | 3 | import android.support.annotation.IntDef; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | 7 | /** 8 | * Created by aashrai on 2/2/16. 9 | */ 10 | @IntDef({ Constants.MAIN_SKITTLE, Constants.SKITTLE, Constants.TEXT_SKITTLE }) 11 | @Retention(RetentionPolicy.SOURCE) @interface SkittleType { 12 | } 13 | -------------------------------------------------------------------------------- /skittles/src/main/java/snow/skittles/BaseSkittle.java: -------------------------------------------------------------------------------- 1 | package snow.skittles; 2 | 3 | import android.graphics.drawable.Drawable; 4 | import android.support.annotation.ColorInt; 5 | 6 | /** 7 | * A contract to be implemented by a Skittle class 8 | */ 9 | public interface BaseSkittle { 10 | 11 | void setIconDrawable(Drawable drawable); 12 | 13 | Drawable getIcon(); 14 | 15 | void setColor(@ColorInt int color); 16 | 17 | @ColorInt int getColor(); 18 | 19 | @SkittleType int getType(); 20 | } 21 | -------------------------------------------------------------------------------- /skittles/src/main/res/layout/skittle_container.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /skittles/src/main/res/layout/main_skittle.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 16 | -------------------------------------------------------------------------------- /skittles/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 0.1dp 3 | 0.1dp 4 | 8dp 5 | 6 | 8dp 7 | 70dp 8 | 0dp 9 | 10 | 5dp 11 | 14sp 12 | 10dp 13 | 14 | 56dp 15 | 40dp 16 | 1500dp 17 | 18 | -------------------------------------------------------------------------------- /sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /sample/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/aashrai/Documents/android-studio-sdk/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /skittles/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/aashrai/Documents/android-studio-sdk/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /skittles/src/main/res/layout/skittle.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 18 | -------------------------------------------------------------------------------- /sample/src/main/java/snow/skittlessample/SkittleSample.java: -------------------------------------------------------------------------------- 1 | package snow.skittlessample; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | import com.squareup.leakcanary.LeakCanary; 7 | import com.squareup.leakcanary.RefWatcher; 8 | 9 | /** 10 | * Created by aashrai on 21/8/15. 11 | */ 12 | public class SkittleSample extends Application{ 13 | 14 | private RefWatcher refWatcher; 15 | 16 | @Override 17 | public void onCreate() { 18 | super.onCreate(); 19 | refWatcher=LeakCanary.install(this); 20 | } 21 | 22 | public static RefWatcher getRefWatcher(Context context){ 23 | SkittleSample application= (SkittleSample) context.getApplicationContext(); 24 | return application.refWatcher; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /sample/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 19 | 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: android 4 | 5 | android: 6 | components: 7 | - platform-tools 8 | - tools 9 | - android-23 10 | - build-tools-23.0.2 11 | - extra-android-m2repository 12 | - extra-google-m2repository 13 | - extra-android-support 14 | - extra-google-google_play_services 15 | - sys-img-armeabi-v7a-android-21 16 | licenses: 17 | - '.+' 18 | 19 | before_script: 20 | - echo no | android create avd --force -n test -t android-21 --abi armeabi-v7a 21 | - emulator -avd test -no-skin -no-audio -no-window & 22 | - android-wait-for-emulator 23 | - adb shell input keyevent 82 24 | 25 | notifications: 26 | email: true 27 | 28 | before_cache: 29 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock 30 | 31 | 32 | install: 33 | # Prevent `gradle assemble` from being invoked by overriding with no-op 34 | - true 35 | 36 | script: 37 | - ./gradlew build -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 24 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 aashrai ravooru 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /skittles/src/main/res/layout/text_skittle.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 19 | 20 | 28 | -------------------------------------------------------------------------------- /skittles/src/main/java/snow/skittles/Skittle.java: -------------------------------------------------------------------------------- 1 | package snow.skittles; 2 | 3 | import android.graphics.drawable.Drawable; 4 | import android.support.annotation.ColorInt; 5 | 6 | /** 7 | * Created by aashrai on 2/2/16. 8 | */ 9 | public class Skittle implements BaseSkittle { 10 | private @ColorInt int color; 11 | private Drawable drawable; 12 | private final @SkittleType int type; 13 | 14 | private Skittle(@ColorInt int color, Drawable drawable, int type) { 15 | this.color = color; 16 | this.drawable = drawable; 17 | this.type = type; 18 | } 19 | 20 | public static Skittle newInstance(@ColorInt int color, Drawable drawable) { 21 | return new Skittle(color, drawable, Constants.SKITTLE); 22 | } 23 | 24 | static Skittle newMainSkittleInstance(@ColorInt int color, Drawable drawable) { 25 | return new Skittle(color, drawable, Constants.MAIN_SKITTLE); 26 | } 27 | 28 | @Override public void setIconDrawable(Drawable drawable) { 29 | this.drawable = drawable; 30 | } 31 | 32 | @Override public Drawable getIcon() { 33 | return drawable; 34 | } 35 | 36 | @Override public void setColor(@ColorInt int color) { 37 | this.color = color; 38 | } 39 | 40 | @Override @ColorInt public int getColor() { 41 | return color; 42 | } 43 | 44 | @Override public int getType() { 45 | return type; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /skittles/src/main/java/snow/skittles/SkittleBuilder_Factory.java: -------------------------------------------------------------------------------- 1 | package snow.skittles; 2 | 3 | import android.graphics.drawable.Drawable; 4 | import android.support.annotation.ColorInt; 5 | import android.support.annotation.IntRange; 6 | import android.support.annotation.NonNull; 7 | 8 | /** 9 | * Created by aashrai on 3/2/16. 10 | */ 11 | public interface SkittleBuilder_Factory { 12 | 13 | /** 14 | * Add skittle at the top 15 | * 16 | * @param skittle Skittle to be added, you can pass {@link Skittle} 17 | * or {@link TextSkittle} 18 | */ 19 | void addSkittle(@NonNull BaseSkittle skittle); 20 | 21 | /** 22 | * Removes the skittle at the given index 23 | *
24 | * NOTE: this does not and cannot remove the main Skittle" 25 | * 26 | * @param index the index starts from 0 and does not include the main skittle 27 | * @return The removed skittle 28 | */ 29 | BaseSkittle removeSkittle(@IntRange(from = 0) int index); 30 | 31 | void changeMainSkittleColor(@ColorInt int color); 32 | 33 | void changeMainSkittleIcon(@NonNull Drawable drawable); 34 | 35 | /** 36 | * Replace the Skittle at the given index 37 | * 38 | * @param index index to change the Skittle at 39 | * @param skittle new skittle to be replaced with the current one, you can pass {@link Skittle} 40 | * or {@link TextSkittle} 41 | * @throws IndexOutOfBoundsException 42 | */ 43 | void changeSkittleAt(@IntRange(from = 0) int index, @NonNull BaseSkittle skittle); 44 | } 45 | -------------------------------------------------------------------------------- /sample/src/main/java/snow/skittlessample/MainActivity3.java: -------------------------------------------------------------------------------- 1 | package snow.skittlessample; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.v4.content.ContextCompat; 7 | import android.support.v7.app.AppCompatActivity; 8 | import snow.skittles.BaseSkittle; 9 | import snow.skittles.Skittle; 10 | import snow.skittles.SkittleBuilder; 11 | import snow.skittles.SkittleLayout; 12 | import snow.skittles.TextSkittle; 13 | 14 | /** 15 | * Created by aashrai on 3/2/16. 16 | */ 17 | public class MainActivity3 extends AppCompatActivity 18 | implements SkittleBuilder.OnSkittleClickListener { 19 | 20 | @Override protected void onCreate(@Nullable Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_main); 23 | final SkittleBuilder skittleBuilder = 24 | SkittleBuilder.newInstance((SkittleLayout) findViewById(R.id.skittleLayout), false); 25 | 26 | skittleBuilder.addSkittle(Skittle.newInstance(ContextCompat.getColor(this, R.color.barratheon), 27 | ContextCompat.getDrawable(this, R.drawable.barratheon_icon))); 28 | 29 | skittleBuilder.addSkittle( 30 | new TextSkittle.Builder("Hello", ContextCompat.getColor(this, R.color.stark), 31 | ContextCompat.getDrawable(this, R.drawable.stark_icon)).setTextBackground( 32 | ContextCompat.getColor(this, android.R.color.background_light)).build()); 33 | 34 | skittleBuilder.addSkittle(Skittle.newInstance(ContextCompat.getColor(this, R.color.lannister), 35 | ContextCompat.getDrawable(this, R.drawable.lannister_icon))); 36 | skittleBuilder.setSkittleClickListener(this); 37 | } 38 | 39 | @Override public void onSkittleClick(BaseSkittle skittle, int position) { 40 | Snackbar.make(findViewById(R.id.skittle_container), "This is a snackbar", Snackbar.LENGTH_SHORT) 41 | .show(); 42 | } 43 | 44 | @Override public void onMainSkittleClick() { 45 | } 46 | } -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | def isTravis = "true".equals(System.getenv("TRAVIS")) 4 | def preDexEnabled = "true".equals(System.getProperty("pre-dex", "true")) 5 | 6 | android { 7 | compileSdkVersion 23 8 | buildToolsVersion "23.0.2" 9 | 10 | dexOptions { 11 | // Skip pre-dexing when running on Travis CI or when disabled via -Dpre-dex=false. 12 | preDexLibraries = preDexEnabled && !isTravis 13 | } 14 | 15 | defaultConfig { 16 | applicationId "snow.skittlessample" 17 | minSdkVersion 14 18 | targetSdkVersion 23 19 | versionCode 1 20 | versionName "1.0" 21 | } 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | productFlavors { 29 | dev { 30 | minSdkVersion 23 31 | } 32 | } 33 | 34 | defaultConfig { 35 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 36 | } 37 | 38 | 39 | packagingOptions { 40 | exclude 'LICENSE.txt' 41 | exclude 'META-INF/LICENSE' 42 | exclude 'META-INF/LICENSE.txt' 43 | exclude 'NOTICE.txt' 44 | exclude 'META-INF/NOTICE' 45 | exclude 'META-INF/NOTICE.txt' 46 | } 47 | 48 | lintOptions { 49 | abortOnError false 50 | } 51 | 52 | compileOptions { 53 | sourceCompatibility JavaVersion.VERSION_1_7 54 | targetCompatibility JavaVersion.VERSION_1_7 55 | } 56 | } 57 | 58 | dependencies { 59 | compile 'com.android.support:cardview-v7:23.1.1' 60 | compile 'com.android.support:design:23.1.1' 61 | compile project(":skittles") 62 | 63 | debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' 64 | releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' 65 | 66 | androidTestCompile('com.android.support.test:runner:0.4.1') { 67 | exclude group: 'com.android.support', module: 'support-annotations' 68 | } 69 | androidTestCompile('com.android.support.test:rules:0.4.1') { 70 | exclude group: 'com.android.support', module: 'support-annotations' 71 | } 72 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.1') { 73 | exclude group: 'com.android.support', module: 'support-annotations' 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /skittles/src/main/java/snow/skittles/TextSkittle.java: -------------------------------------------------------------------------------- 1 | package snow.skittles; 2 | 3 | import android.graphics.Color; 4 | import android.graphics.drawable.Drawable; 5 | import android.support.annotation.ColorInt; 6 | 7 | /** 8 | * Created by aashrai on 2/2/16. 9 | */ 10 | public class TextSkittle implements BaseSkittle { 11 | 12 | private String text; 13 | private @ColorInt int color; 14 | private Drawable icon; 15 | private @ColorInt int textBackground; 16 | private @ColorInt int textColor; 17 | 18 | private TextSkittle(String text, int color, Drawable drawable, int textBackground, 19 | int textColor) { 20 | this.text = text; 21 | this.color = color; 22 | this.icon = drawable; 23 | this.textBackground = textBackground; 24 | this.textColor = textColor; 25 | } 26 | 27 | public static class Builder { 28 | private final String text; 29 | private final @ColorInt int color; 30 | private final Drawable icon; 31 | private @ColorInt int textBackground; 32 | private @ColorInt int textColor; 33 | 34 | public Builder(String text, int color, Drawable drawable) { 35 | this.text = text; 36 | this.color = color; 37 | icon = drawable; 38 | textBackground = Color.parseColor("#ffffff"); 39 | textColor = Color.parseColor("#000000"); 40 | } 41 | 42 | public Builder setTextBackground(@ColorInt int textBackground) { 43 | this.textBackground = textBackground; 44 | return this; 45 | } 46 | 47 | public Builder setTextColor(@ColorInt int textColor) { 48 | this.textColor = textColor; 49 | return this; 50 | } 51 | 52 | public TextSkittle build() { 53 | return new TextSkittle(text, color, icon, textBackground, textColor); 54 | } 55 | } 56 | 57 | public @ColorInt int getTextColor() { 58 | return textColor; 59 | } 60 | 61 | @Override public void setIconDrawable(Drawable drawable) { 62 | this.icon = drawable; 63 | } 64 | 65 | @Override public Drawable getIcon() { 66 | return icon; 67 | } 68 | 69 | @Override public void setColor(@ColorInt int color) { 70 | this.color = color; 71 | } 72 | 73 | @Override public int getColor() { 74 | return color; 75 | } 76 | 77 | @Override public int getType() { 78 | return Constants.TEXT_SKITTLE; 79 | } 80 | 81 | public int getTextBackground() { 82 | return textBackground; 83 | } 84 | 85 | public String getText() { 86 | return text; 87 | } 88 | 89 | public void setText(String text) { 90 | this.text = text; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /skittles/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | ext { 4 | bintrayRepo = 'maven' 5 | bintrayName = 'Skittles' 6 | 7 | publishedGroupId = 'com.rlj.library' 8 | libraryName = 'Skittles' 9 | artifact = 'skittles' 10 | 11 | libraryDescription = 'A simple,clean api for adding PushBullet style skittles ' + 12 | 'to your app for more material design glory.This library uses the ' + 13 | 'FloatingActionButton provided in the android design support library' 14 | 15 | siteUrl = 'https://github.com/aashrairavooru/Skittles' 16 | gitUrl = 'https://github.com/aashrairavooru/Skittles.git' 17 | 18 | libraryVersion = '4.1.1' 19 | 20 | developerId = 'aashrairavooru' 21 | developerName = 'Aashrai Ravooru' 22 | developerEmail = 'ashrair@gmail.com' 23 | 24 | licenseName = 'The Apache Software License, Version 2.0' 25 | licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt' 26 | allLicenses = ["Apache-2.0"] 27 | } 28 | 29 | def isTravis = "true".equals(System.getenv("TRAVIS")) 30 | def preDexEnabled = "true".equals(System.getProperty("pre-dex", "true")) 31 | 32 | android { 33 | compileSdkVersion 23 34 | buildToolsVersion "23.0.2" 35 | 36 | dexOptions { 37 | // Skip pre-dexing when running on Travis CI or when disabled via -Dpre-dex=false. 38 | preDexLibraries = preDexEnabled && !isTravis 39 | } 40 | 41 | defaultConfig { 42 | minSdkVersion 14 43 | targetSdkVersion 23 44 | versionCode 1 45 | versionName "$libraryVersion" 46 | } 47 | buildTypes { 48 | release { 49 | minifyEnabled false 50 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 51 | } 52 | } 53 | 54 | packagingOptions { 55 | exclude 'LICENSE.txt' 56 | exclude 'META-INF/LICENSE' 57 | exclude 'META-INF/LICENSE.txt' 58 | } 59 | 60 | lintOptions { 61 | abortOnError false 62 | } 63 | compileOptions { 64 | sourceCompatibility JavaVersion.VERSION_1_7 65 | targetCompatibility JavaVersion.VERSION_1_7 66 | } 67 | } 68 | 69 | if (!isTravis) { 70 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle' 71 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle' 72 | } 73 | 74 | ext { 75 | supportLibVersion = "23.1.1" 76 | } 77 | 78 | dependencies { 79 | compile fileTree(include: ['*.jar'], dir: 'libs') 80 | compile "com.android.support:design:$supportLibVersion" 81 | compile "com.android.support:recyclerview-v7:$supportLibVersion" 82 | compile "com.android.support:support-annotations:$supportLibVersion" 83 | } 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /sample/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /skittles/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /skittles/src/main/java/snow/skittles/SkittleBuilder.java: -------------------------------------------------------------------------------- 1 | package snow.skittles; 2 | 3 | import android.graphics.drawable.Drawable; 4 | import android.support.annotation.ColorInt; 5 | import android.support.annotation.IntRange; 6 | import android.support.annotation.NonNull; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * Created by aashrai on 3/2/16. 12 | */ 13 | public class SkittleBuilder 14 | implements SkittleBuilder_Factory, SkittleAdapter.OnSkittleClickListener, 15 | SkittleLayout.OnSkittleContainerClickListener { 16 | 17 | private final SkittleAdapter skittleAdapter; 18 | private final SkittleContainer skittleContainer; 19 | private final List skittles; 20 | private final boolean closeOnTap; 21 | boolean miniSkittlesAdded = false; 22 | OnSkittleClickListener skittleClickListener; 23 | 24 | public interface OnSkittleClickListener { 25 | void onSkittleClick(BaseSkittle skittle, int position); 26 | 27 | void onMainSkittleClick(); 28 | } 29 | 30 | private SkittleBuilder(SkittleLayout skittleLayout, boolean closeOnTap) { 31 | this.closeOnTap = closeOnTap; 32 | this.skittleAdapter = skittleLayout.getSkittleAdapter(); 33 | this.skittleAdapter.setMainSkittleClickListener(this); 34 | this.skittleContainer = skittleLayout.getSkittleContainer(); 35 | skittleLayout.setSkittleContainerClickListener(this); 36 | skittles = new ArrayList<>(); 37 | } 38 | 39 | /** 40 | * Returns a new instance of {@link SkittleBuilder} 41 | * 42 | * @param skittleLayout The root container of your layouts 43 | * @param closeOnTap Should the skittle menu be closed on tap or other touch events on the screen 44 | */ 45 | public static SkittleBuilder newInstance(SkittleLayout skittleLayout, boolean closeOnTap) { 46 | return new SkittleBuilder(skittleLayout, closeOnTap); 47 | } 48 | 49 | @Override public void addSkittle(@NonNull BaseSkittle skittle) { 50 | skittles.add(skittle); 51 | } 52 | 53 | @Override public BaseSkittle removeSkittle(@IntRange(from = 0) int index) { 54 | return skittleAdapter.removeSkittle(index + 1);//Adding 1 to prevent removal of main skittle 55 | } 56 | 57 | @Override public void changeMainSkittleColor(@ColorInt int color) { 58 | skittleAdapter.changeMainSkittleColor(color); 59 | } 60 | 61 | @Override public void changeMainSkittleIcon(@NonNull Drawable drawable) { 62 | skittleAdapter.changeMainSkittleIcon(drawable); 63 | } 64 | 65 | @Override 66 | public void changeSkittleAt(@IntRange(from = 0) int index, @NonNull BaseSkittle skittle) { 67 | skittleAdapter.changeSkittleAt(index + 1, skittle);//Adding 1 to account for main skittle 68 | } 69 | 70 | private void onMainSkittleClick() { 71 | if (!miniSkittlesAdded) { 72 | skittleAdapter.addAllSkittles(skittles); 73 | } else { 74 | skittleAdapter.removeAllMiniSkittles(); 75 | } 76 | miniSkittlesAdded = !miniSkittlesAdded; 77 | skittleContainer.setSkittlesAdded(closeOnTap && miniSkittlesAdded); 78 | if (skittleClickListener != null) skittleClickListener.onMainSkittleClick(); 79 | } 80 | 81 | public void setSkittleClickListener(OnSkittleClickListener skittleClickListener) { 82 | this.skittleClickListener = skittleClickListener; 83 | } 84 | 85 | @Override public void onSkittleClick(BaseSkittle skittle, int position) { 86 | if (position == 0) { 87 | onMainSkittleClick(); 88 | } else { 89 | //Subtract the position to make it start from the first mini skittle instead of the main skittle 90 | skittleClickListener.onSkittleClick(skittle, position - 1); 91 | } 92 | } 93 | 94 | @Override public void onSkittleContainerClick() { 95 | if (miniSkittlesAdded) onMainSkittleClick(); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /skittles/src/main/java/snow/skittles/ItemAnimator.java: -------------------------------------------------------------------------------- 1 | package snow.skittles; 2 | 3 | import android.animation.Animator; 4 | import android.content.Context; 5 | import android.support.v7.widget.DefaultItemAnimator; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.util.DisplayMetrics; 8 | import android.view.WindowManager; 9 | import android.view.animation.DecelerateInterpolator; 10 | import android.view.animation.OvershootInterpolator; 11 | 12 | /** 13 | * Created by aashrai on 3/2/16. 14 | */ 15 | public class ItemAnimator extends DefaultItemAnimator { 16 | 17 | private static final OvershootInterpolator OVERSHOOT_INTERPOLATOR = new OvershootInterpolator(2); 18 | private static final DecelerateInterpolator DECELERATE_INTERPOLATOR = 19 | new DecelerateInterpolator(); 20 | 21 | @Override public boolean animateAdd(RecyclerView.ViewHolder holder) { 22 | if (!(holder instanceof SkittleAdapter.MainSkittleViewHolder)) { 23 | runEnterAnimation(holder); 24 | return false; 25 | } 26 | dispatchAddFinished(holder); 27 | return false; 28 | } 29 | 30 | @Override public boolean animateRemove(RecyclerView.ViewHolder holder) { 31 | if (!(holder instanceof SkittleAdapter.MainSkittleViewHolder)) { 32 | runExitAnimation(holder); 33 | return false; 34 | } 35 | dispatchRemoveFinished(holder); 36 | return false; 37 | } 38 | 39 | private void runEnterAnimation(final RecyclerView.ViewHolder holder) { 40 | holder.itemView.setTranslationY( 41 | holder.itemView.getContext().getResources().getDimensionPixelOffset(R.dimen.skittle_size)); 42 | holder.itemView.setAlpha(0); 43 | holder.itemView.animate() 44 | .translationY(0) 45 | .alpha(1) 46 | .setInterpolator(OVERSHOOT_INTERPOLATOR) 47 | .setListener(new Animator.AnimatorListener() { 48 | @Override public void onAnimationStart(Animator animation) { 49 | dispatchAddStarting(holder); 50 | } 51 | 52 | @Override public void onAnimationEnd(Animator animation) { 53 | dispatchAddFinished(holder); 54 | } 55 | 56 | @Override public void onAnimationCancel(Animator animation) { 57 | 58 | } 59 | 60 | @Override public void onAnimationRepeat(Animator animation) { 61 | 62 | } 63 | }) 64 | .start(); 65 | } 66 | 67 | private void runExitAnimation(final RecyclerView.ViewHolder holder) { 68 | holder.itemView.setTranslationY(0); 69 | holder.itemView.setAlpha(1); 70 | holder.itemView.animate() 71 | .alpha(0) 72 | .translationYBy(getExitTranslation(holder)) 73 | .setInterpolator(DECELERATE_INTERPOLATOR) 74 | .setListener(new Animator.AnimatorListener() { 75 | @Override public void onAnimationStart(Animator animation) { 76 | dispatchRemoveStarting(holder); 77 | } 78 | 79 | @Override public void onAnimationEnd(Animator animation) { 80 | dispatchRemoveFinished(holder); 81 | } 82 | 83 | @Override public void onAnimationCancel(Animator animation) { 84 | 85 | } 86 | 87 | @Override public void onAnimationRepeat(Animator animation) { 88 | 89 | } 90 | }) 91 | .start(); 92 | } 93 | 94 | private int getExitTranslation(RecyclerView.ViewHolder holder) { 95 | DisplayMetrics displayMetrics = new DisplayMetrics(); 96 | ((WindowManager) holder.itemView.getContext() 97 | .getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(displayMetrics); 98 | return displayMetrics.heightPixels - holder.itemView.getTop() - 2 * holder.itemView.getHeight(); 99 | } 100 | } -------------------------------------------------------------------------------- /skittles/src/main/java/snow/skittles/SkittleLayout.java: -------------------------------------------------------------------------------- 1 | package snow.skittles; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.drawable.Drawable; 6 | import android.support.design.widget.CoordinatorLayout; 7 | import android.support.design.widget.Snackbar; 8 | import android.support.v4.content.ContextCompat; 9 | import android.support.v7.widget.LinearLayoutManager; 10 | import android.util.AttributeSet; 11 | import android.util.TypedValue; 12 | import android.view.LayoutInflater; 13 | import android.view.MotionEvent; 14 | import android.view.View; 15 | import android.view.ViewGroup; 16 | 17 | /** 18 | * Created by aashrai on 2/2/16. 19 | */ 20 | public class SkittleLayout extends CoordinatorLayout implements View.OnTouchListener { 21 | 22 | SkittleContainer skittleContainer; 23 | OnSkittleContainerClickListener listener; 24 | 25 | public SkittleContainer getSkittleContainer() { 26 | return skittleContainer; 27 | } 28 | 29 | interface OnSkittleContainerClickListener { 30 | void onSkittleContainerClick(); 31 | } 32 | 33 | public SkittleLayout(Context context) { 34 | super(context); 35 | } 36 | 37 | public SkittleLayout(Context context, AttributeSet attrs) { 38 | super(context, attrs); 39 | TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.SkittleLayout); 40 | int color; 41 | Drawable drawable; 42 | color = 43 | array.getColor(R.styleable.SkittleLayout_mainSkittleColor, fetchAccentColor(getContext())); 44 | drawable = array.getDrawable(R.styleable.SkittleLayout_mainSkittleIcon); 45 | if (drawable == null) { 46 | drawable = ContextCompat.getDrawable(context, R.drawable.ic_add_white_18dp); 47 | } 48 | array.recycle(); 49 | 50 | skittleContainer = (SkittleContainer) LayoutInflater.from(context) 51 | .inflate(R.layout.skittle_container, this, false); 52 | SkittleAdapter skittleAdapter = new SkittleAdapter(color, drawable); 53 | skittleContainer.setLayoutManager( 54 | new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, true)); 55 | skittleContainer.setAdapter(skittleAdapter); 56 | skittleContainer.setItemAnimator(new ItemAnimator()); 57 | skittleContainer.setOnTouchListener(this); 58 | addView(skittleContainer); 59 | } 60 | 61 | @Override public void addView(View child) { 62 | super.addView(child); 63 | if (getChildCount() != 1 && !(child instanceof Snackbar.SnackbarLayout)) addSkittleOnTop(); 64 | } 65 | 66 | @Override public void addView(View child, int index) { 67 | super.addView(child, index); 68 | if (getChildCount() != 1 && !(child instanceof Snackbar.SnackbarLayout)) addSkittleOnTop(); 69 | } 70 | 71 | @Override public void addView(View child, int width, int height) { 72 | super.addView(child, width, height); 73 | if (getChildCount() != 1 && !(child instanceof Snackbar.SnackbarLayout)) addSkittleOnTop(); 74 | } 75 | 76 | @Override public void addView(View child, ViewGroup.LayoutParams params) { 77 | super.addView(child, params); 78 | if (getChildCount() != 1 && !(child instanceof Snackbar.SnackbarLayout)) addSkittleOnTop(); 79 | } 80 | 81 | /** 82 | * Utility method called after addView to ensure the skittle container is on top 83 | */ 84 | private void addSkittleOnTop() { 85 | detachViewFromParent(skittleContainer); 86 | attachViewToParent(skittleContainer, getChildCount(), skittleContainer.getLayoutParams()); 87 | } 88 | 89 | public SkittleAdapter getSkittleAdapter() { 90 | return (SkittleAdapter) skittleContainer.getAdapter(); 91 | } 92 | 93 | int fetchAccentColor(Context mContext) { 94 | TypedValue typedValue = new TypedValue(); 95 | 96 | TypedArray a = 97 | mContext.obtainStyledAttributes(typedValue.data, new int[] { R.attr.colorAccent }); 98 | int color = a.getColor(0, 0); 99 | 100 | a.recycle(); 101 | 102 | return color; 103 | } 104 | 105 | public void setSkittleContainerClickListener(OnSkittleContainerClickListener listener) { 106 | this.listener = listener; 107 | } 108 | 109 | @Override public boolean onTouch(View v, MotionEvent event) { 110 | //SkittleContainer accepts only a singleTapUp event 111 | boolean singleTapUp = skittleContainer.gestureDetector.onTouchEvent(event); 112 | if (singleTapUp) listener.onSkittleContainerClick(); 113 | return singleTapUp; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 17 | 18 | 27 | 28 | 36 | 37 | 43 | 44 | 45 | 46 | 47 | 55 | 56 | 60 | 61 | 65 | 66 | 70 | 71 | 76 | 77 | 82 | 83 | 84 | 85 | 89 | 90 | 94 | 95 | 100 | 101 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /skittles/src/main/java/snow/skittles/SkittleContainer.java: -------------------------------------------------------------------------------- 1 | package snow.skittles; 2 | 3 | import android.content.Context; 4 | import android.os.Build; 5 | import android.support.annotation.Nullable; 6 | import android.support.design.widget.CoordinatorLayout; 7 | import android.support.design.widget.Snackbar; 8 | import android.support.v4.view.GestureDetectorCompat; 9 | import android.support.v4.view.ViewCompat; 10 | import android.support.v4.view.animation.FastOutLinearInInterpolator; 11 | import android.support.v7.widget.RecyclerView; 12 | import android.util.AttributeSet; 13 | import android.view.GestureDetector; 14 | import android.view.MotionEvent; 15 | import android.view.View; 16 | import java.util.List; 17 | 18 | /** 19 | * Created by aashrai on 4/2/16. 20 | */ 21 | @CoordinatorLayout.DefaultBehavior(SkittleContainer.FloatingLayoutBehavior.class) 22 | class SkittleContainer extends RecyclerView implements GestureDetector.OnGestureListener { 23 | 24 | GestureDetectorCompat gestureDetector; 25 | boolean isSkittlesAdded = false; 26 | 27 | public SkittleContainer(Context context) { 28 | this(context, null); 29 | } 30 | 31 | public SkittleContainer(Context context, @Nullable AttributeSet attrs) { 32 | this(context, attrs, 0); 33 | } 34 | 35 | public void setSkittlesAdded(boolean skittlesAdded) { 36 | isSkittlesAdded = skittlesAdded; 37 | } 38 | 39 | public SkittleContainer(Context context, @Nullable AttributeSet attrs, int defStyle) { 40 | super(context, attrs, defStyle); 41 | gestureDetector = new GestureDetectorCompat(context, this); 42 | } 43 | 44 | @Override public boolean onTouchEvent(MotionEvent event) { 45 | return gestureDetector.onTouchEvent(event); 46 | } 47 | 48 | @Override public boolean onInterceptTouchEvent(MotionEvent e) { 49 | return false; 50 | } 51 | 52 | @Override public boolean onDown(MotionEvent e) { 53 | return isSkittlesAdded; 54 | } 55 | 56 | @Override public void onShowPress(MotionEvent e) { 57 | 58 | } 59 | 60 | @Override public boolean onSingleTapUp(MotionEvent e) { 61 | return true; 62 | } 63 | 64 | @Override 65 | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 66 | return false; 67 | } 68 | 69 | @Override public void onLongPress(MotionEvent e) { 70 | 71 | } 72 | 73 | @Override 74 | public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 75 | return false; 76 | } 77 | 78 | @SuppressWarnings("unused") public static class FloatingLayoutBehavior 79 | extends CoordinatorLayout.Behavior { 80 | 81 | private static final boolean SNACKBAR_BEHAVIOR_ENABLED; 82 | private float mTranslationY; 83 | private boolean mIsAnimatingOut; 84 | 85 | public FloatingLayoutBehavior() { 86 | } 87 | 88 | public FloatingLayoutBehavior(Context context, AttributeSet attrs) { 89 | super(context, attrs); 90 | } 91 | 92 | @Override public boolean layoutDependsOn(CoordinatorLayout parent, SkittleContainer child, 93 | View dependency) { 94 | return dependency instanceof Snackbar.SnackbarLayout; 95 | } 96 | 97 | @Override 98 | public boolean onDependentViewChanged(CoordinatorLayout parent, SkittleContainer child, 99 | View dependency) { 100 | if (dependency instanceof Snackbar.SnackbarLayout) { 101 | this.updateFabTranslationForSnackbar(parent, child, dependency); 102 | } 103 | return true; 104 | } 105 | 106 | private void updateFabTranslationForSnackbar(CoordinatorLayout parent, 107 | SkittleContainer container, View snackbar) { 108 | float translationY = this.getFabTranslationYForSnackbar(parent, container); 109 | if ((translationY == -snackbar.getHeight())) { 110 | ViewCompat.animate(container) 111 | .translationY(-translationY) 112 | .setInterpolator(new FastOutLinearInInterpolator()) 113 | .setListener(null); 114 | } else if (translationY != this.mTranslationY) { 115 | ViewCompat.animate(container).cancel(); 116 | if (Math.abs(translationY - this.mTranslationY) == (float) snackbar.getHeight()) { 117 | ViewCompat.animate(container) 118 | .translationY(translationY) 119 | .setInterpolator(new FastOutLinearInInterpolator()) 120 | .setListener(null); 121 | } else { 122 | ViewCompat.setTranslationY(container, translationY); 123 | } 124 | 125 | this.mTranslationY = translationY; 126 | } 127 | } 128 | 129 | private float getFabTranslationYForSnackbar(CoordinatorLayout parent, 130 | SkittleContainer container) { 131 | float minOffset = 0.0F; 132 | List dependencies = parent.getDependencies(container); 133 | int i = 0; 134 | 135 | for (int z = dependencies.size(); i < z; ++i) { 136 | View view = (View) dependencies.get(i); 137 | if (view instanceof Snackbar.SnackbarLayout && parent.doViewsOverlap(container, view)) { 138 | minOffset = 139 | Math.min(minOffset, ViewCompat.getTranslationY(view) - (float) view.getHeight()); 140 | } 141 | } 142 | 143 | return minOffset; 144 | } 145 | 146 | static { 147 | 148 | SNACKBAR_BEHAVIOR_ENABLED = Build.VERSION.SDK_INT >= 11; 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | #Skittles 2 | [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Skittles-brightgreen.svg?style=flat)](http://android-arsenal.com/details/1/2076) [![Build Status](https://travis-ci.org/aashrairavooru/Skittles.svg)](https://travis-ci.org/aashrairavooru/Skittles) [ ![Jcenter](https://img.shields.io/github/release/aashrairavooru/Skittles.svg?label=Jcenter) ](https://bintray.com/aashrairavooru/maven/Skittles/_latestVersion) 3 | [ 4 | ![JitPackv](https://img.shields.io/github/release/aashrairavooru/Skittles.svg?label=JitPack)](https://jitpack.io/#aashrairavooru/Skittles/) 5 | 6 | A simple,clean api for adding PushBullet style skittles to your app for more material design glory.This library uses the FloatingActionButton provided in the android design support library 7 | 8 | 9 | 10 | 11 | ##Guide ([Sample](sample/src/main/java/snow/skittlessample/MainActivity.java)) 12 | 13 | First some housekeeping code: 14 | 15 | Use 16 | [SkittleLayout](skittles/src/main/java/snow/skittles/SkittleLayout.java) as a root view in your layouts 17 | 18 | ```xml 19 | 29 | 30 | 36 | ... 37 | 38 | 39 | ``` 40 | 41 | Some further housekeeping... 42 | 43 | Declare a [SkittleBuilder](skittles/src/main/java/snow/skittles/SkittleBuilder.java),used to add skittles and pass the root SkittleLayout to it 44 | 45 | ```java 46 | SkittleLayout skittleLayout = (SkittleLayout) findViewById(R.id.skittleLayout); 47 | //Pass false as the second param if you don't want the menu to be closed on screen tap 48 | SkittleBuilder skittleBuilder = SkittleBuilder.newInstance((SkittleLayout) findViewById(R.id.skittleLayout), true); 49 | 50 | ``` 51 | 52 | Now for the fun part 53 | 54 | Add skittles to your activity/fragment 55 | 56 | ```java 57 | skittleBuilder.addSkittle(Skittle.newInstance(ContextCompat.getColor(this, R.color.barratheon), 58 | ContextCompat.getDrawable(this, R.drawable.barratheon_icon))); 59 | skittleBuilder.addSkittle(Skittle.newInstance(ContextCompat.getColor(this, R.color.lannister), 60 | ContextCompat.getDrawable(this, R.drawable.lannister_icon))); 61 | ``` 62 | 63 | Add [TextSkittle](skittles/src/main/java/snow/skittles/TextSkittle.java) to your activity/fragment 64 | 65 | ```java 66 | skittleBuilder.addSkittle(new TextSkittle.Builder("Hello", ContextCompat.getColor(this, R.color.stark), 67 | ContextCompat.getDrawable(this, R.drawable.stark_icon)).setTextBackground( 68 | ContextCompat.getColor(this, android.R.color.background_light)).build()); 69 | 70 | ``` 71 | 72 | Flexible callback for clicks: 73 | 74 | + Add a click listener(SkittleBuilder.SkittleClickListener) to the [SkittleBuilder](skittles/src/main/java/snow/skittles/SkittleBuilder.java) object 75 | `skittleBuilder.setSkittleListener(this);` 76 | 77 | + This exposes two methods for Skittle and MainSkittle click events 78 | 79 | ```java 80 | void onSkittleClick(BaseSkittle skittle, int position); 81 | 82 | void onMainSkittleClick(); 83 | ``` 84 | [BaseSkittle](skittles/src/main/java/snow/skittles/BaseSkittle.java) is an interface that every skittle implements 85 | 86 | ```java 87 | public void onSkittleClick(BaseSkittle skittle, int position) { 88 | if(skittle instanceOf TextSkittle) 89 | ... 90 | else if(skittle instanceOf Skittle) 91 | ... 92 | } 93 | ``` 94 | Here the `position` does not include the mainSkittle and starts from `0` 95 | 96 | You can now create your very own Skittle you just have to implement the [BaseSkittle](skittles/src/main/java/snow/skittles/BaseSkittle.java), check [TextSkittle](skittles/src/main/java/snow/skittles/TextSkittle.java) or [Skittle](skittles/src/main/java/snow/skittles/Skittle.java) for further reference 97 | 98 | ##Snackbar Support 99 | 100 | 101 | 102 | When using snackbars ensure that you use [SkittleContainer](skittles/src/main/java/snow/skittles/SkittleContainer.java) 103 | 104 | ```java 105 | Snackbar.make(skittleLayout.getSkittleContainer(), "Skittle Pressed", Snackbar.LENGTH_LONG) 106 | .show(); 107 | ``` 108 | 109 | ##Gradle 110 | ```groovy 111 | dependencies{ 112 | compile 'com.rlj.library:skittles:4.1.1' 113 | } 114 | ``` 115 | 116 | See the **[Sample](sample/src/main/java/snow/skittlessample/MainActivity.java)** and **[JavaDoc](http://aashrairavooru.github.io/Skittles/)** for further guidance 117 | 118 | ##Upcoming 119 | + Better support for animations 120 | + Option for adding skittles by xml (inspired by Navigation View) 121 | 122 | 123 | #Taste the rainbow 124 | ![Skittles](art/Taste the rainbow.jpg) 125 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /sample/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /skittles/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /skittles/src/main/java/snow/skittles/SkittleAdapter.java: -------------------------------------------------------------------------------- 1 | package snow.skittles; 2 | 3 | import android.content.res.ColorStateList; 4 | import android.graphics.drawable.Drawable; 5 | import android.support.annotation.ColorInt; 6 | import android.support.annotation.LayoutRes; 7 | import android.support.annotation.NonNull; 8 | import android.support.design.widget.FloatingActionButton; 9 | import android.support.v7.widget.RecyclerView; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.TextView; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | /** 18 | * Created by aashrai on 2/2/16. 19 | */ 20 | class SkittleAdapter extends RecyclerView.Adapter { 21 | 22 | private final List skittles = new ArrayList<>(); 23 | private OnSkittleClickListener onSkittleClickListener; 24 | 25 | interface OnSkittleClickListener { 26 | void onSkittleClick(BaseSkittle skittle, int position); 27 | } 28 | 29 | /** 30 | * @param color color of the main skittle 31 | * @param icon icon of the main skittle 32 | */ 33 | public SkittleAdapter(@ColorInt int color, @NonNull Drawable icon) { 34 | //This ensures that no matter what there is always one main skittle available 35 | addSkittle(Skittle.newMainSkittleInstance(color, icon)); 36 | } 37 | 38 | @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 39 | switch (viewType) { 40 | case Constants.MAIN_SKITTLE: 41 | return new MainSkittleViewHolder(getInflatedView(R.layout.main_skittle, parent)); 42 | case Constants.TEXT_SKITTLE: 43 | return new TextSkittleViewHolder(getInflatedView(R.layout.text_skittle, parent)); 44 | default: 45 | return new SkittleViewHolder(getInflatedView(R.layout.skittle, parent)); 46 | } 47 | } 48 | 49 | public void addSkittle(@NonNull BaseSkittle skittle) { 50 | int previousSize = skittles.size(); 51 | skittles.add(skittle); 52 | notifyItemInserted(previousSize); 53 | } 54 | 55 | public void addAllSkittles(@NonNull List skittles) { 56 | int previousSize = skittles.size(); 57 | this.skittles.addAll(skittles); 58 | notifyItemRangeInserted(previousSize, this.skittles.size()); 59 | } 60 | 61 | public void removeAllMiniSkittles() { 62 | int prevSize = this.skittles.size(); 63 | BaseSkittle mainSkittle = this.skittles.get(0); 64 | this.skittles.clear(); 65 | this.skittles.add(mainSkittle); 66 | notifyItemRangeRemoved(1, prevSize); 67 | } 68 | 69 | public List removeAllSkittles(List skittles) { 70 | int prevSize = this.skittles.size(); 71 | this.skittles.removeAll(skittles); 72 | notifyItemRangeRemoved(1, prevSize); 73 | return skittles; 74 | } 75 | 76 | public BaseSkittle removeSkittle(int position) { 77 | final BaseSkittle skittle = this.skittles.remove(position); 78 | notifyItemRemoved(position); 79 | return skittle; 80 | } 81 | 82 | private View getInflatedView(@LayoutRes int id, ViewGroup parent) { 83 | return LayoutInflater.from(parent.getContext()).inflate(id, parent, false); 84 | } 85 | 86 | @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 87 | if (holder instanceof MainSkittleViewHolder) { 88 | configureMainSkittle((MainSkittleViewHolder) holder, position); 89 | } else if (holder instanceof TextSkittleViewHolder) { 90 | configureTextSkittle((TextSkittleViewHolder) holder, position); 91 | } else if (holder instanceof SkittleViewHolder) { 92 | configureSkittle((SkittleViewHolder) holder, position); 93 | } 94 | } 95 | 96 | private void configureMainSkittle(MainSkittleViewHolder holder, int position) { 97 | configureSkittle(holder, position); 98 | } 99 | 100 | private void configureTextSkittle(TextSkittleViewHolder holder, int position) { 101 | TextSkittle textSkittle = (TextSkittle) skittles.get(position); 102 | holder.text.setText(textSkittle.getText()); 103 | holder.text.setTextColor(textSkittle.getTextColor()); 104 | holder.text.setBackgroundColor(textSkittle.getTextBackground()); 105 | holder.skittle.setBackgroundTintList(ColorStateList.valueOf(textSkittle.getColor())); 106 | holder.skittle.setImageDrawable(textSkittle.getIcon()); 107 | } 108 | 109 | private void configureSkittle(SkittleViewHolder holder, int position) { 110 | holder.skittle.setBackgroundTintList(ColorStateList.valueOf(skittles.get(position).getColor())); 111 | holder.skittle.setImageDrawable(skittles.get(position).getIcon()); 112 | } 113 | 114 | @Override public int getItemViewType(int position) { 115 | return skittles.get(position).getType(); 116 | } 117 | 118 | @Override public int getItemCount() { 119 | return skittles.size(); 120 | } 121 | 122 | public void changeMainSkittleColor(@ColorInt int color) { 123 | skittles.get(0).setColor(color); 124 | notifyItemChanged(0); 125 | } 126 | 127 | public void changeMainSkittleIcon(Drawable drawable) { 128 | skittles.get(0).setIconDrawable(drawable); 129 | notifyItemChanged(0); 130 | } 131 | 132 | public void changeSkittleAt(int index, BaseSkittle skittle) { 133 | skittles.set(index, skittle); 134 | notifyItemChanged(index); 135 | } 136 | 137 | class MainSkittleViewHolder extends SkittleViewHolder implements View.OnClickListener { 138 | public MainSkittleViewHolder(View itemView) { 139 | super(itemView); 140 | itemView.findViewById(R.id.skittle).setOnClickListener(this); 141 | } 142 | 143 | @Override public void onClick(View v) { 144 | if (onSkittleClickListener != null) onSkittleClickListener.onSkittleClick(skittles.get(0), 0); 145 | } 146 | } 147 | 148 | class SkittleViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 149 | 150 | FloatingActionButton skittle; 151 | 152 | public SkittleViewHolder(View itemView) { 153 | super(itemView); 154 | skittle = (FloatingActionButton) itemView.findViewById(R.id.skittle); 155 | skittle.setOnClickListener(this); 156 | } 157 | 158 | @Override public void onClick(View v) { 159 | if (onSkittleClickListener != null) { 160 | onSkittleClickListener.onSkittleClick(skittles.get(getAdapterPosition()), 161 | getAdapterPosition()); 162 | } 163 | } 164 | } 165 | 166 | class TextSkittleViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 167 | TextView text; 168 | FloatingActionButton skittle; 169 | 170 | public TextSkittleViewHolder(View itemView) { 171 | super(itemView); 172 | text = (TextView) itemView.findViewById(R.id.tv_skittle); 173 | skittle = (FloatingActionButton) itemView.findViewById(R.id.skittle); 174 | text.setOnClickListener(this); 175 | skittle.setOnClickListener(this); 176 | } 177 | 178 | @Override public void onClick(View v) { 179 | if (onSkittleClickListener != null) { 180 | onSkittleClickListener.onSkittleClick(skittles.get(getAdapterPosition()), 181 | getAdapterPosition()); 182 | } 183 | } 184 | } 185 | 186 | public void setMainSkittleClickListener(OnSkittleClickListener skittleClickListener) { 187 | this.onSkittleClickListener = skittleClickListener; 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /sample/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | SkittlesSample 3 | Settings 4 | 5 | #673ab7 6 | #009688 7 | #ec4d4d 8 | #656c75 9 | #d7c137 10 | #aeffffff 11 | 12 | Background 13 | History 14 | 15 | 16 | House Stark 17 | House Stark of Winterfell is one of the Great Houses of Westeros and the principal noble house of the North; many lesser houses are sworn to them. In days of old they ruled as Kings of Winter, but since the Wars of Conquest by House Targaryen they have been Wardens of the North. Their seat, Winterfell, is an ancient castle renowned for its strength. 18 | 19 | Their sigil is a grey direwolf racing across a field of white, and their words are "Winter is Coming", one of only a few house mottoes to be a warning rather than a boast.[1] Members of the family tend to be lean of build and long of face, with dark brown hair and grey eyes. Several of the POV characters of A Song of Ice and Fire are members of House Stark. 20 | 21 | Aside from the Karstarks of Karhold, the Starks of Winterfell may have distant relatives elsewhere in the North, possibly in White Harbor and Barrowton.[2] Some younger Starks have also held vassal holdfasts for the lords of Winterfell.[3] 22 | 23 | The Starks are an ancient house descended from Bran the Builder, a legendary figure from the Age of Heroes said to have raised their ancestral home at Winterfell thousands of years in the past, as well as the Wall. They are descendants of the First Men[1] and still follow some of their ancient traditions and the old gods of the forest. The Starks were Kings of Winter in the North for thousands of years from the Age of Heroes, possibly beginning with Bran the Builder. Ever since Bran constructed the Wall, the Starks have been friends of the Night\'s Watch, and have manned the Wall for thousands of years. The Night\'s King, the attainted 13th Lord Commander of the Night\'s Watch, is said to have been a Stark, among his many possible origins. The Starks also helped repel several major wildling invasions, such as when they and their Umber bannermen defeated the Kings-Beyond-the-Wall like the brothers Gendel and Gorne, as well as Bael the Bard, who both sired and fought a Stark. 24 | 25 | The ancient Starks gradually defeated rival kings, such as the Barrow Kings to their south and the Red Kings to their east.[4] For several millennia, the Starks were not the uncontested Kings in the North, but their primary antagonists, the Boltons of the Dreadfort, swore fealty some 1,000 years ago, ending their flesh-flaying ways. Meanwhile, King Jon Stark drove pirates from the White Knife, and the Wolf\'s Den was built at its mouth. This stronghold was often granted to sons and grandsons of the King in the North; one such branch, the Greystarks, was extinguished after allying with the Boltons against the Starks.[5] The Wolf\'s Den was eventually granted to the Manderlys, a house exiled from the Reach and taken in by the Starks. The Manderlys developed the city of White Harbor around the castle.[6][7] King Jon\'s son, Rickard, defeated the Marsh King and married his daughter, bringing the Neck into Winterfell\'s realm under the lordship of House Reed. The Karstarks were founded when Karlon Stark, brother to the reigning king, helped crush a rebel lord and was granted a keep for his service. Finally, the Mormonts were granted Bear Island when King Rodrik Stark won it from the ironborn in a wrestling match. The Starks fought the Arryns of the Vale after the Rape of the Three Sisters, eventually ceding control of the islands.[8] 26 | 27 | 28 | 29 | House Lannister 30 | House Lannister of Casterly Rock is one of the Great Houses of Seven Kingdoms, and the principal house of the westerlands. Their seat is Casterly Rock, though another branch exists that is based in nearby Lannisport. Their sigil is a golden lion on a field of crimson.[1] Their official motto is "Hear Me Roar!" However, their unofficial motto, equally well known, is "A Lannister always pays his debts."[2][3] The Warden of the West is a Lannister by tradition. 31 | 32 | Fair-haired, tall, and handsome, the Lannisters are the blood of Andal adventurers who carved out a mighty kingdom in the western hills and valleys. Through the female line they boast of descent from Lann the Clever, the legendary trickster of the Age of Heroes who tricked the members of House Casterly into giving him Casterly Rock[4] during the era of the First Men.[5] 33 | 34 | The Lannisters reigned as Kings of the Rock until they fell to the Targaryen conquest, but were allowed to remain the liege lords of the westerlands. The House had fallen on hard times during the rule of Lord Tytos, but was restored to its former glory by Lord Tywin. His daughter Cersei is the queen of King Robert I Baratheon, while her twin Ser Jaime is a knight of Robert\'s Kingsguard. Members of the family tend to have golden hair and emerald green eyes. 35 | The Lannisters suddenly appear as First Men in historical records of the Age of Heroes, ruling large portions of the westerlands from Casterly Rock just as the Casterlys vanished from the chronicles. They claim descent from Lann the Clever, the legendary figure who tricked the Casterlys from their seat, Casterly Rock.[5] 36 | 37 | According to a semi-canon source, members of lesser branches of the family left Casterly Rock and developed a nearby village into the city of Lannisport, forming House Lannister of Lannisport. Meanwhile, the Lannisters of Casterly Rock grew to become Kings of the Rock.[6] The first known King of the Rock was Loreon I Lannister, although Lann the Clever has posthumously been called by the same title.[5] 38 | 39 | 40 | House Barratheon 41 | House Baratheon of Storm\'s End is one of the Great Houses of Westeros, and is the principal house in the stormlands, which they rule as Lords Paramount of the Stormlands. Their seat, Storm\'s End, is an ancient castle raised by the Storm Kings from the now-extinct House Durrandon. The Baratheon sigil is a crowned black stag on a field of gold.[1] Members of the family tend to be tall and powerfully built, with black hair and blue eyes, as well as strong, square jawlines. They are known for their mercurial tempers, and their words are "Ours is the Fury". 42 | 43 | After Robert\'s Rebellion, House Baratheon split into three branches: Lord Robert Baratheon was crowned King and took residence at King\'s Landing, thereby creating House Baratheon of King\'s Landing. Robert gave the seat of Dragonstone to his younger brother, Stannis, creating House Baratheon of Dragonstone. Robert\'s youngest brother, Renly, became the Lord of Storm\'s End, continuing House Baratheon of Storm\'s End. 44 | House Baratheon is the youngest of the great houses, tracing its descent from Orys Baratheon, one of Aegon I Targaryen\'s fiercest generals, and rumored to be his bastard brother. Through the female line, the Baratheons are descended from the Storm Kings, as Orys slew Argilac the Arrogant, last of the Storm Kings, and married his daughter Argella Durrandon. Orys adopted the sigil and words of his wife\'s ancestral line.[2] The line of the Storm Kings dates back to the Age of Heroes when their kingdom was founded by King Durran I "Godsgrief", a legendary hero. 45 | 46 | Baratheon support for the Targaryens was initially strong. A knight of the House was elevated to the Kingsguard, saving the life of King Aenys I Targaryen during the Faith Militant uprising. 47 | 48 | During the Dance of the Dragons, Lord Borros Baratheon sided the House with Aegon II Targaryen and the greens despite his late father Boremund\'s support of the blacks and relation to Rhaenys Targaryen (through Jocelyn Baratheon).[3] There was talk of one of Borros\'s daughters wedding Prince Aemond Targaryen, a green prince, but it is unknown if this occurred before the prince\'s death. 49 | 50 | During the First Blackfyre Rebellion, the Baratheons remained loyal to the Targaryen dynasty, providing much of the force commanded by Prince Baelor Targaryen at the decisive Battle of the Redgrass Field. 51 | 52 | Nine years before the tourney at Ashford Meadow, Lord Baratheon held a tourney to celebrate the birth of his grandson. Ser Lyonel Baratheon, called the Laughing Storm, participated in the Ashford tourney and fought on the side of Ser Duncan the Tall during a trial of seven. 53 | 54 | Princess Rhaelle Targaryen, daughter of Aegon V Targaryen, married into the House and birthed Lord Steffon Baratheon, continuing the close ties between the dragon and the stag. Prince Rhaegar Targaryen defeated Lord Steffon Baratheon in a tourney at Storm\'s End that was eventually won by Ser Barristan Selmy. Lord Steffon also went on a journey across the narrow sea to find a bride for Prince Rhaegar, a voyage that would be his last. 55 | 56 | 57 | --------------------------------------------------------------------------------