├── app ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── drawable-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_action_navigation_accept.png │ │ ├── drawable-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_action_navigation_accept.png │ │ ├── drawable-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_action_navigation_accept.png │ │ ├── drawable-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_action_navigation_accept.png │ │ ├── values │ │ │ ├── styles.xml │ │ │ ├── dimens.xml │ │ │ └── strings.xml │ │ ├── layout │ │ │ ├── activity_main.xml │ │ │ └── fragment_main.xml │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ └── menu │ │ │ └── main.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── jesusm │ │ └── floatinglabelpass │ │ └── app │ │ └── ui │ │ └── activities │ │ └── MainActivity.java ├── proguard-rules.txt └── build.gradle ├── lib ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ ├── attrs.xml │ │ │ │ └── styles.xml │ │ │ ├── drawable-hdpi │ │ │ │ └── ic_action_navigation_accept.png │ │ │ ├── drawable-mdpi │ │ │ │ └── ic_action_navigation_accept.png │ │ │ ├── drawable-xhdpi │ │ │ │ └── ic_action_navigation_accept.png │ │ │ └── drawable-xxhdpi │ │ │ │ └── ic_action_navigation_accept.png │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── jesusm │ │ │ └── floatlabellayout │ │ │ └── lib │ │ │ ├── SimpleLabelLayoutCheck.java │ │ │ ├── MailLabelLayoutCheck.java │ │ │ ├── PasswordFloatLabelLayoutCheck.java │ │ │ ├── CheckStrenghtLabelLayout.java │ │ │ └── FloatLabelLayout.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── example │ │ └── jesus │ │ └── lib │ │ └── ApplicationTest.java ├── build.gradle └── proguard-rules.pro ├── settings.gradle ├── images └── FloatLabelLayoutGif.gif ├── gradle.properties ├── README.md └── .gitignore /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /lib/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':lib' 2 | -------------------------------------------------------------------------------- /lib/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | lib 3 | 4 | -------------------------------------------------------------------------------- /images/FloatLabelLayoutGif.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JesusM/PasswordFloatingLabelLayout/HEAD/images/FloatLabelLayoutGif.gif -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JesusM/PasswordFloatingLabelLayout/HEAD/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JesusM/PasswordFloatingLabelLayout/HEAD/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JesusM/PasswordFloatingLabelLayout/HEAD/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JesusM/PasswordFloatingLabelLayout/HEAD/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_action_navigation_accept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JesusM/PasswordFloatingLabelLayout/HEAD/app/src/main/res/drawable-hdpi/ic_action_navigation_accept.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_action_navigation_accept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JesusM/PasswordFloatingLabelLayout/HEAD/app/src/main/res/drawable-mdpi/ic_action_navigation_accept.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_action_navigation_accept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JesusM/PasswordFloatingLabelLayout/HEAD/app/src/main/res/drawable-xhdpi/ic_action_navigation_accept.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_action_navigation_accept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JesusM/PasswordFloatingLabelLayout/HEAD/app/src/main/res/drawable-xxhdpi/ic_action_navigation_accept.png -------------------------------------------------------------------------------- /lib/src/main/res/drawable-hdpi/ic_action_navigation_accept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JesusM/PasswordFloatingLabelLayout/HEAD/lib/src/main/res/drawable-hdpi/ic_action_navigation_accept.png -------------------------------------------------------------------------------- /lib/src/main/res/drawable-mdpi/ic_action_navigation_accept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JesusM/PasswordFloatingLabelLayout/HEAD/lib/src/main/res/drawable-mdpi/ic_action_navigation_accept.png -------------------------------------------------------------------------------- /lib/src/main/res/drawable-xhdpi/ic_action_navigation_accept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JesusM/PasswordFloatingLabelLayout/HEAD/lib/src/main/res/drawable-xhdpi/ic_action_navigation_accept.png -------------------------------------------------------------------------------- /lib/src/main/res/drawable-xxhdpi/ic_action_navigation_accept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JesusM/PasswordFloatingLabelLayout/HEAD/lib/src/main/res/drawable-xxhdpi/ic_action_navigation_accept.png -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /lib/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /lib/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ff007ef0 4 | #ffac0005 5 | #fff0b31a 6 | #ff1ca71c 7 | #5d000000 8 | -------------------------------------------------------------------------------- /lib/src/androidTest/java/com/example/jesus/lib/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.example.jesus.lib; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Strong Label Layout 5 | Hello world! 6 | Settings 7 | Username 8 | Pass 9 | Email 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /lib/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lib/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /lib/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion parent.ext.compileSdkVersion 5 | buildToolsVersion parent.ext.buildToolsVersion 6 | 7 | defaultConfig { 8 | minSdkVersion parent.ext.minSdkVersion 9 | targetSdkVersion parent.ext.targetSdkVersion 10 | versionName parent.ext.versionName 11 | } 12 | buildTypes { 13 | release { 14 | minifyEnabled false 15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 16 | } 17 | } 18 | } 19 | 20 | dependencies { 21 | compile 'com.android.support:support-v4:22.+' 22 | compile 'com.nineoldandroids:library:2.4.0' 23 | } 24 | -------------------------------------------------------------------------------- /lib/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/jesus/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/proguard-rules.txt: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Applications/Android Studio.app/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the ProGuard 5 | # include property in project.properties. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion parent.ext.compileSdkVersion 5 | buildToolsVersion parent.ext.buildToolsVersion 6 | 7 | defaultConfig { 8 | minSdkVersion parent.ext.minSdkVersion 9 | targetSdkVersion parent.ext.targetSdkVersion 10 | versionName parent.ext.versionName 11 | versionCode parent.ext.versionCode 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile 'com.android.support:appcompat-v7:22.+' 23 | compile project(':lib') 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Settings specified in this file will override any Gradle settings 5 | # configured through the IDE. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | FloatingLabelLayout with custom behaviours 2 | =========================== 3 | Forked from FloatingLabelLayout https://gist.github.com/chrisbanes/11247418, the lib provides floating text label with extra behaviors based on customizable criteria. 4 | 5 | ![Demo gif](https://github.com/JesusM/PasswordFloatingLabelLayout/blob/master/images/FloatLabelLayoutGif.gif?raw=true) 6 | 7 | 8 | [Video] (http://youtu.be/_oNO-fIk1Ys) 9 | 10 | You need to add this to your xml layout: 11 | 12 | ````XML 13 | 18 | 19 | 20 | 21 | 22 | ```` 23 | 24 | app:showStateIcon (false by default) indicates if you want to show an icon when your password is considered as "strong" (you can change this behavior). 25 | -------------------------------------------------------------------------------- /lib/src/main/java/jesusm/floatlabellayout/lib/SimpleLabelLayoutCheck.java: -------------------------------------------------------------------------------- 1 | package jesusm.floatlabellayout.lib; 2 | 3 | import android.content.Context; 4 | import android.text.InputType; 5 | import android.util.AttributeSet; 6 | 7 | import com.example.jesus.lib.R; 8 | 9 | public class SimpleLabelLayoutCheck extends CheckStrenghtLabelLayout { 10 | 11 | private int color = getResources().getColor(R.color.float_label); 12 | 13 | public SimpleLabelLayoutCheck(Context context) { 14 | this(context, null); 15 | } 16 | 17 | public SimpleLabelLayoutCheck(Context context, AttributeSet attrs) { 18 | this(context, attrs, 0); 19 | } 20 | 21 | public SimpleLabelLayoutCheck(Context context, AttributeSet attrs, int defStyle) { 22 | super(context, attrs, defStyle); 23 | } 24 | 25 | @Override 26 | int getColorFromCriteria(String text) { 27 | return color; 28 | } 29 | 30 | @Override 31 | int checkInputType() { 32 | return InputType.TYPE_CLASS_TEXT; 33 | } 34 | 35 | @Override 36 | protected boolean showLabelIcon(String text) { 37 | return false; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | # Copyright: Benjamin Weiss (keyboardsurfer) https://github.com/keyboardsurfer 3 | # Under CC-BY-SA V3.0 (https://creativecommons.org/licenses/by-sa/3.0/legalcode) 4 | 5 | # built application files 6 | *.apk 7 | *.ap_ 8 | *.jar 9 | 10 | # lint folder 11 | lint 12 | 13 | # files for the dex VM 14 | *.dex 15 | 16 | # Java class files 17 | *.class 18 | 19 | # generated files 20 | bin/ 21 | gen/ 22 | classes/ 23 | gen-external-apklibs/ 24 | 25 | # maven output folder 26 | target 27 | 28 | # Local configuration file (sdk path, etc) 29 | local.properties 30 | 31 | # Eclipse project files 32 | .classpath 33 | .project 34 | .metadata 35 | .settings 36 | 37 | # IntelliJ files 38 | .idea/ 39 | *.iml 40 | 41 | # OSX files 42 | .DS_Store 43 | 44 | # Windows files 45 | Thumbs.db 46 | 47 | # vi swap files 48 | *.swp 49 | 50 | # backup files 51 | *.bak 52 | 53 | # gradle directory 54 | .gradle 55 | gradlew 56 | gradlew.bat 57 | gradle/ 58 | build/ 59 | 60 | #for oh-my-zsh jira plugin (https://github.com/robbyrussell/oh-my-zsh/wiki/Plugins#jira) 61 | .jira-url 62 | atlassian-ide-plugin.xml 63 | .gradle 64 | /local.properties 65 | /.idea/workspace.xml 66 | .DS_Store 67 | -------------------------------------------------------------------------------- /lib/src/main/java/jesusm/floatlabellayout/lib/MailLabelLayoutCheck.java: -------------------------------------------------------------------------------- 1 | package jesusm.floatlabellayout.lib; 2 | 3 | import android.content.Context; 4 | import android.text.InputType; 5 | import android.text.TextUtils; 6 | import android.util.AttributeSet; 7 | 8 | import com.example.jesus.lib.R; 9 | 10 | public class MailLabelLayoutCheck extends CheckStrenghtLabelLayout { 11 | private boolean valid = false; 12 | 13 | 14 | public MailLabelLayoutCheck(Context context) { 15 | this(context, null); 16 | } 17 | 18 | public MailLabelLayoutCheck(Context context, AttributeSet attributeSet) { 19 | this(context, attributeSet, 0); 20 | } 21 | 22 | public MailLabelLayoutCheck(Context context, AttributeSet attrs, int defStyle) { 23 | super(context, attrs, defStyle); 24 | } 25 | 26 | @Override 27 | int getColorFromCriteria(String target) { 28 | valid = isValidEmail(target); 29 | return valid ? getResources().getColor(R.color.float_label_password_good) : 30 | getResources().getColor(R.color.float_label_password_error); 31 | } 32 | 33 | @Override 34 | public int checkInputType() { 35 | return InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS; 36 | } 37 | 38 | public final static boolean isValidEmail(CharSequence target) { 39 | if (TextUtils.isEmpty(target)) { 40 | return false; 41 | } else { 42 | return android.util.Patterns.EMAIL_ADDRESS.matcher(target).matches(); 43 | } 44 | } 45 | 46 | @Override 47 | protected boolean showLabelIcon(String text) { 48 | return valid; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/src/main/java/jesusm/floatlabellayout/lib/PasswordFloatLabelLayoutCheck.java: -------------------------------------------------------------------------------- 1 | package jesusm.floatlabellayout.lib; 2 | 3 | import android.content.Context; 4 | import android.text.InputType; 5 | import android.util.AttributeSet; 6 | 7 | import com.example.jesus.lib.R; 8 | 9 | public class PasswordFloatLabelLayoutCheck extends CheckStrenghtLabelLayout { 10 | 11 | private boolean showLabelIcon = false; 12 | 13 | public PasswordFloatLabelLayoutCheck(Context context) { 14 | this(context, null); 15 | } 16 | 17 | public PasswordFloatLabelLayoutCheck(Context context, AttributeSet attrs) { 18 | this(context, attrs, 0); 19 | } 20 | 21 | public PasswordFloatLabelLayoutCheck(Context context, AttributeSet attrs, int defStyle) { 22 | super(context, attrs, defStyle); 23 | 24 | } 25 | 26 | 27 | @Override 28 | int getColorFromCriteria(String text) { 29 | int passLength = getEditText().getText().toString().length(); 30 | if (passLength < 3) { 31 | showLabelIcon = false; 32 | return getResources().getColor(R.color.float_label_password_error); 33 | } else if (passLength < 6) { 34 | showLabelIcon = false; 35 | return getResources().getColor(R.color.float_label_password_regular); 36 | } else { 37 | showLabelIcon = true; 38 | return getResources().getColor(R.color.float_label_password_good); 39 | } 40 | 41 | 42 | } 43 | 44 | @Override 45 | public int checkInputType() { 46 | return InputType.TYPE_TEXT_VARIATION_PASSWORD; 47 | } 48 | 49 | @Override 50 | protected boolean showLabelIcon(String text) { 51 | return showLabelIcon; 52 | } 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/jesusm/floatinglabelpass/app/ui/activities/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.jesusm.floatinglabelpass.app.ui.activities; 2 | 3 | import android.support.v7.app.ActionBarActivity; 4 | import android.support.v7.app.ActionBar; 5 | import android.support.v4.app.Fragment; 6 | import android.os.Bundle; 7 | import android.view.LayoutInflater; 8 | import android.view.Menu; 9 | import android.view.MenuItem; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.os.Build; 13 | 14 | import com.jesusm.floatinglabelpass.app.R; 15 | 16 | 17 | public class MainActivity extends ActionBarActivity { 18 | 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_main); 23 | if (savedInstanceState == null) { 24 | getSupportFragmentManager().beginTransaction() 25 | .add(R.id.container, new PlaceholderFragment()) 26 | .commit(); 27 | } 28 | } 29 | 30 | 31 | @Override 32 | public boolean onCreateOptionsMenu(Menu menu) { 33 | // Inflate the menu; this adds items to the action bar if it is present. 34 | getMenuInflater().inflate(R.menu.main, menu); 35 | return true; 36 | } 37 | 38 | @Override 39 | public boolean onOptionsItemSelected(MenuItem item) { 40 | // Handle action bar item clicks here. The action bar will 41 | // automatically handle clicks on the Home/Up button, so long 42 | // as you specify a parent activity in AndroidManifest.xml. 43 | int id = item.getItemId(); 44 | if (id == R.id.action_settings) { 45 | return true; 46 | } 47 | return super.onOptionsItemSelected(item); 48 | } 49 | 50 | /** 51 | * A placeholder fragment containing a simple view. 52 | */ 53 | public static class PlaceholderFragment extends Fragment { 54 | 55 | public PlaceholderFragment() { 56 | } 57 | 58 | @Override 59 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 60 | Bundle savedInstanceState) { 61 | View rootView = inflater.inflate(R.layout.fragment_main, container, false); 62 | return rootView; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 14 | 15 | 24 | 25 | 26 | 27 | 32 | 33 | 40 | 41 | 42 | 43 | 48 | 49 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /lib/src/main/java/jesusm/floatlabellayout/lib/CheckStrenghtLabelLayout.java: -------------------------------------------------------------------------------- 1 | package jesusm.floatlabellayout.lib; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.drawable.BitmapDrawable; 6 | import android.graphics.drawable.Drawable; 7 | import android.support.v4.content.res.ResourcesCompat; 8 | import android.text.InputType; 9 | import android.util.AttributeSet; 10 | import android.widget.EditText; 11 | 12 | import com.example.jesus.lib.R; 13 | import com.nineoldandroids.animation.ArgbEvaluator; 14 | import com.nineoldandroids.animation.ValueAnimator; 15 | 16 | public abstract class CheckStrenghtLabelLayout extends FloatLabelLayout { 17 | 18 | private static final long LABEL_COLOR_CHANGE_ANIMATION_TIME = 333L; 19 | 20 | private BitmapDrawable acceptDrawable; 21 | private int lastColor = getResources().getColor(R.color.float_label); 22 | 23 | public CheckStrenghtLabelLayout(Context context) { 24 | this(context, null); 25 | } 26 | 27 | public CheckStrenghtLabelLayout(Context context, AttributeSet attrs) { 28 | this(context, attrs, 0); 29 | } 30 | 31 | public CheckStrenghtLabelLayout(Context context, AttributeSet attrs, int defStyle) { 32 | super(context, attrs, defStyle); 33 | 34 | initAcceptDrawableCompound(); 35 | } 36 | 37 | abstract int getColorFromCriteria(String text); 38 | 39 | 40 | private void checkPassLabelColor() { 41 | int color = getColorFromCriteria(getEditText().getText().toString()); 42 | setmLabelColor(color); 43 | boolean animateLabel = lastColor != color; 44 | if (animateLabel) { 45 | animateLabelColor(); 46 | checkDrawAcceptIcon(); 47 | } else { 48 | getLabel().setTextColor(getmLabelColor()); 49 | } 50 | updateLabelText(); 51 | lastColor = color; 52 | } 53 | 54 | abstract int checkInputType(); 55 | 56 | 57 | private void checkDrawAcceptIcon() { 58 | boolean showCompoundDrawable = showLabelIcon(getEditText().getText().toString()); 59 | getLabel().setCompoundDrawablesWithIntrinsicBounds(null, null, 60 | showCompoundDrawable ? acceptDrawable : null, null); 61 | } 62 | 63 | protected abstract boolean showLabelIcon(String text); 64 | 65 | 66 | private void initAcceptDrawableCompound() { 67 | // Read your drawable from somewhere 68 | Drawable dr = ResourcesCompat.getDrawable(getResources(), R.drawable.ic_action_navigation_accept, null); 69 | Bitmap bitmap = ((BitmapDrawable) dr).getBitmap(); 70 | // Scale it to the label size 71 | int acceptDrawableSize = (int) getLabel().getTextSize(); 72 | acceptDrawable = new BitmapDrawable(getResources(), 73 | Bitmap.createScaledBitmap(bitmap, acceptDrawableSize, 74 | acceptDrawableSize, true) 75 | ); 76 | } 77 | 78 | @Override 79 | protected void setEditText(EditText editText) { 80 | super.setEditText(editText); 81 | int inputType = checkInputType(); 82 | getEditText().setInputType(InputType.TYPE_CLASS_TEXT | inputType); 83 | 84 | } 85 | 86 | 87 | public void updateLabelColor() { 88 | checkPassLabelColor(); 89 | } 90 | 91 | 92 | /** 93 | * Animate label text color 94 | */ 95 | private void animateLabelColor() { 96 | 97 | ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), getLabel().getCurrentTextColor(), getmLabelColor()); 98 | colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 99 | 100 | @Override 101 | public void onAnimationUpdate(ValueAnimator animator) { 102 | getLabel().setTextColor((Integer) animator.getAnimatedValue()); 103 | } 104 | 105 | }); 106 | colorAnimation.setDuration(LABEL_COLOR_CHANGE_ANIMATION_TIME); 107 | colorAnimation.start(); 108 | 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /lib/src/main/java/jesusm/floatlabellayout/lib/FloatLabelLayout.java: -------------------------------------------------------------------------------- 1 | package jesusm.floatlabellayout.lib;/* 2 | * Copyright (C) 2014 Chris Banes 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 | import android.content.Context; 18 | import android.content.res.TypedArray; 19 | import android.graphics.Color; 20 | import android.support.annotation.NonNull; 21 | import android.text.Editable; 22 | import android.text.TextUtils; 23 | import android.text.TextWatcher; 24 | import android.util.AttributeSet; 25 | import android.util.TypedValue; 26 | import android.view.View; 27 | import android.view.ViewGroup; 28 | import android.widget.EditText; 29 | import android.widget.LinearLayout; 30 | import android.widget.TextView; 31 | 32 | import com.example.jesus.lib.R; 33 | import com.nineoldandroids.animation.Animator; 34 | import com.nineoldandroids.animation.AnimatorSet; 35 | import com.nineoldandroids.animation.ObjectAnimator; 36 | import com.nineoldandroids.view.ViewHelper; 37 | 38 | /** 39 | * Layout which an {@link android.widget.EditText} to show a floating label when the hint is hidden 40 | * due to the user inputting text. 41 | * 42 | * @see Matt D. Smith on Dribble 43 | * @see Brad Frost's blog post 44 | */ 45 | public class FloatLabelLayout extends LinearLayout { 46 | 47 | private static final int DEFAULT_PADDING_TOP_BOTTOM_DP = 8; 48 | private static final long ANIMATION_DURATION = 100; 49 | private int mLabelColor = Color.GRAY; 50 | 51 | private EditText mEditText; 52 | private TextView mLabel; 53 | 54 | public FloatLabelLayout(Context context) { 55 | this(context, null); 56 | } 57 | 58 | public FloatLabelLayout(Context context, AttributeSet attrs) { 59 | this(context, attrs, 0); 60 | } 61 | 62 | public FloatLabelLayout(Context context, AttributeSet attrs, int defStyle) { 63 | super(context, attrs, defStyle); 64 | setOrientation(VERTICAL); 65 | 66 | final TypedArray a = context 67 | .obtainStyledAttributes(attrs, R.styleable.FloatLabelLayout); 68 | 69 | mLabel = new TextView(context); 70 | initLabelAppearance(context, a); 71 | mLabelColor = mLabel.getCurrentTextColor(); 72 | addView(mLabel, 0, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 73 | 74 | a.recycle(); 75 | } 76 | 77 | private void initLabelAppearance(Context context, TypedArray a) { 78 | mLabel.setVisibility(INVISIBLE); 79 | mLabel.setPadding(0, dipsToPix(DEFAULT_PADDING_TOP_BOTTOM_DP), 0, 0); 80 | mLabel.setTextAppearance(context, 81 | a.getResourceId(R.styleable.FloatLabelLayout_floatLabelTextAppearance, 82 | R.style.PasswordFloatingLabelLayout_DefaultStyle) 83 | ); 84 | } 85 | 86 | 87 | @Override 88 | public final void addView(@NonNull View child, int index, ViewGroup.LayoutParams params) { 89 | if (child instanceof EditText) { 90 | // If we already have an EditText, throw an exception 91 | if (mEditText != null) { 92 | throw new IllegalArgumentException("We already have an EditText, can only have one"); 93 | } 94 | child.setPadding(child.getPaddingLeft(), dipsToPix(DEFAULT_PADDING_TOP_BOTTOM_DP), 95 | child.getPaddingRight(), dipsToPix(DEFAULT_PADDING_TOP_BOTTOM_DP)); 96 | if (mLabel != null) { 97 | mLabel.setPadding(child.getPaddingLeft(), mLabel.getPaddingTop(), 98 | child.getPaddingRight(), mLabel.getPaddingBottom()); 99 | } 100 | setEditText((EditText) child); 101 | } 102 | 103 | // Carry on adding the View... 104 | super.addView(child, index, params); 105 | } 106 | 107 | protected void setEditText(EditText editText) { 108 | mEditText = editText; 109 | 110 | // Add focus listener to the EditText so that we can notify the label that it is activated. 111 | // Allows the use of a ColorStateList for the text color on the label 112 | mEditText.setOnFocusChangeListener(new OnFocusChangeListener() { 113 | @Override 114 | public void onFocusChange(View view, boolean focused) { 115 | mLabel.setEnabled(focused); 116 | } 117 | }); 118 | 119 | initTextWatcher(); 120 | updateLabelText(); 121 | 122 | } 123 | 124 | protected void updateLabelText() { 125 | mLabel.setText(mEditText.getHint()); 126 | } 127 | 128 | private void initTextWatcher() { 129 | getEditText().addTextChangedListener(new TextWatcher() { 130 | @Override 131 | public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { 132 | 133 | } 134 | 135 | @Override 136 | public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { 137 | 138 | } 139 | 140 | @Override 141 | public void afterTextChanged(Editable editable) { 142 | checkAfterTextChanged(editable); 143 | 144 | } 145 | }); 146 | } 147 | 148 | 149 | protected void checkAfterTextChanged(Editable s) { 150 | if (TextUtils.isEmpty(s)) { 151 | // The text is empty, so hide the label if it is visible 152 | if (mLabel.getVisibility() == View.VISIBLE) { 153 | hideLabel(); 154 | } 155 | } else { 156 | actionTextNotEmpty(); 157 | } 158 | } 159 | 160 | protected void actionTextNotEmpty() { 161 | // The text is not empty, so show the label if it is not visible 162 | if (mLabel.getVisibility() != View.VISIBLE) { 163 | showLabel(); 164 | } 165 | updateLabelColor(); 166 | 167 | } 168 | 169 | 170 | /** 171 | * Need to be overriden to update the label text color 172 | */ 173 | public void updateLabelColor() { 174 | getLabel().setTextColor(getmLabelColor()); 175 | } 176 | 177 | /** 178 | * @return the {@link android.widget.EditText} text input 179 | */ 180 | public EditText getEditText() { 181 | return mEditText; 182 | } 183 | 184 | /** 185 | * @return the {@link android.widget.TextView} label 186 | */ 187 | public TextView getLabel() { 188 | return mLabel; 189 | } 190 | 191 | /** 192 | * Show the label using an animation 193 | */ 194 | private void showLabel() { 195 | ObjectAnimator alpha = ObjectAnimator.ofFloat(mLabel, "alpha", 0f, 1f); 196 | ObjectAnimator translationY = ObjectAnimator.ofFloat(mLabel, "translationY", mLabel.getHeight() / 2, 0f); 197 | AnimatorSet animatorSet = new AnimatorSet(); 198 | animatorSet.setDuration(ANIMATION_DURATION); 199 | animatorSet.playTogether(alpha, translationY); 200 | animatorSet.addListener(new Animator.AnimatorListener() { 201 | @Override 202 | public void onAnimationStart(Animator animation) { 203 | mLabel.setVisibility(View.VISIBLE); 204 | } 205 | 206 | @Override 207 | public void onAnimationEnd(Animator animation) { 208 | 209 | } 210 | 211 | @Override 212 | public void onAnimationCancel(Animator animation) { 213 | 214 | } 215 | 216 | @Override 217 | public void onAnimationRepeat(Animator animation) { 218 | 219 | } 220 | }); 221 | animatorSet.start(); 222 | 223 | } 224 | 225 | /** 226 | * Hide the label using an animation 227 | */ 228 | private void hideLabel() { 229 | ViewHelper.setAlpha(mLabel, 1f); 230 | ViewHelper.setTranslationY(mLabel, 0f); 231 | ObjectAnimator alpha = ObjectAnimator.ofFloat(mLabel, "alpha", 0f); 232 | ObjectAnimator translationY = ObjectAnimator.ofFloat(mLabel, "translationY", mLabel.getHeight() / 2); 233 | AnimatorSet animatorSet = new AnimatorSet(); 234 | animatorSet.addListener(new com.nineoldandroids.animation.Animator.AnimatorListener() { 235 | @Override 236 | public void onAnimationStart(com.nineoldandroids.animation.Animator animation) { 237 | 238 | } 239 | 240 | @Override 241 | public void onAnimationEnd(com.nineoldandroids.animation.Animator animation) { 242 | mLabel.setVisibility(View.INVISIBLE); 243 | } 244 | 245 | @Override 246 | public void onAnimationCancel(com.nineoldandroids.animation.Animator animation) { 247 | 248 | } 249 | 250 | @Override 251 | public void onAnimationRepeat(com.nineoldandroids.animation.Animator animation) { 252 | 253 | } 254 | }); 255 | animatorSet.setDuration(ANIMATION_DURATION); 256 | animatorSet.playTogether(alpha, translationY); 257 | animatorSet.start(); 258 | 259 | } 260 | 261 | /** 262 | * Helper method to convert dips to pixels. 263 | */ 264 | private int dipsToPix(float dps) { 265 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dps, 266 | getResources().getDisplayMetrics()); 267 | } 268 | 269 | 270 | public int getmLabelColor() { 271 | return mLabelColor; 272 | } 273 | 274 | public void setmLabelColor(int color) { 275 | this.mLabelColor = color; 276 | } 277 | } --------------------------------------------------------------------------------