
Table of contents

Nonthawit
CEO | Engineer | Designer
VIEW
5,210
CATEGORY
LAST UPDATED
July 29, 2017
nontravis/format-edit-text-example
Contribute to format-edit-text-example development by creating an account on GitHub.github.com
เนื่องจากเจ้าของบล็อกเคยได้โจทย์ให้ใส่ phone format ใหักับตัว EditText สิ่งแรกที่คิดขึ้นมาคงหนีไม่พ้น TextWatcher เป็นแน่แท้
แต่เราเจอปัญหาคือ user ไม่สามารถพิมพ์เบอร์เร็วๆได้ทำให้เกิด UX ที่แย่กับ user มาก และไม่สามารถกดค้างเพื่อลบตัวเลขแบบเร็วๆได้ด้วยซึ่งวันนี้เราจะมาดูสาเหตุและทำให้มันถูกต้องกัน

EditText.addTextChangedListener( new TextWatcher(){@Override
public void beforeTextChanged( CharSequence charSequence, int i, int i1, int i2 ){
...
}
@Override
public void onTextChanged( CharSequence charSequence, int i, int i1, int i2 ){
...
}
@Override
public void afterTextChanged( Editable editable ){
...
}
} );
StringBuilder textBuilder = new StringBuilder(); เป็นต้น
NOTE: Editable เป็นแค่ interface นะ object จริงๆที่ส่งเข้ามาคือ SpannableStringBuilder
จากโค้ดตัวอย่างใน Github
อธิบายการทำงานคร่าวๆของโค้ดด้านบนอาจดูซับซ้อนซักหน่อยแต่หลักๆคือ การดักตัวอักษรที่ user พิมพ์เข้ามาแล้วเอามาก map กับ ###-####-#### format นั่นเอง (สามารถไปดูละเอียดได้ที่ link Github) เช่น
09212345678 --เป็น--> 092-1234-5678
แล้วเก็บไว้ในตัวแปร "strResult"
NOTE: สังเกตใน method TextWatcher.afterText(…) เราสั่ง EditText.removeTextChangedListener( this ) ตอนแรก และ EditText.addTextChangedListener( this ) ตอนสุดท้าย เพราะถ้าเราไม่ทำอย่างนี้ TextWatcher จะถูกเรียกขึ้นมาใหม่อีกถ้าเราสั่ง EditText.setText(…) มันจะทำให้ program เราติด infinity loop ไปเรื่อยๆนั่นเอง
ต่อมาให้สังเกตบรรทัดที่ 44
edt.setText( strResult );
method เจ้าปัญหาที่ไม่ควรใช้ใน TextWatcher เป็นอันขาด ถ้าเข้าไปดูโค้ดข้างในกันเล่นๆ เราก๊อปมาให้ละ
>>What!!?<< นี่ EditText.setText(…) จริงๆใช่ไหมทำไมมันทำอะไรเยอะแยะขนาดนั้น
ใช่ครับมันเป็น method ที่หนักพอสมควรเลยเราขอไม่ไล่ให้ดูนะว่ามันทำอะไรบ้าง ซึ่งการที่นำมาใช้กับ TextWatcher จึงเป็นบาปมหันต์ เพราะทุกครั้งที่เรากดตัวอักษรที่คีย์บอร์ดหนึ่งตัวเพื่อใส่ลง EditText เจ้า TextWatcher จะทำงานและ setText(…) ใหม่ทุกครั้ง ซึ่งเป็นสามารถเหตุว่า user ไม่สามารถพิมพ์ตัวเลขได้เร็วๆรวมถึงการกดค้างเพื่อลบตัวเลขในทีเดียวด้วยเนื่องจาก event มันถูก cancel ไป 😫
เราจึงควรใช้ Editable ที่ส่งเป็น param เข้ามามากกว่า
อยากบอกว่าแก้แค่บรรทัดเดียวคือบรรทัดที่ 44 (ที่เดิม)
edt.setText( strResult );
เป็น
s.append( strResult ); จบ 😱
ซึ่ง s ในที่นี้ก็คือ SpannableStringBuilder ที่ส่งเป็น param เข้ามา เราต้องใช้ object ตัวนี้จัดการข้อความใน EditText นะถึงจะถูก เพราะเป็น SpannableStringBuilder.append(…) เป็น method ที่เบากว่า EditText.setText(…) มาก
ถ้าลองเข้าไปดูโค้ดกันเล่นๆ
เราคงไม่ได้ไล่ให้ดู แต่คร่าวๆมันคือการ replace ข้อความ และจัดการเกี่ยวกับข้อความทั้งหมด
คราวนี้การพิมพ์ของ User ก็จะลื่นไหลแล้วครับ หมดปัญหา user ไม่สามารถพิมพ์ตัวเลขได้เร็วๆได้และกดค้างเพื่อลบตัวเลข 😎

วันนี้คงไว้เท่านี้เจอกันบล็อกหน้าครับผม 😎

อย่าลืม share มนุษย์ Android คนอื่นด้วยหละ 😎
KNOWLEDGE


Nonthawit
CEO | Engineer | Designer
เข้าใจการทำ Selector แบบ Ripple effect


Nonthawit
CEO | Engineer | Designer
20 สิ่ง ที่ได้หลังจากเป็น Android developer ที่ Nextzy 3 เดือน
บทความนี้แชร์ประสบการณ์ 3 เดือนแรกของการทำงานเป็น Android Developer ที่ Nextzy ครอบคลุมทั้งด้าน technical เช่น MVP architecture, Android Lifecycle, ProGuard, Git workflow และการเขียน Unit Test รวมถึงด้าน soft skill อย่างการสื่อสารกับทีม, การแชร์ความรู้, และการเขียนโค้ดให้ readable และยืดหยุ่น นอกจากนี้ยังสะท้อนวัฒนธรรมองค์กรที่เน้นทีมเวิร์ค การ review โค้ด และบรรยากาศการทำงานที่สนุกสนาน ซึ่งล้วนช่วยลด learning curve และพัฒนาทักษะได้เร็วกว่าการเรียนรู้คนเดียว
![[Tip/Trick] วิธีติดต่อกับ WebView ผ่าน JavascriptInterface มันเท่มาก](https://image.nextzy.tech/1_Aleix_TFC_7yz_Qh_Q_Sx_GV_Rqxw_a29e28219a.png)

Nonthawit
CEO | Engineer | Designer
[Tip/Trick] วิธีติดต่อกับ WebView ผ่าน JavascriptInterface มันเท่มาก