Обработка \ n в LineBreakMeasurer - PullRequest
2 голосов
/ 13 июля 2009

Существуют тысячи статей о том, как использовать LineBreakMeasurer для рисования многострочного текста, но нет ничего о том, как рисовать многострочный текст, принимая во внимание также \ n (когда вы хотите задать новую строку в определенной позиции в тексте, а не только когда заканчивается правое или левое поле).

Секрет, похоже, кроется в BreakIterator, но я не смог найти реализацию, которая обрабатывает \ n.

Ответы [ 4 ]

3 голосов
/ 21 ноября 2010

Вместо LineBreakMeasurer (LBM) nextLayout(float), используйте перегруженный LBM.nextLayout(float, int, boolean) метод. Это позволяет вам ограничить текст, который LBM будет включать в возвращаемый TextLayout. В вашем случае вы проинструктируете его не выходить за пределы следующего символа новой строки.

Этот фрагмент кода должен дать вам идею. Сначала используйте LBM.nextOffset, чтобы «посмотреть», какой индекс символов будет концом следующего макета. Затем переберите содержимое строки до этого смещения, чтобы увидеть, есть ли символы новой строки. Если вы это сделаете, то используйте этот найденный предел в качестве второго аргумента nextLayout(float, int, boolean), который скажет LBM не превышать символ новой строки:

int next = lineMeasurer.nextOffset(formatWidth);
int limit = next;
if (limit < totalLength) {
   for (int i = lineMeasurer.getPosition(); i < next; ++i) {
      char c = string.charAt(i);
      if (c == '\n') {
         limit = i;
         break;
      }
   }
}

TextLayout layout = lineMeasurer.nextLayout(formatWidth, limit, false);

Ссылки

http://java.sun.com/developer/onlineTraining/Media/2DText/style.html#layout http://java.sun.com/developer/onlineTraining/Media/2DText/Code/LineBreakSample.java

2 голосов
/ 13 июля 2009

Сначала токенизируйте текст, затем просто примените LineBreakMeasureCode к каждому токену.

1 голос
/ 04 июня 2013

Код Аарона не всегда работает правильно, поэтому вот немного подправленного кода, который работает для меня:

int next = measurer.nextOffset(width);
int limit = next;
if (limit <= text.length()) {
  for (int i = measurer.getPosition(); i < next; ++i) {
    char c = text.charAt(i);
    if (c == '\n') {
      limit = i + 1;
      break;
    }
  }
}
TextLayout textLayout = measurer.nextLayout(width, limit, false);

Если вам нужен текст из AttributedString, вы можете просто сделать это заранее

AttributedCharacterIterator iterator = attributedString.getIterator();
StringBuilder stringBuilder = new StringBuilder(iterator.getEndIndex());
while (iterator.getIndex() < iterator.getEndIndex()) {
  stringBuilder.append(iterator.current());
  iterator.next();
}
String text = stringBuilder.toString();
1 голос
/ 22 марта 2012

Я считаю, что этот код хорошо работает для новой строки. Я использовал Atdixon в качестве шаблона, чтобы получить это.

while (measurer.getPosition() < paragraph.getEndIndex()) {
   next = measurer.nextOffset(wrappingWidth);
   limit = next;
   charat = tested.indexOf('\n',measurer.getPosition()+1);
   if(next > (charat - measurer.getPosition()) && charat != -1){
      limit = charat - measurer.getPosition();
   }
   layout = measurer.nextLayout(wrappingWidth, measurer.getPosition()+limit, false);
   // Do the rest of your layout and pen work.
}
...