├── .gitignore ├── LICENSE.md ├── README.md ├── build.gradle ├── device-2015-05-04-090851.png ├── device-2015-05-04-090914.png ├── device-2015-05-04-090952.png ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── AndroidManifest.xml ├── build.gradle ├── res │ ├── layout │ │ └── mt_tab.xml │ └── values │ │ └── attrs.xml └── src │ └── io │ └── karim │ ├── MaterialRippleLayout.java │ ├── MaterialTabs.java │ └── Utils.java ├── sample ├── AndroidManifest.xml ├── build.gradle ├── res │ ├── drawable-hdpi │ │ ├── ic_action_content_clear.png │ │ ├── ic_action_github.png │ │ ├── ic_action_info_outline.png │ │ ├── ic_action_navigation_arrow_forward.png │ │ ├── ic_action_social_mood.png │ │ ├── ic_action_social_share.png │ │ ├── ic_action_twitter.png │ │ ├── ic_navigation_arrow_back_white.png │ │ ├── ic_ripple_selected.png │ │ ├── ic_ripple_unselected.png │ │ ├── ic_tabs_selected.png │ │ ├── ic_tabs_unselected.png │ │ ├── ic_toggle_check_box_dark.png │ │ └── ic_toggle_check_box_light.png │ ├── drawable-mdpi │ │ ├── ic_action_content_clear.png │ │ ├── ic_action_github.png │ │ ├── ic_action_info_outline.png │ │ ├── ic_action_navigation_arrow_forward.png │ │ ├── ic_action_social_mood.png │ │ ├── ic_action_social_share.png │ │ ├── ic_action_twitter.png │ │ ├── ic_navigation_arrow_back_white.png │ │ ├── ic_ripple_selected.png │ │ ├── ic_ripple_unselected.png │ │ ├── ic_tabs_selected.png │ │ ├── ic_tabs_unselected.png │ │ ├── ic_toggle_check_box_dark.png │ │ └── ic_toggle_check_box_light.png │ ├── drawable-xhdpi │ │ ├── ic_action_content_clear.png │ │ ├── ic_action_github.png │ │ ├── ic_action_info_outline.png │ │ ├── ic_action_navigation_arrow_forward.png │ │ ├── ic_action_social_mood.png │ │ ├── ic_action_social_share.png │ │ ├── ic_action_twitter.png │ │ ├── ic_navigation_arrow_back_blue.png │ │ ├── ic_ripple_selected.png │ │ ├── ic_ripple_unselected.png │ │ ├── ic_tabs_selected.png │ │ ├── ic_tabs_unselected.png │ │ ├── ic_toggle_check_box_dark.png │ │ └── ic_toggle_check_box_light.png │ ├── drawable-xxhdpi │ │ ├── ic_action_content_clear.png │ │ ├── ic_action_github.png │ │ ├── ic_action_info_outline.png │ │ ├── ic_action_navigation_arrow_forward.png │ │ ├── ic_action_social_mood.png │ │ ├── ic_action_social_share.png │ │ ├── ic_action_twitter.png │ │ ├── ic_navigation_arrow_back_white.png │ │ ├── ic_ripple_selected.png │ │ ├── ic_ripple_unselected.png │ │ ├── ic_tabs_selected.png │ │ ├── ic_tabs_unselected.png │ │ ├── ic_toggle_check_box_dark.png │ │ └── ic_toggle_check_box_light.png │ ├── drawable-xxxhdpi │ │ ├── ic_action_content_clear.png │ │ ├── ic_action_github.png │ │ ├── ic_action_info_outline.png │ │ ├── ic_action_navigation_arrow_forward.png │ │ ├── ic_action_social_mood.png │ │ ├── ic_action_social_share.png │ │ ├── ic_action_twitter.png │ │ ├── ic_navigation_arrow_back_white.png │ │ ├── ic_ripple_selected.png │ │ ├── ic_ripple_unselected.png │ │ ├── ic_tabs_selected.png │ │ ├── ic_tabs_unselected.png │ │ ├── ic_toggle_check_box_dark.png │ │ ├── ic_toggle_check_box_light.png │ │ └── me.jpg │ ├── drawable │ │ ├── radio_button_dark.xml │ │ └── radio_button_light.xml │ ├── layout │ │ ├── activity_tabs.xml │ │ ├── dialog_me.xml │ │ ├── fragment_card.xml │ │ ├── fragment_ripple_settings.xml │ │ ├── fragment_tabs_settings.xml │ │ └── toolbar.xml │ ├── menu │ │ ├── menu_main.xml │ │ └── menu_tabs.xml │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ ├── resize_xxxhdpi_pictures_to_other_dpis.sh │ ├── values-v19 │ │ └── themes.xml │ ├── values-v20 │ │ └── themes.xml │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml ├── sample-release.apk ├── src │ └── io │ │ └── karim │ │ └── materialtabs │ │ └── sample │ │ ├── MainActivity.java │ │ ├── MyApplication.java │ │ ├── ResettableFragment.java │ │ ├── RippleSettingsFragment.java │ │ ├── SampleFragment.java │ │ ├── TabsActivity.java │ │ ├── TabsSettingsFragment.java │ │ └── ui │ │ └── RadioButtonCenter.java └── web_hi_res_512.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | #Android generated 2 | bin 3 | gen 4 | gen* 5 | 6 | #Eclipse 7 | .project 8 | .classpath 9 | .settings 10 | 11 | #IntelliJ IDEA 12 | .idea 13 | *.iml 14 | *.ipr 15 | *.iws 16 | out 17 | 18 | #Maven 19 | target 20 | release.properties 21 | pom.xml.* 22 | 23 | #Ant 24 | build.xml 25 | local.properties 26 | proguard.cfg 27 | 28 | #Gradle 29 | .gradle 30 | build 31 | 32 | #OSX 33 | .DS_Store 34 | 35 | #Personal Files 36 | signing.properties 37 | fabric.properties 38 | material_tabs_sample_keystore.jks 39 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Karim Frenn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MaterialTabs 2 | 3 | [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-pizza%2FMaterialTabs-brightgreen.svg?style=flat)](http://android-arsenal.com/details/1/1874) 4 | 5 | An easy-to-integrate tab bar for Android that completely respects the [Material Design guidelines] (http://www.google.com/design/spec/components/tabs.html) and **supports all versions of Android since API 9**! 6 | 7 | If you think that this library does not fully respect the Material Design guidelines, file an issue, send a pull request or reach out to me! The goal of this library is to be 100% MaterialDesign-compliant. 8 | 9 | Animated screenshot 10 | 11 | ## Sample 12 | 13 | You can find a sample app showing what this library can do on the Google Play Store. 14 | **This sample can also generate the XML code you need instantly and export it!** You can then copy paste it in your corresponding layout XML file. Done! 15 | 16 | 17 | Material Tabs Demo on Google Play 18 | 19 | 20 | ## Download 21 | 22 | Download the [latest AAR](http://search.maven.org/remotecontent?filepath=io/karim/materialtabs/2.0.5/materialtabs-2.0.5.aar) or add the following dependency in your **build.gradle** file: 23 | 24 | ```groovy 25 | dependencies { 26 | compile 'io.karim:materialtabs:2.0.5' 27 | } 28 | ``` 29 | 30 | ## Usage 31 | 32 | 1. Add the MaterialTabs widget (io.karim.MaterialTabs) in your `layout.xml` file: 33 | 34 | ```xml 35 | 42 | ``` 43 | Normally, this should go below a Toolbar (android.support.v7.widget.Toolbar) and above a ViewPager (android.support.v4.view.ViewPager). 44 | Take a look at [this file] (https://github.com/pizza/MaterialTabs/blob/master/sample/res/layout/activity_tabs.xml) for a better understanding. 45 | 46 | 2. In your onCreate method (or onCreateView for a fragment), bind the widget to the ViewPager: 47 | 48 | ```java 49 | // Initialize the ViewPager and set an adapter 50 | ViewPager pager = (ViewPager) findViewById(R.id.pager); 51 | pager.setAdapter(new SamplePagerAdapter(getSupportFragmentManager())); 52 | 53 | // Bind the tabs to the ViewPager 54 | MaterialTabs tabs = (MaterialTabs) findViewById(R.id.tabs); 55 | tabs.setViewPager(pager); 56 | ``` 57 | 58 | 3. Create a new class extending FragmentPagerAdapter, and take a look at the "Custom view" section for more info. 59 | 60 | ## Customization 61 | 62 | ### Custom view 63 | 64 | #### Just a TextView (titles) 65 | If you're looking for tabs with text, take a look at the `SamplePagerAdapter` in [this file] (https://github.com/pizza/MaterialTabs/blob/master/sample/src/io/karim/materialtabs/sample/TabsActivity.java#L331) for a better example. 66 | 67 | #### Everything else (icons and more complex views) 68 | 69 | Whether you're looking for tabs with icons instead of text or for more complex custom views, take a look at the `MainActivityPagerAdapter` in [this example](https://github.com/pizza/MaterialTabs/blob/master/sample/src/io/karim/materialtabs/sample/MainActivity.java#L152) instead. 70 | 71 | Specifically, make sure that your class implements `MaterialTabs.CustomTabProvider` and overrides the following methods: 72 | 73 | ``` 74 | View getCustomTabView(ViewGroup parent, int position); 75 | void onCustomTabViewSelected(View view, int position, boolean alreadySelected); 76 | void onCustomTabViewUnselected(View view, int position, boolean alreadyUnselected); 77 | ``` 78 | 79 | In the first one, create your View from scratch. 80 | In the second and third methods, write code that you want to run when a tab is selected and unselected. A common use case is to replace an icon with another icon when selected. This is exactly the use case demonstrated in the example linked above. 81 | 82 | *Note: these last two methods might be called several times even though the user just clicked on a tab once (for example). To deal with this case, the `alreadySelected` and `alreadyUnselected` boolean parameters specify if the corresponding tab was already selected or unselected respectively so that code that should only be executed once isn't executed more than once.* 83 | 84 | ### Custom font/typeface 85 | 86 | If you're using the default TextView (i.e. not using custom views) and would like to use a custom font in the tabs' title text, you can do so in your Java code by adding the last two lines just after binding the tabs to the ViewPager: 87 | 88 | ```java 89 | // Initialize the ViewPager and set an adapter 90 | ViewPager pager = (ViewPager) findViewById(R.id.pager); 91 | pager.setAdapter(new SamplePagerAdapter(getSupportFragmentManager())); 92 | 93 | // Bind the tabs to the ViewPager 94 | MaterialTabs tabs = (MaterialTabs) findViewById(R.id.tabs); 95 | tabs.setViewPager(pager); 96 | 97 | // Set custom font/typeface to text in tabs' title 98 | Typeface selectedTypeface = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Bold.ttf"); 99 | Typeface unselectedTypeface = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Regular.ttf"); 100 | tabs.setTypefaceSelected(selectedTypeface); 101 | tabs.setTypefaceUnselected(unselectedTypeface); 102 | ``` 103 | 104 | For this to work, make sure to add your font file (in this case, `Roboto-Bold.ttf` and `Robot-Regular.ttf`) in the `fonts` folder under `assets`. 105 | 106 | ### Other customizations 107 | 108 | There are many attributes that you can override in the XML layout. 109 | Here is a table of these attributes, their descriptions and their default value: 110 | 111 | | Attribute | Description | 112 | | ------------- | ------------- | 113 | | android:textColor | Color of text in non-selected tabs | 114 | | app:mtIndicatorColor | Color of the sliding indicator | 115 | | app:mtUnderlineColor | Color of the full-width line on the bottom of the view | 116 | | app:mtIndicatorHeight | Height of the sliding indicator | 117 | | app:mtUnderlineHeight | Height of the full-width line on the bottom of the view | 118 | | app:mtTabPaddingLeftRight | Left and right padding of each tab | 119 | | app:mtSameWeightTabs | If set to true, each tab is given the same weight | 120 | | app:mtTextAllCaps | If true, all tab titles will be upper case | 121 | | app:mtPaddingMiddle | If true, the tabs start at the middle of the view | 122 | | app:mtTextColorSelected | Color of text in selected tab | 123 | | app:mtMrlRippleColor | Color of the ripple | 124 | | app:mtMrlRippleHighlightColor | Color of the background while the ripple is undergoing an animation | 125 | | app:mtMrlRippleDiameter | Radius of starting ripple | 126 | | app:mtMrlRippleOverlay | If true, ripple is drawn in foreground of view. Otherwise, it will drawn in the background | 127 | | app:mtMrlRippleAlpha | Level of transparency (alpha) of the ripple | 128 | | app:mtMrlRippleDuration | Duration of the ripple animation | 129 | | app:mtMrlRippleFadeDuration | Duration of fade out effect on ripple | 130 | | app:mtMrlRippleDelayClick | If true, delays calls to OnClickListeners until ripple effect ends. In that case, the indicator line's move to the clicked tab will also be delayed | 131 | | app:mtMrlRipplePersistent | If true, the ripple background color persists after animation, until setRadius(0) is called | 132 | | app:mtMrlRippleInAdapter | if true, MaterialRippleLayout will be optimized for use in AdapterViews | 133 | | app:mtMrlRippleRoundedCorners | Radius of corners of the ripple. Note: it uses software rendering pipeline for API 17 and below | 134 | 135 | Don't forget to add `xmlns:app="http://schemas.android.com/apk/res-auto"` to the root item in your layout. 136 | 137 | ## Contribution 138 | If you would like to contribute code you can do so through GitHub by forking the repository and sending a pull request. 139 | 140 | ## Credits 141 | This library is based on the great [PagerSlidingTabStrip](https://github.com/jpardogo/PagerSlidingTabStrip) library by [jpardogo](https://github.com/jpardogo) and [astuetz](https://github.com/astuetz) and on the great [material-ripple](https://github.com/balysv/material-ripple) library by [balysv](https://github.com/balysv). 142 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | 3 | repositories { 4 | mavenCentral() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.2.3' 9 | classpath 'com.github.dcendents:android-maven-plugin:1.2' 10 | 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files 13 | } 14 | } 15 | 16 | def isReleaseBuild() { 17 | return version.contains("SNAPSHOT") == false 18 | } 19 | 20 | allprojects { 21 | version = VERSION_NAME 22 | group = GROUP 23 | 24 | repositories { 25 | mavenCentral() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /device-2015-05-04-090851.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/device-2015-05-04-090851.png -------------------------------------------------------------------------------- /device-2015-05-04-090914.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/device-2015-05-04-090914.png -------------------------------------------------------------------------------- /device-2015-05-04-090952.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/device-2015-05-04-090952.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Dec 22 11:17:57 BRST 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.4-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/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | minSdkVersion 9 9 | targetSdkVersion 23 10 | } 11 | 12 | android { 13 | lintOptions { 14 | abortOnError false 15 | } 16 | } 17 | 18 | sourceSets { 19 | main { 20 | manifest.srcFile 'AndroidManifest.xml' 21 | java.srcDirs = ['src'] 22 | res.srcDirs = ['res'] 23 | } 24 | } 25 | } 26 | 27 | dependencies { 28 | compile 'com.android.support:support-v4:23.1.1' 29 | compile 'com.nineoldandroids:library:2.4.0' 30 | } 31 | 32 | apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle' 33 | -------------------------------------------------------------------------------- /library/res/layout/mt_tab.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | -------------------------------------------------------------------------------- /library/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /library/src/io/karim/MaterialRippleLayout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Balys Valentukevicius 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.karim; 18 | 19 | import com.nineoldandroids.animation.Animator; 20 | import com.nineoldandroids.animation.AnimatorListenerAdapter; 21 | import com.nineoldandroids.animation.AnimatorSet; 22 | import com.nineoldandroids.animation.ObjectAnimator; 23 | import com.nineoldandroids.util.Property; 24 | 25 | import android.content.Context; 26 | import android.content.res.TypedArray; 27 | import android.graphics.Canvas; 28 | import android.graphics.Color; 29 | import android.graphics.Paint; 30 | import android.graphics.Path; 31 | import android.graphics.Point; 32 | import android.graphics.Rect; 33 | import android.graphics.RectF; 34 | import android.os.Build; 35 | import android.support.annotation.NonNull; 36 | import android.util.AttributeSet; 37 | import android.view.GestureDetector; 38 | import android.view.MotionEvent; 39 | import android.view.View; 40 | import android.view.ViewConfiguration; 41 | import android.view.ViewGroup; 42 | import android.view.ViewParent; 43 | import android.view.animation.AccelerateInterpolator; 44 | import android.view.animation.DecelerateInterpolator; 45 | import android.view.animation.LinearInterpolator; 46 | import android.widget.AdapterView; 47 | import android.widget.FrameLayout; 48 | 49 | import io.karim.materialtabs.R; 50 | 51 | import static android.view.GestureDetector.SimpleOnGestureListener; 52 | import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; 53 | 54 | public class MaterialRippleLayout extends FrameLayout { 55 | 56 | private static final String TAG = MaterialRippleLayout.class.getSimpleName(); 57 | 58 | public static final int DEFAULT_DURATION = 250; 59 | public static final int DEFAULT_FADE_DURATION = 125; 60 | public static final float DEFAULT_DIAMETER_DP = 20; 61 | public static final float DEFAULT_ALPHA = 0.2f; 62 | public static final int DEFAULT_COLOR = Color.WHITE; 63 | public static final boolean DEFAULT_DELAY_CLICK = false; 64 | public static final boolean DEFAULT_PERSISTENT = false; 65 | public static final boolean DEFAULT_SEARCH_ADAPTER = false; 66 | public static final boolean DEFAULT_RIPPLE_OVERLAY = false; 67 | public static final int DEFAULT_ROUNDED_CORNERS_DP = 0; 68 | public static final int FADE_EXTRA_DELAY = 50; 69 | public static final long HOVER_DURATION = 2500; 70 | 71 | private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 72 | private final Rect bounds = new Rect(); 73 | 74 | private int rippleColor; 75 | private int rippleHighlightColor; 76 | private boolean rippleOverlay; 77 | private int rippleDiameterPx; 78 | private int rippleDuration; 79 | private int rippleAlphaInt; 80 | private boolean rippleDelayClick; 81 | private int rippleFadeDuration; 82 | private boolean ripplePersistent; 83 | private boolean rippleInAdapter; 84 | private float rippleRoundedCornersPx; 85 | 86 | private float radius; 87 | 88 | private AdapterView parentAdapter; 89 | private View childView; 90 | 91 | private AnimatorSet rippleAnimator; 92 | private ObjectAnimator hoverAnimator; 93 | 94 | private Point currentCoordinates = new Point(); 95 | private Point previousCoordinates = new Point(); 96 | 97 | private int layerType; 98 | 99 | private boolean eventCancelled; 100 | private boolean prepressed; 101 | private int positionInAdapter; 102 | 103 | private final GestureDetector gestureDetector; 104 | private PressedEvent pendingPressEvent; 105 | 106 | public static RippleBuilder on(View view) { 107 | return new RippleBuilder(view); 108 | } 109 | 110 | public MaterialRippleLayout(Context context) { 111 | this(context, null, 0); 112 | } 113 | 114 | public MaterialRippleLayout(Context context, AttributeSet attrs) { 115 | this(context, attrs, 0); 116 | } 117 | 118 | /** 119 | * Animations 120 | */ 121 | private final Property radiusProperty = new Property(Float.class, "radius") { 122 | @Override 123 | public Float get(MaterialRippleLayout object) { 124 | return object.getRadius(); 125 | } 126 | 127 | @Override 128 | public void set(MaterialRippleLayout object, Float value) { 129 | object.setRadius(value); 130 | } 131 | }; 132 | 133 | @Override 134 | public final void addView(@NonNull View child, int index, ViewGroup.LayoutParams params) { 135 | if (getChildCount() > 0) { 136 | throw new IllegalStateException("MaterialRippleLayout can host only one child"); 137 | } 138 | childView = child; 139 | super.addView(child, index, params); 140 | } 141 | 142 | @Override 143 | public void setOnClickListener(OnClickListener onClickListener) { 144 | if (childView == null) { 145 | throw new IllegalStateException("MaterialRippleLayout must have a child view to handle clicks"); 146 | } 147 | childView.setOnClickListener(onClickListener); 148 | } 149 | 150 | @Override 151 | public boolean onInterceptTouchEvent(MotionEvent event) { 152 | return !findClickableViewInChild(childView, (int) event.getX(), (int) event.getY()); 153 | } 154 | 155 | @Override 156 | public boolean onTouchEvent(@NonNull MotionEvent event) { 157 | boolean superOnTouchEvent = super.onTouchEvent(event); 158 | 159 | if (!isEnabled() || !childView.isEnabled()) { 160 | return superOnTouchEvent; 161 | } 162 | 163 | boolean isEventInBounds = bounds.contains((int) event.getX(), (int) event.getY()); 164 | 165 | if (isEventInBounds) { 166 | previousCoordinates.set(currentCoordinates.x, currentCoordinates.y); 167 | currentCoordinates.set((int) event.getX(), (int) event.getY()); 168 | } 169 | 170 | boolean gestureResult = gestureDetector.onTouchEvent(event); 171 | if (gestureResult || mHasPerformedLongPress) { 172 | return true; 173 | } else { 174 | int action = event.getActionMasked(); 175 | switch (action) { 176 | case MotionEvent.ACTION_UP: 177 | if (prepressed) { 178 | childView.setPressed(true); 179 | postDelayed(new Runnable() { 180 | @Override 181 | public void run() { 182 | childView.setPressed(false); 183 | } 184 | }, ViewConfiguration.getPressedStateDuration()); 185 | } 186 | 187 | if (isEventInBounds) { 188 | PerformClickEvent pendingClickEvent = new PerformClickEvent(); 189 | startRipple(pendingClickEvent); 190 | if (!rippleDelayClick) { 191 | pendingClickEvent.run(); 192 | } 193 | } 194 | 195 | cancelPressedEvent(); 196 | break; 197 | case MotionEvent.ACTION_DOWN: 198 | setBackgroundColor(rippleHighlightColor); 199 | 200 | setPositionInAdapter(); 201 | eventCancelled = false; 202 | pendingPressEvent = new PressedEvent(event); 203 | if (isInScrollingContainer()) { 204 | cancelPressedEvent(); 205 | prepressed = true; 206 | postDelayed(pendingPressEvent, ViewConfiguration.getTapTimeout()); 207 | } else { 208 | pendingPressEvent.run(); 209 | } 210 | break; 211 | case MotionEvent.ACTION_CANCEL: 212 | if (rippleInAdapter) { 213 | // Do not use current coordinates in adapter since they tend to jump drastically on scroll. 214 | currentCoordinates.set(previousCoordinates.x, previousCoordinates.y); 215 | previousCoordinates = new Point(); 216 | } 217 | childView.onTouchEvent(event); 218 | startRipple(null); 219 | cancelPressedEvent(); 220 | break; 221 | case MotionEvent.ACTION_MOVE: 222 | setBackgroundColor(rippleHighlightColor); 223 | 224 | if (isEventInBounds && !eventCancelled) { 225 | invalidate(); 226 | } else if (!isEventInBounds) { 227 | startRipple(null); 228 | } 229 | 230 | if (!isEventInBounds) { 231 | cancelPressedEvent(); 232 | if (hoverAnimator != null) { 233 | hoverAnimator.cancel(); 234 | } 235 | childView.onTouchEvent(event); 236 | eventCancelled = true; 237 | } 238 | break; 239 | } 240 | return true; 241 | } 242 | } 243 | 244 | private void cancelPressedEvent() { 245 | if (pendingPressEvent != null) { 246 | removeCallbacks(pendingPressEvent); 247 | prepressed = false; 248 | } 249 | } 250 | 251 | private boolean mHasPerformedLongPress; 252 | 253 | private void startHover() { 254 | if (eventCancelled) { 255 | return; 256 | } 257 | 258 | if (hoverAnimator != null) { 259 | hoverAnimator.cancel(); 260 | } 261 | final float radius = (float) (Math.sqrt(Math.pow(getWidth(), 2) + Math.pow(getHeight(), 2)) * 1.2f); 262 | hoverAnimator = ObjectAnimator.ofFloat(this, radiusProperty, rippleDiameterPx, radius).setDuration(HOVER_DURATION); 263 | hoverAnimator.setInterpolator(new LinearInterpolator()); 264 | hoverAnimator.start(); 265 | } 266 | 267 | private void startRipple(final Runnable animationEndRunnable) { 268 | if (eventCancelled) { 269 | return; 270 | } 271 | 272 | float endRadius = getEndRadius(); 273 | 274 | cancelAnimations(); 275 | 276 | rippleAnimator = new AnimatorSet(); 277 | rippleAnimator.addListener(new AnimatorListenerAdapter() { 278 | @Override 279 | public void onAnimationEnd(Animator animation) { 280 | if (!ripplePersistent) { 281 | setRadius(0); 282 | setRippleAlphaInt(rippleAlphaInt); 283 | } 284 | if (animationEndRunnable != null && rippleDelayClick) { 285 | animationEndRunnable.run(); 286 | } 287 | childView.setPressed(false); 288 | 289 | setBackgroundColor(Color.TRANSPARENT); 290 | } 291 | }); 292 | 293 | ObjectAnimator ripple = ObjectAnimator.ofFloat(this, radiusProperty, radius, endRadius); 294 | ripple.setDuration(rippleDuration); 295 | ripple.setInterpolator(new DecelerateInterpolator()); 296 | ObjectAnimator fade = ObjectAnimator.ofInt(this, circleAlphaProperty, rippleAlphaInt, 0); 297 | fade.setDuration(rippleFadeDuration); 298 | fade.setInterpolator(new AccelerateInterpolator()); 299 | fade.setStartDelay(rippleDuration - rippleFadeDuration - FADE_EXTRA_DELAY); 300 | 301 | if (ripplePersistent) { 302 | rippleAnimator.play(ripple); 303 | } else if (getRadius() > endRadius) { 304 | fade.setStartDelay(0); 305 | rippleAnimator.play(fade); 306 | } else { 307 | rippleAnimator.playTogether(ripple, fade); 308 | } 309 | rippleAnimator.start(); 310 | } 311 | 312 | private void cancelAnimations() { 313 | if (rippleAnimator != null) { 314 | rippleAnimator.cancel(); 315 | rippleAnimator.removeAllListeners(); 316 | } 317 | 318 | if (hoverAnimator != null) { 319 | hoverAnimator.cancel(); 320 | } 321 | } 322 | 323 | private final Property circleAlphaProperty = new Property(Integer.class, 324 | "rippleAlphaFloat") { 325 | @Override 326 | public Integer get(MaterialRippleLayout object) { 327 | return object.getRippleAlphaInt(); 328 | } 329 | 330 | @Override 331 | public void set(MaterialRippleLayout object, Integer value) { 332 | object.setRippleAlphaInt(value); 333 | } 334 | }; 335 | 336 | private boolean isInScrollingContainer() { 337 | ViewParent p = getParent(); 338 | while (p != null && p instanceof ViewGroup) { 339 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 340 | 341 | if (((ViewGroup) p).shouldDelayChildPressedState()) { 342 | return true; 343 | } 344 | } 345 | p = p.getParent(); 346 | } 347 | return false; 348 | } 349 | 350 | private AdapterView findParentAdapterView() { 351 | if (parentAdapter != null) { 352 | return parentAdapter; 353 | } 354 | ViewParent current = getParent(); 355 | while (true) { 356 | if (current instanceof AdapterView) { 357 | parentAdapter = (AdapterView) current; 358 | return parentAdapter; 359 | } else { 360 | try { 361 | current = current.getParent(); 362 | } catch (NullPointerException npe) { 363 | throw new RuntimeException("Could not find a parent AdapterView"); 364 | } 365 | } 366 | } 367 | } 368 | 369 | private void setPositionInAdapter() { 370 | if (rippleInAdapter) { 371 | positionInAdapter = findParentAdapterView().getPositionForView(MaterialRippleLayout.this); 372 | } 373 | } 374 | 375 | private boolean adapterPositionChanged() { 376 | if (rippleInAdapter) { 377 | int newPosition = findParentAdapterView().getPositionForView(MaterialRippleLayout.this); 378 | final boolean changed = newPosition != positionInAdapter; 379 | positionInAdapter = newPosition; 380 | if (changed) { 381 | cancelPressedEvent(); 382 | cancelAnimations(); 383 | childView.setPressed(false); 384 | setRadius(0); 385 | } 386 | return changed; 387 | } 388 | return false; 389 | } 390 | 391 | private boolean findClickableViewInChild(View view, int x, int y) { 392 | if (view instanceof ViewGroup) { 393 | ViewGroup viewGroup = (ViewGroup) view; 394 | for (int i = 0; i < viewGroup.getChildCount(); i++) { 395 | View child = viewGroup.getChildAt(i); 396 | final Rect rect = new Rect(); 397 | child.getHitRect(rect); 398 | 399 | final boolean contains = rect.contains(x, y); 400 | if (contains) { 401 | return findClickableViewInChild(child, x - rect.left, y - rect.top); 402 | } 403 | } 404 | } else if (view != childView) { 405 | return (view.isEnabled() && (view.isClickable() || view.isLongClickable() || view.isFocusableInTouchMode())); 406 | } 407 | 408 | return view.isFocusableInTouchMode(); 409 | } 410 | 411 | @Override 412 | protected void onSizeChanged(int w, int h, int oldw, int oldh) { 413 | super.onSizeChanged(w, h, oldw, oldh); 414 | bounds.set(0, 0, w, h); 415 | } 416 | 417 | @Override 418 | public boolean isInEditMode() { 419 | return true; 420 | } 421 | 422 | /** 423 | * Drawing 424 | */ 425 | @Override 426 | public void draw(@NonNull Canvas canvas) { 427 | final boolean positionChanged = adapterPositionChanged(); 428 | if (rippleOverlay) { 429 | super.draw(canvas); 430 | if (!positionChanged) { 431 | if (rippleRoundedCornersPx != 0) { 432 | Path clipPath = new Path(); 433 | RectF rect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight()); 434 | clipPath.addRoundRect(rect, rippleRoundedCornersPx, rippleRoundedCornersPx, Path.Direction.CW); 435 | canvas.clipPath(clipPath); 436 | } 437 | canvas.drawCircle(currentCoordinates.x, currentCoordinates.y, radius, paint); 438 | } 439 | } else { 440 | if (!positionChanged) { 441 | canvas.drawCircle(currentCoordinates.x, currentCoordinates.y, radius, paint); 442 | } 443 | super.draw(canvas); 444 | } 445 | } 446 | 447 | public MaterialRippleLayout(Context context, AttributeSet attrs, int defStyle) { 448 | super(context, attrs, defStyle); 449 | 450 | setWillNotDraw(false); 451 | gestureDetector = new GestureDetector(context, new SimpleOnGestureListener() { 452 | public void onLongPress(MotionEvent e) { 453 | mHasPerformedLongPress = childView.performLongClick(); 454 | if (mHasPerformedLongPress) { 455 | startRipple(null); 456 | cancelPressedEvent(); 457 | } 458 | } 459 | 460 | @Override 461 | public boolean onDown(MotionEvent e) { 462 | mHasPerformedLongPress = false; 463 | return super.onDown(e); 464 | } 465 | }); 466 | 467 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MaterialRippleLayout); 468 | rippleColor = a.getColor(R.styleable.MaterialRippleLayout_mrlRippleColor, DEFAULT_COLOR); 469 | 470 | // Making default ripple highlight color the same as rippleColor but with 1/4 the alpha. 471 | rippleHighlightColor = Color.argb((int) (Color.alpha(rippleColor) * 0.25), Color.red(rippleColor), Color.green(rippleColor), 472 | Color.blue(rippleColor)); 473 | rippleHighlightColor = a.getColor(R.styleable.MaterialRippleLayout_mrlRippleHighlightColor, rippleHighlightColor); 474 | rippleDiameterPx = a.getDimensionPixelSize(R.styleable.MaterialRippleLayout_mrlRippleDiameter, 475 | Utils.dpToPx(getResources(), DEFAULT_DIAMETER_DP)); 476 | rippleOverlay = a.getBoolean(R.styleable.MaterialRippleLayout_mrlRippleOverlay, DEFAULT_RIPPLE_OVERLAY); 477 | rippleDuration = a.getInt(R.styleable.MaterialRippleLayout_mrlRippleDuration, DEFAULT_DURATION); 478 | rippleAlphaInt = (int) (255 * a.getFloat(R.styleable.MaterialRippleLayout_mrlRippleAlpha, DEFAULT_ALPHA)); 479 | rippleDelayClick = a.getBoolean(R.styleable.MaterialRippleLayout_mrlRippleDelayClick, DEFAULT_DELAY_CLICK); 480 | rippleFadeDuration = a.getInteger(R.styleable.MaterialRippleLayout_mrlRippleFadeDuration, DEFAULT_FADE_DURATION); 481 | ripplePersistent = a.getBoolean(R.styleable.MaterialRippleLayout_mrlRipplePersistent, DEFAULT_PERSISTENT); 482 | rippleInAdapter = a.getBoolean(R.styleable.MaterialRippleLayout_mrlRippleInAdapter, DEFAULT_SEARCH_ADAPTER); 483 | rippleRoundedCornersPx = a.getDimensionPixelSize(R.styleable.MaterialRippleLayout_mrlRippleRoundedCorners, DEFAULT_ROUNDED_CORNERS_DP); 484 | 485 | a.recycle(); 486 | 487 | paint.setColor(rippleColor); 488 | paint.setAlpha(rippleAlphaInt); 489 | 490 | enableClipPathSupportIfNecessary(); 491 | } 492 | 493 | private float getRadius() { 494 | return radius; 495 | } 496 | 497 | 498 | public void setRadius(float radius) { 499 | this.radius = radius; 500 | invalidate(); 501 | } 502 | 503 | private float getEndRadius() { 504 | final int width = getWidth(); 505 | final int height = getHeight(); 506 | 507 | final int halfWidth = width / 2; 508 | final int halfHeight = height / 2; 509 | 510 | final float radiusX = halfWidth > currentCoordinates.x ? width - currentCoordinates.x : currentCoordinates.x; 511 | final float radiusY = halfHeight > currentCoordinates.y ? height - currentCoordinates.y : currentCoordinates.y; 512 | 513 | //noinspection SuspiciousNameCombination 514 | return (float) Math.sqrt(Math.pow(radiusX, 2) + Math.pow(radiusY, 2)) * 1.2f; 515 | } 516 | 517 | public int getRippleAlphaInt() { 518 | return paint.getAlpha(); 519 | } 520 | 521 | public void setRippleAlphaInt(Integer alphaInt) { 522 | paint.setAlpha(alphaInt); 523 | invalidate(); 524 | } 525 | 526 | /** 527 | * Accessor 528 | */ 529 | public void setRippleColor(int rippleColor) { 530 | this.rippleColor = rippleColor; 531 | this.rippleHighlightColor = Color.argb((int) (Color.alpha(rippleColor) * 0.25), Color.red(rippleColor), Color.green(rippleColor), 532 | Color.blue(rippleColor)); 533 | paint.setColor(rippleColor); 534 | paint.setAlpha(rippleAlphaInt); 535 | invalidate(); 536 | } 537 | 538 | public void setRippleHighlightColor(int rippleHighlightColor) { 539 | this.rippleHighlightColor = rippleHighlightColor; 540 | invalidate(); 541 | } 542 | 543 | public void setRippleOverlay(boolean rippleOverlay) { 544 | this.rippleOverlay = rippleOverlay; 545 | } 546 | 547 | public void setRippleDiameterPx(int rippleDiameterPx) { 548 | this.rippleDiameterPx = rippleDiameterPx; 549 | } 550 | 551 | public void setRippleDuration(int rippleDuration) { 552 | this.rippleDuration = rippleDuration; 553 | } 554 | 555 | public void setRippleDelayClick(boolean rippleDelayClick) { 556 | this.rippleDelayClick = rippleDelayClick; 557 | } 558 | 559 | public void setRippleFadeDuration(int rippleFadeDuration) { 560 | this.rippleFadeDuration = rippleFadeDuration; 561 | } 562 | 563 | public void setRipplePersistent(boolean ripplePersistent) { 564 | this.ripplePersistent = ripplePersistent; 565 | } 566 | 567 | public void setRippleInAdapter(boolean rippleInAdapter) { 568 | this.rippleInAdapter = rippleInAdapter; 569 | } 570 | 571 | public void setRippleRoundedCornersPx(int rippleRoundedCornerPx) { 572 | this.rippleRoundedCornersPx = rippleRoundedCornerPx; 573 | enableClipPathSupportIfNecessary(); 574 | } 575 | 576 | public void setDefaultRippleAlphaInt(int alphaInt) { 577 | this.rippleAlphaInt = alphaInt; 578 | paint.setAlpha(alphaInt); 579 | invalidate(); 580 | } 581 | 582 | public void performRipple() { 583 | currentCoordinates = new Point(getWidth() / 2, getHeight() / 2); 584 | startRipple(null); 585 | } 586 | 587 | public void performRipple(Point anchor) { 588 | currentCoordinates = new Point(anchor.x, anchor.y); 589 | startRipple(null); 590 | } 591 | 592 | /** 593 | * {@link Canvas#clipPath(Path)} is not supported in hardware accelerated layers before API 18. Use software layer instead 594 | *

595 | * https://developer.android.com/guide/topics/graphics/hardware-accel.html#unsupported 596 | */ 597 | private void enableClipPathSupportIfNecessary() { 598 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR1 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 599 | if (rippleRoundedCornersPx != 0) { 600 | layerType = getLayerType(); 601 | setLayerType(LAYER_TYPE_SOFTWARE, null); 602 | } else { 603 | setLayerType(layerType, null); 604 | } 605 | } 606 | } 607 | 608 | /** 609 | * Helper 610 | */ 611 | private class PerformClickEvent implements Runnable { 612 | 613 | @Override 614 | public void run() { 615 | if (mHasPerformedLongPress) { 616 | return; 617 | } 618 | 619 | // If parent is an AdapterView, try to call its ItemClickListener. 620 | if (getParent() instanceof AdapterView) { 621 | clickAdapterView((AdapterView) getParent()); 622 | } else if (rippleInAdapter) { 623 | // Find adapter view. 624 | clickAdapterView(findParentAdapterView()); 625 | } else { 626 | // Otherwise, just perform click on child. 627 | childView.performClick(); 628 | } 629 | } 630 | 631 | private void clickAdapterView(AdapterView parent) { 632 | final int position = parent.getPositionForView(MaterialRippleLayout.this); 633 | final long itemId = parent.getAdapter() != null ? parent.getAdapter().getItemId(position) : 0; 634 | if (position != AdapterView.INVALID_POSITION) { 635 | parent.performItemClick(MaterialRippleLayout.this, position, itemId); 636 | } 637 | } 638 | } 639 | 640 | private final class PressedEvent implements Runnable { 641 | 642 | private final MotionEvent event; 643 | 644 | public PressedEvent(MotionEvent event) { 645 | this.event = event; 646 | } 647 | 648 | @Override 649 | public void run() { 650 | prepressed = false; 651 | 652 | // Prevent the child's long click, let the ripple layout call its performLongClick 653 | childView.setLongClickable(false); 654 | childView.onTouchEvent(event); 655 | childView.setPressed(true); 656 | startHover(); 657 | } 658 | } 659 | 660 | /** 661 | * Builder 662 | */ 663 | public static class RippleBuilder { 664 | 665 | private final Context context; 666 | private final View child; 667 | 668 | private int rippleColor = DEFAULT_COLOR; 669 | private int rippleHighlightColor; 670 | private boolean rippleOverlay = DEFAULT_RIPPLE_OVERLAY; 671 | private float rippleDiameterDp = DEFAULT_DIAMETER_DP; 672 | private int rippleDuration = DEFAULT_DURATION; 673 | private float rippleAlphaFloat = DEFAULT_ALPHA; 674 | private boolean rippleDelayClick = DEFAULT_DELAY_CLICK; 675 | private int rippleFadeDuration = DEFAULT_FADE_DURATION; 676 | private boolean ripplePersistent = DEFAULT_PERSISTENT; 677 | private boolean rippleSearchAdapter = DEFAULT_SEARCH_ADAPTER; 678 | private float rippleRoundedCornerDp = DEFAULT_ROUNDED_CORNERS_DP; 679 | 680 | public RippleBuilder(View child) { 681 | this.child = child; 682 | this.context = child.getContext(); 683 | } 684 | 685 | public RippleBuilder rippleColor(int color) { 686 | this.rippleColor = color; 687 | this.rippleHighlightColor = Color.argb((int) (Color.alpha(rippleColor) * 0.25), Color.red(rippleColor), Color.green(rippleColor), 688 | Color.blue(rippleColor)); 689 | return this; 690 | } 691 | 692 | /** 693 | * Make sure to call this after rippleColor() in the Builder. 694 | */ 695 | public RippleBuilder rippleHighlightColor(int highlightColor) { 696 | this.rippleHighlightColor = highlightColor; 697 | return this; 698 | } 699 | 700 | public RippleBuilder rippleOverlay(boolean overlay) { 701 | this.rippleOverlay = overlay; 702 | return this; 703 | } 704 | 705 | public RippleBuilder rippleDiameterDp(float diameterDp) { 706 | this.rippleDiameterDp = diameterDp; 707 | return this; 708 | } 709 | 710 | public RippleBuilder rippleDuration(int duration) { 711 | this.rippleDuration = duration; 712 | return this; 713 | } 714 | 715 | /** 716 | * @param alpha value between 0 and 1 717 | */ 718 | public RippleBuilder rippleAlpha(float alpha) { 719 | this.rippleAlphaFloat = alpha; 720 | return this; 721 | } 722 | 723 | public RippleBuilder rippleDelayClick(boolean delayClick) { 724 | this.rippleDelayClick = delayClick; 725 | return this; 726 | } 727 | 728 | public RippleBuilder rippleFadeDuration(int fadeDuration) { 729 | this.rippleFadeDuration = fadeDuration; 730 | return this; 731 | } 732 | 733 | public RippleBuilder ripplePersistent(boolean persistent) { 734 | this.ripplePersistent = persistent; 735 | return this; 736 | } 737 | 738 | public RippleBuilder rippleInAdapter(boolean inAdapter) { 739 | this.rippleSearchAdapter = inAdapter; 740 | return this; 741 | } 742 | 743 | public RippleBuilder rippleRoundedCornersDp(float radiusDp) { 744 | this.rippleRoundedCornerDp = radiusDp; 745 | return this; 746 | } 747 | 748 | public MaterialRippleLayout create() { 749 | MaterialRippleLayout layout = new MaterialRippleLayout(context); 750 | layout.setRippleColor(rippleColor); 751 | layout.setDefaultRippleAlphaInt((int) (255 * rippleAlphaFloat)); 752 | layout.setRippleDelayClick(rippleDelayClick); 753 | layout.setRippleDiameterPx(Utils.dpToPx(context.getResources(), rippleDiameterDp)); 754 | layout.setRippleDuration(rippleDuration); 755 | layout.setRippleFadeDuration(rippleFadeDuration); 756 | layout.setRippleHighlightColor(rippleHighlightColor); 757 | layout.setRipplePersistent(ripplePersistent); 758 | layout.setRippleOverlay(rippleOverlay); 759 | layout.setRippleInAdapter(rippleSearchAdapter); 760 | layout.setRippleRoundedCornersPx(Utils.dpToPx(context.getResources(), rippleRoundedCornerDp)); 761 | 762 | ViewGroup.LayoutParams params = child.getLayoutParams(); 763 | ViewGroup parent = (ViewGroup) child.getParent(); 764 | int index = 0; 765 | 766 | if (parent != null && parent instanceof MaterialRippleLayout) { 767 | throw new IllegalStateException("MaterialRippleLayout could not be created: parent of the view already is a MaterialRippleLayout"); 768 | } 769 | 770 | if (parent != null) { 771 | index = parent.indexOfChild(child); 772 | parent.removeView(child); 773 | } 774 | 775 | layout.addView(child, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); 776 | 777 | if (parent != null) { 778 | parent.addView(layout, index, params); 779 | } 780 | 781 | return layout; 782 | } 783 | } 784 | } 785 | -------------------------------------------------------------------------------- /library/src/io/karim/Utils.java: -------------------------------------------------------------------------------- 1 | package io.karim; 2 | 3 | import android.content.res.Resources; 4 | import android.util.TypedValue; 5 | 6 | public class Utils { 7 | public static int dpToPx(Resources resources, float dp) { 8 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.getDisplayMetrics()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /sample/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | maven { url 'https://maven.fabric.io/public' } 4 | } 5 | 6 | dependencies { 7 | classpath 'io.fabric.tools:gradle:1.19.0' 8 | } 9 | } 10 | 11 | apply plugin: 'com.android.application' 12 | apply plugin: 'io.fabric' 13 | 14 | repositories { 15 | mavenCentral() 16 | 17 | maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } 18 | maven { url 'https://maven.fabric.io/public' } 19 | } 20 | 21 | 22 | dependencies { 23 | compile project(':library') 24 | compile 'com.android.support:appcompat-v7:23.1.1' 25 | compile 'com.android.support:cardview-v7:23.1.1' 26 | compile 'com.jakewharton:butterknife:6.0.0' 27 | compile 'com.readystatesoftware.systembartint:systembartint:1.0.3' 28 | compile 'com.nineoldandroids:library:2.4.0' 29 | compile('com.crashlytics.sdk.android:crashlytics:2.5.5@aar') { 30 | transitive = true; 31 | } 32 | } 33 | 34 | android { 35 | compileSdkVersion 23 36 | buildToolsVersion "23.0.2" 37 | 38 | defaultConfig { 39 | minSdkVersion 9 40 | targetSdkVersion 23 41 | 42 | versionName "1.0.7" 43 | versionCode 11 44 | } 45 | 46 | signingConfigs { release } 47 | 48 | buildTypes { 49 | release { 50 | signingConfig signingConfigs.release 51 | } 52 | } 53 | 54 | sourceSets { 55 | main { 56 | manifest.srcFile 'AndroidManifest.xml' 57 | java.srcDirs = ['src'] 58 | res.srcDirs = ['res'] 59 | } 60 | } 61 | 62 | android { 63 | lintOptions { 64 | abortOnError false 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /sample/res/drawable-hdpi/ic_action_content_clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-hdpi/ic_action_content_clear.png -------------------------------------------------------------------------------- /sample/res/drawable-hdpi/ic_action_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-hdpi/ic_action_github.png -------------------------------------------------------------------------------- /sample/res/drawable-hdpi/ic_action_info_outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-hdpi/ic_action_info_outline.png -------------------------------------------------------------------------------- /sample/res/drawable-hdpi/ic_action_navigation_arrow_forward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-hdpi/ic_action_navigation_arrow_forward.png -------------------------------------------------------------------------------- /sample/res/drawable-hdpi/ic_action_social_mood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-hdpi/ic_action_social_mood.png -------------------------------------------------------------------------------- /sample/res/drawable-hdpi/ic_action_social_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-hdpi/ic_action_social_share.png -------------------------------------------------------------------------------- /sample/res/drawable-hdpi/ic_action_twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-hdpi/ic_action_twitter.png -------------------------------------------------------------------------------- /sample/res/drawable-hdpi/ic_navigation_arrow_back_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-hdpi/ic_navigation_arrow_back_white.png -------------------------------------------------------------------------------- /sample/res/drawable-hdpi/ic_ripple_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-hdpi/ic_ripple_selected.png -------------------------------------------------------------------------------- /sample/res/drawable-hdpi/ic_ripple_unselected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-hdpi/ic_ripple_unselected.png -------------------------------------------------------------------------------- /sample/res/drawable-hdpi/ic_tabs_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-hdpi/ic_tabs_selected.png -------------------------------------------------------------------------------- /sample/res/drawable-hdpi/ic_tabs_unselected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-hdpi/ic_tabs_unselected.png -------------------------------------------------------------------------------- /sample/res/drawable-hdpi/ic_toggle_check_box_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-hdpi/ic_toggle_check_box_dark.png -------------------------------------------------------------------------------- /sample/res/drawable-hdpi/ic_toggle_check_box_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-hdpi/ic_toggle_check_box_light.png -------------------------------------------------------------------------------- /sample/res/drawable-mdpi/ic_action_content_clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-mdpi/ic_action_content_clear.png -------------------------------------------------------------------------------- /sample/res/drawable-mdpi/ic_action_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-mdpi/ic_action_github.png -------------------------------------------------------------------------------- /sample/res/drawable-mdpi/ic_action_info_outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-mdpi/ic_action_info_outline.png -------------------------------------------------------------------------------- /sample/res/drawable-mdpi/ic_action_navigation_arrow_forward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-mdpi/ic_action_navigation_arrow_forward.png -------------------------------------------------------------------------------- /sample/res/drawable-mdpi/ic_action_social_mood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-mdpi/ic_action_social_mood.png -------------------------------------------------------------------------------- /sample/res/drawable-mdpi/ic_action_social_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-mdpi/ic_action_social_share.png -------------------------------------------------------------------------------- /sample/res/drawable-mdpi/ic_action_twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-mdpi/ic_action_twitter.png -------------------------------------------------------------------------------- /sample/res/drawable-mdpi/ic_navigation_arrow_back_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-mdpi/ic_navigation_arrow_back_white.png -------------------------------------------------------------------------------- /sample/res/drawable-mdpi/ic_ripple_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-mdpi/ic_ripple_selected.png -------------------------------------------------------------------------------- /sample/res/drawable-mdpi/ic_ripple_unselected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-mdpi/ic_ripple_unselected.png -------------------------------------------------------------------------------- /sample/res/drawable-mdpi/ic_tabs_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-mdpi/ic_tabs_selected.png -------------------------------------------------------------------------------- /sample/res/drawable-mdpi/ic_tabs_unselected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-mdpi/ic_tabs_unselected.png -------------------------------------------------------------------------------- /sample/res/drawable-mdpi/ic_toggle_check_box_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-mdpi/ic_toggle_check_box_dark.png -------------------------------------------------------------------------------- /sample/res/drawable-mdpi/ic_toggle_check_box_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-mdpi/ic_toggle_check_box_light.png -------------------------------------------------------------------------------- /sample/res/drawable-xhdpi/ic_action_content_clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xhdpi/ic_action_content_clear.png -------------------------------------------------------------------------------- /sample/res/drawable-xhdpi/ic_action_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xhdpi/ic_action_github.png -------------------------------------------------------------------------------- /sample/res/drawable-xhdpi/ic_action_info_outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xhdpi/ic_action_info_outline.png -------------------------------------------------------------------------------- /sample/res/drawable-xhdpi/ic_action_navigation_arrow_forward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xhdpi/ic_action_navigation_arrow_forward.png -------------------------------------------------------------------------------- /sample/res/drawable-xhdpi/ic_action_social_mood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xhdpi/ic_action_social_mood.png -------------------------------------------------------------------------------- /sample/res/drawable-xhdpi/ic_action_social_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xhdpi/ic_action_social_share.png -------------------------------------------------------------------------------- /sample/res/drawable-xhdpi/ic_action_twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xhdpi/ic_action_twitter.png -------------------------------------------------------------------------------- /sample/res/drawable-xhdpi/ic_navigation_arrow_back_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xhdpi/ic_navigation_arrow_back_blue.png -------------------------------------------------------------------------------- /sample/res/drawable-xhdpi/ic_ripple_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xhdpi/ic_ripple_selected.png -------------------------------------------------------------------------------- /sample/res/drawable-xhdpi/ic_ripple_unselected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xhdpi/ic_ripple_unselected.png -------------------------------------------------------------------------------- /sample/res/drawable-xhdpi/ic_tabs_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xhdpi/ic_tabs_selected.png -------------------------------------------------------------------------------- /sample/res/drawable-xhdpi/ic_tabs_unselected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xhdpi/ic_tabs_unselected.png -------------------------------------------------------------------------------- /sample/res/drawable-xhdpi/ic_toggle_check_box_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xhdpi/ic_toggle_check_box_dark.png -------------------------------------------------------------------------------- /sample/res/drawable-xhdpi/ic_toggle_check_box_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xhdpi/ic_toggle_check_box_light.png -------------------------------------------------------------------------------- /sample/res/drawable-xxhdpi/ic_action_content_clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxhdpi/ic_action_content_clear.png -------------------------------------------------------------------------------- /sample/res/drawable-xxhdpi/ic_action_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxhdpi/ic_action_github.png -------------------------------------------------------------------------------- /sample/res/drawable-xxhdpi/ic_action_info_outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxhdpi/ic_action_info_outline.png -------------------------------------------------------------------------------- /sample/res/drawable-xxhdpi/ic_action_navigation_arrow_forward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxhdpi/ic_action_navigation_arrow_forward.png -------------------------------------------------------------------------------- /sample/res/drawable-xxhdpi/ic_action_social_mood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxhdpi/ic_action_social_mood.png -------------------------------------------------------------------------------- /sample/res/drawable-xxhdpi/ic_action_social_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxhdpi/ic_action_social_share.png -------------------------------------------------------------------------------- /sample/res/drawable-xxhdpi/ic_action_twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxhdpi/ic_action_twitter.png -------------------------------------------------------------------------------- /sample/res/drawable-xxhdpi/ic_navigation_arrow_back_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxhdpi/ic_navigation_arrow_back_white.png -------------------------------------------------------------------------------- /sample/res/drawable-xxhdpi/ic_ripple_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxhdpi/ic_ripple_selected.png -------------------------------------------------------------------------------- /sample/res/drawable-xxhdpi/ic_ripple_unselected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxhdpi/ic_ripple_unselected.png -------------------------------------------------------------------------------- /sample/res/drawable-xxhdpi/ic_tabs_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxhdpi/ic_tabs_selected.png -------------------------------------------------------------------------------- /sample/res/drawable-xxhdpi/ic_tabs_unselected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxhdpi/ic_tabs_unselected.png -------------------------------------------------------------------------------- /sample/res/drawable-xxhdpi/ic_toggle_check_box_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxhdpi/ic_toggle_check_box_dark.png -------------------------------------------------------------------------------- /sample/res/drawable-xxhdpi/ic_toggle_check_box_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxhdpi/ic_toggle_check_box_light.png -------------------------------------------------------------------------------- /sample/res/drawable-xxxhdpi/ic_action_content_clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxxhdpi/ic_action_content_clear.png -------------------------------------------------------------------------------- /sample/res/drawable-xxxhdpi/ic_action_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxxhdpi/ic_action_github.png -------------------------------------------------------------------------------- /sample/res/drawable-xxxhdpi/ic_action_info_outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxxhdpi/ic_action_info_outline.png -------------------------------------------------------------------------------- /sample/res/drawable-xxxhdpi/ic_action_navigation_arrow_forward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxxhdpi/ic_action_navigation_arrow_forward.png -------------------------------------------------------------------------------- /sample/res/drawable-xxxhdpi/ic_action_social_mood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxxhdpi/ic_action_social_mood.png -------------------------------------------------------------------------------- /sample/res/drawable-xxxhdpi/ic_action_social_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxxhdpi/ic_action_social_share.png -------------------------------------------------------------------------------- /sample/res/drawable-xxxhdpi/ic_action_twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxxhdpi/ic_action_twitter.png -------------------------------------------------------------------------------- /sample/res/drawable-xxxhdpi/ic_navigation_arrow_back_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxxhdpi/ic_navigation_arrow_back_white.png -------------------------------------------------------------------------------- /sample/res/drawable-xxxhdpi/ic_ripple_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxxhdpi/ic_ripple_selected.png -------------------------------------------------------------------------------- /sample/res/drawable-xxxhdpi/ic_ripple_unselected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxxhdpi/ic_ripple_unselected.png -------------------------------------------------------------------------------- /sample/res/drawable-xxxhdpi/ic_tabs_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxxhdpi/ic_tabs_selected.png -------------------------------------------------------------------------------- /sample/res/drawable-xxxhdpi/ic_tabs_unselected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxxhdpi/ic_tabs_unselected.png -------------------------------------------------------------------------------- /sample/res/drawable-xxxhdpi/ic_toggle_check_box_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxxhdpi/ic_toggle_check_box_dark.png -------------------------------------------------------------------------------- /sample/res/drawable-xxxhdpi/ic_toggle_check_box_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxxhdpi/ic_toggle_check_box_light.png -------------------------------------------------------------------------------- /sample/res/drawable-xxxhdpi/me.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/drawable-xxxhdpi/me.jpg -------------------------------------------------------------------------------- /sample/res/drawable/radio_button_dark.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /sample/res/drawable/radio_button_light.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /sample/res/layout/activity_tabs.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 20 | 21 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /sample/res/layout/dialog_me.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 11 | 12 | 17 | 18 | 25 | 26 | 32 | 33 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /sample/res/layout/fragment_card.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /sample/res/layout/fragment_ripple_settings.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 | 12 | 16 | 17 | 21 | 22 | 29 | 30 | 40 | 41 | 42 | 46 | 47 | 48 | 49 | 52 | 53 | 54 | 58 | 59 | 63 | 64 | 71 | 72 | 82 | 83 | 84 | 88 | 89 | 90 | 91 | 94 | 95 | 96 | 100 | 101 | 105 | 106 | 113 | 114 | 123 | 124 | 128 | 137 | 138 | 147 | 148 | 157 | 158 | 167 | 168 | 177 | 178 | 187 | 188 | 197 | 198 | 199 | 200 | 201 | 204 | 205 | 206 | 207 | 212 | 213 | 220 | 221 | 227 | 228 | 235 | 236 | 239 | 240 | 241 | 242 | 243 | 244 | 247 | 248 | 249 | 253 | 254 | 258 | 259 | 266 | 267 | 277 | 278 | 279 | 283 | 284 | 285 | 286 | 289 | 290 | 291 | 295 | 296 | 300 | 301 | 308 | 309 | 319 | 320 | 321 | 325 | 326 | 327 | 328 | 331 | 332 | 333 | 337 | 338 | 342 | 343 | 350 | 351 | 360 | 361 | 362 | 366 | 375 | 376 | 385 | 386 | 395 | 396 | 405 | 406 | 415 | 416 | 425 | 426 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 444 | 445 | 446 | 447 | 452 | 453 | 460 | 461 | 467 | 468 | 475 | 478 | 479 | 480 | 481 | 482 | 483 | 486 | 487 | 488 | 489 | 494 | 495 | 502 | 503 | 509 | 510 | 517 | 518 | 521 | 522 | 523 | 524 | 525 | 526 | 529 | 530 | 531 | 535 | 536 | 540 | 541 | 548 | 549 | 559 | 560 | 564 | 565 | 566 | 567 | 568 | -------------------------------------------------------------------------------- /sample/res/layout/toolbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | -------------------------------------------------------------------------------- /sample/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 |

5 | 10 | 15 | 20 | 21 | -------------------------------------------------------------------------------- /sample/res/menu/menu_tabs.xml: -------------------------------------------------------------------------------- 1 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /sample/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/res/resize_xxxhdpi_pictures_to_other_dpis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #--------------------------------------------------------------- 3 | # Given an xxxhdpi image or an App Icon (launcher), this script 4 | # creates different dpis resources 5 | # 6 | # Place this script, as well as the source image, inside res 7 | # folder and execute it passing the image filename as argument 8 | # 9 | # Example: 10 | # ./drawables_dpis_creation.sh ic_launcher.png 11 | # OR 12 | # ./drawables_dpis_creation.sh my_cool_xxhdpi_image.png 13 | #--------------------------------------------------------------- 14 | 15 | echo " Creating different dimensions (dips) of "$1" ..." 16 | 17 | if [ $1 = "ic_launcher.png" ]; then 18 | echo " App icon detected" 19 | 20 | convert ic_launcher.png -resize 192x192 drawable-xxxhdpi/ic_launcher.png 21 | convert ic_launcher.png -resize 144x144 drawable-xxhdpi/ic_launcher.png 22 | convert ic_launcher.png -resize 96x96 drawable-xhdpi/ic_launcher.png 23 | convert ic_launcher.png -resize 72x72 drawable-hdpi/ic_launcher.png 24 | convert ic_launcher.png -resize 48x48 drawable-mdpi/ic_launcher.png 25 | # convert ic_launcher.png -resize 36x36 drawable-ldpi/ic_launcher.png 26 | 27 | rm -i ic_launcher.png 28 | else 29 | convert $1 -resize 75% drawable-xxhdpi/$1 30 | convert $1 -resize 50% drawable-xhdpi/$1 31 | convert $1 -resize 37.5% drawable-hdpi/$1 32 | convert $1 -resize 25% drawable-mdpi/$1 33 | # convert $1 -resize 18.75% drawable-ldpi/$1 34 | mv $1 drawable-xxxhdpi/$1 35 | 36 | fi 37 | 38 | echo " Done" 39 | -------------------------------------------------------------------------------- /sample/res/values-v19/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /sample/res/values-v20/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /sample/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /sample/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFF 4 | #000 5 | #40FFFFFF 6 | #40000000 7 | 8 | #80888888 9 | 10 | #FFE5E5E5 11 | #3E5F22 12 | 13 | 14 | #8BC24A 15 | #FF9700 16 | #FFEB3C 17 | #D01715 18 | #00BCD5 19 | 20 | 21 | 22 | #408BC24A 23 | #40FF9700 24 | #40FFEB3C 25 | #40D01715 26 | #4000BCD5 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /sample/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | MaterialTabs 4 | Cook Your Tabs 5 | 6 | Underline Height 7 | Indicator Height 8 | Tab Padding Left Right 9 | Same Weight Tabs 10 | Underline Color 11 | Indicator Color 12 | Text All Caps 13 | Padding Middle 14 | Tab Text Unselected Color 15 | Tab Text Selected Color 16 | Tab Bar Background Color 17 | Selected Text Style 18 | Unselected Text Style 19 | Ripple Duration 20 | Ripple Alpha Float 21 | Ripple Color 22 | Ripple Delay Click 23 | Ripple Diameter 24 | Ripple Fade Duration 25 | Ripple Highlight Color 26 | Ripple Overlay 27 | Ripple Persistent 28 | Ripple Rounded Corners Radius 29 | Me 30 | Go 31 | Normal 32 | Bold 33 | Italic 34 | Share 35 | Reset 36 | Toolbar (ActionBar) Color 37 | 38 | Level of transparency (alpha) of the ripple 39 | Color of the ripple 40 | Radius of starting ripple 41 | Duration of the ripple animation 42 | If true, delays calls to OnClickListeners until ripple effect ends. In that case, the indicator line\'s 43 | move to the clicked tab will also be delayed 44 | 45 | Duration of fade out effect on ripple 46 | If true, ripple is drawn in foreground of view. Otherwise, it will drawn in the background 47 | If true, the ripple background color persists after animation, until setRadius(0) is called 48 | Color of the background while the ripple is undergoing an animation 49 | Radius of corners of the ripple. Note: it uses software rendering pipeline for API 17 and 50 | below 51 | 52 | 53 | If set to true, each tab is given the same weight 54 | If true, the tabs start at the middle of the view 55 | Height of the sliding indicator 56 | Color of the sliding indicator 57 | Height of the full-width line on the bottom of the view 58 | Color of the full-width line on the bottom of the view 59 | If true, all tab titles will be upper case 60 | Style of text in unselected tab 61 | Style of text in selected tab 62 | Left and right padding of each tab 63 | Color of text in selected tab 64 | Color of text in non-selected tabs 65 | Color of toolbar in the next Activity 66 | Background color of tab bar 67 | pizza 68 | \@KarimFrenn 69 | Karim Frenn 70 | http://github.com/pizza 71 | http://twitter.com/karimfrenn 72 | Show Toolbar 73 | Show/hide toolbar in next Activity 74 | Number of Tabs 75 | Send to 76 | The number of tabs to be shown in next Activity 77 | 78 | -------------------------------------------------------------------------------- /sample/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 15 | 16 | 19 | 20 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /sample/sample-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/sample-release.apk -------------------------------------------------------------------------------- /sample/src/io/karim/materialtabs/sample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package io.karim.materialtabs.sample; 2 | 3 | import com.readystatesoftware.systembartint.SystemBarTintManager; 4 | 5 | import android.app.AlertDialog; 6 | import android.content.DialogInterface; 7 | import android.content.Intent; 8 | import android.os.Bundle; 9 | import android.support.v4.app.DialogFragment; 10 | import android.support.v4.app.Fragment; 11 | import android.support.v4.app.FragmentManager; 12 | import android.support.v4.app.FragmentPagerAdapter; 13 | import android.support.v4.view.ViewPager; 14 | import android.support.v7.app.AppCompatActivity; 15 | import android.support.v7.widget.Toolbar; 16 | import android.text.Spannable; 17 | import android.text.SpannableString; 18 | import android.text.Spanned; 19 | import android.text.method.LinkMovementMethod; 20 | import android.text.style.URLSpan; 21 | import android.util.Log; 22 | import android.util.TypedValue; 23 | import android.view.LayoutInflater; 24 | import android.view.Menu; 25 | import android.view.MenuItem; 26 | import android.view.View; 27 | import android.view.ViewGroup; 28 | import android.view.Window; 29 | import android.widget.ImageView; 30 | import android.widget.TextView; 31 | 32 | import java.util.ArrayList; 33 | 34 | import butterknife.ButterKnife; 35 | import butterknife.InjectView; 36 | import io.karim.MaterialTabs; 37 | 38 | 39 | public class MainActivity extends AppCompatActivity { 40 | 41 | private static final String TAG = MainActivity.class.getSimpleName(); 42 | 43 | @InjectView(R.id.toolbar) 44 | Toolbar mToolbar; 45 | 46 | @InjectView(R.id.material_tabs) 47 | MaterialTabs mMaterialTabs; 48 | 49 | @InjectView(R.id.view_pager) 50 | ViewPager mViewPager; 51 | 52 | /** 53 | * Intent used to start {@link TabsActivity}. 54 | */ 55 | public Intent startTabsActivityIntent; 56 | 57 | /** 58 | * Holds references to fragments from the time they are attached to Activity until they are dettached. 59 | */ 60 | private ArrayList mFragments = new ArrayList<>(); 61 | 62 | @Override 63 | protected void onCreate(Bundle savedInstanceState) { 64 | super.onCreate(savedInstanceState); 65 | setContentView(R.layout.activity_tabs); 66 | ButterKnife.inject(this); 67 | setSupportActionBar(mToolbar); 68 | getSupportActionBar().setTitle(getString(R.string.title_activity_main)); 69 | 70 | // Apply background tinting to the Android system UI when using KitKat translucent modes. 71 | SystemBarTintManager tintManager = new SystemBarTintManager(this); 72 | tintManager.setStatusBarTintEnabled(true); 73 | 74 | startTabsActivityIntent = new Intent(this, TabsActivity.class); 75 | 76 | MainActivityPagerAdapter adapter = new MainActivityPagerAdapter(getSupportFragmentManager()); 77 | mViewPager.setAdapter(adapter); 78 | 79 | mMaterialTabs.setViewPager(mViewPager); 80 | 81 | final int pageMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, getResources().getDisplayMetrics()); 82 | mViewPager.setPageMargin(pageMargin); 83 | mViewPager.setCurrentItem(0); 84 | } 85 | 86 | @Override 87 | public boolean onCreateOptionsMenu(Menu menu) { 88 | // Inflate the menu; this adds items to the action bar if it is present. 89 | getMenuInflater().inflate(R.menu.menu_main, menu); 90 | return true; 91 | } 92 | 93 | @Override 94 | public boolean onOptionsItemSelected(MenuItem item) { 95 | // Handle action bar item clicks here. The action bar will automatically handle clicks on the Home/Up button, so long 96 | // as you specify a parent activity in AndroidManifest.xml. 97 | switch (item.getItemId()) { 98 | case R.id.action_me: 99 | DialogFragment newFragment = new MeDialogFragment(); 100 | newFragment.show(getSupportFragmentManager(), "dialog"); 101 | return true; 102 | case R.id.action_reset: 103 | AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this); 104 | alertDialogBuilder.setMessage("Reset everything to default?") 105 | .setCancelable(false) 106 | .setPositiveButton("Yes", new DialogInterface.OnClickListener() { 107 | public void onClick(DialogInterface dialog, int id) { 108 | resetDefaults(); 109 | } 110 | }) 111 | .setNegativeButton("No", new DialogInterface.OnClickListener() { 112 | public void onClick(DialogInterface dialog, int id) { 113 | dialog.cancel(); 114 | } 115 | }); 116 | AlertDialog alertDialog = alertDialogBuilder.create(); 117 | // show it 118 | alertDialog.show(); 119 | return true; 120 | case R.id.action_go: 121 | startActivity(startTabsActivityIntent); 122 | return true; 123 | } 124 | 125 | return super.onOptionsItemSelected(item); 126 | } 127 | 128 | /** 129 | * Resets default values of all the settings in both {@link TabsSettingsFragment} and {@link RippleSettingsFragment}. 130 | */ 131 | private void resetDefaults() { 132 | for (ResettableFragment f : mFragments) { 133 | f.setupAndReset(); 134 | } 135 | } 136 | 137 | /** 138 | * Add fragment to {@link #mFragments} when attached to Activity. 139 | */ 140 | public void addFragment(ResettableFragment f) { 141 | mFragments.add(f); 142 | } 143 | 144 | 145 | /** 146 | * Remove fragment from {@link #mFragments} when detached to Activity. 147 | */ 148 | public void removeFragment(ResettableFragment f) { 149 | mFragments.remove(f); 150 | } 151 | 152 | public class MainActivityPagerAdapter extends FragmentPagerAdapter implements MaterialTabs.CustomTabProvider { 153 | 154 | private final String[] TITLES = {"Tabs", "Ripple"}; 155 | 156 | private final int[] UNSELECTED_ICONS = {R.drawable.ic_tabs_unselected, R.drawable.ic_ripple_unselected}; 157 | private final int[] SELECTED_ICONS = {R.drawable.ic_tabs_selected, R.drawable.ic_ripple_selected}; 158 | 159 | public MainActivityPagerAdapter(FragmentManager fm) { 160 | super(fm); 161 | } 162 | 163 | @Override 164 | public CharSequence getPageTitle(int position) { 165 | return TITLES[position]; 166 | } 167 | 168 | @Override 169 | public int getCount() { 170 | return TITLES.length; 171 | } 172 | 173 | @Override 174 | public Fragment getItem(int position) { 175 | switch (position) { 176 | case 0: 177 | default: 178 | return new TabsSettingsFragment(); 179 | case 1: 180 | return new RippleSettingsFragment(); 181 | } 182 | } 183 | 184 | @Override 185 | public View getCustomTabView(ViewGroup parent, int position) { 186 | ImageView imageView = new ImageView(MainActivity.this); 187 | imageView.setImageResource(UNSELECTED_ICONS[position]); 188 | return imageView; 189 | } 190 | 191 | @Override 192 | public void onCustomTabViewSelected(View view, int position, boolean alreadySelected) { 193 | Log.i(TAG, "custom tab view selected with position = " + position); 194 | if (view instanceof ImageView) { 195 | ((ImageView) view).setImageResource(SELECTED_ICONS[position]); 196 | } 197 | } 198 | 199 | @Override 200 | public void onCustomTabViewUnselected(View view, int position, boolean alreadyUnselected) { 201 | Log.i(TAG, "custom tab view unselected with position = " + position); 202 | if (view instanceof ImageView) { 203 | ((ImageView) view).setImageResource(UNSELECTED_ICONS[position]); 204 | } 205 | } 206 | } 207 | 208 | 209 | public static class MeDialogFragment extends DialogFragment { 210 | @Override 211 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 212 | View view = inflater.inflate(R.layout.dialog_me, container, false); 213 | TextView githubTextView = (TextView) view.findViewById(R.id.github_text_view); 214 | TextView twitterTextView = (TextView) view.findViewById(R.id.twitter_text_view); 215 | 216 | String link = getString(R.string.github); 217 | Spannable spannable = new SpannableString(link); 218 | spannable.setSpan(new URLSpan(getString(R.string.github_link)), 0, link.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 219 | githubTextView.setText(spannable, TextView.BufferType.SPANNABLE); 220 | githubTextView.setMovementMethod(LinkMovementMethod.getInstance()); 221 | 222 | link = getString(R.string.twitter); 223 | spannable = new SpannableString(link); 224 | spannable.setSpan(new URLSpan(getString(R.string.twitter_link)), 0, link.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 225 | twitterTextView.setText(spannable, TextView.BufferType.SPANNABLE); 226 | twitterTextView.setMovementMethod(LinkMovementMethod.getInstance()); 227 | 228 | getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); 229 | return view; 230 | } 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /sample/src/io/karim/materialtabs/sample/MyApplication.java: -------------------------------------------------------------------------------- 1 | package io.karim.materialtabs.sample; 2 | 3 | import com.crashlytics.android.Crashlytics; 4 | 5 | import android.app.Application; 6 | 7 | import io.fabric.sdk.android.Fabric; 8 | 9 | /** 10 | * Created by karim on 5/20/15. 11 | */ 12 | public class MyApplication extends Application { 13 | 14 | /** 15 | * Called when the application is starting, before any activity, service, or receiver objects (excluding content providers) have been created. 16 | * Implementations should be as quick as possible (for example using lazy initialization of state) since the time spent in this function directly 17 | * impacts the performance of starting the first activity, service, or receiver in a process. If you override this method, be sure to call 18 | * super.onCreate(). 19 | */ 20 | @Override 21 | public void onCreate() { 22 | super.onCreate(); 23 | Fabric.with(this, new Crashlytics()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /sample/src/io/karim/materialtabs/sample/ResettableFragment.java: -------------------------------------------------------------------------------- 1 | package io.karim.materialtabs.sample; 2 | 3 | public interface ResettableFragment { 4 | void setupAndReset(); 5 | } 6 | -------------------------------------------------------------------------------- /sample/src/io/karim/materialtabs/sample/RippleSettingsFragment.java: -------------------------------------------------------------------------------- 1 | package io.karim.materialtabs.sample; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v7.app.AlertDialog; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.CheckBox; 11 | import android.widget.CompoundButton; 12 | import android.widget.RadioButton; 13 | import android.widget.RadioGroup; 14 | import android.widget.SeekBar; 15 | import android.widget.TextView; 16 | 17 | import butterknife.ButterKnife; 18 | import butterknife.InjectView; 19 | import butterknife.OnClick; 20 | import io.karim.MaterialRippleLayout; 21 | 22 | public class RippleSettingsFragment extends Fragment implements ResettableFragment { 23 | 24 | public static final String RIPPLE_DURATION = "RIPPLE_DURATION"; 25 | public static final String RIPPLE_ALPHA_FLOAT = "RIPPLE_ALPHA_FLOAT"; 26 | public static final String RIPPLE_COLOR = "RIPPLE_COLOR"; 27 | public static final String RIPPLE_DELAY_CLICK = "RIPPLE_DELAY_CLICK"; 28 | public static final String RIPPLE_DIAMETER = "RIPPLE_DIAMETER"; 29 | public static final String RIPPLE_FADE_DURATION = "RIPPLE_FADE_DURATION"; 30 | public static final String RIPPLE_HIGHLIGHT_COLOR = "RIPPLE_HIGHLIGHT_COLOR"; 31 | public static final String RIPPLE_OVERLAY = "RIPPLE_OVERLAY"; 32 | public static final String RIPPLE_PERSISTENT = "RIPPLE_PERSISTENT"; 33 | public static final String RIPPLE_ROUNDED_CORNERS_RADIUS = "RIPPLE_ROUNDED_CORNERS_RADIUS"; 34 | 35 | private static final int RIPPLE_DURATION_MULTIPLIER = 50; 36 | 37 | private MainActivity mainActivity; 38 | 39 | int rippleDurationMs; 40 | float rippleAlphaFloat; 41 | int rippleFadeDurationMs; 42 | int rippleRoundedCornersRadiusDp; 43 | float rippleDiameterDp; 44 | 45 | // Ripple Duration 46 | @InjectView(R.id.rippleDurationSeekBar) 47 | SeekBar rippleDurationSeekBar; 48 | @InjectView(R.id.rippleDurationTextView) 49 | TextView rippleDurationTextView; 50 | 51 | // Ripple Alpha Float 52 | @InjectView(R.id.rippleAlphaFloatSeekBar) 53 | SeekBar rippleAlphaFloatSeekBar; 54 | @InjectView(R.id.rippleAlphaFloatTextView) 55 | TextView rippleAlphaFloatTextView; 56 | 57 | // Ripple Color 58 | @InjectView(R.id.rippleColorRadioGroup) 59 | RadioGroup rippleColorRadioGroup; 60 | @InjectView(R.id.rippleColorButtonWhite) 61 | RadioButton rippleColorButtonWhite; 62 | 63 | // Ripple Delay Click 64 | @InjectView(R.id.rippleDelayClickCheckBox) 65 | CheckBox rippleDelayClickCheckBox; 66 | 67 | // Ripple Diameter 68 | @InjectView(R.id.rippleDiameterSeekBar) 69 | SeekBar rippleDiameterSeekBar; 70 | @InjectView(R.id.rippleDiameterTextView) 71 | TextView rippleDiameterTextView; 72 | 73 | // Ripple Fade Duration 74 | @InjectView(R.id.rippleFadeDurationSeekBar) 75 | SeekBar rippleFadeDurationSeekBar; 76 | @InjectView(R.id.rippleFadeDurationTextView) 77 | TextView rippleFadeDurationTextView; 78 | 79 | // Ripple Highlight Color 80 | @InjectView(R.id.rippleHighlightColorRadioGroup) 81 | RadioGroup rippleHighlightColorRadioGroup; 82 | @InjectView(R.id.rippleHighlightColorButtonWhite) 83 | RadioButton rippleHighlightColorButtonWhite; 84 | 85 | // Ripple Overlay 86 | @InjectView(R.id.rippleOverlayCheckBox) 87 | CheckBox rippleOverlayCheckBox; 88 | 89 | // Ripple Persistent 90 | @InjectView(R.id.ripplePersistentCheckBox) 91 | CheckBox ripplePersistentCheckBox; 92 | 93 | // Ripple Rounded Corners Radius 94 | @InjectView(R.id.rippleRoundedCornersRadiusSeekBar) 95 | SeekBar rippleRoundedCornersRadiusSeekBar; 96 | @InjectView(R.id.rippleRoundedCornersRadiusTextView) 97 | TextView rippleRoundedCornersRadiusTextView; 98 | 99 | @Override 100 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 101 | View rootView = inflater.inflate(R.layout.fragment_ripple_settings, container, false); 102 | ButterKnife.inject(this, rootView); 103 | 104 | setupAndReset(); 105 | return rootView; 106 | } 107 | 108 | @Override 109 | public void onAttach(Activity activity) { 110 | super.onAttach(activity); 111 | mainActivity = (MainActivity) getActivity(); 112 | mainActivity.addFragment(this); 113 | } 114 | 115 | @Override 116 | public void onDetach() { 117 | mainActivity.removeFragment(this); 118 | super.onDetach(); 119 | } 120 | 121 | @Override 122 | public void setupAndReset() { 123 | /** SeekBars **/ 124 | 125 | rippleDurationMs = MaterialRippleLayout.DEFAULT_DURATION; 126 | rippleDurationTextView.setText(getString(R.string.ripple_duration) + ": " + rippleDurationMs + "ms"); 127 | rippleDurationSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 128 | @Override 129 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 130 | rippleDurationMs = progress * RIPPLE_DURATION_MULTIPLIER; 131 | rippleDurationTextView.setText(getString(R.string.ripple_duration) + ": " + rippleDurationMs + "ms"); 132 | mainActivity.startTabsActivityIntent.putExtra(RIPPLE_DURATION, rippleDurationMs); 133 | } 134 | 135 | @Override 136 | public void onStartTrackingTouch(SeekBar seekBar) { 137 | } 138 | 139 | @Override 140 | public void onStopTrackingTouch(SeekBar seekBar) { 141 | } 142 | }); 143 | 144 | rippleAlphaFloat = MaterialRippleLayout.DEFAULT_ALPHA; 145 | rippleAlphaFloatTextView.setText(getString(R.string.ripple_alpha_float) + ": " + rippleAlphaFloat); 146 | rippleAlphaFloatSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 147 | @Override 148 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 149 | rippleAlphaFloat = (float) progress / rippleAlphaFloatSeekBar.getMax(); 150 | rippleAlphaFloatTextView.setText(getString(R.string.ripple_alpha_float) + ": " + rippleAlphaFloat); 151 | mainActivity.startTabsActivityIntent.putExtra(RIPPLE_ALPHA_FLOAT, rippleAlphaFloat); 152 | } 153 | 154 | @Override 155 | public void onStartTrackingTouch(SeekBar seekBar) { 156 | } 157 | 158 | @Override 159 | public void onStopTrackingTouch(SeekBar seekBar) { 160 | } 161 | }); 162 | 163 | rippleFadeDurationMs = MaterialRippleLayout.DEFAULT_FADE_DURATION; 164 | rippleFadeDurationTextView.setText(getString(R.string.ripple_fade_duration) + ": " + rippleFadeDurationMs + "ms"); 165 | rippleFadeDurationSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 166 | @Override 167 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 168 | rippleFadeDurationMs = progress * RIPPLE_DURATION_MULTIPLIER; 169 | rippleFadeDurationTextView.setText(getString(R.string.ripple_fade_duration) + ": " + rippleFadeDurationMs + "ms"); 170 | mainActivity.startTabsActivityIntent.putExtra(RIPPLE_FADE_DURATION, rippleFadeDurationMs); 171 | } 172 | 173 | @Override 174 | public void onStartTrackingTouch(SeekBar seekBar) { 175 | } 176 | 177 | @Override 178 | public void onStopTrackingTouch(SeekBar seekBar) { 179 | } 180 | }); 181 | 182 | rippleRoundedCornersRadiusDp = MaterialRippleLayout.DEFAULT_ROUNDED_CORNERS_DP; 183 | rippleRoundedCornersRadiusTextView.setText(getString(R.string.ripple_rounded_corners_radius) + ": " + rippleRoundedCornersRadiusDp + "dp"); 184 | rippleRoundedCornersRadiusSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 185 | @Override 186 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 187 | rippleRoundedCornersRadiusDp = progress; 188 | rippleRoundedCornersRadiusTextView.setText( 189 | getString(R.string.ripple_rounded_corners_radius) + ": " + rippleRoundedCornersRadiusDp + "dp"); 190 | mainActivity.startTabsActivityIntent.putExtra(RIPPLE_ROUNDED_CORNERS_RADIUS, rippleRoundedCornersRadiusDp); 191 | } 192 | 193 | @Override 194 | public void onStartTrackingTouch(SeekBar seekBar) { 195 | } 196 | 197 | @Override 198 | public void onStopTrackingTouch(SeekBar seekBar) { 199 | } 200 | }); 201 | 202 | rippleDiameterDp = MaterialRippleLayout.DEFAULT_DIAMETER_DP; 203 | rippleDiameterTextView.setText(getString(R.string.ripple_diameter) + ": " + rippleDiameterDp + "dp"); 204 | rippleDiameterSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 205 | @Override 206 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 207 | rippleDiameterDp = progress; 208 | rippleDiameterTextView.setText(getString(R.string.ripple_diameter) + ": " + rippleDiameterDp + "dp"); 209 | mainActivity.startTabsActivityIntent.putExtra(RIPPLE_DIAMETER, rippleDiameterDp); 210 | } 211 | 212 | @Override 213 | public void onStartTrackingTouch(SeekBar seekBar) { 214 | } 215 | 216 | @Override 217 | public void onStopTrackingTouch(SeekBar seekBar) { 218 | } 219 | }); 220 | 221 | rippleDurationSeekBar.setProgress(rippleDurationMs / RIPPLE_DURATION_MULTIPLIER); 222 | rippleAlphaFloatSeekBar.setProgress((int) (rippleAlphaFloat * rippleAlphaFloatSeekBar.getMax())); 223 | rippleFadeDurationSeekBar.setProgress(rippleFadeDurationMs / RIPPLE_DURATION_MULTIPLIER); 224 | rippleRoundedCornersRadiusSeekBar.setProgress(rippleRoundedCornersRadiusDp); 225 | rippleDiameterSeekBar.setProgress((int) rippleDiameterDp); 226 | 227 | /** RadioGroups **/ 228 | 229 | // Ripple Color 230 | rippleColorRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { 231 | @Override 232 | public void onCheckedChanged(RadioGroup group, int checkedId) { 233 | String key = RIPPLE_COLOR; 234 | switch (checkedId) { 235 | case R.id.rippleColorButtonFireEngineRed: 236 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.fire_engine_red); 237 | break; 238 | case R.id.rippleColorButtonGorse: 239 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.gorse); 240 | break; 241 | case R.id.rippleColorButtonIrisBlue: 242 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.iris_blue); 243 | break; 244 | case R.id.rippleColorButtonSafetyOrange: 245 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.safety_orange); 246 | break; 247 | case R.id.rippleColorButtonWhite: 248 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.white); 249 | break; 250 | case R.id.rippleColorButtonBlack: 251 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.black); 252 | break; 253 | case R.id.rippleColorButtonMantis: 254 | default: 255 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.mantis); 256 | break; 257 | } 258 | } 259 | }); 260 | 261 | // Ripple Highlight Color 262 | rippleHighlightColorRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { 263 | @Override 264 | public void onCheckedChanged(RadioGroup group, int checkedId) { 265 | String key = RIPPLE_HIGHLIGHT_COLOR; 266 | switch (checkedId) { 267 | case R.id.rippleHighlightColorButtonFireEngineRed: 268 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.fire_engine_red_75); 269 | break; 270 | case R.id.rippleHighlightColorButtonGorse: 271 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.gorse_75); 272 | break; 273 | case R.id.rippleHighlightColorButtonIrisBlue: 274 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.iris_blue_75); 275 | break; 276 | case R.id.rippleHighlightColorButtonSafetyOrange: 277 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.safety_orange_75); 278 | break; 279 | case R.id.rippleHighlightColorButtonWhite: 280 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.white_75); 281 | break; 282 | case R.id.rippleHighlightColorButtonBlack: 283 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.black_75); 284 | break; 285 | case R.id.rippleHighlightColorButtonMantis: 286 | default: 287 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.mantis_75); 288 | break; 289 | } 290 | } 291 | }); 292 | 293 | rippleColorButtonWhite.setChecked(true); 294 | rippleHighlightColorButtonWhite.setChecked(true); 295 | 296 | /** Checkboxes **/ 297 | 298 | rippleDelayClickCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 299 | @Override 300 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 301 | mainActivity.startTabsActivityIntent.putExtra(RippleSettingsFragment.RIPPLE_DELAY_CLICK, isChecked); 302 | } 303 | }); 304 | 305 | ripplePersistentCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 306 | @Override 307 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 308 | mainActivity.startTabsActivityIntent.putExtra(RippleSettingsFragment.RIPPLE_PERSISTENT, isChecked); 309 | } 310 | }); 311 | 312 | rippleOverlayCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 313 | @Override 314 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 315 | mainActivity.startTabsActivityIntent.putExtra(RippleSettingsFragment.RIPPLE_OVERLAY, isChecked); 316 | } 317 | }); 318 | 319 | rippleDelayClickCheckBox.setChecked(MaterialRippleLayout.DEFAULT_DELAY_CLICK); 320 | ripplePersistentCheckBox.setChecked(MaterialRippleLayout.DEFAULT_PERSISTENT); 321 | rippleOverlayCheckBox.setChecked(MaterialRippleLayout.DEFAULT_RIPPLE_OVERLAY); 322 | } 323 | 324 | @OnClick(R.id.rippleAlphaFloatInfoButton) 325 | public void rippleAlphaFloatInfoButtonClicked() { 326 | new AlertDialog.Builder(getActivity()).setTitle(R.string.ripple_alpha_float).setMessage(R.string.ripple_alpha_float_details).create().show(); 327 | } 328 | 329 | @OnClick(R.id.rippleColorInfoButton) 330 | public void rippleColorInfoButtonClicked() { 331 | new AlertDialog.Builder(getActivity()).setTitle(R.string.ripple_color).setMessage(R.string.ripple_color_details).create().show(); 332 | } 333 | 334 | @OnClick(R.id.rippleDiameterInfoButton) 335 | public void rippleDiameterInfoButtonClicked() { 336 | new AlertDialog.Builder(getActivity()).setTitle(R.string.ripple_diameter).setMessage(R.string.ripple_diameter_details).create().show(); 337 | } 338 | 339 | @OnClick(R.id.rippleDurationInfoButton) 340 | public void rippleDurationInfoButtonClicked() { 341 | new AlertDialog.Builder(getActivity()).setTitle(R.string.ripple_duration).setMessage(R.string.ripple_duration_details).create().show(); 342 | } 343 | 344 | @OnClick(R.id.rippleDelayClickInfoButton) 345 | public void rippleDelayClickInfoButtonClicked() { 346 | new AlertDialog.Builder(getActivity()).setTitle(R.string.ripple_delay_click).setMessage(R.string.ripple_delay_click_details).create().show(); 347 | } 348 | 349 | @OnClick(R.id.rippleFadeDurationInfoButton) 350 | public void rippleFadeDurationInfoButtonClicked() { 351 | new AlertDialog.Builder(getActivity()).setTitle(R.string.ripple_fade_duration) 352 | .setMessage(R.string.ripple_fade_duration_details) 353 | .create() 354 | .show(); 355 | } 356 | 357 | @OnClick(R.id.rippleOverlayInfoButton) 358 | public void rippleOverlayInfoButtonClicked() { 359 | new AlertDialog.Builder(getActivity()).setTitle(R.string.ripple_overlay).setMessage(R.string.ripple_overlay_details).create().show(); 360 | } 361 | 362 | @OnClick(R.id.ripplePersistentInfoButton) 363 | public void ripplePersistentInfoButtonClicked() { 364 | new AlertDialog.Builder(getActivity()).setTitle(R.string.ripple_persistent).setMessage(R.string.ripple_persistent_details).create().show(); 365 | } 366 | 367 | @OnClick(R.id.rippleHighlightColorInfoButton) 368 | public void rippleHighlightColorInfoButtonClicked() { 369 | new AlertDialog.Builder(getActivity()).setTitle(R.string.ripple_highlight_color) 370 | .setMessage(R.string.ripple_highlight_color_details) 371 | .create() 372 | .show(); 373 | } 374 | 375 | @OnClick(R.id.rippleRoundedCornersRadiusInfoButton) 376 | public void rippleRoundedCornersRadiusInfoButtonClicked() { 377 | new AlertDialog.Builder(getActivity()).setTitle(R.string.ripple_rounded_corners_radius) 378 | .setMessage(R.string.ripple_rounded_corners_radius_details) 379 | .create() 380 | .show(); 381 | } 382 | } 383 | -------------------------------------------------------------------------------- /sample/src/io/karim/materialtabs/sample/SampleFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Andreas Stuetz 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.karim.materialtabs.sample; 18 | 19 | 20 | import android.os.Bundle; 21 | import android.support.v4.app.Fragment; 22 | import android.support.v4.view.ViewCompat; 23 | import android.view.LayoutInflater; 24 | import android.view.View; 25 | import android.view.ViewGroup; 26 | import android.widget.TextView; 27 | 28 | import butterknife.ButterKnife; 29 | import butterknife.InjectView; 30 | 31 | public class SampleFragment extends Fragment { 32 | 33 | private static final String ARG_POSITION = "position"; 34 | 35 | @InjectView(R.id.textView) 36 | TextView mTextView; 37 | 38 | private int position; 39 | 40 | public static SampleFragment newInstance(int position) { 41 | SampleFragment f = new SampleFragment(); 42 | Bundle b = new Bundle(); 43 | b.putInt(ARG_POSITION, position); 44 | f.setArguments(b); 45 | return f; 46 | } 47 | 48 | @Override 49 | public void onCreate(Bundle savedInstanceState) { 50 | super.onCreate(savedInstanceState); 51 | position = getArguments().getInt(ARG_POSITION); 52 | } 53 | 54 | @Override 55 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 56 | View rootView = inflater.inflate(R.layout.fragment_card, container, false); 57 | ButterKnife.inject(this, rootView); 58 | ViewCompat.setElevation(rootView, 50); 59 | mTextView.setText("Fragment #" + position); 60 | return rootView; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /sample/src/io/karim/materialtabs/sample/TabsActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Andreas Stuetz 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.karim.materialtabs.sample; 18 | 19 | import com.readystatesoftware.systembartint.SystemBarTintManager; 20 | 21 | import android.annotation.TargetApi; 22 | import android.content.Context; 23 | import android.content.Intent; 24 | import android.content.res.Resources; 25 | import android.graphics.Color; 26 | import android.graphics.Typeface; 27 | import android.graphics.drawable.Drawable; 28 | import android.os.Build; 29 | import android.os.Bundle; 30 | import android.support.annotation.DrawableRes; 31 | import android.support.v4.app.Fragment; 32 | import android.support.v4.app.FragmentManager; 33 | import android.support.v4.app.FragmentPagerAdapter; 34 | import android.support.v4.view.ViewPager; 35 | import android.support.v7.app.AppCompatActivity; 36 | import android.support.v7.widget.Toolbar; 37 | import android.util.Log; 38 | import android.util.TypedValue; 39 | import android.view.Menu; 40 | import android.view.MenuItem; 41 | import android.view.View; 42 | import android.view.Window; 43 | import android.view.WindowManager; 44 | 45 | import java.util.ArrayList; 46 | 47 | import butterknife.ButterKnife; 48 | import butterknife.InjectView; 49 | import io.karim.MaterialTabs; 50 | import io.karim.Utils; 51 | 52 | public class TabsActivity extends AppCompatActivity { 53 | 54 | private static final String TAG = TabsActivity.class.getSimpleName(); 55 | 56 | @InjectView(R.id.toolbar) 57 | Toolbar mToolbar; 58 | 59 | @InjectView(R.id.material_tabs) 60 | MaterialTabs mMaterialTabs; 61 | 62 | @InjectView(R.id.view_pager) 63 | ViewPager mViewPager; 64 | 65 | private String mExportableString; 66 | 67 | @Override 68 | protected void onCreate(Bundle savedInstanceState) { 69 | super.onCreate(savedInstanceState); 70 | setContentView(R.layout.activity_tabs); 71 | ButterKnife.inject(this); 72 | setSupportActionBar(mToolbar); 73 | 74 | // Setting navigation icon 75 | mToolbar.setNavigationIcon(getDrawable(this, R.drawable.ic_navigation_arrow_back_white)); 76 | 77 | // Setting this navigation icon's onClickListener 78 | mToolbar.setNavigationOnClickListener(new View.OnClickListener() { 79 | @Override 80 | public void onClick(View v) { 81 | onBackPressed(); 82 | } 83 | }); 84 | 85 | // Apply background tinting to the Android system UI when using KitKat translucent modes. 86 | SystemBarTintManager tintManager = new SystemBarTintManager(this); 87 | tintManager.setStatusBarTintEnabled(true); 88 | 89 | int numberOfTabs = 3; 90 | if (getIntent() != null && getIntent().getExtras() != null) { 91 | numberOfTabs = getIntent().getExtras().getInt(TabsSettingsFragment.NUMBER_OF_TABS); 92 | } 93 | 94 | SamplePagerAdapter adapter = new SamplePagerAdapter(getSupportFragmentManager(), numberOfTabs); 95 | mViewPager.setAdapter(adapter); 96 | 97 | mMaterialTabs.setViewPager(mViewPager); 98 | 99 | mMaterialTabs.setOnTabSelectedListener(new MaterialTabs.OnTabSelectedListener() { 100 | @Override 101 | public void onTabSelected(int position) { 102 | Log.i(TAG, "onTabSelected called with position " + position); 103 | } 104 | }); 105 | 106 | mMaterialTabs.setOnTabReselectedListener(new MaterialTabs.OnTabReselectedListener() { 107 | @Override 108 | public void onTabReselected(int position) { 109 | Log.i(TAG, "onTabReselected called with position " + position); 110 | } 111 | }); 112 | 113 | applyParametersFromIntentExtras(); 114 | 115 | final int pageMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, getResources().getDisplayMetrics()); 116 | mViewPager.setPageMargin(pageMargin); 117 | } 118 | 119 | @Override 120 | public boolean onCreateOptionsMenu(Menu menu) { 121 | // Inflate the menu; this adds items to the action bar if it is present. 122 | getMenuInflater().inflate(R.menu.menu_tabs, menu); 123 | return true; 124 | } 125 | 126 | @Override 127 | public boolean onOptionsItemSelected(MenuItem item) { 128 | // Handle action bar item clicks here. The action bar will automatically handle clicks on the Home/Up button, so long 129 | // as you specify a parent activity in AndroidManifest.xml. 130 | switch (item.getItemId()) { 131 | case R.id.action_share: 132 | Intent sendIntent = new Intent(); 133 | sendIntent.setAction(Intent.ACTION_SEND); 134 | sendIntent.putExtra(Intent.EXTRA_TEXT, mExportableString); 135 | sendIntent.setType("text/plain"); 136 | startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to))); 137 | return true; 138 | } 139 | 140 | return super.onOptionsItemSelected(item); 141 | } 142 | 143 | private void applyParametersFromIntentExtras() { 144 | Intent intent = getIntent(); 145 | if (intent != null) { 146 | Bundle extras = intent.getExtras(); 147 | if (extras != null) { 148 | Resources resources = getResources(); 149 | 150 | int showToolbar = extras.getBoolean(TabsSettingsFragment.SHOW_TOOLBAR) ? View.VISIBLE : View.GONE; 151 | int indicatorColor = resources.getColor(extras.getInt(TabsSettingsFragment.INDICATOR_COLOR)); 152 | int underlineColor = resources.getColor(extras.getInt(TabsSettingsFragment.UNDERLINE_COLOR)); 153 | int indicatorHeightDp = extras.getInt(TabsSettingsFragment.INDICATOR_HEIGHT); 154 | int underlineHeightDp = extras.getInt(TabsSettingsFragment.UNDERLINE_HEIGHT); 155 | int tabPaddingDp = extras.getInt(TabsSettingsFragment.TAB_PADDING); 156 | 157 | mToolbar.setVisibility(showToolbar); 158 | 159 | mMaterialTabs.setIndicatorColor(indicatorColor); 160 | mMaterialTabs.setUnderlineColor(underlineColor); 161 | mMaterialTabs.setIndicatorHeight(Utils.dpToPx(resources, indicatorHeightDp)); 162 | mMaterialTabs.setUnderlineHeight(Utils.dpToPx(resources, underlineHeightDp)); 163 | mMaterialTabs.setTabPaddingLeftRight(Utils.dpToPx(resources, tabPaddingDp)); 164 | 165 | boolean paddingMiddle = extras.getBoolean(TabsSettingsFragment.PADDING_MIDDLE); 166 | boolean sameWeightTabs = extras.getBoolean(TabsSettingsFragment.SAME_WEIGHT_TABS); 167 | boolean textAllCaps = extras.getBoolean(TabsSettingsFragment.TEXT_ALL_CAPS); 168 | 169 | mMaterialTabs.setPaddingMiddle(paddingMiddle); 170 | mMaterialTabs.setSameWeightTabs(sameWeightTabs); 171 | mMaterialTabs.setAllCaps(textAllCaps); 172 | 173 | int toolbarColor = resources.getColor(extras.getInt(TabsSettingsFragment.TOOLBAR_BACKGROUND)); 174 | int tabBackgroundColor = resources.getColor(extras.getInt(TabsSettingsFragment.TAB_BACKGROUND)); 175 | mToolbar.setBackgroundColor(toolbarColor); 176 | mMaterialTabs.setBackgroundColor(tabBackgroundColor); 177 | 178 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 179 | Window window = getWindow(); 180 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 181 | window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 182 | window.setStatusBarColor(Color.argb(Color.alpha(toolbarColor), Color.red(toolbarColor) / 2, Color.green(toolbarColor) / 2, 183 | Color.blue(toolbarColor) / 2)); 184 | } 185 | 186 | int textColorSelected = resources.getColor(extras.getInt(TabsSettingsFragment.TEXT_COLOR_SELECTED)); 187 | int textColorUnselected = resources.getColor(extras.getInt(TabsSettingsFragment.TEXT_COLOR_UNSELECTED)); 188 | 189 | mMaterialTabs.setTextColorSelected(textColorSelected); 190 | mMaterialTabs.setTextColorUnselected(textColorUnselected); 191 | 192 | int rippleDuration = extras.getInt(RippleSettingsFragment.RIPPLE_DURATION); 193 | float rippleAlphaFloat = extras.getFloat(RippleSettingsFragment.RIPPLE_ALPHA_FLOAT); 194 | int rippleColor = resources.getColor(extras.getInt(RippleSettingsFragment.RIPPLE_COLOR)); 195 | boolean rippleDelayClick = extras.getBoolean(RippleSettingsFragment.RIPPLE_DELAY_CLICK); 196 | float rippleDiameterDp = extras.getFloat(RippleSettingsFragment.RIPPLE_DIAMETER); 197 | int rippleFadeDuration = extras.getInt(RippleSettingsFragment.RIPPLE_FADE_DURATION); 198 | int rippleHighlightColor = resources.getColor(extras.getInt(RippleSettingsFragment.RIPPLE_HIGHLIGHT_COLOR)); 199 | boolean rippleOverlay = extras.getBoolean(RippleSettingsFragment.RIPPLE_OVERLAY); 200 | boolean ripplePersistent = extras.getBoolean(RippleSettingsFragment.RIPPLE_PERSISTENT); 201 | int rippleRoundedCornusRadiusDp = extras.getInt(RippleSettingsFragment.RIPPLE_ROUNDED_CORNERS_RADIUS); 202 | 203 | mMaterialTabs.setRippleDuration(rippleDuration); 204 | mMaterialTabs.setRippleAlphaFloat(rippleAlphaFloat); 205 | mMaterialTabs.setRippleColor(rippleColor); 206 | mMaterialTabs.setRippleDelayClick(rippleDelayClick); 207 | mMaterialTabs.setRippleDiameterDp(rippleDiameterDp); 208 | mMaterialTabs.setRippleFadeDuration(rippleFadeDuration); 209 | mMaterialTabs.setRippleHighlightColor(rippleHighlightColor); 210 | mMaterialTabs.setRippleInAdapter(false); 211 | mMaterialTabs.setRippleOverlay(rippleOverlay); 212 | mMaterialTabs.setRipplePersistent(ripplePersistent); 213 | mMaterialTabs.setRippleRoundedCornersDp(rippleRoundedCornusRadiusDp); 214 | 215 | mExportableString = createExportableText(showToolbar, indicatorColor, underlineColor, indicatorHeightDp, underlineHeightDp, 216 | tabPaddingDp, paddingMiddle, sameWeightTabs, textAllCaps, toolbarColor, tabBackgroundColor, textColorSelected, 217 | textColorUnselected, rippleDuration, rippleAlphaFloat, rippleColor, rippleDelayClick, 218 | rippleDiameterDp, rippleFadeDuration, rippleHighlightColor, rippleOverlay, ripplePersistent, rippleRoundedCornusRadiusDp); 219 | } 220 | } 221 | } 222 | 223 | private static String createExportableText(int showToolbar, int indicatorColor, int underlineColor, int indicatorHeightDp, int underlineHeightDp, 224 | int tabPaddingDp, boolean paddingMiddle, boolean sameWeightTabs, boolean textAllCaps, int toolbarColor, int tabBackgroundColor, 225 | int textColorSelected, int textColorUnselected, int rippleDuration, float rippleAlphaFloat, 226 | int rippleColor, boolean rippleDelayClick, float rippleDiameterDp, int rippleFadeDuration, int rippleHighlightColor, 227 | boolean rippleOverlay, boolean ripplePersistent, int rippleRoundedCornusRadiusDp) { 228 | 229 | StringBuilder stringBuilder = new StringBuilder(); 230 | stringBuilder.append(""); 304 | return stringBuilder.toString(); 305 | } 306 | 307 | private static String getStyleFromStyleInt(int styleInt) { 308 | switch (styleInt) { 309 | case Typeface.BOLD: 310 | default: 311 | return "bold"; 312 | case Typeface.ITALIC: 313 | return "italic"; 314 | case Typeface.NORMAL: 315 | return "normal"; 316 | } 317 | } 318 | 319 | /** 320 | * Convenience to use the new getDrawable(...) on Lollipop and the deprecated one on preLollipop. 321 | */ 322 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 323 | private static Drawable getDrawable(Context context, @DrawableRes int drawableResId) { 324 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 325 | return context.getDrawable(drawableResId); 326 | } else { 327 | return context.getResources().getDrawable(drawableResId); 328 | } 329 | } 330 | 331 | public class SamplePagerAdapter extends FragmentPagerAdapter { 332 | 333 | private final String[] TITLES = {"Item One", "Item Two", "Item Three", "Item Four", "Item Five", "Item Six", "Item Seven", "Item Eight", 334 | "Item Nine", "Item Ten", "Item Eleven"}; 335 | 336 | private final ArrayList mTitles; 337 | 338 | public SamplePagerAdapter(FragmentManager fm, int numberOfTabs) { 339 | super(fm); 340 | mTitles = new ArrayList<>(); 341 | for (int i = 0; i < numberOfTabs; i++) { 342 | mTitles.add(TITLES[i]); 343 | } 344 | } 345 | 346 | @Override 347 | public CharSequence getPageTitle(int position) { 348 | return mTitles.get(position); 349 | } 350 | 351 | @Override 352 | public int getCount() { 353 | return mTitles.size(); 354 | } 355 | 356 | @Override 357 | public Fragment getItem(int position) { 358 | return SampleFragment.newInstance(position); 359 | } 360 | } 361 | } 362 | -------------------------------------------------------------------------------- /sample/src/io/karim/materialtabs/sample/TabsSettingsFragment.java: -------------------------------------------------------------------------------- 1 | package io.karim.materialtabs.sample; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v7.app.AlertDialog; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.CheckBox; 11 | import android.widget.CompoundButton; 12 | import android.widget.RadioGroup; 13 | import android.widget.SeekBar; 14 | import android.widget.TextView; 15 | 16 | import butterknife.ButterKnife; 17 | import butterknife.InjectView; 18 | import butterknife.OnClick; 19 | import io.karim.materialtabs.sample.ui.RadioButtonCenter; 20 | 21 | public class TabsSettingsFragment extends Fragment implements ResettableFragment { 22 | 23 | public static final String INDICATOR_COLOR = "INDICATOR_COLOR"; 24 | public static final String UNDERLINE_COLOR = "UNDERLINE_COLOR"; 25 | public static final String INDICATOR_HEIGHT = "INDICATOR_HEIGHT"; 26 | public static final String UNDERLINE_HEIGHT = "UNDERLINE_HEIGHT"; 27 | public static final String TAB_PADDING = "TAB_PADDING"; 28 | public static final String PADDING_MIDDLE = "PADDING_MIDDLE"; 29 | public static final String SAME_WEIGHT_TABS = "SAME_WEIGHT_TABS"; 30 | public static final String TEXT_ALL_CAPS = "TEXT_ALL_CAPS"; 31 | public static final String TAB_BACKGROUND = "TAB_BACKGROUND"; 32 | public static final String TOOLBAR_BACKGROUND = "TOOLBAR_BACKGROUND"; 33 | public static final String TEXT_COLOR_UNSELECTED = "TEXT_COLOR_UNSELECTED"; 34 | public static final String TEXT_COLOR_SELECTED = "TEXT_COLOR_SELECTED"; 35 | public static final String SHOW_TOOLBAR = "SHOW_TOOLBAR"; 36 | public static final String NUMBER_OF_TABS = "NUMBER_OF_TABS"; 37 | 38 | private static final int UNDERLINE_HEIGHT_DEFAULT_DP = 0; 39 | private static final int INDICATOR_HEIGHT_DEFAULT_DP = 2; 40 | private static final int TAB_PADDING_DEFAULT_DP = 12; 41 | private static final int NUMBER_OF_TABS_DEFAULT = 3; 42 | 43 | private MainActivity mainActivity; 44 | 45 | // Indicator Height 46 | @InjectView(R.id.numberOfTabsSeekBar) 47 | SeekBar numberOfTabsSeekBar; 48 | @InjectView(R.id.numberOfTabsTextView) 49 | TextView numberOfTabsTextView; 50 | 51 | // Indicator Color 52 | @InjectView(R.id.indicatorColorRadioGroup) 53 | RadioGroup indicatorColorRadioGroup; 54 | @InjectView(R.id.indicatorColorButtonWhite) 55 | RadioButtonCenter indicatorColorButtonWhite; 56 | 57 | // Underline Color 58 | @InjectView(R.id.underlineColorRadioGroup) 59 | RadioGroup underlineColorRadioGroup; 60 | @InjectView(R.id.underlineColorButtonMantis) 61 | RadioButtonCenter underlineColorButtonMantis; 62 | 63 | // Indicator Height 64 | @InjectView(R.id.indicatorHeightSeekBar) 65 | SeekBar indicatorHeightSeekBar; 66 | @InjectView(R.id.indicatorHeightTextView) 67 | TextView indicatorHeightTextView; 68 | 69 | // Underline Height 70 | @InjectView(R.id.underlineHeightSeekBar) 71 | SeekBar underlineHeightSeekBar; 72 | @InjectView(R.id.underlineHeightTextView) 73 | TextView underlineHeightTextView; 74 | 75 | // Tab Padding Left Right 76 | @InjectView(R.id.tabPaddingSeekBar) 77 | SeekBar tabPaddingSeekBar; 78 | @InjectView(R.id.tabPaddingTextView) 79 | TextView tabPaddingTextView; 80 | 81 | // Padding Middle 82 | @InjectView(R.id.paddingMiddleCheckBox) 83 | CheckBox paddingMiddleCheckBox; 84 | 85 | // Should Expand 86 | @InjectView(R.id.sameWeightTabsCheckBox) 87 | CheckBox sameWeightTabsCheckBox; 88 | 89 | // Text All Caps 90 | @InjectView(R.id.textAllCapsCheckBox) 91 | CheckBox textAllCapsCheckBox; 92 | 93 | // Show Toolbar 94 | @InjectView(R.id.showToolbarCheckBox) 95 | CheckBox showToolbarCheckBox; 96 | 97 | // Tab Text Color 98 | @InjectView(R.id.tabTextColorRadioGroup) 99 | RadioGroup tabTextColorRadioGroup; 100 | @InjectView(R.id.tabTextColorButtonWhite) 101 | RadioButtonCenter tabTextColorButtonWhite; 102 | 103 | // Tab Text Selected Color 104 | @InjectView(R.id.tabTextSelectedColorRadioGroup) 105 | RadioGroup tabTextSelectedColorRadioGroup; 106 | @InjectView(R.id.tabTextSelectedColorButtonWhite) 107 | RadioButtonCenter tabTextSelectedColorButtonWhite; 108 | 109 | // Tab Background Color 110 | @InjectView(R.id.tabBackgroundColorRadioGroup) 111 | RadioGroup tabBackgroundColorRadioGroup; 112 | @InjectView(R.id.tabBackgroundColorButtonFireEngineRed) 113 | RadioButtonCenter tabBackgroundColorButtonFireEngineRed; 114 | 115 | // Toolbar Background Color 116 | @InjectView(R.id.toolbarColorRadioGroup) 117 | RadioGroup toolbarColorRadioGroup; 118 | @InjectView(R.id.toolbarColorButtonFireEngineRed) 119 | RadioButtonCenter toolbarColorButtonFireEngineRed; 120 | 121 | int underlineHeightDp; 122 | int indicatorHeightDp; 123 | int tabPaddingDp; 124 | int numberOfTabs; 125 | 126 | @Override 127 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 128 | View rootView = inflater.inflate(R.layout.fragment_tabs_settings, container, false); 129 | ButterKnife.inject(this, rootView); 130 | 131 | setupAndReset(); 132 | return rootView; 133 | } 134 | 135 | @Override 136 | public void onAttach(Activity activity) { 137 | super.onAttach(activity); 138 | mainActivity = (MainActivity) getActivity(); 139 | mainActivity.addFragment(this); 140 | } 141 | 142 | @Override 143 | public void onDetach() { 144 | mainActivity.removeFragment(this); 145 | super.onDetach(); 146 | } 147 | 148 | @Override 149 | public void setupAndReset() { 150 | /** SeekBars **/ 151 | 152 | underlineHeightDp = UNDERLINE_HEIGHT_DEFAULT_DP; 153 | underlineHeightTextView.setText(getString(R.string.underline_height) + ": " + underlineHeightDp + "dp"); 154 | underlineHeightSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 155 | @Override 156 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 157 | underlineHeightDp = progress; 158 | underlineHeightTextView.setText(getString(R.string.underline_height) + ": " + underlineHeightDp + "dp"); 159 | mainActivity.startTabsActivityIntent.putExtra(UNDERLINE_HEIGHT, underlineHeightDp); 160 | } 161 | 162 | @Override 163 | public void onStartTrackingTouch(SeekBar seekBar) { 164 | } 165 | 166 | @Override 167 | public void onStopTrackingTouch(SeekBar seekBar) { 168 | } 169 | }); 170 | 171 | numberOfTabs = NUMBER_OF_TABS_DEFAULT; 172 | numberOfTabsTextView.setText(getString(R.string.number_of_tabs) + ": " + numberOfTabs); 173 | numberOfTabsSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 174 | @Override 175 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 176 | numberOfTabs = progress + 1; 177 | numberOfTabsTextView.setText(getString(R.string.number_of_tabs) + ": " + numberOfTabs); 178 | mainActivity.startTabsActivityIntent.putExtra(NUMBER_OF_TABS, numberOfTabs); 179 | } 180 | 181 | @Override 182 | public void onStartTrackingTouch(SeekBar seekBar) { 183 | } 184 | 185 | @Override 186 | public void onStopTrackingTouch(SeekBar seekBar) { 187 | } 188 | }); 189 | 190 | indicatorHeightDp = INDICATOR_HEIGHT_DEFAULT_DP; 191 | indicatorHeightTextView.setText(getString(R.string.indicator_height) + ": " + indicatorHeightDp + "dp"); 192 | indicatorHeightSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 193 | @Override 194 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 195 | indicatorHeightDp = progress; 196 | indicatorHeightTextView.setText(getString(R.string.indicator_height) + ": " + indicatorHeightDp + "dp"); 197 | mainActivity.startTabsActivityIntent.putExtra(INDICATOR_HEIGHT, indicatorHeightDp); 198 | } 199 | 200 | @Override 201 | public void onStartTrackingTouch(SeekBar seekBar) { 202 | } 203 | 204 | @Override 205 | public void onStopTrackingTouch(SeekBar seekBar) { 206 | } 207 | }); 208 | 209 | tabPaddingDp = TAB_PADDING_DEFAULT_DP; 210 | tabPaddingTextView.setText(getString(R.string.tab_padding) + ": " + tabPaddingDp + "dp"); 211 | tabPaddingSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 212 | @Override 213 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 214 | tabPaddingDp = progress; 215 | tabPaddingTextView.setText(getString(R.string.tab_padding) + ": " + tabPaddingDp + "dp"); 216 | mainActivity.startTabsActivityIntent.putExtra(TAB_PADDING, tabPaddingDp); 217 | } 218 | 219 | @Override 220 | public void onStartTrackingTouch(SeekBar seekBar) { 221 | } 222 | 223 | @Override 224 | public void onStopTrackingTouch(SeekBar seekBar) { 225 | } 226 | }); 227 | 228 | underlineHeightSeekBar.setProgress(underlineHeightDp); 229 | numberOfTabsSeekBar.setProgress(numberOfTabs); 230 | indicatorHeightSeekBar.setProgress(indicatorHeightDp); 231 | tabPaddingSeekBar.setProgress(tabPaddingDp); 232 | 233 | /** RadioGroups **/ 234 | 235 | // Indicator Color 236 | indicatorColorRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { 237 | @Override 238 | public void onCheckedChanged(RadioGroup group, int checkedId) { 239 | String key = INDICATOR_COLOR; 240 | switch (checkedId) { 241 | case R.id.indicatorColorButtonFireEngineRed: 242 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.fire_engine_red); 243 | break; 244 | case R.id.indicatorColorButtonGorse: 245 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.gorse); 246 | break; 247 | case R.id.indicatorColorButtonIrisBlue: 248 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.iris_blue); 249 | break; 250 | case R.id.indicatorColorButtonSafetyOrange: 251 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.safety_orange); 252 | break; 253 | case R.id.indicatorColorButtonWhite: 254 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.white); 255 | break; 256 | case R.id.indicatorColorButtonBlack: 257 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.black); 258 | break; 259 | case R.id.indicatorColorButtonMantis: 260 | default: 261 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.mantis); 262 | break; 263 | } 264 | } 265 | }); 266 | 267 | // Underline Color 268 | underlineColorRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { 269 | @Override 270 | public void onCheckedChanged(RadioGroup group, int checkedId) { 271 | String key = UNDERLINE_COLOR; 272 | switch (checkedId) { 273 | case R.id.underlineColorButtonFireEngineRed: 274 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.fire_engine_red); 275 | break; 276 | case R.id.underlineColorButtonGorse: 277 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.gorse); 278 | break; 279 | case R.id.underlineColorButtonIrisBlue: 280 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.iris_blue); 281 | break; 282 | case R.id.underlineColorButtonSafetyOrange: 283 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.safety_orange); 284 | break; 285 | case R.id.underlineColorButtonWhite: 286 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.white); 287 | break; 288 | case R.id.underlineColorButtonBlack: 289 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.black); 290 | break; 291 | case R.id.underlineColorButtonMantis: 292 | default: 293 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.mantis); 294 | break; 295 | } 296 | } 297 | }); 298 | 299 | // Tab Background Color 300 | tabBackgroundColorRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { 301 | @Override 302 | public void onCheckedChanged(RadioGroup group, int checkedId) { 303 | String key = TAB_BACKGROUND; 304 | switch (checkedId) { 305 | case R.id.tabBackgroundColorButtonFireEngineRed: 306 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.fire_engine_red); 307 | break; 308 | case R.id.tabBackgroundColorButtonGorse: 309 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.gorse); 310 | break; 311 | case R.id.tabBackgroundColorButtonIrisBlue: 312 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.iris_blue); 313 | break; 314 | case R.id.tabBackgroundColorButtonSafetyOrange: 315 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.safety_orange); 316 | break; 317 | case R.id.tabBackgroundColorButtonWhite: 318 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.white); 319 | break; 320 | case R.id.tabBackgroundColorButtonBlack: 321 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.black); 322 | break; 323 | case R.id.tabBackgroundColorButtonMantis: 324 | default: 325 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.mantis); 326 | break; 327 | } 328 | } 329 | }); 330 | 331 | // Toolbar Background Color 332 | toolbarColorRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { 333 | @Override 334 | public void onCheckedChanged(RadioGroup group, int checkedId) { 335 | String key = TOOLBAR_BACKGROUND; 336 | switch (checkedId) { 337 | case R.id.toolbarColorButtonFireEngineRed: 338 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.fire_engine_red); 339 | break; 340 | case R.id.toolbarColorButtonGorse: 341 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.gorse); 342 | break; 343 | case R.id.toolbarColorButtonIrisBlue: 344 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.iris_blue); 345 | break; 346 | case R.id.toolbarColorButtonSafetyOrange: 347 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.safety_orange); 348 | break; 349 | case R.id.toolbarColorButtonWhite: 350 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.white); 351 | break; 352 | case R.id.toolbarColorButtonBlack: 353 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.black); 354 | break; 355 | case R.id.toolbarColorButtonMantis: 356 | default: 357 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.mantis); 358 | break; 359 | } 360 | } 361 | }); 362 | 363 | // Text Color Unselected 364 | tabTextColorRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { 365 | @Override 366 | public void onCheckedChanged(RadioGroup group, int checkedId) { 367 | String key = TEXT_COLOR_UNSELECTED; 368 | switch (checkedId) { 369 | case R.id.tabTextColorButtonFireEngineRed: 370 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.fire_engine_red); 371 | break; 372 | case R.id.tabTextColorButtonGorse: 373 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.gorse); 374 | break; 375 | case R.id.tabTextColorButtonIrisBlue: 376 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.iris_blue); 377 | break; 378 | case R.id.tabTextColorButtonSafetyOrange: 379 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.safety_orange); 380 | break; 381 | case R.id.tabTextColorButtonWhite: 382 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.white); 383 | break; 384 | case R.id.tabTextColorButtonBlack: 385 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.black); 386 | break; 387 | case R.id.tabTextColorButtonMantis: 388 | default: 389 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.mantis); 390 | break; 391 | } 392 | } 393 | }); 394 | 395 | // Text Color Selected 396 | tabTextSelectedColorRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { 397 | @Override 398 | public void onCheckedChanged(RadioGroup group, int checkedId) { 399 | String key = TEXT_COLOR_SELECTED; 400 | switch (checkedId) { 401 | case R.id.tabTextSelectedColorButtonFireEngineRed: 402 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.fire_engine_red); 403 | break; 404 | case R.id.tabTextSelectedColorButtonGorse: 405 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.gorse); 406 | break; 407 | case R.id.tabTextSelectedColorButtonIrisBlue: 408 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.iris_blue); 409 | break; 410 | case R.id.tabTextSelectedColorButtonSafetyOrange: 411 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.safety_orange); 412 | break; 413 | case R.id.tabTextSelectedColorButtonWhite: 414 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.white); 415 | break; 416 | case R.id.tabTextSelectedColorButtonBlack: 417 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.black); 418 | break; 419 | case R.id.tabTextSelectedColorButtonMantis: 420 | default: 421 | mainActivity.startTabsActivityIntent.putExtra(key, R.color.mantis); 422 | break; 423 | } 424 | } 425 | }); 426 | 427 | indicatorColorButtonWhite.setChecked(true); 428 | underlineColorButtonMantis.setChecked(true); 429 | 430 | tabTextColorButtonWhite.setChecked(true); 431 | tabTextSelectedColorButtonWhite.setChecked(true); 432 | 433 | tabBackgroundColorButtonFireEngineRed.setChecked(true); 434 | toolbarColorButtonFireEngineRed.setChecked(true); 435 | 436 | /** CheckBoxes **/ 437 | 438 | // Text Style Unselected 439 | sameWeightTabsCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 440 | @Override 441 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 442 | mainActivity.startTabsActivityIntent.putExtra(SAME_WEIGHT_TABS, isChecked); 443 | } 444 | }); 445 | 446 | // Text Style Unselected 447 | paddingMiddleCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 448 | @Override 449 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 450 | mainActivity.startTabsActivityIntent.putExtra(PADDING_MIDDLE, isChecked); 451 | } 452 | }); 453 | 454 | // Text Style Unselected 455 | textAllCapsCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 456 | @Override 457 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 458 | mainActivity.startTabsActivityIntent.putExtra(TEXT_ALL_CAPS, isChecked); 459 | } 460 | }); 461 | 462 | // Text Style Unselected 463 | showToolbarCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 464 | @Override 465 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 466 | mainActivity.startTabsActivityIntent.putExtra(SHOW_TOOLBAR, isChecked); 467 | } 468 | }); 469 | 470 | sameWeightTabsCheckBox.setChecked(true); 471 | paddingMiddleCheckBox.setChecked(false); 472 | textAllCapsCheckBox.setChecked(true); 473 | showToolbarCheckBox.setChecked(true); 474 | } 475 | 476 | @OnClick(R.id.tabPaddingInfoButton) 477 | public void tabPaddingInfoButtonClicked() { 478 | new AlertDialog.Builder(getActivity()).setTitle(R.string.tab_padding).setMessage(R.string.tab_padding_details).create().show(); 479 | } 480 | 481 | @OnClick(R.id.tabBackgroundColorInfoButton) 482 | public void tabBackgroundColorInfoButtonClicked() { 483 | new AlertDialog.Builder(getActivity()).setTitle(R.string.tab_background_color) 484 | .setMessage(R.string.tab_background_color_details) 485 | .create() 486 | .show(); 487 | } 488 | 489 | @OnClick(R.id.tabTextColorInfoButton) 490 | public void tabTextColorInfoButtonClicked() { 491 | new AlertDialog.Builder(getActivity()).setTitle(R.string.tab_text_color).setMessage(R.string.tab_text_color_details).create().show(); 492 | } 493 | 494 | @OnClick(R.id.tabTextSelectedColorInfoButton) 495 | public void tabTextSelectedColorInfoButtonClicked() { 496 | new AlertDialog.Builder(getActivity()).setTitle(R.string.tab_text_selected_color) 497 | .setMessage(R.string.tab_text_selected_color_details) 498 | .create() 499 | .show(); 500 | } 501 | 502 | @OnClick(R.id.toolbarColorInfoButton) 503 | public void toolbarColorInfoButtonClicked() { 504 | new AlertDialog.Builder(getActivity()).setTitle(R.string.toolbar_color).setMessage(R.string.toolbar_color_details).create().show(); 505 | } 506 | 507 | @OnClick(R.id.textAllCapsInfoButton) 508 | public void textAllCapsInfoButtonClicked() { 509 | new AlertDialog.Builder(getActivity()).setTitle(R.string.text_all_caps).setMessage(R.string.text_all_caps_details).create().show(); 510 | } 511 | 512 | @OnClick(R.id.underlineColorInfoButton) 513 | public void underlineColorInfoButtonClicked() { 514 | new AlertDialog.Builder(getActivity()).setTitle(R.string.underline_color).setMessage(R.string.underline_color_details).create().show(); 515 | } 516 | 517 | @OnClick(R.id.underlineHeightInfoButton) 518 | public void underlineHeightInfoButtonClicked() { 519 | new AlertDialog.Builder(getActivity()).setTitle(R.string.underline_height).setMessage(R.string.underline_height_details).create().show(); 520 | } 521 | 522 | @OnClick(R.id.indicatorColorInfoButton) 523 | public void indicatorColorInfoButtonClicked() { 524 | new AlertDialog.Builder(getActivity()).setTitle(R.string.indicator_color).setMessage(R.string.indicator_color_details).create().show(); 525 | } 526 | 527 | @OnClick(R.id.indicatorHeightInfoButton) 528 | public void indicatorHeightInfoButtonClicked() { 529 | new AlertDialog.Builder(getActivity()).setTitle(R.string.indicator_height).setMessage(R.string.indicator_height_details).create().show(); 530 | } 531 | 532 | 533 | @OnClick(R.id.paddingMiddleInfoButton) 534 | public void paddingMiddleInfoButtonClicked() { 535 | new AlertDialog.Builder(getActivity()).setTitle(R.string.padding_middle).setMessage(R.string.padding_middle_details).create().show(); 536 | } 537 | 538 | @OnClick(R.id.sameWeighTabsInfoButton) 539 | public void sameWeighTabsInfoButtonClicked() { 540 | new AlertDialog.Builder(getActivity()).setTitle(R.string.same_weight_tabs).setMessage(R.string.same_weight_tabs_details).create().show(); 541 | } 542 | 543 | @OnClick(R.id.showToolbarInfoButton) 544 | public void showToolbarInfoButtonClicked() { 545 | new AlertDialog.Builder(getActivity()).setTitle(R.string.show_toolbar).setMessage(R.string.show_toolbar_details).create().show(); 546 | } 547 | 548 | @OnClick(R.id.numberOfTabsInfoButton) 549 | public void numberOfTabsInfoButtonClicked() { 550 | new AlertDialog.Builder(getActivity()).setTitle(R.string.number_of_tabs).setMessage(R.string.number_of_tabs_details).create().show(); 551 | } 552 | } 553 | -------------------------------------------------------------------------------- /sample/src/io/karim/materialtabs/sample/ui/RadioButtonCenter.java: -------------------------------------------------------------------------------- 1 | package io.karim.materialtabs.sample.ui; 2 | 3 | 4 | import android.content.Context; 5 | import android.content.res.TypedArray; 6 | import android.graphics.Canvas; 7 | import android.graphics.drawable.Drawable; 8 | import android.support.annotation.NonNull; 9 | import android.util.AttributeSet; 10 | import android.view.Gravity; 11 | import android.widget.RadioButton; 12 | 13 | import io.karim.materialtabs.sample.R; 14 | 15 | public class RadioButtonCenter extends RadioButton { 16 | 17 | final Drawable buttonDrawable; 18 | 19 | public RadioButtonCenter(Context context, AttributeSet attrs) { 20 | super(context, attrs); 21 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CompoundButton, 0, 0); 22 | buttonDrawable = a.getDrawable(1); 23 | a.recycle(); 24 | setButtonDrawable(android.R.color.transparent); 25 | } 26 | 27 | @Override 28 | protected void onDraw(@NonNull Canvas canvas) { 29 | super.onDraw(canvas); 30 | 31 | if (buttonDrawable != null) { 32 | buttonDrawable.setState(getDrawableState()); 33 | final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; 34 | final int height = buttonDrawable.getIntrinsicHeight(); 35 | 36 | int y = 0; 37 | 38 | switch (verticalGravity) { 39 | case Gravity.BOTTOM: 40 | y = getHeight() - height; 41 | break; 42 | case Gravity.CENTER_VERTICAL: 43 | y = (getHeight() - height) / 2; 44 | break; 45 | } 46 | 47 | int buttonWidth = buttonDrawable.getIntrinsicWidth(); 48 | int buttonLeft = (getWidth() - buttonWidth) / 2; 49 | buttonDrawable.setBounds(buttonLeft, y, buttonLeft + buttonWidth, y + height); 50 | buttonDrawable.draw(canvas); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /sample/web_hi_res_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pizza/MaterialTabs/24c9bf922f29f0fbb201fb6b8f13d915fd87d322/sample/web_hi_res_512.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include 'library' 2 | include 'sample' --------------------------------------------------------------------------------