Intereting Posts
Компиляция Google Download Library, ориентированная на API 23 Android Marshmallow Android конвертировать ширину текста (в пикселях) в проценты от ширины / высоты экрана Как отобразить вывод console.log () в приложении PhoneGap с использованием Eclipse и HTC Desire HD? Как установить вид изображения в диалоговом окне андроида? Android Hello GridView Tutorial не отображает изображения Как удалить прописку из горизонтальной штриховки mpandroidchart? Арабский номер в арабском тексте на Android Android: получить текущее местоположение пользователя без использования gps или Интернета Как использовать RenderScript с SurfaceView / View Сброс значения Textview при изменении фрагмента Карты Android – использование макета в качестве элемента наложения Являются ли Android Geofences активными до удаления / истечения срока действия или только до тех пор, пока не будет запущен мой PendingIntent Автоматическое публикация приложения Beta Android в магазине Google Play Обнаружение, если ключи доступны на экранной клавиатуре мобильного устройства Как назначить уникальные идентификаторы динамически созданным представлениям?

Вертикальная (повернутая) этикетка в Android

Мне нужно два способа показать вертикальную метку в Android:

  1. Горизонтальная метка повернута на 90 градусов против часовой стрелки (буквы сбоку)
  2. Горизонтальная метка с буквами одна под другой (например, знак магазина)

Нужно ли мне разрабатывать пользовательские виджеты для обоих случаев (в одном случае), могу ли я сделать TextView таким образом, и что было бы хорошим способом сделать что-то подобное, если мне нужно полностью настраиваться?

Вот моя элегантная и простая реализация вертикального текста, расширяющая TextView. Это означает, что могут использоваться все стандартные стили TextView, поскольку они расширены 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+(bt), t+(rl)); } @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); } } 

По умолчанию повернутый текст сверху вниз. Если вы установите андроид: gravity = "bottom", то он будет рисоваться снизу вверх.

Технически это обманывает TextView, чтобы думать, что это нормальное вращение (ширина / высота подкачки в нескольких местах), при этом он поворачивается. Он отлично работает и при использовании в XML-макете.

EDIT: публикация другой версии, выше, имеет проблемы с анимацией. Эта новая версия работает лучше, но теряет некоторые функции TextView, такие как marquee и аналогичные специальности.

 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(); } } 

Я реализовал это для своего проекта ChartDroid . Создать 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); } } 

И в 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> 

Один из способов их достижения:

  1. Напишите свой собственный пользовательский вид и переопределите onDraw (Canvas). Вы можете нарисовать текст на холсте, а затем повернуть холст.
  2. То же, что и 1. кроме этого времени используйте Path и нарисуйте текст, используя drawTextOnPath (…)
 check = (TextView)findViewById(R.id.check); check.setRotation(-90); 

Это сработало для меня, отлично. Что касается вертикально идущих букв – я не знаю.

На некоторые мелочи нужно обратить внимание.

Это зависит от набора символов при выборе поворота или путей пути. Например, если целевая кодировка похожа на английский, и ожидаемый эффект выглядит,

 a b c d 

Вы можете получить этот эффект, вычерчивая каждый символ по одному, не поворачиваясь и не направляясь.

Введите описание изображения здесь

Вам может потребоваться поворот или путь, чтобы получить этот эффект.

Трудная часть – это когда вы пытаетесь сделать такую ​​кодировку, как монгольский. Глиф в Typeface необходимо поворачивать на 90 градусов, поэтому drawTextOnPath () будет хорошим кандидатом для использования.

Пробовал оба класса VerticalTextView в одобренном ответе, и они работали достаточно хорошо.

Но независимо от того, что я пробовал, я не смог разместить эти VerticalTextViews в центре содержащего макета (RelativeLayout, который является частью элемента, накаченного для RecyclerView).

FWIW, после осмотра, я нашел класс VerticalTextView yoog568 в GitHub:

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

Которые я смог установить по желанию.

Следуя ответу указателя Нулла , я смог onDraw текст по горизонтали, изменив метод onDraw следующим образом:

 @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(); } 

Возможно, вам потребуется добавить часть TextView measuredWidth для центрирования многострочного текста.