/** * Resize the text size with specified width and height * * @param width * @param height */ public void resizeText(int width, int height) { CharSequence text = getText(); // Do not resize if the view does not have dimensions or there is no text if (text == null || text.length() == 0 || height <= 0 || width <= 0 || mTextSize == 0) { return; } // Get the text view's paint object TextPaint textPaint = getPaint(); // Store the current text size float oldTextSize = textPaint.getTextSize(); // If there is a max text size set, use the lesser of that and the default text size float targetTextSize = mMaxTextSize > 0 ? Math.min(mTextSize, mMaxTextSize) : mTextSize; // Get the required text height int textHeight = getTextHeight(text, textPaint, width, targetTextSize); // Until we either fit within our text view or we had reached our min text size, incrementally // try smaller sizes while (textHeight > height && targetTextSize > mMinTextSize) { targetTextSize = Math.max(targetTextSize - 2, mMinTextSize); textHeight = getTextHeight(text, textPaint, width, targetTextSize); } // If we had reached our minimum text size and still don't fit, append an ellipsis if (mAddEllipsis && targetTextSize == mMinTextSize && textHeight > height) { // Draw using a static layout StaticLayout layout = new StaticLayout( text, textPaint, width, Alignment.ALIGN_NORMAL, mSpacingMult, mSpacingAdd, false); // Check that we have a least one line of rendered text if (layout.getLineCount() > 0) { // Since the line at the specific vertical position would be cut off, // we must trim up to the previous line int lastLine = layout.getLineForVertical(height) - 1; // If the text would not even fit on a single line, clear it if (lastLine < 0) { setText(""); } // Otherwise, trim to the previous line and add an ellipsis else { int start = layout.getLineStart(lastLine); int end = layout.getLineEnd(lastLine); float lineWidth = layout.getLineWidth(lastLine); float ellipseWidth = textPaint.measureText(mEllipsis); // Trim characters off until we have enough room to draw the ellipsis while (width < lineWidth + ellipseWidth) { lineWidth = textPaint.measureText(text.subSequence(start, --end + 1).toString()); } setText(text.subSequence(0, end) + mEllipsis); } } } // Some devices try to auto adjust line spacing, so force default line spacing // and invalidate the layout as a side effect textPaint.setTextSize(targetTextSize); setLineSpacing(mSpacingAdd, mSpacingMult); // Notify the listener if registered if (mTextResizeListener != null) { mTextResizeListener.onTextResize(this, oldTextSize, targetTextSize); } // Reset force resize flag mNeedsResize = false; }
@Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); boolean result = false; if (event.getAction() == MotionEvent.ACTION_DOWN) { if (delegate != null) { if (currentMessageObject.type == 11 && imageReceiver.isInsideImage(x, y)) { imagePressed = true; result = true; } if (result) { startCheckLongPress(); } } } else { if (event.getAction() != MotionEvent.ACTION_MOVE) { cancelCheckLongPress(); } if (imagePressed) { if (event.getAction() == MotionEvent.ACTION_UP) { imagePressed = false; if (delegate != null) { delegate.didClickedImage(this); playSoundEffect(SoundEffectConstants.CLICK); } } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { imagePressed = false; } else if (event.getAction() == MotionEvent.ACTION_MOVE) { if (!imageReceiver.isInsideImage(x, y)) { imagePressed = false; } } } } if (!result) { if (event.getAction() == MotionEvent.ACTION_DOWN || pressedLink != null && event.getAction() == MotionEvent.ACTION_UP) { if (x >= textX && y >= textY && x <= textX + textWidth && y <= textY + textHeight) { y -= textY; x -= textXLeft; final int line = textLayout.getLineForVertical((int) y); final int off = textLayout.getOffsetForHorizontal(line, x); final float left = textLayout.getLineLeft(line); if (left <= x && left + textLayout.getLineWidth(line) >= x && currentMessageObject.messageText instanceof Spannable) { Spannable buffer = (Spannable) currentMessageObject.messageText; URLSpan[] link = buffer.getSpans(off, off, URLSpan.class); if (link.length != 0) { if (event.getAction() == MotionEvent.ACTION_DOWN) { pressedLink = link[0]; result = true; } else { if (link[0] == pressedLink) { if (delegate != null) { delegate.needOpenUserProfile(Integer.parseInt(link[0].getURL())); } result = true; } } } else { pressedLink = null; } } else { pressedLink = null; } } else { pressedLink = null; } } } if (!result) { result = super.onTouchEvent(event); } return result; }
@Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); boolean result = false; int side = AndroidUtilities.dp(48); if (textLayout != null) { if (event.getAction() == MotionEvent.ACTION_DOWN || pressedLink != null && event.getAction() == MotionEvent.ACTION_UP) { if (event.getAction() == MotionEvent.ACTION_DOWN) { resetPressedLink(); try { int x2 = (int) (x - textX); int y2 = (int) (y - textY); final int line = textLayout.getLineForVertical(y2); final int off = textLayout.getOffsetForHorizontal(line, x2); final float left = textLayout.getLineLeft(line); if (left <= x2 && left + textLayout.getLineWidth(line) >= x2) { Spannable buffer = (Spannable) textLayout.getText(); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); if (link.length != 0) { resetPressedLink(); pressedLink = link[0]; result = true; try { int start = buffer.getSpanStart(pressedLink); urlPath.setCurrentLayout(textLayout, start); textLayout.getSelectionPath(start, buffer.getSpanEnd(pressedLink), urlPath); } catch (Exception e) { FileLog.e("tmessages", e); } } else { resetPressedLink(); } } else { resetPressedLink(); } } catch (Exception e) { resetPressedLink(); FileLog.e("tmessages", e); } } else if (pressedLink != null) { try { if (pressedLink instanceof URLSpanNoUnderline) { String url = ((URLSpanNoUnderline) pressedLink).getURL(); if (url.startsWith("@") || url.startsWith("#") || url.startsWith("/")) { if (delegate != null) { delegate.didPressUrl(url); } } } else { pressedLink.onClick(this); } } catch (Exception e) { FileLog.e("tmessages", e); } resetPressedLink(); result = true; } } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { resetPressedLink(); } } return result || super.onTouchEvent(event); }
/** * Resize the text size with specified width and height * * @param width * @param height */ public void resizeText(int width, int height) { CharSequence text = getText(); // Do not resize if the view does not have dimensions or there is no // text // or if mTextSize has not been initialized if (text == null || text.length() == 0 || height <= 0 || width <= 0 || mTextSize == 0) { return; } // Get the text view's paint object TextPaint textPaint = getPaint(); // Store the current text size float oldTextSize = textPaint.getTextSize(); // If there is a max text size set, use the lesser of that and the // default text size float targetTextSize = mMaxTextSize > 0 ? Math.min(mTextSize, mMaxTextSize) : mTextSize; // Get the required text height int textHeight = getTextHeight(text, textPaint, width, targetTextSize); int textWidth = getTextWidth(text, textPaint, width, targetTextSize); int lineHeight = getTextHeight(text, textPaint, width * 10, targetTextSize); // Until we either fit within our text view or we had reached our min // text size, incrementally try smaller sizes while (((textHeight > height) || (textWidth > width) || (textHeight > lineHeight)) && targetTextSize > mMinTextSize) { targetTextSize = Math.max(targetTextSize - 2, mMinTextSize); textHeight = getTextHeight(text, textPaint, width, targetTextSize); textWidth = getTextWidth(text, textPaint, width, targetTextSize); lineHeight = getTextHeight(text, textPaint, width * 10, targetTextSize); } // If we had reached our minimum text size and still don't fit, append // an ellipsis if (mAddEllipsis && targetTextSize == mMinTextSize && textHeight > height) { // Draw using a static layout StaticLayout layout = new StaticLayout( text, textPaint, width, Alignment.ALIGN_NORMAL, mSpacingMult, mSpacingAdd, false); layout.draw(sTextResizeCanvas); int lastLine = layout.getLineForVertical(height) - 1; int start = layout.getLineStart(lastLine); int end = layout.getLineEnd(lastLine); float lineWidth = layout.getLineWidth(lastLine); float ellipseWidth = textPaint.measureText(mEllipsis); // Trim characters off until we have enough room to draw the // ellipsis while (width < lineWidth + ellipseWidth) { lineWidth = textPaint.measureText(text.subSequence(start, --end + 1).toString()); } setText(text.subSequence(0, end) + mEllipsis); } // Some devices try to auto adjust line spacing, so force default line // spacing // and invalidate the layout as a side effect textPaint.setTextSize(targetTextSize); setLineSpacing(mSpacingAdd, mSpacingMult); // Notify the listener if registered if (mTextResizeListener != null) { mTextResizeListener.onTextResize(this, oldTextSize, targetTextSize); } // Reset force resize flag mNeedsResize = false; }
public List<Integer> getPageOffsets(CharSequence text, boolean includePageNumbers) { if (text == null) { return new ArrayList<Integer>(); } List<Integer> pageOffsets = new ArrayList<Integer>(); TextPaint textPaint = bookView.getInnerView().getPaint(); int boundedWidth = bookView.getInnerView().getWidth(); LOG.debug("Page width: " + boundedWidth); StaticLayout layout = layoutFactory.create(text, textPaint, boundedWidth, bookView.getLineSpacing()); LOG.debug("Layout height: " + layout.getHeight()); layout.draw(new Canvas()); // Subtract the height of the top margin int pageHeight = bookView.getHeight() - bookView.getVerticalMargin(); if (includePageNumbers) { String bottomSpace = "0\n"; StaticLayout numLayout = layoutFactory.create(bottomSpace, textPaint, boundedWidth, bookView.getLineSpacing()); numLayout.draw(new Canvas()); // Subtract the height needed to show page numbers, or the // height of the margin, whichever is more pageHeight = pageHeight - Math.max(numLayout.getHeight(), bookView.getVerticalMargin()); } else { // Just subtract the bottom margin pageHeight = pageHeight - bookView.getVerticalMargin(); } LOG.debug("Got pageHeight " + pageHeight); int totalLines = layout.getLineCount(); int topLineNextPage = -1; int pageStartOffset = 0; while (topLineNextPage < totalLines - 1) { LOG.debug("Processing line " + topLineNextPage + " / " + totalLines); int topLine = layout.getLineForOffset(pageStartOffset); topLineNextPage = layout.getLineForVertical(layout.getLineTop(topLine) + pageHeight); LOG.debug("topLine " + topLine + " / " + topLineNextPage); if (topLineNextPage == topLine) { // If lines are bigger than can fit on a page topLineNextPage = topLine + 1; } int pageEnd = layout.getLineEnd(topLineNextPage - 1); LOG.debug("pageStartOffset=" + pageStartOffset + ", pageEnd=" + pageEnd); if (pageEnd > pageStartOffset) { if (text.subSequence(pageStartOffset, pageEnd).toString().trim().length() > 0) { pageOffsets.add(pageStartOffset); } pageStartOffset = layout.getLineStart(topLineNextPage); } } return pageOffsets; }