Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to validate only on-demand #70

Merged
merged 7 commits into from
Apr 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.Space;
Expand Down Expand Up @@ -146,6 +147,10 @@ public class TextFieldBoxes extends FrameLayout {
protected int ANIMATION_DURATION = 100;
protected boolean onError = false;
protected boolean activated = false;
/**
* See {@link #setValidateOnDemand(boolean)}
*/
protected boolean isValidateOnDemand = false;

protected View panel;
protected View bottomLine;
Expand Down Expand Up @@ -181,14 +186,12 @@ public TextFieldBoxes(Context context, AttributeSet attrs) {
}

public TextFieldBoxes(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);
init();
handleAttributes(context, attrs);
}

protected void init() {

initDefaultColor();
inputMethodManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
}
Expand Down Expand Up @@ -448,8 +451,11 @@ public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
public void afterTextChanged(Editable editable) {
if (!activated && !editable.toString().isEmpty()) activate(true);
if (activated && editable.toString().isEmpty() && !hasFocus) deactivate();
removeError();
updateCounterText();
if (isValidateOnDemand) {
updateCounterText(false);
} else {
validate(); //this will call updateCounterText(true);
}
if (textChangeListener != null) {
textChangeListener.onTextChanged(editable.toString(), onError);
}
Expand Down Expand Up @@ -495,6 +501,7 @@ protected void handleAttributes(Context context, AttributeSet attrs) {
this.minCharacters = styledAttrs.getInt(R.styleable.TextFieldBoxes_minCharacters, 0);

/* Others */
this.isValidateOnDemand = styledAttrs.getBoolean(R.styleable.TextFieldBoxes_validateOnDemand, false);
this.enabled = styledAttrs.getBoolean(R.styleable.TextFieldBoxes_enabled, true);
this.iconSignifierResourceId = styledAttrs.
getResourceId(R.styleable.TextFieldBoxes_iconSignifier, 0);
Expand Down Expand Up @@ -624,6 +631,29 @@ protected void setHighlightColor(int colorRes) {
this.bottomLine.setBackgroundColor(colorRes);
}

/**
* By default the field is validated each time a key is pressed and at construction,
* this means a field with a minimum length requirement will start in Error state.
* Set this value to true to validate only when {@link #validate()} is called.
* @param isValidateOnDemand the new value
*/
protected void setValidateOnDemand(boolean isValidateOnDemand) {
this.isValidateOnDemand = isValidateOnDemand;
}

/**
* Update the onError state of this component
* @return true if valid (the inverse value of onError)
*/
public boolean validate() {
removeError();
updateCounterText(true);
if (onError) {
setError(null, false);
}
return !onError;
}

/**
* check if the TextFieldBox should use a dense spacing,
* then change the layout dimens accordingly
Expand Down Expand Up @@ -674,59 +704,69 @@ protected void updateDimens(boolean useDenseSpacing) {
/**
* check if the character count meets the upper or lower limits,
* <p>
* if exceeds limit, setCounterError()
* if performValidation and exceeds limit, setCounterError()
* otherwise removeCounterError()
* <p>
* <p>
* @param performValidation - true if error state should be applied or removed by this calls
* See {@link #setValidateOnDemand(boolean)}
* </p>
* <i>NOTE: SPACE AND LINE FEED WILL NOT COUNT</i>
*/
protected void updateCounterText() {
protected void updateCounterText(boolean performValidation) {

/* Show clear button if there is anything */
if (hasClearButton)
if (this.editText.getText().toString().length() == 0) showClearButton(false);
else showClearButton(true);
if (hasClearButton) {
if (this.editText.getText().toString().length() == 0) {
showClearButton(false);
} else {
showClearButton(true);
}
}

/* Don't Count Space & Line Feed */
int length = this.editText.getText().toString()
.replaceAll(" ", "").replaceAll("\n", "").length();
int length = this.editText.getText().toString() .replaceAll(" ", "")
.replaceAll("\n", "").length();
String lengthStr = Integer.toString(length) + " / ";

String counterLabelResourceStr = getResources().getString(R.string.counter_label_text_constructor);
if (this.maxCharacters > 0) {
if (this.minCharacters > 0) {
/* MAX & MIN */
this.counterLabel.setText(String.format(
getResources().getString(R.string.counter_label_text_constructor),
lengthStr,
Integer.toString(this.minCharacters),
"-",
Integer.toString(this.maxCharacters)));
if (length < this.minCharacters || length > this.maxCharacters) setCounterError();
else removeCounterError();

this.counterLabel.setText(String.format(counterLabelResourceStr, lengthStr, Integer.toString(this.minCharacters), "-", Integer.toString(this.maxCharacters)));
if (performValidation) {
if (length < this.minCharacters || length > this.maxCharacters) {
setCounterError();
} else {
removeCounterError();
}
}
} else {
/* MAX ONLY */
this.counterLabel.setText(String.format(
getResources().getString(R.string.counter_label_text_constructor),
lengthStr,
Integer.toString(this.maxCharacters),
"", ""));
if (length > this.maxCharacters) setCounterError();
else removeCounterError();
this.counterLabel.setText(String.format(counterLabelResourceStr, lengthStr, Integer.toString(this.maxCharacters), "", ""));
if (performValidation) {
if (length > this.maxCharacters) {
setCounterError();
} else {
removeCounterError();
}
}
}
} else {
if (this.minCharacters > 0) {
/* MIN ONLY */
this.counterLabel.setText(String.format(
getResources().getString(R.string.counter_label_text_constructor),
lengthStr,
Integer.toString(this.minCharacters),
"+", ""));
if (length < this.minCharacters) setCounterError();
else removeCounterError();

this.counterLabel.setText(String.format(counterLabelResourceStr, lengthStr, Integer.toString(this.minCharacters), "+", ""));
if (performValidation) {
if (length < this.minCharacters) {
setCounterError();
} else {
removeCounterError();
}
}
} else {
this.counterLabel.setText("");
removeCounterError();
if (performValidation) {
removeCounterError();
}
}
}
}
Expand All @@ -748,7 +788,6 @@ protected void updateBottomViewVisibility() {
* set highlight color and counter Label text color to error color
*/
protected void setCounterError() {

this.onError = true;
setHighlightColor(this.errorColor);
this.counterLabel.setTextColor(this.errorColor);
Expand All @@ -760,7 +799,6 @@ protected void setCounterError() {
* set counterLabel Label text color to DEFAULT_TEXT_COLOR
*/
protected void removeCounterError() {

this.onError = false;
if (this.hasFocus) setHighlightColor(this.primaryColor);
else setHighlightColor(this.secondaryColor);
Expand All @@ -771,16 +809,18 @@ protected void removeCounterError() {
* set highlight color and helperLabel Label text color to errorColor
* set helperLabel Label text to error message
*
* @param errorText error message
* @param errorText optional error message
* @param giveFocus whether the field will gain focus when set error on
*/
public void setError(String errorText, boolean giveFocus) {
public void setError(@Nullable String errorText, boolean giveFocus) {
if (this.enabled) {
this.onError = true;
activate(true);
setHighlightColor(this.errorColor);
this.helperLabel.setTextColor(this.errorColor);
this.helperLabel.setText(errorText);
if (errorText != null) {
this.helperLabel.setText(errorText);
}
if (giveFocus) setHasFocus(true);
makeCursorBlink();
}
Expand All @@ -791,10 +831,9 @@ public void setError(String errorText, boolean giveFocus) {
* otherwise set to secondaryColor
* set helperLabel Label text color to DEFAULT_TEXT_COLOR
* <p>
* <i>NOTE: WILL BE CALLED WHEN THE EDITTEXT CHANGES</i>
* <i>NOTE: WILL BE CALLED WHEN THE EDITTEXT CHANGES UNLESS YOU {@link #setValidateOnDemand(boolean)} TO TRUE</i>
*/
public void removeError() {

this.onError = false;
if (this.hasFocus) setHighlightColor(this.primaryColor);
else setHighlightColor(this.secondaryColor);
Expand Down Expand Up @@ -834,7 +873,7 @@ private void triggerSetters() {
setHasClearButton(this.hasClearButton);
setHasFocus(this.hasFocus);
setAlwaysShowHint(this.alwaysShowHint);
updateCounterText();
updateCounterText(!isValidateOnDemand);
updateBottomViewVisibility();
}

Expand Down Expand Up @@ -902,33 +941,29 @@ public void setPanelBackgroundColor(int colorRes) {

/* Characters Counter Setters */
public void setMaxCharacters(int maxCharacters) {

this.maxCharacters = maxCharacters;
updateCounterText();
updateCounterText(!isValidateOnDemand);
}

/**
* remove the max character count limit by setting it to 0
*/
public void removeMaxCharacters() {

this.maxCharacters = 0;
updateCounterText();
updateCounterText(!isValidateOnDemand);
}

public void setMinCharacters(int minCharacters) {

this.minCharacters = minCharacters;
updateCounterText();
updateCounterText(!isValidateOnDemand);
}

/**
* remove the min character count limit by setting it to 0
*/
public void removeMinCharacters() {

this.minCharacters = 0;
updateCounterText();
updateCounterText(!isValidateOnDemand);
}

/* Other Setters */
Expand All @@ -946,7 +981,7 @@ public void setEnabled(boolean enabled) {
this.iconImageButton.setEnabled(true);
this.iconImageButton.setClickable(true);
setHighlightColor(secondaryColor);
updateCounterText();
updateCounterText(!isValidateOnDemand);

} else {
removeError();
Expand Down
4 changes: 4 additions & 0 deletions textfieldboxes/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
<attr name="alwaysShowHint" format="boolean" />
<attr name="useDenseSpacing" format="boolean" />

<!-- Set whether to automatically validate, or only on demand
@see {@link TextFieldBoxes#setValidateOnDemand(boolean) } -->
<attr name="validateOnDemand" format="boolean" />

</declare-styleable>

<declare-styleable name="ExtendedEditText">
Expand Down