Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Kết quả 1 đến 6 của 6
  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    Định dạng số decimal trong EditText như thế nào?

    Hi all, mình gặp một chút vấn đề với việc format tự động trong quá trình nhập dữ liệu trên EditText trong Android. Mình mô tả cụ thể như sau:
    Nếu nhập vào: 1000 -> EditText sẽ hiển thị luôn: 1,000
    Tương tự khi nhập đang là 1,000 mà nhập tiếp 3 số 0, sẽ là: 1,000,000.
    Nếu như nhập số thập phân: 1,000.56 thì sẽ hiển thị như vậy luôn.
    Mình đang bị rối trong phần này, bạn nào có thể giúp mình giải quyết vấn đề này được không? Mình xin cảm ơn nhiều!
    Mình đã sử dụng TextWatcher để bắt sự kiện nhập giá trị vào, nhưng chưa nghĩ ra giải pháp.

  2. #2
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Không ai giúp mình với à...

  3. #3
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Để xử lý bài này thì bạn nên dùng state machine, cách clean và robust nhất là bạn dùng DFA (Deterministic Finite Automaton) cho thằng formatter, rồi xử lý theo. Mặc dù làm cách này thủ công, nhưng bạn có full-control.
    Mình làm nháp sơ, ý tưởng của mình tương tự như trên nhưng mình chỉ làm sơ xài thôi. Bạn nên test lại cẩn thận rồi mới nên đưa vào production. Ý tưởng của mình là tạo 2 buffer, một thằng cho integer, một thằng cho decimal, tùy vào giá trị nhập vào mà mình xử lý. Máy này mình không có Android, nên mình dùng tạm thằng JTextField với KeyListener, làm với Android thì nó tương ứng với EditText và TextWatcher, cụ thể:

    Mã:
    afterTextChanged = keyReleaseonTextChange = keyTyped
    MyApp.java

    Mã:
    import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import java.text.DecimalFormat; import javax.swing.JEditorPane;import javax.swing.JPanel;import javax.swing.JTextField;  public class MyApp extends JPanel {    enum FormatTypingMode {        Integer,        Decimal,        Empty    }     private JTextField mTextField;        /**     * Constructor     */    public MyApp() {        mTextField = new JTextField(20);        mTextField.addKeyListener(new FormatDecimalListener());        add(mTextField);    }        /**     *  KeyEvent for JTextFieldc     */    private class FormatDecimalListener implements KeyListener {        /*         * The pattern         */        private static final String pattern = "###,###.###";                /*         * Formatter         */        private DecimalFormat formatter;                /*         * Buffer holding digits of integer part         */        private StringBuilder integerBuffer;                /*         * Buffer holding digits of decimal part         */        private StringBuilder decimalBuffer;                /*         * Current typing mode         */        private FormatTypingMode mode;                /**         * Constructor         */        public FormatDecimalListener() {            mode = FormatTypingMode.Empty;            integerBuffer = new StringBuilder();            decimalBuffer = new StringBuilder();            formatter = new DecimalFormat(pattern);        }                /**         * Calculate double value of both buffers         * @return a double         */        private double getDoubleValue() {            double integer = 0;            double decimal = 0;                        try {                integer = Double.parseDouble(integerBuffer.toString());                decimal = Double.parseDouble("0." + decimalBuffer.toString());            }            catch (NumberFormatException e) {                // handle error            }                        return integer + decimal;        }                /**         * Calculate value of integer buffer          * @return an integer         */        private int getIntegerValue() {            int integer = 0;                        try {                integer = Integer.parseInt(integerBuffer.toString());            }            catch (NumberFormatException e) {                // handle error            }                        return integer;        }            /**         * Modify mode and buffer when a digit is entered         * @param d         *          a digit [0, 9]         */        private void handleDigit(char d) {            if (mode == FormatTypingMode.Integer) {                integerBuffer.append(d);            }            else if (mode == FormatTypingMode.Decimal){                decimalBuffer.append(d);            }        }                /**         * Modify mode and buffer when a backspace is entered         */        private void handleBackspace() {            if (mode == FormatTypingMode.Integer) {                if (integerBuffer.length() == 0) {                    mode = FormatTypingMode.Empty;                }                else {                    integerBuffer.deleteCharAt(integerBuffer.length() - 1);                }            }            else if (mode == FormatTypingMode.Decimal) {                if (decimalBuffer.length() == 0) {                    mode = FormatTypingMode.Integer;                }                else {                    decimalBuffer.deleteCharAt(decimalBuffer.length() - 1);                }            }            else {                mode = FormatTypingMode.Empty;            }        }                @Override        public void keyPressed(KeyEvent e) {                    }         @Override        public void keyReleased(KeyEvent e) {            if (mode == FormatTypingMode.Integer) {                mTextField.setText(formatter.format(getIntegerValue()));            }            else if (mode == FormatTypingMode.Decimal){                if (!decimalBuffer.toString().equals("")) {                    mTextField.setText(formatter.format(getDoubleValue()));                }                else {                    mTextField.setText(formatter.format(getIntegerValue()) + ".");                }            }            else {                // both buffer are empty, do nothing             }        }         @Override        public void keyTyped(KeyEvent e) {            // start getting input            if (mode == FormatTypingMode.Empty && integerBuffer.length() == 0 && decimalBuffer.length() == 0) {                mode = FormatTypingMode.Integer;            }                        char c = e.getKeyChar();            if (c == '.') {                mode = FormatTypingMode.Decimal;            }            else if (c >= '0' && c <= '9') {                handleDigit(c);            }            else if (c == KeyEvent.VK_BACK_SPACE) {                handleBackspace();            }        }    }}
    Main.java

    Mã:
    import java.text.DecimalFormat;import java.util.*;import java.awt.*;import java.awt.event.KeyEvent;import java.awt.event.KeyListener; import javax.swing.JFrame;import javax.swing.JTextField; public class Main {    public static void main(String[] args) {        JFrame frame = new JFrame("Text state machine");        frame.setSize(400, 100);        frame.setResizable(true);        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        frame.setContentPane(new MyApp());        frame.setVisible(true);    }}
    Lưu ý: mình không có handle overflow

  4. #4
    Ngày tham gia
    Sep 2015
    Đang ở
    hà nội
    Bài viết
    0
    Thanks bạn! Lúc đầu mình cũng có tính xử lý như vậy, tuy nhiên do app đang làm có quá nhiều EditText nên việc xử lý với TextWatcher hay nẩy sinh lỗi, khá là đau đầu. Nhưng giờ cũng đã có giải quyết riêng rồi.[IMG]images/smilies/smile.png[/IMG]

  5. #5
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Đúng là thằng TextWatcher khó xài, và sorry bạn là mình không coi kĩ về 2 hàm beforeTextChanged()với onTextChanged(). Chúng ta chỉ có thể chỉnh sữa buffer ở hàm afterTextChanged() mà thôi.
    Tuy nhiên, làm với Android có một cái sướng là nó open-source [IMG]images/smilies/wink.png[/IMG]! Nếu cùng đường thì bạn down source nó về rồi coi sẽ tìm ra cách thôi, và mình nghĩ vọc sâu tí xíu sẽ có performance tốt hơn.
    À, tại sao bạn nói nhiều EditText lại sinh lỗi nhỉ? Tụi nó không register cùng một event sao? Nếu được bạn post ví dụ cho mình tham khảo với nha. Thanks bạn trước.

  6. #6
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Khi xử lý với TextWatcher, do dữ liệu là thay đổi liên tục và mỗi lần nhập là 1 lần gọi lại. Nhiều thằng EditText có thể set chung 1 Watcher, không có vấn đề gì cả. Thực sự thì cũng khó mô tả cái vất vả khi mình làm việc với thằng này. Tuy nhiên để đơn giản đi thì mình đã sử dụng sự kiện : onFocusChange. Khi thay đổi focus thì mới formart nó, thay vì format ngay lúc nhập liệu.

 

 

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •