В этом уроке:

- работаем с текстом

 

В прошлых уроках мы уже выводили текст, настраивали для него выравнивание, использовали path для указания линии текста. Посмотрим какие еще операции доступны при работе с текстом.

 

Определение размеров

Есть несколько методов, позволяющих определить размеры текста.

Для начала определим ширину всего текста и каждого символа по отдельности.

 

Создадим проект:

Project name: P1491_CanvasText
Build Target: Android 2.3.3
Application name: CanvasText
Package name: ru.startandroid.develop.p1491canvastext
Create Activity: MainActivity

 

MainActivity.java:

package ru.startandroid.develop.p1491canvastext;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new DrawView(this));
  }

  class DrawView extends View {

    Paint fontPaint;
    Paint redPaint;
    String text = "Test width text";
    int fontSize = 100;
    float[] widths;
    float width;

    public DrawView(Context context) {
      super(context);
      redPaint = new Paint();
      redPaint.setColor(Color.RED);

      fontPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
      fontPaint.setTextSize(fontSize);
      fontPaint.setStyle(Paint.Style.STROKE);

      // ширина текста
      width = fontPaint.measureText(text);

      // посимвольная ширина 
      widths = new float[text.length()];
      fontPaint.getTextWidths(text, widths);
    }

    @Override
    protected void onDraw(Canvas canvas) {
      canvas.drawARGB(80, 102, 204, 255);

      canvas.translate(50, 250);

      // вывод текста
      canvas.drawText(text, 0, 0, fontPaint);

      // линия шириной в текст
      canvas.drawLine(0, 0, width, 0, fontPaint);

      // посимвольные красные точки 
      canvas.drawCircle(0, 0, 3, redPaint);
      for (float w : widths) {
        canvas.translate(w, 0);
        canvas.drawCircle(0, 0, 3, redPaint);
      }
    }
  }

}

В конструкторе DrawView мы создаем и настраиваем fontPaint, который будет использован для вывода текста. Здесь же мы вычисляем размеры текста. Метод measureText вернет ширину указанного текста. Сохраним ее в переменную width. А метод getTextWidths позволяет получить массив, содержащий значения ширины для каждого символа текста. Используем массив widths, размер которого равен кол-ву символов в тексте.

В onDraw рисуем текст. А под текстом рисуем линию шириной равной ранее полученной ширине текста - width, и используя массив widths выводим красные точки, отмечая ширину каждого символа.

 

Результат:

 

 

Далее рассмотрим метод breakText. Он позволит нам узнать сколько символов текста поместится в указанную нами ширину.

 

Перепишем класс DrawView:

class DrawView extends View {

    Paint p;
    String text = "Test width text";
    int fontSize = 80;
    int maxWidth = 350;
    float realWidth = 0;
    int cnt = 0;
    String info = "";

    public DrawView(Context context) {
      super(context);
      p = new Paint(Paint.ANTI_ALIAS_FLAG);
      p.setTextSize(fontSize);

      // кол-во символов и их ширина
      float[] measuredWidth = new float[1];
      cnt = p.breakText(text, true, maxWidth, measuredWidth);
      realWidth = measuredWidth[0];

      info = "cnt = " + cnt + ", realWidth = " + realWidth
          + ", maxWidth = " + maxWidth;

    }

    @Override
    protected void onDraw(Canvas canvas) {
      canvas.drawARGB(80, 102, 204, 255);

      // данные о ширине
      p.setTextSize(24);
      canvas.drawText(info, 50, 50, p);

      // текст
      p.setTextSize(fontSize);
      canvas.drawText(text, 50, 250, p);

      p.setStrokeWidth(10);

      // полоса реальной ширины урезанного текста
      p.setColor(Color.BLUE);
      canvas.drawLine(50, 260, 50 + realWidth, 260, p);

      // полоса лимита
      p.setColor(Color.GREEN);
      canvas.drawLine(50, 270, 50 + maxWidth, 270, p);

    }
  }

В конструкторе DrawView вызываем метод breakText. На вход передаем: 

- текст
- true, означает что пойдем по тексту вперед, начиная с первого символа. Если false, то пойдем с конца.
- ширину, которая будет ограничивать текст
- массив, для получения точного значения ширины

Метод breakText возвращает кол-во символов.

Т.е. мы у объекта Paint спрашиваем, сколько символов указанного текста text влезет в указанную ширину maxWidth. Ответ мы получаем в переменную cnt. А в массив measuredWidth также попадает точная ширина урезанного текста, для удобства сохраним ее в переменную realWidth.

 

В onDraw выводим текст с полученными данными, искомый текст и две полосы для наглядности. Синяя полоса покажет точную ширину (realWidth) урезанного текста, а зеленая покажет лимит (maxWidth), который мы задавали.

 

Результат:

 

maxWidth у нас равен 350. Метод breakText выяснил, что из указанного текста в 350 px влезет лишь 9 символов и они займут 330 px по ширине.

Синяя полоса показывает ширину урезанного текста. Видно что над этой полосой 9 символов (включая пробел).

Зеленая полоса показала лимит, который мы ставили - 350.

 

Среди методов измерения также есть метод getTextBounds, который позволит получить вам прямоугольник, в который заключен текст.

 

 

Шрифты, стили

Рассмотрим возможность использования типов и стилей шрифтов.

 

Перепишем класс DrawView:

class DrawView extends View {

    Paint p;
    String text = "Test width text";
    int fontSize = 60;
    float y = 80;

    public DrawView(Context context) {
      super(context);
      p = new Paint(Paint.ANTI_ALIAS_FLAG);
      p.setTextSize(fontSize);
      p.setStyle(Paint.Style.STROKE);
    }

    @Override
    protected void onDraw(Canvas canvas) {
      canvas.drawARGB(80, 102, 204, 255);

      // обычный текст
      canvas.translate(50, y);
      canvas.drawText(text, 0, 0, p);

      // моноширинный
      canvas.translate(0, y);
      p.setTypeface(Typeface.create(Typeface.MONOSPACE, Typeface.NORMAL));
      canvas.drawText(text, 0, 0, p);

      // с засечками
      canvas.translate(0, y);
      p.setTypeface(Typeface.create(Typeface.SERIF, Typeface.NORMAL));
      canvas.drawText(text, 0, 0, p);

      // обычный жирный 
      canvas.translate(0, y);
      p.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
      canvas.drawText(text, 0, 0, p);

      // обычный жирный курсивный
      canvas.translate(0, y);
      p.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD_ITALIC));
      canvas.drawText(text, 0, 0, p);

      // обычный курсивный
      canvas.translate(0, y);
      p.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.ITALIC));
      canvas.drawText(text, 0, 0, p);

    }
  }

В onDraw мы выводим один и тот же текст, используя различные типы и стили шрифта. Для этого используем метод setTypeface, который требует на вход Typeface. Создать Typeface можно методом create, который требует на вход тип и стиль.

 

Результат:

 

Сначала используем шрифт по умолчанию, затем строим различные комбинации

 

из типов:

MONOSPACE – моноширинный, т.е. ширина всех символов одинакова

SERIF – шрифт с засечками

DEFAULT - шрифт по умолчанию

 

и стилей:

NORMAL – обычный

BOLD – жирный

BOLD_ITALIC – жирный курсивный

ITALIC - курсивный

 

Кроме системных шрифтов, существует возможность использовать свои шрифты. Для этого вместо метода Typeface.create необходимо использовать другие его разновидности. Например createFromAsset. Помещаете ваш шрифт в папку assets и в методе createFromAsset указываете имя файла.

 

 

Рассмотрим еще несколько методов форматирования текста. 

Перепишем класс DrawView:

class DrawView extends View {

    Paint p;
    String text = "Test width text";
    int fontSize = 60;
    float y = 80;

    public DrawView(Context context) {
      super(context);
      p = new Paint(Paint.ANTI_ALIAS_FLAG);
      p.setTextSize(fontSize);
    }

    @Override
    protected void onDraw(Canvas canvas) {
      canvas.drawARGB(80, 102, 204, 255);

      // обычный текст
      canvas.translate(50, y);
      canvas.drawText(text, 0, 0, p);

      // растянутый
      canvas.translate(0, y);
      p.setTextScaleX(1.5f);
      canvas.drawText(text, 0, 0, p);
      p.setTextScaleX(1);

      // наклоненный
      canvas.translate(0, y);
      p.setTextSkewX(0.5f);
      canvas.drawText(text, 0, 0, p);
      p.setTextSkewX(0);

      // подчеркнутый
      canvas.translate(0, y);
      p.setUnderlineText(true);
      canvas.drawText(text, 0, 0, p);
      p.setUnderlineText(false);

      // зачеркнутый
      canvas.translate(0, y);
      p.setStrikeThruText(true);
      canvas.drawText(text, 0, 0, p);
      p.setStrikeThruText(false);

    }
  }

setTextScaleX – позволяет растянуть/сжать текст

setTextSkewX – наклон текста

setUnderlineText – подчеркнутый текст

setStrikeThruText – зачеркнутый текст

 

Результат:

 

 

 

Прочее

Метод drawPosText позволяет при выводе раскидать текст посимвольно по различным точкам

Перепишем класс DrawView:

class DrawView extends View {

    Paint p;
    String text = "Test text";
    int fontSize = 100;
    float pos[];

    public DrawView(Context context) {
      super(context);
      p = new Paint(Paint.ANTI_ALIAS_FLAG);
      p.setTextSize(fontSize);

      pos = new float[] { 100, 300, 200, 150, 300, 500, 400, 300, 500,
          250, 600, 350, 700, 400, 800, 200, 900, 500 };

    }

    @Override
    protected void onDraw(Canvas canvas) {
      canvas.drawARGB(80, 102, 204, 255);

      canvas.drawPosText(text, pos, p);

    }
  }

В конструкторе создаем массив pos. В нем указаны координаты точек, по которым поочередно будут раскиданы символы текста.

В onDraw вызываем drawPosText и передаем ему текст и массив.

 

Результат:

 

 

Методы измерения можно использовать не только в рисовании. Вы можете для обычного TextView получить объект Paint методом getPaint, и далее уже вызывать необходимые вам методы. А метод setTypeface (для задания шрифта) у TextView есть свой.

 

На следующем уроке:

- используем PathMeasure для работы c Path


Присоединяйтесь к нам в Telegram:

- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance 

- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня




Language

Автор сайта

Дмитрий Виноградов

Подробнее можно посмотреть или почитать.

Никакие другие люди не имеют к этому сайту никакого отношения и просто занимаются плагиатом.

Социальные сети

 

В канале я публикую ссылки на интересные и полезные статьи по Android

В чате можно обсудить вопросы и проблемы, возникающие при разработке



Группа ВКонтакте



Поддержка проекта

Яндекс
410011180491924

WebMoney
R248743991365
Z551306702056

Paypal