Necesito 2 formas de mostrar vertical de la etiqueta en Android:

  1. Etiqueta Horizontal al girar 90 grados hacia la izquierda (las letras en el lado)
  2. Horizontal de la etiqueta con las letras una debajo de la otra (como una tienda signo)

Necesito para desarrollar widgets personalizados para ambos casos (un caso), ¿puedo hacer TextView para representar de esa manera, y lo que sería una buena manera de hacer algo como que si tengo que ir completamente personalizado?

InformationsquelleAutor Bostone | 2009-08-11

9 Comentarios

  1. 232

    Aquí está mi elegante y simple vertical de texto de la aplicación, que se extiende TextView. Esto significa que todos los estilos estándar de TextView puede ser utilizado, ya que se extiende TextView.

    public class VerticalTextView extends TextView{
       final boolean topDown;
    
       public VerticalTextView(Context context, AttributeSet attrs){
          super(context, attrs);
          final int gravity = getGravity();
          if(Gravity.isVertical(gravity) && (gravity&Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
             setGravity((gravity&Gravity.HORIZONTAL_GRAVITY_MASK) | Gravity.TOP);
             topDown = false;
          }else
             topDown = true;
       }
    
       @Override
       protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
          super.onMeasure(heightMeasureSpec, widthMeasureSpec);
          setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
       }
    
       @Override
       protected boolean setFrame(int l, int t, int r, int b){
          return super.setFrame(l, t, l+(b-t), t+(r-l));
       }
    
       @Override
       public void draw(Canvas canvas){
          if(topDown){
             canvas.translate(getHeight(), 0);
             canvas.rotate(90);
          }else {
             canvas.translate(0, getWidth());
             canvas.rotate(-90);
          }
          canvas.clipRect(0, 0, getWidth(), getHeight(), android.graphics.Region.Op.REPLACE);
          super.draw(canvas);
       }
    }

    De forma predeterminada, el texto girado es de arriba a abajo. Si establece android:gravity=»fondo», a continuación, se dibuja desde la parte inferior a la parte superior.

    Técnicamente, es de tontos subyacente TextView a pensar que es normal que la rotación (cambiando la anchura/altura en algunos lugares), mientras que el trazado de la gira.
    Funciona bien también cuando se utiliza en un xml de diseño.

    EDICIÓN:
    publicar otra versión, la de arriba tiene problemas con las animaciones. Esta nueva versión funciona mejor, pero pierde un poco el TextView características, tales como marquesinas y similares especialidades.

    public class VerticalTextView extends TextView{
       final boolean topDown;
    
       public VerticalTextView(Context context, AttributeSet attrs){
          super(context, attrs);
          final int gravity = getGravity();
          if(Gravity.isVertical(gravity) && (gravity&Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
             setGravity((gravity&Gravity.HORIZONTAL_GRAVITY_MASK) | Gravity.TOP);
             topDown = false;
          }else
             topDown = true;
       }
    
       @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();
    
          if(topDown){
             canvas.translate(getWidth(), 0);
             canvas.rotate(90);
          }else {
             canvas.translate(0, getHeight());
             canvas.rotate(-90);
          }
    
    
          canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
    
          getLayout().draw(canvas);
          canvas.restore();
      }
    }
    • Su solución deshabilita enlaces en TextView. En realidad, los enlaces están subrayados, pero no responde en haga clic en.
    • Hola Ratones, la Gran solución, gracias, por favor, ¿puede explicar por qué las correcciones que se hacen en la versión fija. Muy apreciado. M
    • Alguien ha experimentado problemas en la parte superior y la parte inferior de relleno?
    • Intencional, porque estamos girando.
    • considerar comentario para onMeasure como: el uso de la superclase de medición y cambiar la anchura/altura de medidas
    • No, eso es como el truco está hecha para trabajar. Pensar un poco sobre ello.
    • este tiene problemas con varias líneas y barras de desplazamiento.
    • lo siento por mi pregunta, Si tengo un TextView (en un archivo XML) y quiero girar, cómo hacer una llamada de VerticalTextView clase?
    • en lugar de <TextView> etiquetas, utilice una vista personalizada de la etiqueta: <com.YOUR_PACKAGE_NAME.VerticalTextView>
    • no se puede crear la vista mediante programación, cdu no tiene un constructor sólo con el contexto
    • no funciona en la vista de lista, el texto no se puede mostrar en la vista
    • El último código es buena. A la hora de crear un VerticalTextView en .archivo xml, usted puede agregar algunos valores como: android:width=»150dp» android:layout_height=»150dp», android:ellipsize= «final», android:maxLines=»1″. Si el texto es un texto largo, se mostrarán los 3 puntos (…)
    • funciona muy bien, en mi caso he tenido que ampliar android.apoyo.v7.widget.AppCompatTextView en lugar de TextView para realizar mi atributo de estilo de trabajo
    • Cuando tengo una cadena como esta «Valor: 20%», el porcentaje y el número siempre son atraídos superponen unos a otros. No puedo entender por qué.
    • tengo esta excepción con androidx java.lang.IllegalArgumentException: No Válido Región.Op – sólo se CRUZAN y la DIFERENCIA son permitidos VerticalTextView.java:44

  2. 31

    He implementado esta para mi ChartDroid proyecto. Crear VerticalLabelView.java:

    public class VerticalLabelView extends View {
    private TextPaint mTextPaint;
    private String mText;
    private int mAscent;
    private Rect text_bounds = new Rect();
    final static int DEFAULT_TEXT_SIZE = 15;
    public VerticalLabelView(Context context) {
    super(context);
    initLabelView();
    }
    public VerticalLabelView(Context context, AttributeSet attrs) {
    super(context, attrs);
    initLabelView();
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VerticalLabelView);
    CharSequence s = a.getString(R.styleable.VerticalLabelView_text);
    if (s != null) setText(s.toString());
    setTextColor(a.getColor(R.styleable.VerticalLabelView_textColor, 0xFF000000));
    int textSize = a.getDimensionPixelOffset(R.styleable.VerticalLabelView_textSize, 0);
    if (textSize > 0) setTextSize(textSize);
    a.recycle();
    }
    private final void initLabelView() {
    mTextPaint = new TextPaint();
    mTextPaint.setAntiAlias(true);
    mTextPaint.setTextSize(DEFAULT_TEXT_SIZE);
    mTextPaint.setColor(0xFF000000);
    mTextPaint.setTextAlign(Align.CENTER);
    setPadding(3, 3, 3, 3);
    }
    public void setText(String text) {
    mText = text;
    requestLayout();
    invalidate();
    }
    public void setTextSize(int size) {
    mTextPaint.setTextSize(size);
    requestLayout();
    invalidate();
    }
    public void setTextColor(int color) {
    mTextPaint.setColor(color);
    invalidate();
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    mTextPaint.getTextBounds(mText, 0, mText.length(), text_bounds);
    setMeasuredDimension(
    measureWidth(widthMeasureSpec),
    measureHeight(heightMeasureSpec));
    }
    private int measureWidth(int measureSpec) {
    int result = 0;
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);
    if (specMode == MeasureSpec.EXACTLY) {
    //We were told how big to be
    result = specSize;
    } else {
    //Measure the text
    result = text_bounds.height() + getPaddingLeft() + getPaddingRight();
    if (specMode == MeasureSpec.AT_MOST) {
    //Respect AT_MOST value if that was what is called for by measureSpec
    result = Math.min(result, specSize);
    }
    }
    return result;
    }
    private int measureHeight(int measureSpec) {
    int result = 0;
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);
    mAscent = (int) mTextPaint.ascent();
    if (specMode == MeasureSpec.EXACTLY) {
    //We were told how big to be
    result = specSize;
    } else {
    //Measure the text
    result = text_bounds.width() + getPaddingTop() + getPaddingBottom();
    if (specMode == MeasureSpec.AT_MOST) {
    //Respect AT_MOST value if that was what is called for by measureSpec
    result = Math.min(result, specSize);
    }
    }
    return result;
    }
    @Override
    protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    float text_horizontally_centered_origin_x = getPaddingLeft() + text_bounds.width()/2f;
    float text_horizontally_centered_origin_y = getPaddingTop() - mAscent;
    canvas.translate(text_horizontally_centered_origin_y, text_horizontally_centered_origin_x);
    canvas.rotate(-90);
    canvas.drawText(mText, 0, 0, mTextPaint);
    }
    }

    Y en attrs.xml:

    <resources>
    <declare-styleable name="VerticalLabelView">
    <attr name="text" format="string" />
    <attr name="textColor" format="color" />
    <attr name="textSize" format="dimension" />
    </declare-styleable>
    </resources>
  3. 9

    Una forma de lograr estos serían:

    1. Escribir su propio personalizado ver y reemplazar onDraw(Canvas). puede dibujar el texto en el lienzo y, a continuación, girar el lienzo.
    2. Igual a 1. excepto que esta vez el uso de un Camino y dibujar texto utilizando drawTextOnPath(…)
    • Así que antes de ir por ese camino (miré en el método onDraw para TextView – es enorme) me di cuenta de que toda la diferencia entre TextView y la ampliación de Botón es un estilo de IDENTIFICACIÓN (com.android.interna.R.attr.buttonStyle) Sería posible simplemente definir un estilo personalizado y extender TextView similar al Botón? Supongo que la respuesta sería no, ya que probablemente no sea posible el texto del estilo de diseño vertical
    • ¿Este enfoque en realidad? Yo no he tenido éxito y no tiene este tipo… osdir.com/ml/Android-Developers/2009-11/msg02810.html
    • 2. drawTextOnPath() dibuja el texto como fue girado, igual a 1. Para escribir cartas uno en el otro, ya sea de uso \n después de cada carácter o si usted tiene una fuente de ancho fijo, límite de la TextView ancho para adaptarse a un solo personaje.
  4. 7

    Intentado tanto de la VerticalTextView clases en la aprobación de respuesta, y que ha funcionado razonablemente bien.

    Pero no importa lo que he intentado, no he podido posición de los VerticalTextViews en el centro de la que contiene el diseño (un RelativeLayout que es parte de un elemento inflados por un RecyclerView).

    Por lo que vale, después de mirar alrededor, me encontré con yoog568 del VerticalTextView clase en GitHub:

    https://github.com/yoog568/VerticalTextView/blob/master/src/com/yoog/widget/VerticalTextView.java

    que pude hasta la posición deseada. También deberá incluir los siguientes atributos de definición de su proyecto:

    https://github.com/yoog568/VerticalTextView/blob/master/res/values/attr.xml

    • He encontrado esta aplicación es realmente fácil!
  5. 3
    check = (TextView)findViewById(R.id.check);
    check.setRotation(-90);

    Esto funcionó para mí, muy bien. Como para la vertical que va abajo de las letras – yo no sé.

    • pero incluso toma el espacio en horizontal, y girar verticalmente
  6. 2

    Hay algunas cosas que hay que prestar atención en el.

    Depende de el juego de caracteres cuando la elección de la rotación o la ruta de acceso maneras. por ejemplo, si el conjunto de caracteres de destino es el inglés como, y el efecto esperado parece,

    a
    b
    c
    d

    usted puede conseguir este efecto mediante el dibujo de cada uno de los caracteres uno por uno, no gire o la ruta de acceso necesarios.

    Vertical (girado) etiqueta en Android

    usted puede necesitar girar o camino para llegar a este efecto.

    la parte difícil es cuando se intenta representar un conjunto de caracteres, tales como el mongol. el glifo en el tipo de Letra necesidad de ser girado 90 grados, por lo que drawTextOnPath() será un buen candidato para su uso.

    • ¿Cómo se puede hacer revés de izquierda a Derecha
    • textview.setTextDirection(Ver.TEXT_DIRECTION_RTL) o textview.setTextDirection(Ver.TEXT_DIRECTION_ANY_RTL) puede funcionar por encima de la API de nivel 17. usted puede probarlo.
  7. 1

    Siguientes Puntero Null‘s respuesta, he sido capaz de centrar el texto horizontalmente mediante la modificación de la onDraw método de esta manera:

    @Override
    protected void onDraw(Canvas canvas){
    TextPaint textPaint = getPaint();
    textPaint.setColor(getCurrentTextColor());
    textPaint.drawableState = getDrawableState();
    canvas.save();
    if(topDown){
    canvas.translate(getWidth()/2, 0);
    canvas.rotate(90);
    }else{
    TextView temp = new TextView(getContext());
    temp.setText(this.getText().toString());
    temp.setTypeface(this.getTypeface());
    temp.measure(0, 0);
    canvas.rotate(-90);
    int max = -1 * ((getWidth() - temp.getMeasuredHeight())/2);
    canvas.translate(canvas.getClipBounds().left, canvas.getClipBounds().top - max);
    }
    canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
    getLayout().draw(canvas);
    canvas.restore();
    }

    Usted puede ser que necesite para agregar una porción de la TextView measuredWidth a un centro de multilined texto.

  8. 1

    Puede añadir a su TextView o Vista xml valor de rotación. Esta es la manera más fácil y para mí el trabajo correcto.

    <LinearLayout
    android:rotation="-90"
    android:layout_below="@id/image_view_qr_code"
    android:layout_above="@+id/text_view_savva_club"
    android:layout_marginTop="20dp"
    android:gravity="bottom"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <TextView
    android:textColor="@color/colorPrimary"
    android:layout_marginStart="40dp"
    android:textSize="20sp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Дмитриевский Дмитрий Дмитриевич"
    android:maxLines="2"
    android:id="@+id/vertical_text_view_name"/>
    <TextView
    android:textColor="#B32B2A29"
    android:layout_marginStart="40dp"
    android:layout_marginTop="15dp"
    android:textSize="16sp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/vertical_text_view_phone"
    android:text="+38 (000) 000-00-00"/>
    </LinearLayout>

    Vertical (girado) etiqueta en Android

  9. 0

    Me gustó @kostmo del enfoque. La he modificado un poco, porque tenía un problema – cortar girar verticalmente de la etiqueta cuando me ajustar sus parámetros como WRAP_CONTENT. Por lo tanto, un texto no es totalmente visible.

    Esto es cómo lo resolví:

    import android.annotation.TargetApi;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.graphics.Typeface;
    import android.os.Build;
    import android.text.TextPaint;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.util.TypedValue;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    public class VerticalLabelView extends View
    {
    private final String LOG_TAG           = "VerticalLabelView";
    private final int    DEFAULT_TEXT_SIZE = 30;
    private int          _ascent           = 0;
    private int          _leftPadding      = 0;
    private int          _topPadding       = 0;
    private int          _rightPadding     = 0;
    private int          _bottomPadding    = 0;
    private int          _textSize         = 0;
    private int          _measuredWidth;
    private int          _measuredHeight;
    private Rect         _textBounds;
    private TextPaint    _textPaint;
    private String       _text             = "";
    private TextView     _tempView;
    private Typeface     _typeface         = null;
    private boolean      _topToDown = false;
    public VerticalLabelView(Context context)
    {
    super(context);
    initLabelView();
    }
    public VerticalLabelView(Context context, AttributeSet attrs)
    {
    super(context, attrs);
    initLabelView();
    }
    public VerticalLabelView(Context context, AttributeSet attrs, int defStyleAttr)
    {
    super(context, attrs, defStyleAttr);
    initLabelView();
    }
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public VerticalLabelView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
    {
    super(context, attrs, defStyleAttr, defStyleRes);
    initLabelView();
    }
    private final void initLabelView()
    {
    this._textBounds = new Rect();
    this._textPaint = new TextPaint();
    this._textPaint.setAntiAlias(true);
    this._textPaint.setTextAlign(Paint.Align.CENTER);
    this._textPaint.setTextSize(DEFAULT_TEXT_SIZE);
    this._textSize = DEFAULT_TEXT_SIZE;
    }
    public void setText(String text)
    {
    this._text = text;
    requestLayout();
    invalidate();
    }
    public void topToDown(boolean topToDown)
    {
    this._topToDown = topToDown;
    }
    public void setPadding(int padding)
    {
    setPadding(padding, padding, padding, padding);
    }
    public void setPadding(int left, int top, int right, int bottom)
    {
    this._leftPadding = left;
    this._topPadding = top;
    this._rightPadding = right;
    this._bottomPadding = bottom;
    requestLayout();
    invalidate();
    }
    public void setTextSize(int size)
    {
    this._textSize = size;
    this._textPaint.setTextSize(size);
    requestLayout();
    invalidate();
    }
    public void setTextColor(int color)
    {
    this._textPaint.setColor(color);
    invalidate();
    }
    public void setTypeFace(Typeface typeface)
    {
    this._typeface = typeface;
    this._textPaint.setTypeface(typeface);
    requestLayout();
    invalidate();
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
    try
    {
    this._textPaint.getTextBounds(this._text, 0, this._text.length(), this._textBounds);
    this._tempView = new TextView(getContext());
    this._tempView.setPadding(this._leftPadding, this._topPadding, this._rightPadding, this._bottomPadding);
    this._tempView.setText(this._text);
    this._tempView.setTextSize(TypedValue.COMPLEX_UNIT_PX, this._textSize);
    this._tempView.setTypeface(this._typeface);
    this._tempView.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    this._measuredWidth = this._tempView.getMeasuredHeight();
    this._measuredHeight = this._tempView.getMeasuredWidth();
    this._ascent = this._textBounds.height() / 2 + this._measuredWidth / 2;
    setMeasuredDimension(this._measuredWidth, this._measuredHeight);
    }
    catch (Exception e)
    {
    setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
    Log.e(LOG_TAG, Log.getStackTraceString(e));
    }
    }
    @Override
    protected void onDraw(Canvas canvas)
    {
    super.onDraw(canvas);
    if (!this._text.isEmpty())
    {
    float textHorizontallyCenteredOriginX = this._measuredHeight / 2f;
    float textHorizontallyCenteredOriginY = this._ascent;
    canvas.translate(textHorizontallyCenteredOriginY, textHorizontallyCenteredOriginX);
    float rotateDegree = -90;
    float y = 0;
    if (this._topToDown)
    {
    rotateDegree = 90;
    y = this._measuredWidth / 2;
    }
    canvas.rotate(rotateDegree);
    canvas.drawText(this._text, 0, y, this._textPaint);
    }
    }
    }

    Si quieres tener un texto de arriba a abajo, a continuación, utilizar topToDown(true) método.

Dejar respuesta

Please enter your comment!
Please enter your name here