Страницы

Поиск по вопросам

вторник, 25 декабря 2018 г.

Нестандартный вывод текста в TextView

Необходимо вписать текст в TextView ограниченный кругом. пример Подскажите, в какую сторону копать


Ответ

Написал код onDraw(Canvas canvas) своего класса наследника TextViewрешающий задачу для меня. Комментарии описываю последовательность действий:
@Override protected void onDraw(Canvas canvas) { // круг, в который вписан текст canvas.drawCircle(mRadius, mRadius, mRadius, mGlowPaint); // высота строки float textHeight = mTextPaint.getFontSpacing(); // измеряем длинну текста float widthText = mTextPaint.measureText(mText); if(widthText <= mRadius*2) { // всего одна строка помещается - рисуем ее и выходим canvas.drawText(mText, mRadius, mRadius, mTextPaint); return; } // 1 Делим строку на два, сдвигаем к ближайшему пробелу. получаем индекс пробела, близкого к середине текста int centerSpace = calcCenterSpace(mText); // 2 Сначала рисуем текст вверх : String leftString = mText.substring(0, centerSpace); int cnt = 0; // количество прорисованных строк вверх float widthLine; int n; while (true) { // измеряем длинну строки widthLine = calcWidthLine(mRadius, textHeight * cnt++); // считаем сколько символов поместится в новой строке n = mTextPaint.breakText(leftString, false, widthLine, null); if (n == 0) // прерываем, так как строка слишком длинная break; // создаем строку int rest = leftString.length() - n; // проверка на последнюю строку if (rest != 0) { String s = leftString.substring(leftString.length() - n); // обрезаем до первого пробела int fixed = s.indexOf(' '); // создаем новую аккуратную строку s = s.substring(fixed + 1); // рисуем ее на высоте соответствующую данной строке canvas.drawText(s, mRadius, mRadius - textHeight * cnt + textHeight, mTextPaint); // сокращаем левый кусок текста на длинну отрисованной строки leftString = leftString.substring(0, leftString.length() - s.length()); } else { // последняя строка canvas.drawText(leftString, mRadius, mRadius - textHeight * cnt + textHeight, mTextPaint); break; } } // 3. Теперь рисуем вниз String rightString = mText.substring(centerSpace); cnt = 0; // количество прорисованных строк вверх while(true){ widthLine = calcWidthLine(mRadius, textHeight * cnt++); n = mTextPaint.breakText(rightString, false, widthLine, null); if (n == 0) // прерываем если весь текст не поместился break; int rest = rightString.length() - n; if(rest != 0) { String s = rightString.substring(0, n); int fixed = s.lastIndexOf(' '); s = s.substring(0, fixed); canvas.drawText(s, mRadius, mRadius + textHeight * cnt, mTextPaint); rightString = rightString.substring(s.length(), rightString.length()); } else { canvas.drawText(rightString, mRadius, mRadius + textHeight * cnt, mTextPaint); break; } } }
private static int calcWidthLine(float r, float b){ double a = Math.sqrt(r * r - b * b); return (int)(2*a); }
private static int calcCenterSpace(String text){ int index = text.length()/2; if(text.charAt(index) == ' ') return index; String subLeft = text.substring(0, index); int indexSpaceLeft = subLeft.lastIndexOf(' '); String subRight = text.substring(index + 2); int indexSpaceRight = subRight.indexOf(' '); if(index - indexSpaceLeft <= indexSpaceRight) return indexSpaceLeft; else return indexSpaceRight; }
Алгоритм не идеален, на поставленную задачу выполняет. Еще в планах сделать растягивание строки. Оптимизация и недочеты приветствую. Вот скриншоты:

Комментариев нет:

Отправить комментарий