2010-06-10 7 views
10

¿Cómo se crea una entrada de texto de edición que formatea la entrada solo en formato de dinero? Cuando el usuario ingresa 5, quiero que la entrada se vea como "$ 0.05" y cuando luego ingrese 3, la entrada debe verse como "$ 0.53" y finalmente ingresan 6 y la entrada debe verse como "$ 5.36".Android Money Input con decimal fijo

Respuesta

1

Puede usar un TextWatcher para hacer ese tipo de cosas.

Extender TextWatcher: http://d.android.com/reference/android/text/TextWatcher.html

public class MyTextWatcher implements TextWatcher { 

    public void afterTextChanged(Editable arg0) { 

    } 

    public void beforeTextChanged(CharSequence s, int start, int count, int after) { 

    } 

    public void onTextChanged(CharSequence s, int start, int before, int count) { 

    } 

} 

después añadirlo a su EDITTEXT con

myEditText.addTextChangedListener(new MyTextWatcher()); 
1

encontré el TextWatcher a ser un poco engorroso. En su lugar, se puede establecer el detector de teclas:

setKeyListener(new CalculatorKeyListener()); 
// Must be called after setKeyListener(), otherwise is overridden 
setRawInputType(Configuration.KEYBOARD_12KEY); 

y luego crear un KeyListener que se extiende NumberKeyListener:

class CalculatorKeyListener extends NumberKeyListener { 
    @Override 
    public int getInputType() { 
     return InputType.TYPE_CLASS_NUMBER; 
    } 

    @Override 
    public boolean onKeyDown(View view, Editable content, int keyCode, KeyEvent event) { 
     if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) { 
      digitPressed(keyCode - KeyEvent.KEYCODE_0); 
     } else if (keyCode == KeyEvent.KEYCODE_DEL) {           
      deletePressed(); 
     } 
     return true; 
    } 

    @Override 
    protected char[] getAcceptedChars() { 
     return new char[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
    } 
} 

A continuación, deberá mostrar los caracteres correctamente, pero eso no es difícil; solo haga un seguimiento de los centavos, y luego divida o multiplique por 10, y use un NumberFormat para obtener el formato correcto.

+2

KeyListener ya no funciona en algunos dispositivos, consulte esta nota: Las pulsaciones de teclas en los métodos de entrada suaves no son necesarios para activar los métodos de este oyente, y son, de hecho, desaniman a hacerlo. El teclado predeterminado de Android no los desencadenará para ninguna tecla de ninguna aplicación que apunte a Jelly Bean o más tarde, y solo lo entregará para algunas pulsaciones de teclas a las aplicaciones dirigidas a Ice Cream Sandwich o antes. Fuente: http://developer.android.com/reference/android/text/method/KeyListener.html –

1

Aquí está mi solución completa: solución completa

   tvValue.setRawInputType(Configuration.KEYBOARD_12KEY); 

      tvValue.addTextChangedListener(new TextWatcher(){ 


       @Override 
       public void afterTextChanged(Editable arg0) { 
        // TODO Auto-generated method stub 

       } 

       @Override 
       public void beforeTextChanged(CharSequence s, int start, 
         int count, int after) { 
        // TODO Auto-generated method stub 

       } 

       @Override 
       public void onTextChanged(CharSequence s, int start, 
         int before, int count) { 
        // TODO Auto-generated method stub 

        // here i converted to string 
        if(!s.toString().matches("^\\$(\\d{1,3}(\\,\\d{3})*|(\\d+))(\\.\\d{2})?$")) 
        { 
         String userInput= ""+s.toString().replaceAll("[^\\d]", ""); 
         Float in=Float.parseFloat(userInput); 
         float percen = in/100; 
         tvValue.setText("$"+percen); 
        } 

       } 

      }); 
8

de ninjasense trabaja básicamente, pero tiene algunos problemas:

  1. Cada vez que los datos del campo se altera en el "OnTextChanged" manipulador, la posición del cursor se restablece al índice 0 en el campo, lo cual es un poco molesto cuando se ingresan los valores monetarios.
  2. Utiliza flotadores para formatear valores monetarios, lo que puede ser contraproducente.

Para el primer problema que no tengo solución, sin embargo, para el segundo código como este funciona:

@Override 
    public void onTextChanged(CharSequence s, int start, 
      int before, int count) { 
     if(!s.toString().matches("^\\$(\\d{1,3}(\\,\\d{3})*|(\\d+))(\\.\\d{2})?$")) 
     { 
      String userInput= ""+s.toString().replaceAll("[^\\d]", ""); 
      StringBuilder cashAmountBuilder = new StringBuilder(userInput); 

      while (cashAmountBuilder.length() > 3 && cashAmountBuilder.charAt(0) == '0') { 
       cashAmountBuilder.deleteCharAt(0); 
      } 
      while (cashAmountBuilder.length() < 3) { 
       cashAmountBuilder.insert(0, '0'); 
      } 
      cashAmountBuilder.insert(cashAmountBuilder.length()-2, '.'); 
      cashAmountBuilder.insert(0, '$'); 

      cashAmountEdit.setText(cashAmountBuilder.toString()); 
     } 

    } 
3

Construido a partir zds.

Para mantener el cursor al final del campo, utilícelo.

cashAmountEdit.setTextKeepState(cashAmountBuilder.toString()); 
Selection.setSelection(cashAmountEdit.getText(), cashAmountBuilder.toString().length()); 
0

Hice esto pero sin decimal y con punto por millas, verifique el código y agregue la funcionalidad para admitir decimales.

MyEditText.addTextChangedListener(new TextWatcher() 
     { 
      @Override 
      public void onTextChanged(CharSequence s, int start, int before, int count){ 
       if(s.toString().length() > 0){ 
        MyEditText.removeTextChangedListener(this);     
        String numbers = removeCharacters(s.toString()); 
        int money = 0; 
        try{ 
         money = Integer.parseInt(numbers); 
        } 
        catch(Exception ex){ 
         money = 0; 
        } 

        MyEditText.setText(getMoney(money)); 
        //Set cursor on correct position 
        int selection = start; 
        if(count > 0){ 
         selection++; 
         if(MyEditText.getText().toString().length() == 2 || MyEditText.getText().toString().length() == 6 || MyEditText.getText().toString().length() == 10){ 
          selection++; 
         }       
        } 
        else{ 
         if(MyEditText.getText().toString().length() == 4 || MyEditText.getText().toString().length() == 8){ 
          selection--; 
         } 
        } 

        if(selection > MyEditText.getText().toString().length()){ 
         selection = MyEditText.getText().toString().length(); 
        }      

        MyEditText.setSelection(selection); 
        MyEditText.addTextChangedListener(this); 
       } 
       if(s.toString().length() == 1 && count < 1 && start == 1){ 
        MyEditText.removeTextChangedListener(this); 
        MyEditText.setText(""); 
        MyEditText.addTextChangedListener(this); 
       } 

      }   

      @Override 
      public void beforeTextChanged(CharSequence s, int start, int count, 
        int after){ 

      }   

      @Override 
      public void afterTextChanged(Editable s) 
      { 

      } 

     }); 



    public String removeCharacters(String money){  

    int i=0; 
    while (i<money.length()) 
    { 
     Character c = money.charAt(i);   
      if (Character.isDigit(c) && c != '.') 
      {    
       i++; 
      } 
      else 
      {    
       money = money.replace(c.toString(), "");     
      } 
    } 

    return money; 
} 


public String getMoney(int value){ 
    String money = "$"; 
    NumberFormat numberFormatter;  
    numberFormatter = NumberFormat.getNumberInstance(Locale.GERMAN);   
    money += numberFormatter.format(value); 

    return money; 
} 
0

Esta respuesta se basa en Zds' answer (que a su vez se basa en ninjasense's answer), pero esto debería resolver el problema posición del cursor:

if(!text.matches("^\\$(\\d{1,2})(\\.\\d{2})?$")) { 
    int originalCursorPosition = view.getSelectionStart(); 
    int cursorOffset = 0; 

    boolean cursorAtEnd = originalCursorPosition == text.length(); 

    String userInput= ""+text.replaceAll("[^\\d]", ""); 
    StringBuilder cashAmountBuilder = new StringBuilder(userInput); 

    while (cashAmountBuilder.length() > 3 && cashAmountBuilder.charAt(0) == '0')   { 
     cashAmountBuilder.deleteCharAt(0); 
     cursorOffset--; 
    } 
    while (cashAmountBuilder.length() < 3) { 
     cashAmountBuilder.insert(0, '0'); 
     cursorOffset++; 
    } 
    cashAmountBuilder.insert(cashAmountBuilder.length() - 2, '.'); 
    cashAmountBuilder.insert(0, '$'); 

    view.setText(cashAmountBuilder.toString()); 
    view.setSelection(cursorAtEnd ? view.getText().length() : originalCursorPosition + cursorOffset); 
} 

Notas:

  • El siguiente es en un TextWatcher.onTextChanged
  • Estoy usando un diferente expresiones regulares que otras respuestas, que mantiene el precio a $ 100 <
  • 'vista' es la EDITTEXT, 'texto' es el contenido de la cadena
  • esto ha funcionado para mí utilizando un EditText con un maxLength de 6 (es decir, $ 00,00)
Cuestiones relacionadas