読者です 読者をやめる 読者になる 読者になる

リア充爆発日記

You don't even know what ria-ju really is.

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自体はあるんだけど、無いメソッドがたくさんあって、こんなことになっている。自分で実装すればいいんだろうけどちょっと時間がない。。。