List of usage examples for android.text StaticLayout getLineCount
@Override public int getLineCount()
From source file:Main.java
private static int getLineCount(CharSequence text, TextPaint paint, float size, float width, DisplayMetrics displayMetrics) { paint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, size, displayMetrics)); StaticLayout layout = new StaticLayout(text, paint, (int) width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true);/* ww w. j a v a2 s.c o m*/ return layout.getLineCount(); }
From source file:Main.java
/** * Recursive binary search to find the best size for the text. *//*from w ww. j a va 2 s . c o m*/ private static float getAutofitTextSize(CharSequence text, TextPaint paint, float targetWidth, int maxLines, float low, float high, float precision, DisplayMetrics displayMetrics) { float mid = (low + high) / 2.0f; int lineCount = 1; StaticLayout layout = null; paint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, mid, displayMetrics)); if (maxLines != 1) { layout = new StaticLayout(text, paint, (int) targetWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true); lineCount = layout.getLineCount(); } if (SPEW) Log.d(TAG, "low=" + low + " high=" + high + " mid=" + mid + " target=" + targetWidth + " maxLines=" + maxLines + " lineCount=" + lineCount); if (lineCount > maxLines) { // For the case that `text` has more newline characters than `maxLines`. if ((high - low) < precision) { return low; } return getAutofitTextSize(text, paint, targetWidth, maxLines, low, mid, precision, displayMetrics); } else if (lineCount < maxLines) { return getAutofitTextSize(text, paint, targetWidth, maxLines, mid, high, precision, displayMetrics); } else { float maxLineWidth = 0; if (maxLines == 1) { maxLineWidth = paint.measureText(text, 0, text.length()); } else { for (int i = 0; i < lineCount; i++) { if (layout.getLineWidth(i) > maxLineWidth) { maxLineWidth = layout.getLineWidth(i); } } } if ((high - low) < precision) { return low; } else if (maxLineWidth > targetWidth) { return getAutofitTextSize(text, paint, targetWidth, maxLines, low, mid, precision, displayMetrics); } else if (maxLineWidth < targetWidth) { return getAutofitTextSize(text, paint, targetWidth, maxLines, mid, high, precision, displayMetrics); } else { return mid; } } }
From source file:org.telegram.ui.Cells.SharedLinkCell.java
@Override protected void onDraw(Canvas canvas) { if (titleLayout != null) { canvas.save();/*from w w w . java2 s . c o m*/ canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), titleY); titleLayout.draw(canvas); canvas.restore(); } if (descriptionLayout != null) { descriptionTextPaint.setColor(TEXT_COLOR); canvas.save(); canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), descriptionY); descriptionLayout.draw(canvas); canvas.restore(); } if (descriptionLayout2 != null) { descriptionTextPaint.setColor(TEXT_COLOR); canvas.save(); canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), description2Y); descriptionLayout2.draw(canvas); canvas.restore(); } if (!linkLayout.isEmpty()) { descriptionTextPaint.setColor(Theme.MSG_LINK_TEXT_COLOR); int offset = 0; for (int a = 0; a < linkLayout.size(); a++) { StaticLayout layout = linkLayout.get(a); if (layout.getLineCount() > 0) { canvas.save(); canvas.translate( AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), linkY + offset); if (pressedLink == a) { canvas.drawPath(urlPath, urlPaint); } layout.draw(canvas); canvas.restore(); offset += layout.getLineBottom(layout.getLineCount() - 1); } } } letterDrawable.draw(canvas); if (drawLinkImageView) { linkImageView.draw(canvas); } if (needDivider) { if (LocaleController.isRTL) { canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline), getMeasuredHeight() - 1, paint); } else { canvas.drawLine(AndroidUtilities.dp(AndroidUtilities.leftBaseline), getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, paint); } } }
From source file:org.telegram.ui.Cells.SharedLinkCell.java
@Override public boolean onTouchEvent(MotionEvent event) { boolean result = false; if (message != null && !linkLayout.isEmpty() && delegate != null && delegate.canPerformActions()) { if (event.getAction() == MotionEvent.ACTION_DOWN || linkPreviewPressed && event.getAction() == MotionEvent.ACTION_UP) { int x = (int) event.getX(); int y = (int) event.getY(); int offset = 0; boolean ok = false; for (int a = 0; a < linkLayout.size(); a++) { StaticLayout layout = linkLayout.get(a); if (layout.getLineCount() > 0) { int height = layout.getLineBottom(layout.getLineCount() - 1); int linkPosX = AndroidUtilities .dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline); if (x >= linkPosX + layout.getLineLeft(0) && x <= linkPosX + layout.getLineWidth(0) && y >= linkY + offset && y <= linkY + offset + height) { ok = true;/*w ww . j a va 2 s .c om*/ if (event.getAction() == MotionEvent.ACTION_DOWN) { resetPressedLink(); pressedLink = a; linkPreviewPressed = true; try { urlPath.setCurrentLayout(layout, 0, 0); layout.getSelectionPath(0, layout.getText().length(), urlPath); } catch (Exception e) { FileLog.e("tmessages", e); } result = true; } else if (linkPreviewPressed) { try { TLRPC.WebPage webPage = pressedLink == 0 && message.messageOwner.media != null ? message.messageOwner.media.webpage : null; if (webPage != null && Build.VERSION.SDK_INT >= 16 && webPage.embed_url != null && webPage.embed_url.length() != 0) { delegate.needOpenWebView(webPage); } else { Browser.openUrl(getContext(), links.get(pressedLink)); } } catch (Exception e) { FileLog.e("tmessages", e); } resetPressedLink(); result = true; } break; } offset += height; } } if (!ok) { resetPressedLink(); } } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { resetPressedLink(); } } else { resetPressedLink(); } return result || super.onTouchEvent(event); }
From source file:org.wikipedia.page.shareafact.SnippetImage.java
/** * If the title or text is too long we first reduce the font size. * If that is not enough it gets ellipsized. *//*w w w . j av a 2s . c o m*/ private static StaticLayout optimizeTextSize(TextLayoutParams params, int maxHeight, int maxLines, float maxFontSize, float minFontSize) { final float threshold1 = 60.0f; final float threshold2 = 40.0f; final float extraStep1 = 3.0f; final float extraStep2 = 1.0f; boolean fits = false; StaticLayout textLayout = null; // Try decreasing font size first for (float fontSize = maxFontSize; fontSize >= minFontSize; fontSize -= 1.0f) { params.textPaint.setTextSize(fontSize); textLayout = buildLayout(params); if (textLayout.getHeight() <= maxHeight) { fits = true; break; } // make it go faster at the beginning... if (fontSize > threshold1) { fontSize -= extraStep1; } else if (fontSize > threshold2) { fontSize -= extraStep2; } } // Then do own ellipsize: cut text off after last fitting space and add "..." // Didn't want to cut off randomly in the middle of a line or word. if (!fits) { final String textStr = params.text.toString(); final int ellipsisLength = 3; final int ellipsisStart = textLayout != null ? textLayout.getLineStart(maxLines) - ellipsisLength : textStr.length(); final int end = textStr.lastIndexOf(' ', ellipsisStart) + 1; if (end > 0) { textLayout = buildLayout(new TextLayoutParams(params, textStr.substring(0, end) + "...")); if (textLayout.getLineCount() <= maxLines) { fits = true; } } } // last resort: use TextUtils.ellipsize() if (!fits) { final float textRatio = .87f; final float maxWidth = textRatio * maxLines * params.lineWidth; textLayout = buildLayout(new TextLayoutParams(params, TextUtils.ellipsize(params.text, params.textPaint, maxWidth, TextUtils.TruncateAt.END))); } return textLayout; }
From source file:com.semfapp.adamdilger.semf.Take5PdfDocument.java
public float drawRiskElement(int height, Take5RiskElement element) { final float singleLineHeight = 12.5f; float totalItemHeight; TextPaint textPaint = new TextPaint(); textPaint.setTypeface(roboto);/*from www. j a va 2 s.c om*/ textPaint.setTextSize(FONT11); textPaint.setColor(Color.BLACK); String oneString = ""; String twoString = ""; if (element.getOne() != null) { oneString = element.getOne(); } if (element.getTwo() != null) { twoString = element.getTwo(); } StaticLayout one = new StaticLayout(oneString, textPaint, 235, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); StaticLayout rating = new StaticLayout(element.getRating().toString(), textPaint, 100, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); StaticLayout two = new StaticLayout(twoString, textPaint, 250, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (one.getLineCount() > two.getLineCount()) { totalItemHeight = singleLineHeight * one.getLineCount(); } else { totalItemHeight = singleLineHeight * two.getLineCount(); } can.save(); can.translate(15, height); one.draw(can); can.restore(); can.save(); can.translate(320, height); two.draw(can); can.restore(); can.save(); can.translate(270, height); rating.draw(can); can.restore(); return totalItemHeight; }
From source file:com.taobao.weex.dom.WXTextDomObject.java
/** * Truncate the source span to the specified lines. * Caller of this method must ensure that the lines of text is <strong>greater than desired lines and need truncate</strong>. * Otherwise, unexpected behavior may happen. * @param source The source span.//from w w w. j a v a 2 s . c o m * @param paint the textPaint * @param desired specified lines. * @param truncateAt truncate method, null value means clipping overflow text directly, non-null value means using ellipsis strategy to clip * @return The spans after clipped. */ private @NonNull Spanned truncate(@Nullable Editable source, @NonNull TextPaint paint, int desired, @Nullable TextUtils.TruncateAt truncateAt) { Spanned ret = new SpannedString(""); if (!TextUtils.isEmpty(source) && source.length() > 0) { if (truncateAt != null) { source.append(ELLIPSIS); Object[] spans = source.getSpans(0, source.length(), Object.class); for (Object span : spans) { int start = source.getSpanStart(span); int end = source.getSpanEnd(span); if (start == 0 && end == source.length() - 1) { source.removeSpan(span); source.setSpan(span, 0, source.length(), source.getSpanFlags(span)); } } } StaticLayout layout; int startOffset; while (source.length() > 1) { startOffset = source.length() - 1; if (truncateAt != null) { startOffset -= 1; } source.delete(startOffset, startOffset + 1); layout = new StaticLayout(source, paint, desired, Layout.Alignment.ALIGN_NORMAL, 1, 0, false); if (layout.getLineCount() <= 1) { ret = source; break; } } } return ret; }
From source file:net.opacapp.multilinecollapsingtoolbar.CollapsingTextHelper.java
private void calculateUsingTextSize(final float textSize) { if (mText == null) return;//w ww .ja va 2 s .com final float availableWidth; final float newTextSize; boolean updateDrawText = false; // BEGIN MODIFICATION: Add maxLines variable int maxLines; // END MODIFICATION if (isClose(textSize, mCollapsedTextSize)) { availableWidth = mCollapsedBounds.width(); newTextSize = mCollapsedTextSize; mScale = 1f; if (mCurrentTypeface != mCollapsedTypeface) { mCurrentTypeface = mCollapsedTypeface; updateDrawText = true; } // BEGIN MODIFICATION: Set maxLines variable maxLines = 1; // END MODIFICATION } else { availableWidth = mExpandedBounds.width(); newTextSize = mExpandedTextSize; if (mCurrentTypeface != mExpandedTypeface) { mCurrentTypeface = mExpandedTypeface; updateDrawText = true; } if (isClose(textSize, mExpandedTextSize)) { // If we're close to the expanded text size, snap to it and use a scale of 1 mScale = 1f; } else { // Else, we'll scale down from the expanded text size mScale = textSize / mExpandedTextSize; } // BEGIN MODIFICATION: Set maxLines variable maxLines = this.maxLines; // END MODIFICATION } if (availableWidth > 0) { updateDrawText = (mCurrentTextSize != newTextSize) || mBoundsChanged || updateDrawText; mCurrentTextSize = newTextSize; mBoundsChanged = false; } if (mTextToDraw == null || updateDrawText) { mTextPaint.setTextSize(mCurrentTextSize); mTextPaint.setTypeface(mCurrentTypeface); // BEGIN MODIFICATION: Text layout creation and text truncation StaticLayout layout = new StaticLayout(mText, mTextPaint, (int) availableWidth, Layout.Alignment.ALIGN_NORMAL, 1, 0, false); CharSequence truncatedText; if (layout.getLineCount() > maxLines) { int lastLine = maxLines - 1; CharSequence textBefore = lastLine > 0 ? mText.subSequence(0, layout.getLineEnd(lastLine - 1)) : ""; CharSequence lineText = mText.subSequence(layout.getLineStart(lastLine), layout.getLineEnd(lastLine)); // if last char in line is space, move it behind the ellipsis CharSequence lineEnd = ""; if (lineText.charAt(lineText.length() - 1) == ' ') { lineEnd = lineText.subSequence(lineText.length() - 1, lineText.length()); lineText = lineText.subSequence(0, lineText.length() - 1); } // insert ellipsis character lineText = TextUtils.concat(lineText, "\u2026", lineEnd); // if the text is too long, truncate it CharSequence truncatedLineText = TextUtils.ellipsize(lineText, mTextPaint, availableWidth, TextUtils.TruncateAt.END); truncatedText = TextUtils.concat(textBefore, truncatedLineText); } else { truncatedText = mText; } if (!TextUtils.equals(truncatedText, mTextToDraw)) { mTextToDraw = truncatedText; mIsRtl = calculateIsRtl(mTextToDraw); } final Layout.Alignment alignment; // Don't rectify gravity for RTL languages, Layout.Alignment does it already. switch (mExpandedTextGravity & GravityCompat.RELATIVE_HORIZONTAL_GRAVITY_MASK) { case Gravity.CENTER_HORIZONTAL: alignment = Layout.Alignment.ALIGN_CENTER; break; case Gravity.RIGHT: case Gravity.END: alignment = Layout.Alignment.ALIGN_OPPOSITE; break; case Gravity.LEFT: case Gravity.START: default: alignment = Layout.Alignment.ALIGN_NORMAL; break; } mTextLayout = new StaticLayout(mTextToDraw, mTextPaint, (int) availableWidth, alignment, 1, 0, false); // END MODIFICATION } }
From source file:android.support.v7.widget.AppCompatTextViewAutoSizeHelper.java
private boolean suggestedSizeFitsInSpace(int suggestedSizeInPx, RectF availableSpace) { CharSequence text = mTextView.getText(); TransformationMethod transformationMethod = mTextView.getTransformationMethod(); if (transformationMethod != null) { CharSequence transformedText = transformationMethod.getTransformation(text, mTextView); if (transformedText != null) { text = transformedText;/*w ww . j a v a 2 s. com*/ } } final int maxLines = Build.VERSION.SDK_INT >= 16 ? mTextView.getMaxLines() : -1; if (mTempTextPaint == null) { mTempTextPaint = new TextPaint(); } else { mTempTextPaint.reset(); } mTempTextPaint.set(mTextView.getPaint()); mTempTextPaint.setTextSize(suggestedSizeInPx); // Needs reflection call due to being private. Layout.Alignment alignment = invokeAndReturnWithDefault(mTextView, "getLayoutAlignment", Layout.Alignment.ALIGN_NORMAL); final StaticLayout layout = Build.VERSION.SDK_INT >= 23 ? createStaticLayoutForMeasuring(text, alignment, Math.round(availableSpace.right), maxLines) : createStaticLayoutForMeasuringPre23(text, alignment, Math.round(availableSpace.right)); // Lines overflow. if (maxLines != -1 && (layout.getLineCount() > maxLines || (layout.getLineEnd(layout.getLineCount() - 1)) != text.length())) { return false; } // Height overflow. if (layout.getHeight() > availableSpace.bottom) { return false; } return true; }
From source file:de.tum.in.tumcampus.auxiliary.calendar.DayView.java
private void drawEventText(StaticLayout eventLayout, Rect rect, Canvas canvas, int top, int bottom, boolean center) { // drawEmptyRect(canvas, rect, 0xFFFF00FF); // for debugging int width = rect.right - rect.left; int height = rect.bottom - rect.top; // If the rectangle is too small for text, then return if (eventLayout == null || width < MIN_CELL_WIDTH_FOR_TEXT) { return;// w w w . j a va2 s . com } int totalLineHeight = 0; int lineCount = eventLayout.getLineCount(); for (int i = 0; i < lineCount; i++) { int lineBottom = eventLayout.getLineBottom(i); if (lineBottom <= height) { totalLineHeight = lineBottom; } else { break; } } // + 2 is small workaround when the font is slightly bigger then the rect. This will // still allow the text to be shown without overflowing into the other all day rects. if (totalLineHeight == 0 || rect.top > bottom || rect.top + totalLineHeight + 2 < top) { return; } // Use a StaticLayout to format the string. canvas.save(); // canvas.translate(rect.left, rect.top + (rect.bottom - rect.top / 2)); int padding = center ? (rect.bottom - rect.top - totalLineHeight) / 2 : 0; canvas.translate(rect.left, rect.top + padding); rect.left = 0; rect.right = width; rect.top = 0; rect.bottom = totalLineHeight; // There's a bug somewhere. If this rect is outside of a previous // cliprect, this becomes a no-op. What happens is that the text draw // past the event rect. The current fix is to not draw the staticLayout // at all if it is completely out of bound. canvas.clipRect(rect); eventLayout.draw(canvas); canvas.restore(); }