android android-edittext rotation mongolian-vertical-script

android - Vista editada del texto rotada personalizada con selección de trabajo, ubicación del cursor, etc.



android-edittext rotation (5)

Lo que quiero hacer

Quiero hacer una vista EditText girada y volteada que tenga todas las propiedades de una vista EditText normal.

Mi problema

He hecho con éxito (con mucha ayuda de los usuarios de SO) una vista personalizada de EditText que está rotada y volteada. Esto se hizo anulando el método onDraw. Sin embargo, el cursor y el resaltado han desaparecido y un evento de pulsación larga aún indica la posición del texto original. Básicamente, la vista fue redibujada pero los eventos táctiles no lo fueron.

¿Cómo puedo hacer que los eventos táctiles, el resaltado y el cursor también se giren y se giren?

Lo que he leído

Escala EditText con selección (un problema similar pero no el mismo).

Cómo hacer un texto de edición personalizado, de modo que se vea como un giro de 45 grados en android (@CommonsWare señaló que para una solución se debería hacer un trabajo de adición con eventos táctiles. ¿Qué es eso?)

http://developer.android.com/training/graphics/opengl/touch.html (Útil, pero no entiendo cómo aplicarlo en esta situación).

Lo que he intentado

Hice una vista personalizada que amplía EditText. En ella anuló el método onDraw para rotar y voltear el lienzo. Anulé onMeasure para que la vista tenga las dimensiones correctas para el diseño.

import android.content.Context; import android.graphics.Canvas; import android.graphics.Typeface; import android.text.TextPaint; import android.util.AttributeSet; import android.widget.EditText; public class MongolEditText extends EditText { // Constructors public MongolEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public MongolEditText(Context context, AttributeSet attrs) { super(context, attrs); init(); } public MongolEditText(Context context) { super(context); init(); } // This class requires the mirrored Mongolian font to be in the assets/fonts folder private void init() { Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "fonts/MongolChagaanMirrored.ttf"); setTypeface(tf); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(heightMeasureSpec, widthMeasureSpec); setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth()); } @Override protected void onDraw(Canvas canvas) { TextPaint textPaint = getPaint(); textPaint.setColor(getCurrentTextColor()); textPaint.drawableState = getDrawableState(); canvas.save(); canvas.translate(getWidth(), 0); canvas.rotate(90); canvas.translate(0, getWidth()); canvas.scale(1, -1); canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop()); getLayout().draw(canvas); canvas.restore(); } }

No hay nada especial para el diseño xml.

(Actualización) Esta pregunta es otro intento, pero al final no pude hacer que funcione: ¿Es necesario invalidar invalidateDrawable () además de onDraw ()?

Explicación adicional

En caso de que se esté preguntando por qué motivo del mundo quiero rotar y voltear una vista de Edición de Texto, esta es la razón. El mongol tradicional se escribe verticalmente en las columnas de izquierda a derecha. En combinación con una fuente mongol reflejada verticalmente, girar el texto 90 grados en el sentido de las agujas del reloj y voltearlo produce resultados legibles con el ajuste de línea correcto.

Este no es un problema oscuro o aislado. Hay millones de usuarios de mongoles tradicionales pero muy pocas aplicaciones de Android. De estos, no he encontrado ninguno que sea de código abierto. Si puedo hacer que esto funcione, quiero que el código esté disponible para otros desarrolladores.

Donde estoy mirando ahora

(actualizar)

Estaba pensando en crear una vista personalizada (que extiende la View ) desde cero para crear algo como un TextView . Este TextView podría actualizarse desde aplicaciones para actuar como una vista EditText . En este caso, solo necesitaría rotar el texto 90 grados con una fuente normal pero no voltearlo. Sin embargo, tendría que hacer mi propia línea de ajuste.

Sin embargo, después de leer la respuesta de @ Chitrang, creo que puedo hacer algo similar simplemente extendiendo un TextView. Entonces puedo evitar la molestia de hacer mi propia línea de envoltura.

Actualización de la imagen

El mongol se escribe de arriba a abajo y de izquierda a derecha. En este momento estoy usando este teclado para mover un cursor alrededor del texto, pero me gustaría poder tocar la pantalla para mover el cursor a una posición.


Actualizar

Terminé desarrollando un script vertical MongolEditText desde cero. Está disponible como parte de mongol-library .

Aquí se está utilizando con dos teclados de terceros diferentes.

Vieja respuesta

Este es todavía un trabajo en progreso, así que no marcaré esto como resuelto todavía, pero permítame publicar lo que tengo hasta ahora. Hace la mayor parte de lo que quería hacer. Básicamente, estoy usando TextView en lugar de EditText porque EditText estaba haciendo muchas cosas extrañas cuando se rotaba.

Tengo un cursor que no parpadea que responde a eventos táctiles, pero aún no se admite el resaltado. Aquí está el código:

public class MongolTextView extends TextView { private TextPaint textPaint; private Paint cursorPaint = new Paint(); private boolean mCursorIsVisible; private CursorTouchLocationListener listener; // Naming is based on pre-rotated/mirrored values private float mCursorBaseY; private float mCursorBottomY; private float mCursorAscentY; // This is a negative number private float mCursorX; private static final float CURSOR_THICKNESS = 2f; // Constructors public MongolTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public MongolTextView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public MongolTextView(Context context) { super(context); init(); } // This class requires the mirrored Mongolian font to be in the assets/fonts folder private void init() { //Typeface tf = Typeface.createFromAsset(getContext().getAssets(), // "fonts/ChimeeWhiteMirrored.ttf"); //setTypeface(tf); // Use the above commented code is using a single font in another application Typeface tf = FontCache.get(SettingsActivity.FONT_DEFAULT, getContext()); if(tf != null) { setTypeface(tf); } this.mCursorIsVisible = true; cursorPaint.setStrokeWidth(CURSOR_THICKNESS); cursorPaint.setColor(Color.BLACK); // TODO should be same as text color } // This interface may be deleted if touch functionality is not needed public interface CursorTouchLocationListener { /** * Returns the touch location to be used for the cursor so you can update the insert * location in a text string. * * @param glyphIndex * You will need to translate glyphIndex into a Unicode index if you are using a * Unicode string. */ public void onCursorTouchLocationChanged(int glyphIndex); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // swap the height and width super.onMeasure(heightMeasureSpec, widthMeasureSpec); setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth()); } @Override protected void onDraw(Canvas canvas) { textPaint = getPaint(); textPaint.setColor(getCurrentTextColor()); textPaint.drawableState = getDrawableState(); canvas.save(); // flip and rotate the canvas canvas.translate(getWidth(), 0); canvas.rotate(90); canvas.translate(0, getWidth()); canvas.scale(1, -1); canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop()); // draw the cursor if (mCursorIsVisible) { canvas.drawLine(mCursorX, mCursorBottomY, mCursorX, mCursorBaseY + mCursorAscentY, cursorPaint); } getLayout().draw(canvas); canvas.restore(); } public void showCursor(boolean visible) { mCursorIsVisible = visible; this.invalidate(); // TODO make the cursor blink } public void setCursorColor(int color) { cursorPaint.setColor(color); } public void setCursorLocation(int characterOffset) { Layout layout = this.getLayout(); if (layout!=null){ try { // This method is giving a lot of crashes so just surrounding with // try catch for now int line = layout.getLineForOffset(characterOffset); mCursorX = layout.getPrimaryHorizontal(characterOffset); mCursorBaseY = layout.getLineBaseline(line); mCursorBottomY = layout.getLineBottom(line); mCursorAscentY = layout.getLineAscent(line); this.invalidate(); } catch (Exception e) { e.printStackTrace(); } } } public class InputWindowTouchListener implements OnTouchListener { @Override public boolean onTouch(View view, MotionEvent event) { Layout layout = ((TextView) view).getLayout(); // swapping x and y for touch events int y = (int) event.getX(); int x = (int) event.getY(); if (layout != null) { int line = layout.getLineForVertical(y); int offset = layout.getOffsetForHorizontal(line, x); mCursorX = layout.getPrimaryHorizontal(offset); mCursorBaseY = layout.getLineBaseline(line); mCursorBottomY = layout.getLineBottom(line); mCursorAscentY = layout.getLineAscent(line); //mCursorHeightY = layout.getLineTop(line); view.invalidate(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: //handler.postDelayed(mLongPressed, 1000); listener.onCursorTouchLocationChanged(offset); break; case MotionEvent.ACTION_UP: //handler.removeCallbacks(mLongPressed); // notify the host activity of the new cursor location break; } } return false; } } public void setCursorTouchLocationListener(CursorTouchLocationListener listener) { this.listener = listener; } }

Siéntase libre de agregar su propia respuesta si tiene algo mejor o haga un comentario si tiene algo que agregar para mejorar esto (agregando resaltado, haciendo que el cursor parpadee, etc.). La versión más reciente de este código debe estar en github .


Hay un atributo para el EditText para la rotación. Es simple y fácil de usar. Creo que podría ayudarte.

<EditText android:id="@+id/editTextNumber" android:layout_width="fill_parent" android:layout_height="wrap_content" android:rotation="90" android:layout_marginBottom="10dp" android:hint="Enter Mobile Number" android:textAppearance="?android:attr/textAppearanceLarge" />


Intenté obtener la solución parcial con cambios menores, verifica si eso es lo que quieres.

1) Establezca android: gravity = "top | left" en su declaración de texto editado dentro de xml.

2) Notó que, sin el súper método, llama al método onDraw, no se puede mostrar el cursor . Así que llamé,

super.onDraw(canvas);

en lugar,

getLayout().draw(canvas);

3) Para eventos táctiles , intenté intercambiar las coordenadas x e y. Para que puedas tener el cursor según el evento táctil (solo lo intenté y funcionó, tuve suerte :))

@Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub event.setLocation(event.getY(), event.getX()); return super.onTouchEvent(event); }

Comente esta línea dentro del método onDraw, para el evento táctil exacto (encontrado por prueba y error).

canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());

4) No pude hacer nada para resaltar o seleccionar texto.

?) Otra solución: si crees que, de alguna manera, la forma en que obtienes el soporte de lenguaje RTL funciona en edittext, solo necesitas rotarlo. Pero lamentablemente no funciona correctamente con Android. Referencia: ¿Cómo manejar los idiomas RTL en versiones anteriores a 4.2 de Android? y la configuración de Android con TextView para texto en hebreo?


Las cosas son mucho más simples. Todo lo que necesita ya está incorporado. Vea la clase: http://developer.android.com/reference/android/view/View.html#setRotation(float) Una solución un poco más complicada si la anterior no funcionara para usted. la razón es: http://developer.android.com/reference/android/view/animation/RotateAnimation.html También se usa para la rotación de vistas (pero animado en la mayoría de los casos, sin embargo, se puede usar con una duración de transición cero).

Por favor, avíseme si tiene preguntas adicionales (suponga que no, hay un método y una clase de autoexplicación).

Girando solo un lienzo, girando solo la imagen en la pantalla. setRotation también maneja todos los eventos, el flujo de diseño, etc. ¡así que debería funcionar bien en su caso!

Espero que ayude!


Prueba esto:

<EditText android:id="@+id/ed1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/textView1" android:layout_centerHorizontal="true" android:layout_marginTop="47dp" android:digits="1234567890" android:ems="10" android:singleLine="true" android:cursorVisible="true" android:hint="Refreshing time in ms" />