2011-07-08 13 views
7

Tengo un EditText. Ahora quiero obtener todos los cambios realizados por el usuario en este EditText y trabajar con ellos antes de insertarlos manualmente en el EditText. No deseo que el usuario cambie directamente el texto en el EditText. Esto solo debe hacerlo mi código (por ejemplo, usando replace() o setText()).Cómo usar InputConnectionWrapper?

Busqué un poco y encontré una clase interesante llamada InputConnectionWrapper. De acuerdo con el javadoc actuará como un proxy para un dado InputConnection. Así que una subclase de esta manera:

private class EditTextInputConnection extends InputConnectionWrapper { 

    public EditTextInputConnection(InputConnection target, boolean mutable) { 
     super(target, mutable); 
    } 

    @Override 
    public boolean commitText(CharSequence text, int newCursorPosition) { 
        // some code which takes the input and manipulates it and calls editText.getText().replace() afterwards 
     return true; 
    } 

} 

Para inicializar la envoltura I sobreescribí el siguiente método en mi EditText -subclass:

public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 
    InputConnection con = super.onCreateInputConnection(outAttrs); 
    EditTextInputConnection connectionWrapper = new EditTextInputConnection(con, true); 
    return connectionWrapper; 
} 

Sin embargo, no se llama a commitText(). El onCreateInputConnection() es llamado y el constructor de EditTextInputConnection también, pero nunca commitText(), Altough debe ser, cuando entro en algún texto en el campo. Al menos, así entiendo el uso de InputConnectionWrapper. ¿O estoy equivocado?

Editar: " 'Parece, que commitText() sólo se le llama para caracteres especiales como,'", etc. A mi entender el código fuente de Android para todos los demás caracteres InputConnectionWrapper.sendKeyEvent() debería ser llamado, pero ese no es el caso .. Estoy absolutamente estancado en este punto. Ya probé EditText.onKeyPreIme(), pero esto solo funciona en teclados de hardware. Entonces no hay alternativa ... Realmente no entiendo, por qué Android maneja teclados suaves que son diferentes de los teclados de hardware. EditText.onTextChanged() también se dispara en la entrada de no usuario, por lo que esto tampoco es lo que estoy buscando.

Respuesta

5

Resultó que el uso anterior del InputConnectionWrapper era totalmente correcto. Sin embargo, commitText() nunca se llama (excepto en casos especiales), ya que hay otros métodos que se utilizan durante el tipeo. Estos son principalmente setComposingText() y sendKeyEvent(). Sin embargo, también es importante sobrescribir los métodos que rara vez se usan, como deleteSurroundingText() o commitText() para asegurarse de capturar cada entrada del usuario.

+1

Esto no impide que el usuario copie y pegue texto aleatorio en EditText, pero funciona para todo lo demás. – Alexey

+0

@Alexey Eso es correcto, buen punto. – ubuntudroid

+0

@ubuntudroid Hola, ¿sabes qué métodos se deben sobrescribir para capturar todas las entradas? Incluyendo copiar pegar. –

1

Blundell sugirió en el chat que utiliza un TextWatcher. Verifica si esto te ayuda.

+0

El problema con un TextWatcher es, que no puedo determinar la fuente de entrada de allí (es decir, la entrada de teclado o de entrada directamente de mi código). También sería notificado, si cambiara el texto por EditText.getText(). Replace() o EditText.setText(), supongo. – ubuntudroid

+0

No estoy seguro, ¿lo has probado? –

+0

Debería ser así, como getText(). Replace()/insert() opera directamente en el Editable detrás de EditText. Por lo tanto, se notificará al TextWatcher que rastrea los cambios del Editable en cualquier cambio del Editable. Actualmente estoy trabajando en otra solución que incorpora una subclase de métodos editables y especiales para acceder a ella desde el código y métodos sobrescritos para insert() y replace(). Publicaré mis hallazgos aquí una vez que esté hecho. – ubuntudroid

0

Usa un TextWatcher, desconéctalo cuando estés modificando tu texto de edición y vuelve a conectarlo cuando hayas terminado. De esta manera, no activará llamadas infinitas.