├── .gitignore
├── LICENSE.MD
├── README.md
├── art
└── demo.gif
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── library
├── .gitignore
├── build.gradle
├── gradle.properties
├── proguard-rules.txt
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── melnykov
│ │ └── fab
│ │ ├── AbsListViewScrollDetector.java
│ │ ├── FloatingActionButton.java
│ │ ├── ObservableScrollView.java
│ │ ├── RecyclerViewScrollDetector.java
│ │ ├── ScrollDirectionListener.java
│ │ └── ScrollViewScrollDetector.java
│ └── res
│ ├── anim-v21
│ └── fab_press_elevation.xml
│ ├── drawable-hdpi
│ ├── fab_shadow.png
│ └── fab_shadow_mini.png
│ ├── drawable-mdpi
│ ├── fab_shadow.png
│ └── fab_shadow_mini.png
│ ├── drawable-xhdpi
│ ├── fab_shadow.png
│ └── fab_shadow_mini.png
│ ├── drawable-xxhdpi
│ ├── fab_shadow.png
│ └── fab_shadow_mini.png
│ ├── drawable-xxxhdpi
│ ├── fab_shadow.png
│ └── fab_shadow_mini.png
│ └── values
│ ├── attrs.xml
│ ├── colors.xml
│ ├── dimens.xml
│ └── info_strings.xml
├── sample.apk
├── sample
├── .gitignore
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── melnykov
│ │ └── fab
│ │ └── sample
│ │ ├── DividerItemDecoration.java
│ │ ├── ListViewAdapter.java
│ │ ├── MainActivity.java
│ │ └── RecyclerViewAdapter.java
│ └── res
│ ├── drawable-hdpi
│ ├── ic_add_white_24dp.png
│ └── ic_launcher.png
│ ├── drawable-mdpi
│ ├── ic_add_white_24dp.png
│ └── ic_launcher.png
│ ├── drawable-xhdpi
│ ├── ic_add_white_24dp.png
│ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ ├── at.png
│ ├── au.png
│ ├── br.png
│ ├── ca.png
│ ├── ch.png
│ ├── cl.png
│ ├── cn.png
│ ├── cz.png
│ ├── de.png
│ ├── dk.png
│ ├── ee.png
│ ├── fi.png
│ ├── fr.png
│ ├── gr.png
│ ├── hr.png
│ ├── hu.png
│ ├── ic_add_white_24dp.png
│ ├── ic_launcher.png
│ ├── ie.png
│ ├── in.png
│ ├── is.png
│ ├── it.png
│ ├── lt.png
│ ├── lv.png
│ ├── nl.png
│ ├── no.png
│ ├── nz.png
│ ├── se.png
│ ├── ua.png
│ └── us.png
│ ├── drawable-xxxhdpi
│ ├── ic_add_white_24dp.png
│ └── ic_launcher.png
│ ├── drawable
│ └── divider.xml
│ ├── layout
│ ├── about_view.xml
│ ├── fragment_listview.xml
│ ├── fragment_recyclerview.xml
│ ├── fragment_scrollview.xml
│ └── list_item.xml
│ ├── menu
│ └── main.xml
│ ├── values-v21
│ └── styles.xml
│ └── values
│ ├── arrays.xml
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Local configuration file (sdk path, etc)
16 | local.properties
17 |
18 | # IntelliJ IDEA
19 | .idea/
20 | *.iml
21 | *.iws
22 | *.ipr
23 |
24 | # Gradle
25 | .gradle
26 | build/
--------------------------------------------------------------------------------
/LICENSE.MD:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Oleksandr Melnykov
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.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | DEPRECATED
2 | ====================
3 |
4 | Use the [FloatingActionButton](https://developer.android.com/reference/android/support/design/widget/FloatingActionButton.html) from the support library instead.
5 |
6 | FloatingActionButton
7 | ====================
8 |
9 | [](http://android-arsenal.com/details/1/824)
10 |
11 | ### Description
12 |
13 | Android [floating action button] which reacts on scrolling events. Becomes visible when an attached target is scrolled up and invisible when scrolled down.
14 |
15 | 
16 |
17 | ### Demo
18 |
19 | [](https://play.google.com/store/apps/details?id=com.melnykov.fab.sample)
20 |
21 | ### Integration
22 |
23 | **1)** Add as a dependency to your ``build.gradle``:
24 |
25 | ```groovy
26 | dependencies {
27 | compile 'com.melnykov:floatingactionbutton:1.3.0'
28 | }
29 | ```
30 |
31 | **2)** Add the ``com.melnykov.fab.FloatingActionButton`` to your layout XML file. The button should be placed in the bottom right corner of the screen. The width and height of the floating action button are hardcoded to **56dp** for the normal and **40dp** for the mini button as specified in the [guidelines].
32 |
33 | ```xml
34 |
38 |
39 |
43 |
44 |
54 |
55 | ```
56 |
57 | **3)** Attach the FAB to ``AbsListView``, ``RecyclerView`` or ``ScrollView`` :
58 |
59 | ```java
60 | ListView listView = (ListView) findViewById(android.R.id.list);
61 | FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
62 | fab.attachToListView(listView);
63 | ```
64 |
65 | Check the sample project to see how to use custom listeners if you need to track scroll events.
66 |
67 | **4)** Add the namespace ``xmlns:fab="http://schemas.android.com/apk/res-auto"`` to your layout file.
68 |
69 | + Set the button type (normal or mini) via the ``fab_type`` xml attribute (default is normal):
70 |
71 | ```xml
72 | fab:fab_type="mini"
73 | ```
74 | or
75 | ```java
76 | fab.setType(FloatingActionButton.TYPE_MINI);
77 | ```
78 | + Set the normal and pressed colors via the xml attributes:
79 |
80 | ```xml
81 | fab:fab_colorNormal="@color/primary"
82 | fab:fab_colorPressed="@color/primary_pressed"
83 | ```
84 | or
85 | ```java
86 | fab.setColorNormal(getResources().getColor(R.color.primary));
87 | fab.setColorPressed(getResources().getColor(R.color.primary_pressed));
88 | ```
89 |
90 | + Enable/disable the button shadow with the ``fab_shadow`` xml attribite (it's enabled by default):
91 |
92 | ```xml
93 | fab:fab_shadow="false"
94 | ```
95 | or
96 | ```java
97 | fab.setShadow(false);
98 | ```
99 |
100 | + Show/hide the button expliciltly:
101 |
102 | ```java
103 | fab.show();
104 | fab.hide();
105 |
106 | fab.show(false); // Show without an animation
107 | fab.hide(false); // Hide without an animation
108 | ```
109 |
110 | + Specify the ripple color for API 21+:
111 |
112 | ```xml
113 | fab:fab_colorRipple="@color/ripple"
114 | ```
115 |
116 | or
117 | ```java
118 | fab.setColorRipple(getResources().getColor(R.color.ripple));
119 | ```
120 |
121 | **5)** Set an icon for the ``FloatingActionButton`` using ``android:src`` xml attribute. Use drawables of size **24dp** as specified by [guidelines]. Icons of desired size can be generated with [Android Asset Studio].
122 |
123 | ### Changelog
124 |
125 | **Version 1.3.0**
126 | + Add the disabled state for the FAB (thanks to [Aleksey Malevaniy](https://github.com/almozavr));
127 | + Fix shadow assets. Rename shadow drawables with a prefix;
128 | + Generate default pressed and ripple colors (thanks to [Aidan Follestad](https://github.com/afollestad)).
129 |
130 | **Version 1.2.0**
131 | + Respect an elevation set manually for the FAB;
132 | + Don't emit a scroll when the listview is empty;
133 | + Add an ability to attach normal listeners for scroll operations (thanks to [Bill Donahue](https://github.com/bdonahue)).
134 |
135 | **Version 1.1.0:**
136 | + Do not ignore negative margins on pre-Lollipop;
137 | + Disable clicks on the FAB when it's hidden on pre-Honeycomb;
138 | + Some shadow tuning.
139 |
140 | **Version 1.0.9:**
141 | + Support API 7;
142 | + Fixed extra margins on pre-Lollipop devices;
143 | + Fixed mini FAB size;
144 | + Updated shadow assets to more accurately match 8dp elevation.
145 |
146 | **Version 1.0.8:**
147 | + ATTENTION! Breaking changes for custom listeners. Check an updated sample how to use them.
148 | + Added support for the ``ScrollView``;
149 | + Significantly optimized scroll detection for the ``RecyclerView``;
150 | + Fixed laggy animation for a list view with items of different height;
151 | + Added ``isVisible`` getter;
152 | + Deleted deprecated methods.
153 |
154 | **Version 1.0.7:**
155 | + Updated shadow assets to better match material design guidelines;
156 | + Make ``FabOnScrollListener`` and ``FabRecyclerOnViewScrollListener`` implement ``ScrollDirectionListener`` for easier custom listeners usage.
157 |
158 | **Version 1.0.6:**
159 | + Added support for the ``RecyclerView``;
160 | + Added ripple effect and elevation for API level 21.
161 |
162 | Thanks to [Aidan Follestad](https://github.com/afollestad).
163 |
164 | **Version 1.0.5:**
165 | + Updated shadow to more accurately match the material design spec;
166 |
167 | **Version 1.0.4:**
168 |
169 | + Allow a custom ``OnScrollListeners`` to be attached to a list view;
170 | + Work properly with list of different height rows;
171 | + Ignore tiny shakes of fingers.
172 |
173 | **Version 1.0.3:**
174 | + Add methods to show/hide without animation;
175 | + Fix show/hide when a view is not measured yet.
176 |
177 |
178 | ### Applications using FloatingActionButton
179 |
180 | Please [ping](mailto:makovkastar@gmail.com) me or send a pull request if you would like to be added here.
181 |
182 | Icon | Application | Icon | Application
183 | ------------ | ------------- | ------------- | -------------
184 |
| [Finger Gesture Launcher] |
| [Vocabletrainer]
185 |
| [Lanekeep GPS Mileage Tracker] |
| [Score It]
186 |
| [Перезвони мне] |
| [App Swap]
187 |
| [QKSMS - Quick Text Messenger] |
| [Uninstaller - Beta Version]
188 |
| [Device Control] |
| [Confide]
189 |
| [Date Night] |
| [Jair Player The Music Rainbow]
190 |
| [Taskr - Lista de Tareas] |
| [Festivos: ¡Conoce el mundo!]
191 |
| [nowPaper] |
| [Vicious chain - Don't do that!]
192 |
| [My Football Stats] |
| [The ScoreBoard]
193 |
| [NavPoint] |
| [Just Reminder]
194 |
| [Early Notes] |
| [Ranch - Smart Tip Calculator]
195 |
| [Thiengo Calopsita] |
| [Tinycore - CPU, RAM monitor] |
196 |
| [Battery Aid Saver & Manager] |
| [GameRaven]
197 |
| [Polaris Office] |
| [Call Utils]
198 |
| [Colorful Note] |
| [CallSticker - заметки звонка]
199 |
200 | ### Links
201 |
202 | Country flag icons used in the sample are taken from www.icondrawer.com
203 |
204 | ### License
205 |
206 | ```
207 | The MIT License (MIT)
208 |
209 | Copyright (c) 2014 Oleksandr Melnykov
210 |
211 | Permission is hereby granted, free of charge, to any person obtaining a copy
212 | of this software and associated documentation files (the "Software"), to deal
213 | in the Software without restriction, including without limitation the rights
214 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
215 | copies of the Software, and to permit persons to whom the Software is
216 | furnished to do so, subject to the following conditions:
217 |
218 | The above copyright notice and this permission notice shall be included in all
219 | copies or substantial portions of the Software.
220 |
221 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
222 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
223 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
224 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
225 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
226 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
227 | SOFTWARE.
228 | ```
229 |
230 | [floating action button]:http://www.google.com/design/spec/components/buttons-floating-action-button.html
231 | [guidelines]:http://www.google.com/design/spec/patterns/promoted-actions.html#promoted-actions-floating-action-button
232 | [Android Asset Studio]:http://romannurik.github.io/AndroidAssetStudio/icons-generic.html
233 | [Finger Gesture Launcher]:https://play.google.com/store/apps/details?id=com.carlosdelachica.finger
234 | [Vocabletrainer]:https://play.google.com/store/apps/details?id=com.rubengees.vocables
235 | [Lanekeep GPS Mileage Tracker]:https://play.google.com/store/apps/details?id=me.hanx.android.dashio&hl=en
236 | [Score It]:https://play.google.com/store/apps/details?id=com.sbgapps.scoreit
237 | [Перезвони мне]:https://play.google.com/store/apps/details?id=com.melnykov.callmeback
238 | [App Swap]:https://play.google.com/store/apps/details?id=net.ebt.appswitch
239 | [QKSMS - Quick Text Messenger]:https://play.google.com/store/apps/details?id=com.moez.QKSMS
240 | [Uninstaller - Beta Version]:https://play.google.com/store/apps/details?id=com.kimcy92.uninstaller
241 | [Device Control]:https://play.google.com/store/apps/details?id=org.namelessrom.devicecontrol
242 | [Confide]:https://play.google.com/store/apps/details?id=cm.confide.android
243 | [Date Night]:https://play.google.com/store/apps/details?id=com.sababado.datenight
244 | [Jair Player The Music Rainbow]:https://play.google.com/store/apps/details?id=aj.jair.music
245 | [Taskr - Lista de Tareas]:https://play.google.com/store/apps/details?id=es.udc.gestortareas
246 | [Festivos: ¡Conoce el mundo!]:https://play.google.com/store/apps/details?id=com.logicapps.holidays
247 | [nowPaper]:https://play.google.com/store/apps/details?id=com.dunrite.now
248 | [Vicious chain - Don't do that!]:https://play.google.com/store/apps/details?id=com.magratheadesign.viciouschain
249 | [My Football Stats]:https://play.google.com/store/apps/details?id=com.nicorz.futbol5
250 | [The ScoreBoard]:https://play.google.com/store/apps/details?id=it.pagano.sp
251 | [NavPoint]:https://play.google.com/store/apps/details?id=com.abi_khalil.remy.nav_point
252 | [Just Reminder]:https://play.google.com/store/apps/details?id=com.cray.software.justreminder
253 | [Early Notes]:https://play.google.com/store/apps/details?id=com.gmail.earlynotesapp.earlynotes
254 | [Ranch - Smart Tip Calculator]:https://play.google.com/store/apps/details?id=com.andreifedianov.android.ranch
255 | [Thiengo Calopsita]:https://play.google.com/store/apps/details?id=br.thiengocalopsita
256 | [Tinycore - CPU, RAM monitor]:https://play.google.com/store/apps/details?id=org.neotech.app.tinycore
257 | [Battery Aid Saver & Manager]:https://play.google.com/store/apps/details?id=com.battery.plusfree
258 | [GameRaven]:https://play.google.com/store/apps/details?id=com.ioabsoftware.gameraven
259 | [Polaris Office]:https://play.google.com/store/apps/details?id=com.infraware.office.link
260 | [Call Utils]:https://play.google.com/store/apps/details?id=callutils.com.scimet.admin.callutils&hl=en
261 | [Colorful Note]:https://play.google.com/store/apps/details?id=notes.colorful
262 | [CallSticker - заметки звонка]:https://play.google.com/store/apps/details?id=ru.vpsoft.callnotesticker
263 |
--------------------------------------------------------------------------------
/art/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/art/demo.gif
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | mavenCentral()
4 | }
5 | dependencies {
6 | classpath 'com.android.tools.build:gradle:1.1.3'
7 | }
8 | }
9 |
10 | allprojects {
11 | version = VERSION_NAME
12 | group = GROUP
13 |
14 | repositories {
15 | mavenCentral()
16 | }
17 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Settings specified in this file will override any Gradle settings
5 | # configured through the IDE.
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
19 |
20 | VERSION_NAME=1.3.0
21 | VERSION_CODE=13
22 | GROUP=com.melnykov
23 |
24 | ANDROID_BUILD_MIN_SDK_VERSION=7
25 | ANDROID_BUILD_TARGET_SDK_VERSION=22
26 | ANDROID_BUILD_SDK_VERSION=22
27 | ANDROID_BUILD_TOOLS_VERSION=22.0.1
28 |
29 | POM_DESCRIPTION=Android floating action button
30 | POM_URL=https://github.com/makovkastar/FloatingActionButton
31 | POM_SCM_URL=https://github.com/makovkastar/FloatingActionButton
32 | POM_SCM_CONNECTION=scm:git@github.com:makovkastar/FloatingActionButton.git
33 | POM_SCM_DEV_CONNECTION=scm:git@github.com:makovkastar/FloatingActionButton.git
34 | POM_LICENCE_NAME=The MIT License (MIT)
35 | POM_LICENCE_URL=https://github.com/makovkastar/FloatingActionButton/blob/master/LICENSE.MD
36 | POM_LICENCE_DIST=repo
37 | POM_DEVELOPER_ID=makovkastar
38 | POM_DEVELOPER_NAME=Oleksandr Melnykov
39 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Nov 24 12:24:27 CET 2014
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.2-all.zip
7 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/library/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | repositories {
4 | mavenCentral()
5 | }
6 |
7 | android {
8 | compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION)
9 | buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION
10 |
11 | defaultConfig {
12 | minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION)
13 | targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)
14 | versionName project.VERSION_NAME
15 | versionCode Integer.parseInt(project.VERSION_CODE)
16 | }
17 |
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | }
22 | }
23 | }
24 |
25 | dependencies {
26 | compile 'com.android.support:support-annotations:22.1.0'
27 | compile 'com.android.support:recyclerview-v7:22.1.0@aar'
28 | compile 'com.nineoldandroids:library:2.4.0'
29 | compile 'com.android.support:support-v4:22.1.1@aar'
30 | }
31 |
32 | apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle'
--------------------------------------------------------------------------------
/library/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=FloatingActionButton
2 | POM_ARTIFACT_ID=floatingactionbutton
3 | POM_PACKAGING=aar
--------------------------------------------------------------------------------
/library/proguard-rules.txt:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:/Users/mea/Downloads/adt-bundle-windows-x86_64-20131030/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the ProGuard
5 | # include property in project.properties.
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 | #}
--------------------------------------------------------------------------------
/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/library/src/main/java/com/melnykov/fab/AbsListViewScrollDetector.java:
--------------------------------------------------------------------------------
1 | package com.melnykov.fab;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.view.View;
5 | import android.widget.AbsListView;
6 |
7 | abstract class AbsListViewScrollDetector implements AbsListView.OnScrollListener {
8 | private int mLastScrollY;
9 | private int mPreviousFirstVisibleItem;
10 | private AbsListView mListView;
11 | private int mScrollThreshold;
12 |
13 | abstract void onScrollUp();
14 |
15 | abstract void onScrollDown();
16 |
17 | @Override
18 | public void onScrollStateChanged(AbsListView view, int scrollState) {
19 | }
20 |
21 | @Override
22 | public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
23 | if(totalItemCount == 0) return;
24 | if (isSameRow(firstVisibleItem)) {
25 | int newScrollY = getTopItemScrollY();
26 | boolean isSignificantDelta = Math.abs(mLastScrollY - newScrollY) > mScrollThreshold;
27 | if (isSignificantDelta) {
28 | if (mLastScrollY > newScrollY) {
29 | onScrollUp();
30 | } else {
31 | onScrollDown();
32 | }
33 | }
34 | mLastScrollY = newScrollY;
35 | } else {
36 | if (firstVisibleItem > mPreviousFirstVisibleItem) {
37 | onScrollUp();
38 | } else {
39 | onScrollDown();
40 | }
41 |
42 | mLastScrollY = getTopItemScrollY();
43 | mPreviousFirstVisibleItem = firstVisibleItem;
44 | }
45 | }
46 |
47 | public void setScrollThreshold(int scrollThreshold) {
48 | mScrollThreshold = scrollThreshold;
49 | }
50 |
51 | public void setListView(@NonNull AbsListView listView) {
52 | mListView = listView;
53 | }
54 |
55 | private boolean isSameRow(int firstVisibleItem) {
56 | return firstVisibleItem == mPreviousFirstVisibleItem;
57 | }
58 |
59 | private int getTopItemScrollY() {
60 | if (mListView == null || mListView.getChildAt(0) == null) return 0;
61 | View topChild = mListView.getChildAt(0);
62 | return topChild.getTop();
63 | }
64 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/melnykov/fab/FloatingActionButton.java:
--------------------------------------------------------------------------------
1 | package com.melnykov.fab;
2 |
3 | import android.animation.AnimatorInflater;
4 | import android.animation.StateListAnimator;
5 | import android.annotation.SuppressLint;
6 | import android.content.Context;
7 | import android.content.res.ColorStateList;
8 | import android.content.res.TypedArray;
9 | import android.graphics.Color;
10 | import android.graphics.Outline;
11 | import android.graphics.drawable.Drawable;
12 | import android.graphics.drawable.LayerDrawable;
13 | import android.graphics.drawable.RippleDrawable;
14 | import android.graphics.drawable.ShapeDrawable;
15 | import android.graphics.drawable.StateListDrawable;
16 | import android.graphics.drawable.shapes.OvalShape;
17 | import android.os.Build;
18 | import android.support.annotation.ColorRes;
19 | import android.support.annotation.DimenRes;
20 | import android.support.annotation.IntDef;
21 | import android.support.annotation.NonNull;
22 | import android.support.v7.widget.RecyclerView;
23 | import android.util.AttributeSet;
24 | import android.view.View;
25 | import android.view.ViewGroup;
26 | import android.view.ViewOutlineProvider;
27 | import android.view.ViewTreeObserver;
28 | import android.view.animation.AccelerateDecelerateInterpolator;
29 | import android.view.animation.Interpolator;
30 | import android.widget.AbsListView;
31 | import android.widget.ImageButton;
32 | import android.widget.ScrollView;
33 |
34 | import com.nineoldandroids.view.ViewHelper;
35 | import com.nineoldandroids.view.ViewPropertyAnimator;
36 |
37 | import java.lang.annotation.Retention;
38 | import java.lang.annotation.RetentionPolicy;
39 |
40 | public class FloatingActionButton extends ImageButton {
41 | private static final int TRANSLATE_DURATION_MILLIS = 200;
42 |
43 | @Retention(RetentionPolicy.SOURCE)
44 | @IntDef({TYPE_NORMAL, TYPE_MINI})
45 | public @interface TYPE {
46 | }
47 |
48 | public static final int TYPE_NORMAL = 0;
49 | public static final int TYPE_MINI = 1;
50 |
51 | private boolean mVisible;
52 |
53 | private int mColorNormal;
54 | private int mColorPressed;
55 | private int mColorRipple;
56 | private int mColorDisabled;
57 | private boolean mShadow;
58 | private int mType;
59 |
60 | private int mShadowSize;
61 |
62 | private int mScrollThreshold;
63 |
64 | private boolean mMarginsSet;
65 |
66 | private final Interpolator mInterpolator = new AccelerateDecelerateInterpolator();
67 |
68 | public FloatingActionButton(Context context) {
69 | this(context, null);
70 | }
71 |
72 | public FloatingActionButton(Context context, AttributeSet attrs) {
73 | super(context, attrs);
74 | init(context, attrs);
75 | }
76 |
77 | public FloatingActionButton(Context context, AttributeSet attrs, int defStyle) {
78 | super(context, attrs, defStyle);
79 | init(context, attrs);
80 | }
81 |
82 | @Override
83 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
84 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
85 | int size = getDimension(
86 | mType == TYPE_NORMAL ? R.dimen.fab_size_normal : R.dimen.fab_size_mini);
87 | if (mShadow && !hasLollipopApi()) {
88 | size += mShadowSize * 2;
89 | setMarginsWithoutShadow();
90 | }
91 | setMeasuredDimension(size, size);
92 | }
93 |
94 | @SuppressLint("NewApi")
95 | private void init(Context context, AttributeSet attributeSet) {
96 | mVisible = true;
97 | mColorNormal = getColor(R.color.material_blue_500);
98 | mColorPressed = darkenColor(mColorNormal);
99 | mColorRipple = lightenColor(mColorNormal);
100 | mColorDisabled = getColor(android.R.color.darker_gray);
101 | mType = TYPE_NORMAL;
102 | mShadow = true;
103 | mScrollThreshold = getResources().getDimensionPixelOffset(R.dimen.fab_scroll_threshold);
104 | mShadowSize = getDimension(R.dimen.fab_shadow_size);
105 | if (hasLollipopApi()) {
106 | StateListAnimator stateListAnimator = AnimatorInflater.loadStateListAnimator(context,
107 | R.anim.fab_press_elevation);
108 | setStateListAnimator(stateListAnimator);
109 | }
110 | if (attributeSet != null) {
111 | initAttributes(context, attributeSet);
112 | }
113 | updateBackground();
114 | }
115 |
116 | private void initAttributes(Context context, AttributeSet attributeSet) {
117 | TypedArray attr = getTypedArray(context, attributeSet, R.styleable.FloatingActionButton);
118 | if (attr != null) {
119 | try {
120 | mColorNormal = attr.getColor(R.styleable.FloatingActionButton_fab_colorNormal,
121 | getColor(R.color.material_blue_500));
122 | mColorPressed = attr.getColor(R.styleable.FloatingActionButton_fab_colorPressed,
123 | darkenColor(mColorNormal));
124 | mColorRipple = attr.getColor(R.styleable.FloatingActionButton_fab_colorRipple,
125 | lightenColor(mColorNormal));
126 | mColorDisabled = attr.getColor(R.styleable.FloatingActionButton_fab_colorDisabled,
127 | mColorDisabled);
128 | mShadow = attr.getBoolean(R.styleable.FloatingActionButton_fab_shadow, true);
129 | mType = attr.getInt(R.styleable.FloatingActionButton_fab_type, TYPE_NORMAL);
130 | } finally {
131 | attr.recycle();
132 | }
133 | }
134 | }
135 |
136 | private void updateBackground() {
137 | StateListDrawable drawable = new StateListDrawable();
138 | drawable.addState(new int[]{android.R.attr.state_pressed}, createDrawable(mColorPressed));
139 | drawable.addState(new int[]{-android.R.attr.state_enabled}, createDrawable(mColorDisabled));
140 | drawable.addState(new int[]{}, createDrawable(mColorNormal));
141 | setBackgroundCompat(drawable);
142 | }
143 |
144 | private Drawable createDrawable(int color) {
145 | OvalShape ovalShape = new OvalShape();
146 | ShapeDrawable shapeDrawable = new ShapeDrawable(ovalShape);
147 | shapeDrawable.getPaint().setColor(color);
148 |
149 | if (mShadow && !hasLollipopApi()) {
150 | Drawable shadowDrawable = getResources().getDrawable(mType == TYPE_NORMAL ? R.drawable.fab_shadow
151 | : R.drawable.fab_shadow_mini);
152 | LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{shadowDrawable, shapeDrawable});
153 | layerDrawable.setLayerInset(1, mShadowSize, mShadowSize, mShadowSize, mShadowSize);
154 | return layerDrawable;
155 | } else {
156 | return shapeDrawable;
157 | }
158 | }
159 |
160 | private TypedArray getTypedArray(Context context, AttributeSet attributeSet, int[] attr) {
161 | return context.obtainStyledAttributes(attributeSet, attr, 0, 0);
162 | }
163 |
164 | private int getColor(@ColorRes int id) {
165 | return getResources().getColor(id);
166 | }
167 |
168 | private int getDimension(@DimenRes int id) {
169 | return getResources().getDimensionPixelSize(id);
170 | }
171 |
172 | private void setMarginsWithoutShadow() {
173 | if (!mMarginsSet) {
174 | if (getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
175 | ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
176 | int leftMargin = layoutParams.leftMargin - mShadowSize;
177 | int topMargin = layoutParams.topMargin - mShadowSize;
178 | int rightMargin = layoutParams.rightMargin - mShadowSize;
179 | int bottomMargin = layoutParams.bottomMargin - mShadowSize;
180 | layoutParams.setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
181 |
182 | requestLayout();
183 | mMarginsSet = true;
184 | }
185 | }
186 | }
187 |
188 | @SuppressWarnings("deprecation")
189 | @SuppressLint("NewApi")
190 | private void setBackgroundCompat(Drawable drawable) {
191 | if (hasLollipopApi()) {
192 | float elevation;
193 | if (mShadow) {
194 | elevation = getElevation() > 0.0f ? getElevation()
195 | : getDimension(R.dimen.fab_elevation_lollipop);
196 | } else {
197 | elevation = 0.0f;
198 | }
199 | setElevation(elevation);
200 | RippleDrawable rippleDrawable = new RippleDrawable(new ColorStateList(new int[][]{{}},
201 | new int[]{mColorRipple}), drawable, null);
202 | setOutlineProvider(new ViewOutlineProvider() {
203 | @Override
204 | public void getOutline(View view, Outline outline) {
205 | int size = getDimension(mType == TYPE_NORMAL ? R.dimen.fab_size_normal
206 | : R.dimen.fab_size_mini);
207 | outline.setOval(0, 0, size, size);
208 | }
209 | });
210 | setClipToOutline(true);
211 | setBackground(rippleDrawable);
212 | } else if (hasJellyBeanApi()) {
213 | setBackground(drawable);
214 | } else {
215 | setBackgroundDrawable(drawable);
216 | }
217 | }
218 |
219 | private int getMarginBottom() {
220 | int marginBottom = 0;
221 | final ViewGroup.LayoutParams layoutParams = getLayoutParams();
222 | if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
223 | marginBottom = ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin;
224 | }
225 | return marginBottom;
226 | }
227 |
228 | public void setColorNormal(int color) {
229 | if (color != mColorNormal) {
230 | mColorNormal = color;
231 | updateBackground();
232 | }
233 | }
234 |
235 | public void setColorNormalResId(@ColorRes int colorResId) {
236 | setColorNormal(getColor(colorResId));
237 | }
238 |
239 | public int getColorNormal() {
240 | return mColorNormal;
241 | }
242 |
243 | public void setColorPressed(int color) {
244 | if (color != mColorPressed) {
245 | mColorPressed = color;
246 | updateBackground();
247 | }
248 | }
249 |
250 | public void setColorPressedResId(@ColorRes int colorResId) {
251 | setColorPressed(getColor(colorResId));
252 | }
253 |
254 | public int getColorPressed() {
255 | return mColorPressed;
256 | }
257 |
258 | public void setColorRipple(int color) {
259 | if (color != mColorRipple) {
260 | mColorRipple = color;
261 | updateBackground();
262 | }
263 | }
264 |
265 | public void setColorRippleResId(@ColorRes int colorResId) {
266 | setColorRipple(getColor(colorResId));
267 | }
268 |
269 | public int getColorRipple() {
270 | return mColorRipple;
271 | }
272 |
273 | public void setShadow(boolean shadow) {
274 | if (shadow != mShadow) {
275 | mShadow = shadow;
276 | updateBackground();
277 | }
278 | }
279 |
280 | public boolean hasShadow() {
281 | return mShadow;
282 | }
283 |
284 | public void setType(@TYPE int type) {
285 | if (type != mType) {
286 | mType = type;
287 | updateBackground();
288 | }
289 | }
290 |
291 | @TYPE
292 | public int getType() {
293 | return mType;
294 | }
295 |
296 | public boolean isVisible() {
297 | return mVisible;
298 | }
299 |
300 | public void show() {
301 | show(true);
302 | }
303 |
304 | public void hide() {
305 | hide(true);
306 | }
307 |
308 | public void show(boolean animate) {
309 | toggle(true, animate, false);
310 | }
311 |
312 | public void hide(boolean animate) {
313 | toggle(false, animate, false);
314 | }
315 |
316 | private void toggle(final boolean visible, final boolean animate, boolean force) {
317 | if (mVisible != visible || force) {
318 | mVisible = visible;
319 | int height = getHeight();
320 | if (height == 0 && !force) {
321 | ViewTreeObserver vto = getViewTreeObserver();
322 | if (vto.isAlive()) {
323 | vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
324 | @Override
325 | public boolean onPreDraw() {
326 | ViewTreeObserver currentVto = getViewTreeObserver();
327 | if (currentVto.isAlive()) {
328 | currentVto.removeOnPreDrawListener(this);
329 | }
330 | toggle(visible, animate, true);
331 | return true;
332 | }
333 | });
334 | return;
335 | }
336 | }
337 | int translationY = visible ? 0 : height + getMarginBottom();
338 | if (animate) {
339 | ViewPropertyAnimator.animate(this).setInterpolator(mInterpolator)
340 | .setDuration(TRANSLATE_DURATION_MILLIS)
341 | .translationY(translationY);
342 | } else {
343 | ViewHelper.setTranslationY(this, translationY);
344 | }
345 |
346 | // On pre-Honeycomb a translated view is still clickable, so we need to disable clicks manually
347 | if (!hasHoneycombApi()) {
348 | setClickable(visible);
349 | }
350 | }
351 | }
352 |
353 | public void attachToListView(@NonNull AbsListView listView) {
354 | attachToListView(listView, null, null);
355 | }
356 |
357 | public void attachToListView(@NonNull AbsListView listView,
358 | ScrollDirectionListener scrollDirectionListener) {
359 | attachToListView(listView, scrollDirectionListener, null);
360 | }
361 |
362 | public void attachToRecyclerView(@NonNull RecyclerView recyclerView) {
363 | attachToRecyclerView(recyclerView, null, null);
364 | }
365 |
366 | public void attachToRecyclerView(@NonNull RecyclerView recyclerView,
367 | ScrollDirectionListener scrollDirectionListener) {
368 | attachToRecyclerView(recyclerView, scrollDirectionListener, null);
369 | }
370 |
371 | public void attachToScrollView(@NonNull ObservableScrollView scrollView) {
372 | attachToScrollView(scrollView, null, null);
373 | }
374 |
375 | public void attachToScrollView(@NonNull ObservableScrollView scrollView,
376 | ScrollDirectionListener scrollDirectionListener) {
377 | attachToScrollView(scrollView, scrollDirectionListener, null);
378 | }
379 |
380 | public void attachToListView(@NonNull AbsListView listView,
381 | ScrollDirectionListener scrollDirectionListener,
382 | AbsListView.OnScrollListener onScrollListener) {
383 | AbsListViewScrollDetectorImpl scrollDetector = new AbsListViewScrollDetectorImpl();
384 | scrollDetector.setScrollDirectionListener(scrollDirectionListener);
385 | scrollDetector.setOnScrollListener(onScrollListener);
386 | scrollDetector.setListView(listView);
387 | scrollDetector.setScrollThreshold(mScrollThreshold);
388 | listView.setOnScrollListener(scrollDetector);
389 | }
390 |
391 | public void attachToRecyclerView(@NonNull RecyclerView recyclerView,
392 | ScrollDirectionListener scrollDirectionlistener,
393 | RecyclerView.OnScrollListener onScrollListener) {
394 | RecyclerViewScrollDetectorImpl scrollDetector = new RecyclerViewScrollDetectorImpl();
395 | scrollDetector.setScrollDirectionListener(scrollDirectionlistener);
396 | scrollDetector.setOnScrollListener(onScrollListener);
397 | scrollDetector.setScrollThreshold(mScrollThreshold);
398 | recyclerView.addOnScrollListener(scrollDetector);
399 | }
400 |
401 | public void attachToScrollView(@NonNull ObservableScrollView scrollView,
402 | ScrollDirectionListener scrollDirectionListener,
403 | ObservableScrollView.OnScrollChangedListener onScrollChangedListener) {
404 | ScrollViewScrollDetectorImpl scrollDetector = new ScrollViewScrollDetectorImpl();
405 | scrollDetector.setScrollDirectionListener(scrollDirectionListener);
406 | scrollDetector.setOnScrollChangedListener(onScrollChangedListener);
407 | scrollDetector.setScrollThreshold(mScrollThreshold);
408 | scrollView.setOnScrollChangedListener(scrollDetector);
409 | }
410 |
411 | private boolean hasLollipopApi() {
412 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
413 | }
414 |
415 | private boolean hasJellyBeanApi() {
416 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
417 | }
418 |
419 | private boolean hasHoneycombApi() {
420 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
421 | }
422 |
423 | private static int darkenColor(int color) {
424 | float[] hsv = new float[3];
425 | Color.colorToHSV(color, hsv);
426 | hsv[2] *= 0.9f;
427 | return Color.HSVToColor(hsv);
428 | }
429 |
430 | private static int lightenColor(int color) {
431 | float[] hsv = new float[3];
432 | Color.colorToHSV(color, hsv);
433 | hsv[2] *= 1.1f;
434 | return Color.HSVToColor(hsv);
435 | }
436 |
437 | private class AbsListViewScrollDetectorImpl extends AbsListViewScrollDetector {
438 | private ScrollDirectionListener mScrollDirectionListener;
439 | private AbsListView.OnScrollListener mOnScrollListener;
440 |
441 | private void setScrollDirectionListener(ScrollDirectionListener scrollDirectionListener) {
442 | mScrollDirectionListener = scrollDirectionListener;
443 | }
444 |
445 | public void setOnScrollListener(AbsListView.OnScrollListener onScrollListener) {
446 | mOnScrollListener = onScrollListener;
447 | }
448 |
449 | @Override
450 | public void onScrollDown() {
451 | show();
452 | if (mScrollDirectionListener != null) {
453 | mScrollDirectionListener.onScrollDown();
454 | }
455 | }
456 |
457 | @Override
458 | public void onScrollUp() {
459 | hide();
460 | if (mScrollDirectionListener != null) {
461 | mScrollDirectionListener.onScrollUp();
462 | }
463 | }
464 |
465 | @Override
466 | public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
467 | int totalItemCount) {
468 | if (mOnScrollListener != null) {
469 | mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
470 | }
471 |
472 | super.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
473 | }
474 |
475 | @Override
476 | public void onScrollStateChanged(AbsListView view, int scrollState) {
477 | if (mOnScrollListener != null) {
478 | mOnScrollListener.onScrollStateChanged(view, scrollState);
479 | }
480 |
481 | super.onScrollStateChanged(view, scrollState);
482 | }
483 | }
484 |
485 | private class RecyclerViewScrollDetectorImpl extends RecyclerViewScrollDetector {
486 | private ScrollDirectionListener mScrollDirectionListener;
487 | private RecyclerView.OnScrollListener mOnScrollListener;
488 |
489 | private void setScrollDirectionListener(ScrollDirectionListener scrollDirectionListener) {
490 | mScrollDirectionListener = scrollDirectionListener;
491 | }
492 |
493 | public void setOnScrollListener(RecyclerView.OnScrollListener onScrollListener) {
494 | mOnScrollListener = onScrollListener;
495 | }
496 |
497 | @Override
498 | public void onScrollDown() {
499 | show();
500 | if (mScrollDirectionListener != null) {
501 | mScrollDirectionListener.onScrollDown();
502 | }
503 | }
504 |
505 | @Override
506 | public void onScrollUp() {
507 | hide();
508 | if (mScrollDirectionListener != null) {
509 | mScrollDirectionListener.onScrollUp();
510 | }
511 | }
512 |
513 | @Override
514 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
515 | if (mOnScrollListener != null) {
516 | mOnScrollListener.onScrolled(recyclerView, dx, dy);
517 | }
518 |
519 | super.onScrolled(recyclerView, dx, dy);
520 | }
521 |
522 | @Override
523 | public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
524 | if (mOnScrollListener != null) {
525 | mOnScrollListener.onScrollStateChanged(recyclerView, newState);
526 | }
527 |
528 | super.onScrollStateChanged(recyclerView, newState);
529 | }
530 | }
531 |
532 | private class ScrollViewScrollDetectorImpl extends ScrollViewScrollDetector {
533 | private ScrollDirectionListener mScrollDirectionListener;
534 |
535 | private ObservableScrollView.OnScrollChangedListener mOnScrollChangedListener;
536 |
537 | private void setScrollDirectionListener(ScrollDirectionListener scrollDirectionListener) {
538 | mScrollDirectionListener = scrollDirectionListener;
539 | }
540 |
541 | public void setOnScrollChangedListener(ObservableScrollView.OnScrollChangedListener onScrollChangedListener) {
542 | mOnScrollChangedListener = onScrollChangedListener;
543 | }
544 |
545 | @Override
546 | public void onScrollDown() {
547 | show();
548 | if (mScrollDirectionListener != null) {
549 | mScrollDirectionListener.onScrollDown();
550 | }
551 | }
552 |
553 | @Override
554 | public void onScrollUp() {
555 | hide();
556 | if (mScrollDirectionListener != null) {
557 | mScrollDirectionListener.onScrollUp();
558 | }
559 | }
560 |
561 | @Override
562 | public void onScrollChanged(ScrollView who, int l, int t, int oldl, int oldt) {
563 | if (mOnScrollChangedListener != null) {
564 | mOnScrollChangedListener.onScrollChanged(who, l, t, oldl, oldt);
565 | }
566 |
567 | super.onScrollChanged(who, l, t, oldl, oldt);
568 | }
569 | }
570 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/melnykov/fab/ObservableScrollView.java:
--------------------------------------------------------------------------------
1 | package com.melnykov.fab;
2 |
3 |
4 | import android.content.Context;
5 | import android.util.AttributeSet;
6 | import android.widget.ScrollView;
7 |
8 | public class ObservableScrollView extends ScrollView {
9 |
10 | public interface OnScrollChangedListener {
11 | void onScrollChanged(ScrollView who, int l, int t, int oldl, int oldt);
12 | }
13 |
14 | private OnScrollChangedListener mOnScrollChangedListener;
15 |
16 | public ObservableScrollView(Context context) {
17 | super(context);
18 | }
19 |
20 | public ObservableScrollView(Context context, AttributeSet attrs) {
21 | super(context, attrs);
22 | }
23 |
24 | public ObservableScrollView(Context context, AttributeSet attrs, int defStyle) {
25 | super(context, attrs, defStyle);
26 | }
27 |
28 | @Override
29 | protected void onScrollChanged(int l, int t, int oldl, int oldt) {
30 | super.onScrollChanged(l, t, oldl, oldt);
31 | if (mOnScrollChangedListener != null) {
32 | mOnScrollChangedListener.onScrollChanged(this, l, t, oldl, oldt);
33 | }
34 | }
35 |
36 | public void setOnScrollChangedListener(OnScrollChangedListener listener) {
37 | mOnScrollChangedListener = listener;
38 | }
39 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/melnykov/fab/RecyclerViewScrollDetector.java:
--------------------------------------------------------------------------------
1 | package com.melnykov.fab;
2 |
3 | import android.support.v7.widget.RecyclerView;
4 |
5 | abstract class RecyclerViewScrollDetector extends RecyclerView.OnScrollListener {
6 | private int mScrollThreshold;
7 |
8 | abstract void onScrollUp();
9 |
10 | abstract void onScrollDown();
11 |
12 | @Override
13 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
14 | boolean isSignificantDelta = Math.abs(dy) > mScrollThreshold;
15 | if (isSignificantDelta) {
16 | if (dy > 0) {
17 | onScrollUp();
18 | } else {
19 | onScrollDown();
20 | }
21 | }
22 | }
23 |
24 | public void setScrollThreshold(int scrollThreshold) {
25 | mScrollThreshold = scrollThreshold;
26 | }
27 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/melnykov/fab/ScrollDirectionListener.java:
--------------------------------------------------------------------------------
1 | package com.melnykov.fab;
2 |
3 | public interface ScrollDirectionListener {
4 | void onScrollDown();
5 |
6 | void onScrollUp();
7 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/melnykov/fab/ScrollViewScrollDetector.java:
--------------------------------------------------------------------------------
1 | package com.melnykov.fab;
2 |
3 | import android.widget.ScrollView;
4 |
5 | abstract class ScrollViewScrollDetector implements ObservableScrollView.OnScrollChangedListener {
6 | private int mLastScrollY;
7 | private int mScrollThreshold;
8 |
9 | abstract void onScrollUp();
10 |
11 | abstract void onScrollDown();
12 |
13 | @Override
14 | public void onScrollChanged(ScrollView who, int l, int t, int oldl, int oldt) {
15 | boolean isSignificantDelta = Math.abs(t - mLastScrollY) > mScrollThreshold;
16 | if (isSignificantDelta) {
17 | if (t > mLastScrollY) {
18 | onScrollUp();
19 | } else {
20 | onScrollDown();
21 | }
22 | }
23 | mLastScrollY = t;
24 | }
25 |
26 | public void setScrollThreshold(int scrollThreshold) {
27 | mScrollThreshold = scrollThreshold;
28 | }
29 | }
--------------------------------------------------------------------------------
/library/src/main/res/anim-v21/fab_press_elevation.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
7 |
8 |
13 |
14 |
15 | -
16 |
17 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable-hdpi/fab_shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/library/src/main/res/drawable-hdpi/fab_shadow.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-hdpi/fab_shadow_mini.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/library/src/main/res/drawable-hdpi/fab_shadow_mini.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-mdpi/fab_shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/library/src/main/res/drawable-mdpi/fab_shadow.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-mdpi/fab_shadow_mini.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/library/src/main/res/drawable-mdpi/fab_shadow_mini.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-xhdpi/fab_shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/library/src/main/res/drawable-xhdpi/fab_shadow.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-xhdpi/fab_shadow_mini.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/library/src/main/res/drawable-xhdpi/fab_shadow_mini.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-xxhdpi/fab_shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/library/src/main/res/drawable-xxhdpi/fab_shadow.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-xxhdpi/fab_shadow_mini.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/library/src/main/res/drawable-xxhdpi/fab_shadow_mini.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-xxxhdpi/fab_shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/library/src/main/res/drawable-xxxhdpi/fab_shadow.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-xxxhdpi/fab_shadow_mini.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/library/src/main/res/drawable-xxxhdpi/fab_shadow_mini.png
--------------------------------------------------------------------------------
/library/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/library/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | #5677fc
6 |
--------------------------------------------------------------------------------
/library/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 56dp
5 | 40dp
6 | 12dp
7 |
8 | 4dp
9 | 8dp
10 | 6dp
11 |
12 |
--------------------------------------------------------------------------------
/library/src/main/res/values/info_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Oleksandr Melnykov
7 | https://github.com/makovkastar/FloatingActionButton
8 |
9 | FloatingActionButton
10 | Android Google+ like floating action button which reacts on the list view scrolling events. Becomes visible when the list view is scrolled up and invisible when scrolled down.
11 | https://github.com/makovkastar/FloatingActionButton
12 | 1.0.0
13 |
14 | true
15 | https://github.com/makovkastar/FloatingActionButton
16 |
17 | mit
18 |
19 |
--------------------------------------------------------------------------------
/sample.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample.apk
--------------------------------------------------------------------------------
/sample/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/sample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION)
5 | buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION
6 |
7 | defaultConfig {
8 | applicationId 'com.melnykov.fab.sample'
9 | minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION)
10 | targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)
11 | versionName project.VERSION_NAME
12 | versionCode Integer.parseInt(project.VERSION_CODE)
13 | }
14 |
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile project(':library')
24 | compile 'com.android.support:appcompat-v7:22.1.0@aar'
25 | compile 'com.android.support:recyclerview-v7:22.1.0@aar'
26 | compile 'com.android.support:support-v4:22.1.0@aar'
27 | }
--------------------------------------------------------------------------------
/sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/melnykov/fab/sample/DividerItemDecoration.java:
--------------------------------------------------------------------------------
1 | package com.melnykov.fab.sample;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Canvas;
6 | import android.graphics.Rect;
7 | import android.graphics.drawable.Drawable;
8 | import android.support.v7.widget.LinearLayoutManager;
9 | import android.support.v7.widget.RecyclerView;
10 | import android.view.View;
11 |
12 | /*
13 | * Copyright (C) 2014 The Android Open Source Project
14 | *
15 | * Licensed under the Apache License, Version 2.0 (the "License");
16 | * you may not use this file except in compliance with the License.
17 | * You may obtain a copy of the License at
18 | *
19 | * http://www.apache.org/licenses/LICENSE-2.0
20 | *
21 | * Unless required by applicable law or agreed to in writing, software
22 | * distributed under the License is distributed on an "AS IS" BASIS,
23 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 | * See the License for the specific language governing permissions and
25 | * limitations under the License.
26 | */
27 | public class DividerItemDecoration extends RecyclerView.ItemDecoration {
28 |
29 | private static final int[] ATTRS = new int[]{
30 | android.R.attr.listDivider
31 | };
32 |
33 | public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
34 |
35 | public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
36 |
37 | private Drawable mDivider;
38 |
39 | private int mOrientation;
40 |
41 | public DividerItemDecoration(Context context, int orientation) {
42 | final TypedArray a = context.obtainStyledAttributes(ATTRS);
43 | mDivider = a.getDrawable(0);
44 | a.recycle();
45 | setOrientation(orientation);
46 | }
47 |
48 | public void setOrientation(int orientation) {
49 | if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
50 | throw new IllegalArgumentException("invalid orientation");
51 | }
52 | mOrientation = orientation;
53 | }
54 |
55 | @Override
56 | public void onDraw(Canvas c, RecyclerView parent) {
57 | if (mOrientation == VERTICAL_LIST) {
58 | drawVertical(c, parent);
59 | } else {
60 | drawHorizontal(c, parent);
61 | }
62 | }
63 |
64 | public void drawVertical(Canvas c, RecyclerView parent) {
65 | final int left = parent.getPaddingLeft();
66 | final int right = parent.getWidth() - parent.getPaddingRight();
67 |
68 | final int childCount = parent.getChildCount();
69 | for (int i = 0; i < childCount; i++) {
70 | final View child = parent.getChildAt(i);
71 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
72 | .getLayoutParams();
73 | final int top = child.getBottom() + params.bottomMargin;
74 | final int bottom = top + mDivider.getIntrinsicHeight();
75 | mDivider.setBounds(left, top, right, bottom);
76 | mDivider.draw(c);
77 | }
78 | }
79 |
80 | public void drawHorizontal(Canvas c, RecyclerView parent) {
81 | final int top = parent.getPaddingTop();
82 | final int bottom = parent.getHeight() - parent.getPaddingBottom();
83 |
84 | final int childCount = parent.getChildCount();
85 | for (int i = 0; i < childCount; i++) {
86 | final View child = parent.getChildAt(i);
87 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
88 | .getLayoutParams();
89 | final int left = child.getRight() + params.rightMargin;
90 | final int right = left + mDivider.getIntrinsicHeight();
91 | mDivider.setBounds(left, top, right, bottom);
92 | mDivider.draw(c);
93 | }
94 | }
95 |
96 | @Override
97 | public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
98 | if (mOrientation == VERTICAL_LIST) {
99 | outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
100 | } else {
101 | outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
102 | }
103 | }
104 | }
--------------------------------------------------------------------------------
/sample/src/main/java/com/melnykov/fab/sample/ListViewAdapter.java:
--------------------------------------------------------------------------------
1 | package com.melnykov.fab.sample;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.BaseAdapter;
8 | import android.widget.TextView;
9 |
10 | public class ListViewAdapter extends BaseAdapter {
11 | private final Context mContext;
12 | private final String[] mDataset;
13 |
14 | public ListViewAdapter(Context context, String[] dataset) {
15 | mContext = context;
16 | mDataset = dataset;
17 | }
18 |
19 | @Override
20 | public int getCount() {
21 | return mDataset.length;
22 | }
23 |
24 | @Override
25 | public String getItem(int position) {
26 | return mDataset[position];
27 | }
28 |
29 | @Override
30 | public long getItemId(int position) {
31 | return position;
32 | }
33 |
34 | @Override
35 | public View getView(int position, View convertView, ViewGroup parent) {
36 | ViewHolder viewHolder;
37 | if (convertView == null) {
38 | convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item, parent, false);
39 | viewHolder = new ViewHolder();
40 | viewHolder.mTextView = (TextView) convertView.findViewById(android.R.id.text1);
41 | convertView.setTag(viewHolder);
42 | } else {
43 | viewHolder = (ViewHolder) convertView.getTag();
44 | }
45 |
46 | String[] values = mDataset[position].split(",");
47 | String countryName = values[0];
48 | int flagResId = mContext.getResources().getIdentifier(values[1], "drawable", mContext.getPackageName());
49 | viewHolder.mTextView.setText(countryName);
50 | viewHolder.mTextView.setCompoundDrawablesWithIntrinsicBounds(flagResId, 0, 0, 0);
51 |
52 | return convertView;
53 | }
54 |
55 | private static class ViewHolder {
56 | public TextView mTextView;
57 | }
58 | }
--------------------------------------------------------------------------------
/sample/src/main/java/com/melnykov/fab/sample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.melnykov.fab.sample;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.app.AlertDialog;
5 | import android.content.DialogInterface;
6 | import android.os.Bundle;
7 | import android.support.v4.app.Fragment;
8 | import android.support.v4.app.FragmentTransaction;
9 | import android.support.v7.app.ActionBar;
10 | import android.support.v7.app.AppCompatActivity;
11 | import android.support.v7.widget.DefaultItemAnimator;
12 | import android.support.v7.widget.LinearLayoutManager;
13 | import android.support.v7.widget.RecyclerView;
14 | import android.text.Html;
15 | import android.text.method.LinkMovementMethod;
16 | import android.util.Log;
17 | import android.view.LayoutInflater;
18 | import android.view.Menu;
19 | import android.view.MenuItem;
20 | import android.view.View;
21 | import android.view.ViewGroup;
22 | import android.widget.AbsListView;
23 | import android.widget.LinearLayout;
24 | import android.widget.ListView;
25 | import android.widget.TextView;
26 |
27 | import com.melnykov.fab.FloatingActionButton;
28 | import com.melnykov.fab.ObservableScrollView;
29 | import com.melnykov.fab.ScrollDirectionListener;
30 |
31 | public class MainActivity extends AppCompatActivity {
32 |
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState) {
35 | super.onCreate(savedInstanceState);
36 | initActionBar();
37 | }
38 |
39 | @SuppressWarnings("deprecation")
40 | private void initActionBar() {
41 | if (getSupportActionBar() != null) {
42 | ActionBar actionBar = getSupportActionBar();
43 | actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
44 | actionBar.addTab(actionBar.newTab()
45 | .setText("ListView")
46 | .setTabListener(new ActionBar.TabListener() {
47 | @Override
48 | public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
49 | fragmentTransaction.replace(android.R.id.content, new ListViewFragment());
50 | }
51 |
52 | @Override
53 | public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
54 | }
55 |
56 | @Override
57 | public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
58 | }
59 | }));
60 | actionBar.addTab(actionBar.newTab()
61 | .setText("RecyclerView")
62 | .setTabListener(new ActionBar.TabListener() {
63 | @Override
64 | public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
65 | fragmentTransaction.replace(android.R.id.content, new RecyclerViewFragment());
66 | }
67 |
68 | @Override
69 | public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
70 | }
71 |
72 | @Override
73 | public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
74 | }
75 | }));
76 | actionBar.addTab(actionBar.newTab()
77 | .setText("ScrollView")
78 | .setTabListener(new ActionBar.TabListener() {
79 | @Override
80 | public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
81 | fragmentTransaction.replace(android.R.id.content, new ScrollViewFragment());
82 | }
83 |
84 | @Override
85 | public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
86 | }
87 |
88 | @Override
89 | public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
90 | }
91 | }));
92 | }
93 | }
94 |
95 | @Override
96 | public boolean onCreateOptionsMenu(Menu menu) {
97 | getMenuInflater().inflate(R.menu.main, menu);
98 | return super.onCreateOptionsMenu(menu);
99 | }
100 |
101 | @Override
102 | public boolean onOptionsItemSelected(MenuItem item) {
103 | if (item.getItemId() == R.id.about) {
104 | TextView content = (TextView) getLayoutInflater().inflate(R.layout.about_view, null);
105 | content.setMovementMethod(LinkMovementMethod.getInstance());
106 | content.setText(Html.fromHtml(getString(R.string.about_body)));
107 | new AlertDialog.Builder(this)
108 | .setTitle(R.string.about)
109 | .setView(content)
110 | .setInverseBackgroundForced(true)
111 | .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
112 | @Override
113 | public void onClick(DialogInterface dialog, int which) {
114 | dialog.dismiss();
115 | }
116 | }).create().show();
117 | }
118 | return super.onOptionsItemSelected(item);
119 | }
120 |
121 | public static class ListViewFragment extends Fragment {
122 |
123 | @SuppressLint("InflateParams")
124 | @Override
125 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
126 | View root = inflater.inflate(R.layout.fragment_listview, container, false);
127 |
128 | ListView list = (ListView) root.findViewById(android.R.id.list);
129 | ListViewAdapter listAdapter = new ListViewAdapter(getActivity(),
130 | getResources().getStringArray(R.array.countries));
131 | list.setAdapter(listAdapter);
132 |
133 | FloatingActionButton fab = (FloatingActionButton) root.findViewById(R.id.fab);
134 | fab.attachToListView(list, new ScrollDirectionListener() {
135 | @Override
136 | public void onScrollDown() {
137 | Log.d("ListViewFragment", "onScrollDown()");
138 | }
139 |
140 | @Override
141 | public void onScrollUp() {
142 | Log.d("ListViewFragment", "onScrollUp()");
143 | }
144 | }, new AbsListView.OnScrollListener() {
145 | @Override
146 | public void onScrollStateChanged(AbsListView view, int scrollState) {
147 | Log.d("ListViewFragment", "onScrollStateChanged()");
148 | }
149 |
150 | @Override
151 | public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
152 | Log.d("ListViewFragment", "onScroll()");
153 | }
154 | });
155 |
156 | return root;
157 | }
158 | }
159 |
160 | public static class RecyclerViewFragment extends Fragment {
161 | @Override
162 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
163 | View root = inflater.inflate(R.layout.fragment_recyclerview, container, false);
164 |
165 | RecyclerView recyclerView = (RecyclerView) root.findViewById(R.id.recycler_view);
166 | recyclerView.setHasFixedSize(true);
167 | recyclerView.setItemAnimator(new DefaultItemAnimator());
168 | recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
169 | recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
170 |
171 | RecyclerViewAdapter adapter = new RecyclerViewAdapter(getActivity(), getResources()
172 | .getStringArray(R.array.countries));
173 | recyclerView.setAdapter(adapter);
174 |
175 | FloatingActionButton fab = (FloatingActionButton) root.findViewById(R.id.fab);
176 | fab.attachToRecyclerView(recyclerView);
177 |
178 | return root;
179 | }
180 | }
181 |
182 | public static class ScrollViewFragment extends Fragment {
183 | @Override
184 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
185 | View root = inflater.inflate(R.layout.fragment_scrollview, container, false);
186 |
187 | ObservableScrollView scrollView = (ObservableScrollView) root.findViewById(R.id.scroll_view);
188 | LinearLayout list = (LinearLayout) root.findViewById(R.id.list);
189 |
190 | String[] countries = getResources().getStringArray(R.array.countries);
191 | for (String country : countries) {
192 | TextView textView = (TextView) inflater.inflate(R.layout.list_item, container, false);
193 | String[] values = country.split(",");
194 | String countryName = values[0];
195 | int flagResId = getResources().getIdentifier(values[1], "drawable", getActivity().getPackageName());
196 | textView.setText(countryName);
197 | textView.setCompoundDrawablesWithIntrinsicBounds(flagResId, 0, 0, 0);
198 |
199 | list.addView(textView);
200 | }
201 |
202 | FloatingActionButton fab = (FloatingActionButton) root.findViewById(R.id.fab);
203 | fab.attachToScrollView(scrollView);
204 |
205 | return root;
206 | }
207 | }
208 | }
--------------------------------------------------------------------------------
/sample/src/main/java/com/melnykov/fab/sample/RecyclerViewAdapter.java:
--------------------------------------------------------------------------------
1 | package com.melnykov.fab.sample;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.LayoutInflater;
6 | import android.view.ViewGroup;
7 | import android.widget.TextView;
8 |
9 | public class RecyclerViewAdapter extends RecyclerView.Adapter {
10 | private final Context mContext;
11 | private final String[] mDataset;
12 |
13 | public RecyclerViewAdapter(Context context, String[] dataset) {
14 | mContext = context;
15 | mDataset = dataset;
16 | }
17 |
18 | @Override
19 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
20 | TextView view = (TextView) LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
21 | return new ViewHolder(view);
22 | }
23 |
24 | @Override
25 | public void onBindViewHolder(ViewHolder viewHolder, int position) {
26 | String[] values = mDataset[position].split(",");
27 | String countryName = values[0];
28 | int flagResId = mContext.getResources().getIdentifier(values[1], "drawable", mContext.getPackageName());
29 | viewHolder.mTextView.setText(countryName);
30 | viewHolder.mTextView.setCompoundDrawablesWithIntrinsicBounds(flagResId, 0, 0, 0);
31 | }
32 |
33 | @Override
34 | public int getItemCount() {
35 | return mDataset.length;
36 | }
37 |
38 | public static class ViewHolder extends RecyclerView.ViewHolder {
39 | public TextView mTextView;
40 |
41 | public ViewHolder(TextView v) {
42 | super(v);
43 | mTextView = v;
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/ic_add_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-hdpi/ic_add_white_24dp.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-mdpi/ic_add_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-mdpi/ic_add_white_24dp.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/ic_add_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xhdpi/ic_add_white_24dp.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/at.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/at.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/au.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/au.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/br.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/br.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/ca.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/ca.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/ch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/ch.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/cl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/cl.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/cn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/cn.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/cz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/cz.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/de.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/de.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/dk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/dk.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/ee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/ee.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/fi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/fi.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/fr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/fr.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/gr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/gr.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/hr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/hr.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/hu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/hu.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/ic_add_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/ic_add_white_24dp.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/ie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/ie.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/in.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/in.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/is.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/is.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/it.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/it.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/lt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/lt.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/lv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/lv.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/nl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/nl.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/no.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/no.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/nz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/nz.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/se.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/se.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/ua.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/ua.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/us.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxhdpi/us.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxxhdpi/ic_add_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxxhdpi/ic_add_white_24dp.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makovkastar/FloatingActionButton/06efd32191812222ea567fe8ae133309112e917f/sample/src/main/res/drawable-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/divider.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/about_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/fragment_listview.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
14 |
15 |
25 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/fragment_recyclerview.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
14 |
15 |
25 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/fragment_scrollview.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
10 |
11 |
18 |
19 |
20 |
30 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/sample/src/main/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sample/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - Australia,au
5 | - Austria,at
6 | - Brazil,br
7 | - Canada,ca
8 | - Chile,cl
9 | - China,cn
10 | - Croatia,hr
11 | - Czech Republic,cz
12 | - Denmark,dk
13 | - Estonia,ee
14 | - Finland,fi
15 | - France,fr
16 | - Germany,de
17 | - Greece,gr
18 | - Hungary,hu
19 | - Iceland,is
20 | - India,in
21 | - Ireland,ie
22 | - Italy,it
23 | - Latvia,lv
24 | - Lithuania,lt
25 | - Netherlands,nl
26 | - New Zealand,nz
27 | - Norway,no
28 | - Sweden,se
29 | - Switzerland,ch
30 | - Ukraine,ua
31 | - United States,us
32 |
33 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3f51b5
4 | #303f9f
5 | #F06292
6 | #E91E63
7 | #C2185B
8 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Floating Action Button
4 | About
5 | Oleksandr Melnykov.
7 | https://github.com/makovkastar/FloatingActionButton
8 | ]]>
9 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':library', ':sample'
--------------------------------------------------------------------------------