EditTextを拡張してメールアドレス用にしてみる
public class EmailEditText extends EditText implements TextWatcher { private static final String TAG = EmailEditText.class.getSimpleName(); public boolean isValid = false; public EmailEditText(Context context) { super(context); initView(); } public EmailEditText(Context context, AttributeSet attrs) { super(context, attrs); initView(); } public EmailEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initView(); } private void initView() { addTextChangedListener(this); this.setFilters( new InputFilter[] { new InputFilter.LengthFilter(User.EMAIL_MAX_LENGTH) } ); } @Override public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { super.onTextChanged(text, start, lengthBefore, lengthAfter); } @Override public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {} @Override public void afterTextChanged(Editable editable) { validate(editable); } private void validate(Editable editable) { isValid = editable.toString().length() <= User.EMAIL_MAX_LENGTH; if (!isValid) { String errMsg = String.format(getContext().getString(R.string.input_too_long), User.EMAIL_MAX_LENGTH); setError(errMsg); return; } String regex = "\\A[\\w+\\-.]+@[a-z\\d\\-.]+\\.[a-z]+\\z"; Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); Matcher m = p.matcher(editable.toString()); isValid = m.find(); if (!isValid) { String errMsg = String.format(getContext().getString(R.string.input_invalid), getContext().getString(R.string.signup_email)); setError(errMsg); return; } isValid = true; } }
まだ汎用性がないし、雑だけどとりあえず動いた。
長さチェックは、
addTextChangedListener(this);
しないとTextWatcherが反応しない(よく考えればあたりまえだけど)けど、気づかずにけっこうハマった。ので記念パピコ。
長さの入力チェックはいらないんじゃないかと、あとで気づいた。
テストもついでに乗っけておこう。
@RunWith(MyTestRunner.class) public class EmailEditTextTest { @Test public void testInit() { // SignUpActivity a = new SignUpActivity(); // AttributeSet attributeSet = Xml.asAttributeSet(a.getResources().getXml(R.id.signup_email_edit_text)); // EmailEditText editText = new EmailEditText(a, attributeSet); // assertThat(editText.getHint().toString(), is(equalTo(a.getString(R.string.signup_email_hint)))); // the shadow has no implementation for getHint() } @Test public void testValidation() { SignUpActivity a = new SignUpActivity(); EmailEditText editText = new EmailEditText(a, null, 0); String validLengthEmail = createValidLengthEmail(); String invalidLengthEmail = "a" + validLengthEmail; assertThat(invalidLengthEmail.length(), is((User.EMAIL_MAX_LENGTH + 1))); String[] invalidEmailArray = {"", "user@foo,com", "user_at_foo.org", "example.user@foo.", "foo@bar_baz.com foo@bar+baz.com", invalidLengthEmail}; // String errMsg = String.format(a.getString(R.string.input_invalid), a.getString(R.string.signup_email)); for (String email : invalidEmailArray) { editText.isValid = true; editText.setText(email); editText.afterTextChanged(editText.getText()); assertThat(editText.isValid, is(false)); // assertThat(editText.getError().toString(), is(equalTo(errMsg))); the shadow has no implementation for getError() } String[] validEmailArray = {"user@foo.COM", "A_US-ER@f.b.org", "frst.lst@foot.jp", "a+b@baz.cn", validLengthEmail}; for (String email : validEmailArray) { editText.isValid = true; editText.setText(email); editText.afterTextChanged(editText.getText()); assertThat(editText.isValid, is(true)); // assertThat(editText.getError(), is(nullValue())); the shadow has no implementation for getError() } } private String createValidLengthEmail() { String userPart = ""; String domain = "@example.com"; for (int i = (User.EMAIL_MAX_LENGTH - domain.length()); i -->0;) { userPart = userPart.concat("a"); } return userPart + domain; } }
Shadow自体はあるんだけど、無いメソッドがたくさんあって、こんなことになっている。自分で実装すればいいんだろうけどちょっと時間がない。。。