안드로이드에서 EditText를 이용하여 Text를 작성할때 Byte단위로 길이를 제한해야 하는 경우가 있다. SMS, MMS 전송을 할 때가 대표적인 예가 될 것이다.
우리가 영어로만 메시지를 보낸다면 문제가 없겠지만 한글의 경우 2~3 Byte로 표현된다.
내가 현재 다루고 있는 디바이스는 3Byte로 한글을 표기하는데 이유는 잘 모르겠으나 안정성을 위해서라 한다.
그러나 물론 CharSet을 이용하여 Byte를 읽어들이면 2Byte로 표현이 가능하다.
방법은 매우 간단하다. InputFilter를 적용시켜 Byte Limit을 걸어준 다음 EditText에 Set 시키기만 하면 끝이다.
InputFilter[] byteFilter = new InputFilter[]{new ByteLengthFilter(80, "KSC5601")};
edittext.setFilters(byteFilter);
여기서 잠깐, ByteLengthFilter를 확인해야 한다. 80은 Byte Limit을 의미하고 EditText 창에서 문자를 입력할때 80Byte가 넘지 않도록 유지시켜준다. "KSC5601"은 CharSet으로 3Byte로 표현되는 한글을 2Byte로 바꿔주는 역할을 하게된다.
그리고 여기서 EditText에서 String을 추출하고 Byte[]로 가져오는 경우 반드시 아래처럼 Charset("KSC5601") 을 지정해줘야 한다.
byte[] byteResult = value.getText().toString().getBytes("KSC5601");
필자는 처음에 getBytes(); 만으로 리턴을 받았다가 계속 3Byte로 들어오는 한글때문에 무척 고생했,, 아니 삽질을 했다.
다시 ByteLengthFilter를 확인해 보자.
class ByteLengthFilter implements InputFilter {
private String mCharset;
protected int mMaxByte;
public ByteLengthFilter(int maxbyte, String charset)
{
this.mMaxByte = maxbyte;
this.mCharset = charset;
}
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart,int dend) {
String expected = new String();
expected += dest.subSequence(0, dstart);
expected += source.subSequence(start, end);
expected += dest.subSequence(dend, dest.length());
int keep = calculateMaxLength(expected) - (dest.length() - (dend - dstart));
if(keep < 0) {
keep = 0;
}
int Rekeep = plusMaxLength(dest.toString(), source.toString(), start);
if (keep <= 0 && Rekeep <= 0) {
return "";
}
else if (keep >= end - start) {
return null;
}
else {
if( dest.length() == 0 && Rekeep <= 0 ) {
return source.subSequence(start, start + keep);
}
else if(Rekeep <= 0) {
return source.subSequence(start, start + (source.length()-1));
}
else {
return source.subSequence(start, start + Rekeep); // source중 일부만입력 허용
}
}
}
protected int plusMaxLength( String expected, String source, int start ) {
int keep = source.length();
int maxByte = mMaxByte - getByteLength(expected.toString()); //입력가능한 byte
while (getByteLength(source.subSequence(start, start + keep).toString()) > maxByte) {
keep--;
};
return keep;
}
protected int calculateMaxLength(String expected) {
int expectedByte = getByteLength(expected);
if (expectedByte == 0) {
return 0;
}
return mMaxByte - (getByteLength(expected) - expected.length());
}
private int getByteLength(String str) {
try {
return str.getBytes(mCharset).length;
} catch (UnsupportedEncodingException e) {
}
return 0;
}
}
EidtText에 문자가 입력 될때마다 Filter 메서드가 호출됨을 확인할 수 있었고 제한하려는 Byte 수에 따라서
문자입력의 허용여부를 리턴한다.
이 외에 인터페이스 동작 방식은 확실하게 파고들기 힘들듯 하다. 필터가 EditText에 어떻게 적용되는지 확인까지는 할 수 없기에..
그러나 Filter 메서드가 리턴하는 값들을 보면 입력한 문자가 MaxByte를 충족한다면 허용을 하고 그렇지 않다면 텅 빈 String을
리턴하는구조다.
이정도까지만 안다면 필터를 적용하는데 무리는 없을 듯 하다.