Máscara no EditText do android

Olá pessoal, estou tentando aplicar uma máscara de cpf no editText enquanto o usuário vai digitando.

Eu já tenho até o regex que valida isso, mas eu não quero validar depois que ele digitar, eu quero ir aplicando a máscara enquanto ele digita.
Tem como fazer isso com o InputFilter ou algo parecido, onde eu coloco o regex e ele vai aplicando? Alguém tem algum ideia?

valeu!

Olá!

Criei meu próprio MaskEditText. Vou compartilha-lo com todos. Espero que seja útil.

package com.mcavalini.lib;

import java.util.ArrayList;

public class Utils {

	public static int tamanhoMaximo(String mascara) {
		String novaString = removeCaracteresEspeciais(mascara);
		return novaString.length();
	}
	
	public static String removeCaracteresEspeciais(String str) {

	    String[] caracteresEspeciais = {"\\.", ",", "-", ":", "\\(", "\\)", "ª", "\\|", "\\\\", "°", "\\/"};

	    for (int i = 0; i < caracteresEspeciais.length; i++) {
	        str = str.replaceAll(caracteresEspeciais[i], "");
	    }

	    return str;
	}
	
	public static ArrayList<Separador> posicaoSeparadoresTexto(String mascara) {
		ArrayList<Separador> listaSeparadores = new ArrayList<Separador>();
		
		for (int i = 0; i < mascara.length(); i++) {
			if ( (mascara.substring(i, i+1).equals(new String(","))) ||
				 (mascara.substring(i, i+1).equals(new String("."))) ||
				 (mascara.substring(i, i+1).equals(new String("-"))) ||
				 (mascara.substring(i, i+1).equals(new String("/"))) ||
				 (mascara.substring(i, i+1).equals(new String("("))) ||
				 (mascara.substring(i, i+1).equals(new String(")")))) {
				listaSeparadores.add(new Separador(new Integer(i), mascara.substring(i, i+1)));
			}
		}
		
		return listaSeparadores;
	}
	
	public static String padString(String numero, int tamanhoMaximo, int tamanhoMascara, ArrayList<Separador> listaSeparadores) {
		String stringMascarada = "";
		boolean isPad = true;
		int indicePadString = 0;
		int indiceNumero = 0;
		int tamanhoNumero = numero.length();
		
		while (isPad) {
			for (Separador separador : listaSeparadores) {
				if (separador.getPosicao().intValue() == indicePadString) {
					stringMascarada += separador.getCaracter();
					indicePadString += 1;
					break;
				}
			}
			
			if ((indiceNumero < tamanhoMaximo) && (indiceNumero < tamanhoNumero) ) {
				stringMascarada += numero.substring(indiceNumero, indiceNumero+1);
			} 
			
			indicePadString += 1;
			indiceNumero += 1;
			
			if (indiceNumero >= tamanhoNumero)
				isPad = false;
		}
		
		return stringMascarada;
	}
}
package com.mcavalini.lib;

import android.text.InputType;
import android.text.method.NumberKeyListener;

public class KeyListenerNumber extends NumberKeyListener {

	public int getInputType() {
		return InputType.TYPE_CLASS_NUMBER | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
	}

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

}
package com.mcavalini.core;

import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.widget.EditText;

import com.mcavalini.lib.KeyListenerNumber;
import com.mcavalini.lib.Utils;

public class MaskEditText extends EditText {
	private String mascara;
	private int tamanhoMascara;
	private int tamanhoMaximo;

	private boolean isUpdating;

	private KeyListenerNumber keyListenerNumber;
	
	public static String CPF_MASK = "   .   .   -  ";
	public static String CEP_MASK = "     -   ";
	public static String TELEFONE_8DIGITOS_MASK = "(  )    -    ";
	
	public MaskEditText(Context context, AttributeSet attrs) {
		super(context, attrs);
	}	
	
	public int getTamanhoMascara() {
		return tamanhoMascara;
	}
	
	public void init(String mascara) {
		this.mascara = mascara;
		this.tamanhoMascara = mascara.length();
		this.tamanhoMaximo = Utils.tamanhoMaximo(mascara);
		
		keyListenerNumber = new KeyListenerNumber();
		this.setKeyListener(keyListenerNumber);
		this.setText("");
		
		this.addTextChangedListener(new TextWatcher() {
			
			public void onTextChanged(CharSequence s, int start, int before, int count) {
				
			}
			
			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
				
			}
			
			public void afterTextChanged(Editable s) {
				String stringAtual = s.toString();
				
				if (isUpdating) {
					isUpdating = false;
					return;
				}
				
				String numero = stringAtual.replaceAll("[^0-9]*", "");
				
				if (numero.length() > tamanhoMaximo)
					numero = numero.substring(0, tamanhoMaximo);
				
				String campo = Utils.padString(numero, tamanhoMaximo, tamanhoMascara, Utils.posicaoSeparadoresTexto(MaskEditText.this.mascara));
				
				isUpdating = true;
				
				MaskEditText.this.setText(campo);
				MaskEditText.this.setSelection(campo.length());
			}
		});
	}
}

Para declarar no XML de view utilize da seguinte maneira:

    <com.mcavalini.core.MaskEditText
        android:id="@+id/txtCpf"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
   		<requestFocus />   
    </com.mcavalini.core.MaskEditText>

E para recuperá-lo na activity:

        MaskEditText txtCpf = (MaskEditText) findViewById(R.id.txtCpf);
        txtCpf.init(MaskEditText.CPF_MASK);

Existe esse ‘init’ pois ainda não consegui fazer o android entender que meu componente pode ser parametrizavel pelo XML de layout.

Outro detalhe é que pode personalizar a mascará que necessitar, passando no init o formato. Por exemplo: Data: " / / ". Hora: " : : " E assim por diante … pode parecer precário, mas funciona. rsrs.

Esse componente já é utilizado por mim há algum tempo com sucesso e espero que sirva pro seu problema.

Abraço.

:shock: Muito Obrigado, :smiley:

O que é esse Objeto Separador que tem na linha 23? Não entendi do que se trata?

[code]public static ArrayList posicaoSeparadoresTexto(String mascara) {
ArrayList listaSeparadores = new ArrayList();

	for (int i = 0; i < mascara.length(); i++) {
		if ( (mascara.substring(i, i+1).equals(new String(","))) ||
			 (mascara.substring(i, i+1).equals(new String("."))) ||
			 (mascara.substring(i, i+1).equals(new String("-"))) ||
			 (mascara.substring(i, i+1).equals(new String("/"))) ||
			 (mascara.substring(i, i+1).equals(new String("("))) ||
			 (mascara.substring(i, i+1).equals(new String(")")))) {
			listaSeparadores.add(new Separador(new Integer(i), mascara.substring(i, i+1)));
		}
	}
	
	return listaSeparadores;
}[/code]