Skip to content
Open
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
6 changes: 0 additions & 6 deletions .idea/encodings.xml

This file was deleted.

18 changes: 17 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package morxander.editcard;

import android.text.method.PasswordTransformationMethod;
import android.view.View;

/**
* Created by Mac on 2017. 1. 25. PM 1:56
* make password bullet
*/

public class CardNumberTransformationMethod extends PasswordTransformationMethod {
final static int NORMAL = 0;
final static int AMERICAN_EXPRESS = 1;
final static int DINERS_CLUB = 2;

// Card type
private int type = 0;

private static CardNumberTransformationMethod ourInstance = new CardNumberTransformationMethod();

public static CardNumberTransformationMethod getInstance() {
return ourInstance;
}

public void setType(int type) {
this.type = type;
}

@Override
public CharSequence getTransformation(CharSequence source, View view) {
return new CardNumberCharSequence(source);
}

private class CardNumberCharSequence implements CharSequence {
private CharSequence mSource;

public CardNumberCharSequence(CharSequence source) {
mSource = source; // Store char sequence
}

public char charAt(int index) {
switch(type) {
case AMERICAN_EXPRESS:
case DINERS_CLUB:
if (index < 11 && index > 4) {
return '*';
}
break;
default:
if (index > 9 && index < 14) {
return '*';
}
break;
}
return mSource.charAt(index);
}

public int length() {
return mSource.length();
}

public CharSequence subSequence(int start, int end) {
CharSequence charSequence = mSource.subSequence(start, end);
return charSequence; // Return default
}
}
}
37 changes: 20 additions & 17 deletions EditCard/src/main/java/morxander/editcard/CardPattern.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,35 @@
public class CardPattern {

// VISA
public static final String VISA = "4[0-9]{12}(?:[0-9]{3})?";
public static final String VISA_VALID = "^4[0-9]{12}(?:[0-9]{3})?$";
public static final String VISA = "4[0-9]{0,15}"; // TODO: 2017. 1. 25. Check this.
public static final String VISA_VALID = "^4[0-9]{12}(?:[0-9]{3})?$";

// MasterCard
public static final String MASTERCARD = "^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$";
public static final String MASTERCARD_SHORT = "^(?:222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)";
public static final String MASTERCARD_SHORTER = "^(?:5[1-5])";
public static final String MASTERCARD_VALID = "^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$";
public static final String MASTERCARD = "^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$";
public static final String MASTERCARD_SHORT = "^(?:222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)";
public static final String MASTERCARD_SHORTER = "^5[1-5][0-9]{0,14}$"; // TODO: 2017. 1. 25. Check this.
public static final String MASTERCARD_VALID = "^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$";

// American Express
public static final String AMERICAN_EXPRESS = "^3[47][0-9]{0,13}";
public static final String AMERICAN_EXPRESS_VALID = "^3[47][0-9]{13}$";
public static final String AMERICAN_EXPRESS = "^3[47][0-9]{0,13}";
public static final String AMERICAN_EXPRESS_VALID = "^3[47][0-9]{13}$";

// DISCOVER
public static final String DISCOVER = "^6(?:011|5[0-9]{1,2})[0-9]{0,12}";
public static final String DISCOVER_SHORT = "^6(?:011|5)";
public static final String DISCOVER_VALID = "^6(?:011|5[0-9]{2})[0-9]{12}$";
public static final String DISCOVER = "^6(?:011|5[0-9]{1,2})[0-9]{0,12}";
public static final String DISCOVER_SHORT = "^6(?:011|5)";
public static final String DISCOVER_VALID = "^6(?:011|5[0-9]{2})[0-9]{12}$";

// JCB
public static final String JCB = "^(?:2131|1800|35\\d{0,3})\\d{0,11}$";
public static final String JCB_SHORT = "^2131|1800";
public static final String JCB_VALID = "^(?:2131|1800|35\\d{3})\\d{11}$";
public static final String JCB = "^(?:2131|1800|35\\d{0,3})\\d{0,11}$";
public static final String JCB_SHORT = "^(2131|1800|35)[0-9]{0,14}$"; // TODO: 2017. 1. 25. Check this.
public static final String JCB_VALID = "^(?:2131|1800|35\\d{3})\\d{11}$";

// Discover
public static final String DINERS_CLUB = "^3(?:0[0-5]|[68][0-9])[0-9]{11}$";
public static final String DINERS_CLUB_SHORT = "^30[0-5]";
public static final String DINERS_CLUB_VALID = "^3(?:0[0-5]|[68][0-9])[0-9]{11}$";
public static final String DINERS_CLUB = "^3(?:0[0-5]|[68][0-9])[0-9]{11}$";
public static final String DINERS_CLUB_SHORT = "^3(0[0-5]|095|[689])[0-9]{0,12}"; // TODO: 2017. 1. 25. Check this.
public static final String DINERS_CLUB_VALID = "^3(?:0[0-5]|[68][0-9])[0-9]{11}$";

// Union 2017.01.25
public static final String UNION_PAY_SHORT = "62[0-9]{0,14}"; // TODO: 2017. 1. 25. Check this.

}
114 changes: 96 additions & 18 deletions EditCard/src/main/java/morxander/editcard/EditCard.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,24 @@
import android.text.InputFilter;
import android.text.Spanned;
import android.text.TextWatcher;
import android.text.method.TransformationMethod;
import android.util.AttributeSet;
import android.widget.EditText;

import java.util.regex.Pattern;

import static android.R.attr.start;

/**
* Created by morxander on 11/19/16.
* Created by Mac on 11/19/16 PM 2:24
*/

public class EditCard extends EditText {

String type = "UNKNOWN";
private String type = "";
public CardNumberTransformationMethod cardNumberTransformationMethod;
// 2017.01.25
public TextWatcher textWatcher;

public EditCard(Context context) {
super(context);
Expand All @@ -44,35 +50,79 @@ public EditCard(Context context, AttributeSet attrs, int defStyleAttr, int defSt
private void addMagic() {
// Changing the icon when it's empty
changeIcon();

cardNumberTransformationMethod = CardNumberTransformationMethod.getInstance();
setTransformationMethod(cardNumberTransformationMethod);

// Adding the TextWatcher
addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {

if (textWatcher != null) textWatcher.beforeTextChanged(s, start,count, after);
}

@Override
public void onTextChanged(CharSequence s, int position, int before, int action) {
if (action == 1) {
if (type.equals("UNKNOWN") || type.equals("Visa") || type.equals("Discover") || type.equals("JCB")) {
if (position == 3 || position == 8 || position == 13) {
if (!s.toString().endsWith("-")) {
append("-");
changeIcon(s.toString());

boolean isChaged = false;
String text = getText().toString();
String onlyNum = getText().toString().replaceAll("-", "");

StringBuilder stringBuilder = new StringBuilder(onlyNum);

if (type.equals("UNKNOWN") || type.equals("MasterCard") || type.equals("Visa") || type.equals("Discover") || type.equals("JCB")|| type.equals("Union_Pay")) {
if (text.length() > 4) {
if ('-' != text.charAt(4)) {
isChaged = true;
}
stringBuilder.insert(4, "-");
if (text.length() > 9) {
if ('-' != text.charAt(9)) {
isChaged = true;
}
stringBuilder.insert(9, "-");
if (text.length() > 14) {
if ('-' != text.charAt(14)) {
isChaged = true;
}
stringBuilder.insert(14, "-");
}
}
} else if (type.equals("American_Express") || type.equals("Diners_Club")) {
if (position == 3 || position == 10) {
if (!s.toString().endsWith("-")) {
append("-");
}
setFilters(new InputFilter[]{new InputFilter.LengthFilter(19)});
cardNumberTransformationMethod.setType(CardNumberTransformationMethod.NORMAL);
} else if (type.equals("American_Express") || type.equals("Diners_Club")) {
if (type.equals("Diners_Club")) {
setFilters(new InputFilter[]{new InputFilter.LengthFilter(16)});
cardNumberTransformationMethod.setType(CardNumberTransformationMethod.DINERS_CLUB);
}else {
setFilters(new InputFilter[]{new InputFilter.LengthFilter(17)});
cardNumberTransformationMethod.setType(CardNumberTransformationMethod.AMERICAN_EXPRESS);
}
if (text.length() > 4) {
if ('-' != text.charAt(4)) {
isChaged = true;
}
stringBuilder.insert(4, "-");
if (text.length() > 11) {
if ('-' != text.charAt(11)) {
isChaged = true;
}
stringBuilder.insert(11, "-");
}
}
}
if (isChaged) {
setText(stringBuilder.toString());
}else{
setSelection(length());
}
}

@Override
public void afterTextChanged(Editable editable) {
changeIcon();
if (textWatcher != null) textWatcher.afterTextChanged(editable);
}
});
// The input filters
Expand All @@ -92,11 +142,17 @@ public CharSequence filter(CharSequence source, int start, int end, Spanned dest
}

private void changeIcon() {
String s = getText().toString().replace("-", "").trim();
String s = getText().toString();
changeIcon(s);
}

// 2017.01.25
private void changeIcon(String s) {
s = s.replaceAll("-", "").trim();
if (s.startsWith("4") || s.matches(CardPattern.VISA)) {
setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.vi, 0);
type = "Visa";
} else if (s.matches(CardPattern.MASTERCARD_SHORTER) || s.matches(CardPattern.MASTERCARD_SHORT) || s.matches(CardPattern.MASTERCARD)) {
} else if (s.matches(CardPattern.MASTERCARD_SHORTER)) {
setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.mc, 0);
type = "MasterCard";
} else if (s.matches(CardPattern.AMERICAN_EXPRESS)) {
Expand All @@ -105,12 +161,15 @@ private void changeIcon() {
} else if (s.matches(CardPattern.DISCOVER_SHORT) || s.matches(CardPattern.DISCOVER)) {
setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ds, 0);
type = "Discover";
} else if (s.matches(CardPattern.JCB_SHORT) || s.matches(CardPattern.JCB)) {
} else if (s.matches(CardPattern.JCB_SHORT)) {
setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.jcb, 0);
type = "JCB";
} else if (s.matches(CardPattern.DINERS_CLUB_SHORT) || s.matches(CardPattern.DINERS_CLUB)) {
} else if (s.matches(CardPattern.DINERS_CLUB_SHORT)) {
setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.dc, 0);
type = "Diners_Club";
} else if (s.matches(CardPattern.UNION_PAY_SHORT)) {
setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.un, 0);
type = "Union_Pay";
} else {
setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.card, 0);
type = "UNKNOWN";
Expand All @@ -128,10 +187,29 @@ public boolean isValid() {
if (getCardNumber().matches(CardPattern.DISCOVER_VALID)) return true;
if (getCardNumber().matches(CardPattern.DINERS_CLUB_VALID)) return true;
if (getCardNumber().matches(CardPattern.JCB_VALID)) return true;
// TODO: 2017. 1. 25. Need to add union-pay valid check
return false;
}

// 2017.01.25
public String getCardType(){
return type;
}

// 2017.01.25
public void addCardTextChangedListener(TextWatcher textWatcher) {
this.textWatcher = textWatcher;
}

// 2017.01.25
public void removeCardNumberTransformationMethod(TransformationMethod method) {
setTransformationMethod(null);
}

// 2017.01.25
public void setCardNumberTransformationMethod(TransformationMethod method) {
if (cardNumberTransformationMethod == null) {
cardNumberTransformationMethod = CardNumberTransformationMethod.getInstance();
}
setTransformationMethod(cardNumberTransformationMethod);
}
}
Binary file added EditCard/src/main/res/drawable/un.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ For now we only support the following card types :
* DISCOVER
* JCB
* Discover
* Union

### License
GNU GENERAL PUBLIC LICENSE 3
2 changes: 0 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@

# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
org.gradle.java.home=/usr/lib/jvm/java-1.8.0-openjdk-amd64
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
Expand Down