@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (currentMessageObject == null) { setMeasuredDimension( MeasureSpec.getSize(widthMeasureSpec), textHeight + AndroidUtilities.dp(14)); return; } int width = Math.max(AndroidUtilities.dp(30), MeasureSpec.getSize(widthMeasureSpec)); if (width != previousWidth) { previousWidth = width; textLayout = new StaticLayout( currentMessageObject.messageText, textPaint, width - AndroidUtilities.dp(30), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); textHeight = 0; textWidth = 0; try { int linesCount = textLayout.getLineCount(); for (int a = 0; a < linesCount; a++) { float lineWidth; try { lineWidth = textLayout.getLineWidth(a); textHeight = (int) Math.max(textHeight, Math.ceil(textLayout.getLineBottom(a))); } catch (Exception e) { FileLog.e("tmessages", e); return; } textWidth = (int) Math.max(textWidth, Math.ceil(lineWidth)); } } catch (Exception e) { FileLog.e("tmessages", e); } textX = (width - textWidth) / 2; textY = AndroidUtilities.dp(7); textXLeft = (width - textLayout.getWidth()) / 2; if (currentMessageObject.type == MessageObject.Type.MSG_ACTION) { imageReceiver.setImageCoords( (width - AndroidUtilities.dp(64)) / 2, textHeight + AndroidUtilities.dp(15), AndroidUtilities.dp(64), AndroidUtilities.dp(64)); } } setMeasuredDimension( width, textHeight + AndroidUtilities.dp( 14 + (currentMessageObject.type == MessageObject.Type.MSG_ACTION ? 70 : 0))); }
@TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public int onTestSize(int suggestedSize, RectF availableSPace) { mPaint.setTextSize(suggestedSize); String text = getText().toString(); boolean singleline = getMaxLines() == 1; if (singleline) { mTextRect.bottom = mPaint.getFontSpacing(); mTextRect.right = mPaint.measureText(text); } else { StaticLayout layout = new StaticLayout( text, mPaint, mWidthLimit, Alignment.ALIGN_NORMAL, mSpacingMult, mSpacingAdd, true); // return early if we have more lines if (getMaxLines() != NO_LINE_LIMIT && layout.getLineCount() > getMaxLines()) { return 1; } mTextRect.bottom = layout.getHeight(); int maxWidth = -1; for (int i = 0; i < layout.getLineCount(); i++) { if (maxWidth < layout.getLineWidth(i)) { maxWidth = (int) layout.getLineWidth(i); } } mTextRect.right = maxWidth; } mTextRect.offsetTo(0, 0); if (availableSPace.contains(mTextRect)) { // may be too small, don't worry we will find the best match return -1; } else { // too big return 1; } }
public void setText(String text) { if (text == null || text.length() == 0) { setVisibility(GONE); return; } if (text != null && oldText != null && text.equals(oldText)) { return; } oldText = text; setVisibility(VISIBLE); if (AndroidUtilities.isTablet()) { width = (int) (AndroidUtilities.getMinTabletSide() * 0.7f); } else { width = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f); } SpannableStringBuilder stringBuilder = new SpannableStringBuilder(); String help = LocaleController.getString("BotInfoTitle", R.string.BotInfoTitle); stringBuilder.append(help); stringBuilder.append("\n\n"); stringBuilder.append(text); MessageObject.addLinks(stringBuilder); stringBuilder.setSpan( new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), 0, help.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); textLayout = new StaticLayout( stringBuilder, textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); width = 0; height = textLayout.getHeight() + AndroidUtilities.dp(4 + 18); int count = textLayout.getLineCount(); for (int a = 0; a < count; a++) { width = (int) Math.ceil(Math.max(width, textLayout.getLineWidth(a) - textLayout.getLineLeft(a))); } width += AndroidUtilities.dp(4 + 18); }
private void renderBottomLabel( Canvas canvas, RadRect dataPointSlot, String labelText, StaticLayout textBounds) { RectF labelBounds = new RectF(); double height = textBounds.getHeight() + this.labelPadding * 2; double top = dataPointSlot.getBottom() + this.labelMargin; labelBounds.set( (float) dataPointSlot.x, (float) top, (float) dataPointSlot.getRight(), (float) (top + height)); canvas.drawRect( labelBounds.left, labelBounds.top, labelBounds.right, labelBounds.bottom, this.lowFill); canvas.drawRect( labelBounds.left, labelBounds.top, labelBounds.right, labelBounds.bottom, this.stroke); canvas.drawText( labelText, (float) (dataPointSlot.x + (dataPointSlot.width / 2.0) - textBounds.getLineWidth(0) / 2.0f), labelBounds.centerY() + textBounds.getLineBottom(0) - textBounds.getLineBaseline(0), paint); }
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) { 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; } } }
public static StaticLayout createStaticLayout( CharSequence source, int bufstart, int bufend, TextPaint paint, int outerWidth, Layout.Alignment align, float spacingMult, float spacingAdd, boolean includePad, TextUtils.TruncateAt ellipsize, int ellipsisWidth, int maxLines) { /*if (Build.VERSION.SDK_INT >= 14) { init(); try { sConstructorArgs[0] = source; sConstructorArgs[1] = bufstart; sConstructorArgs[2] = bufend; sConstructorArgs[3] = paint; sConstructorArgs[4] = outerWidth; sConstructorArgs[5] = align; sConstructorArgs[6] = sTextDirection; sConstructorArgs[7] = spacingMult; sConstructorArgs[8] = spacingAdd; sConstructorArgs[9] = includePad; sConstructorArgs[10] = ellipsize; sConstructorArgs[11] = ellipsisWidth; sConstructorArgs[12] = maxLines; return sConstructor.newInstance(sConstructorArgs); } catch (Exception e) { FileLog.e("tmessages", e); } }*/ try { if (maxLines == 1) { CharSequence text = TextUtils.ellipsize(source, paint, ellipsisWidth, TextUtils.TruncateAt.END); return new StaticLayout( text, 0, text.length(), paint, outerWidth, align, spacingMult, spacingAdd, includePad); } else { StaticLayout layout = new StaticLayout(source, paint, outerWidth, align, spacingMult, spacingAdd, includePad); if (layout.getLineCount() <= maxLines) { return layout; } else { int off; float left = layout.getLineLeft(maxLines - 1); if (left != 0) { off = layout.getOffsetForHorizontal(maxLines - 1, left); } else { off = layout.getOffsetForHorizontal(maxLines - 1, layout.getLineWidth(maxLines - 1)); } SpannableStringBuilder stringBuilder = new SpannableStringBuilder(source.subSequence(0, Math.max(0, off - 1))); stringBuilder.append("\u2026"); return new StaticLayout( stringBuilder, paint, outerWidth, align, spacingMult, spacingAdd, includePad); } } } catch (Exception e) { FileLog.e("tmessages", e); } return null; }
@Override protected void onDraw(Canvas canvas) { if (user == null && chat == null && encryptedChat == null) { return; } if (useSeparator) { if (LocaleController.isRTL) { canvas.drawLine( 0, getMeasuredHeight() - 1, getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline), getMeasuredHeight() - 1, linePaint); } else { canvas.drawLine( AndroidUtilities.dp(AndroidUtilities.leftBaseline), getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, linePaint); } } if (drawAlpha != 1) { canvas.saveLayerAlpha( 0, 0, canvas.getWidth(), canvas.getHeight(), (int) (255 * drawAlpha), Canvas.HAS_ALPHA_LAYER_SAVE_FLAG); } if (drawNameLock) { setDrawableBounds(lockDrawable, nameLockLeft, nameLockTop); lockDrawable.draw(canvas); } else if (drawNameGroup) { setDrawableBounds(groupDrawable, nameLockLeft, nameLockTop); groupDrawable.draw(canvas); } else if (drawNameBroadcast) { setDrawableBounds(broadcastDrawable, nameLockLeft, nameLockTop); broadcastDrawable.draw(canvas); } else if (drawNameBot) { setDrawableBounds(botDrawable, nameLockLeft, nameLockTop); botDrawable.draw(canvas); } if (nameLayout != null) { canvas.save(); canvas.translate(nameLeft, nameTop); nameLayout.draw(canvas); canvas.restore(); if (drawCheck) { if (LocaleController.isRTL) { setDrawableBounds( checkDrawable, nameLeft - AndroidUtilities.dp(4) - checkDrawable.getIntrinsicWidth(), nameLockTop); } else { setDrawableBounds( checkDrawable, nameLeft + (int) nameLayout.getLineWidth(0) + AndroidUtilities.dp(4), nameLockTop); } checkDrawable.draw(canvas); } } if (onlineLayout != null) { canvas.save(); canvas.translate(onlineLeft, AndroidUtilities.dp(40)); onlineLayout.draw(canvas); canvas.restore(); } if (countLayout != null) { if (MessagesController.getInstance().isDialogMuted(dialog_id)) { setDrawableBounds( countDrawableGrey, countLeft - AndroidUtilities.dp(5.5f), countTop, countWidth + AndroidUtilities.dp(11), countDrawableGrey.getIntrinsicHeight()); countDrawableGrey.draw(canvas); } else { setDrawableBounds( countDrawable, countLeft - AndroidUtilities.dp(5.5f), countTop, countWidth + AndroidUtilities.dp(11), countDrawable.getIntrinsicHeight()); countDrawable.draw(canvas); } canvas.save(); canvas.translate(countLeft, countTop + AndroidUtilities.dp(4)); countLayout.draw(canvas); canvas.restore(); } avatarImage.draw(canvas); }
public void buildLayout() { CharSequence nameString; TextPaint currentNamePaint; drawNameBroadcast = false; drawNameLock = false; drawNameGroup = false; drawCheck = false; drawNameBot = false; if (encryptedChat != null) { drawNameLock = true; dialog_id = ((long) encryptedChat.id) << 32; if (!LocaleController.isRTL) { nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + lockDrawable.getIntrinsicWidth(); } else { nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline + 2) - lockDrawable.getIntrinsicWidth(); nameLeft = AndroidUtilities.dp(11); } nameLockTop = AndroidUtilities.dp(16.5f); } else { if (chat != null) { if (chat.id < 0) { dialog_id = AndroidUtilities.makeBroadcastId(chat.id); drawNameBroadcast = true; nameLockTop = AndroidUtilities.dp(28.5f); } else { dialog_id = -chat.id; if (ChatObject.isChannel(chat) && !chat.megagroup) { drawNameBroadcast = true; nameLockTop = AndroidUtilities.dp(28.5f); } else { drawNameGroup = true; nameLockTop = AndroidUtilities.dp(30); } } drawCheck = chat.verified; if (!LocaleController.isRTL) { nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + (drawNameGroup ? groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); } else { nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline + 2) - (drawNameGroup ? groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); nameLeft = AndroidUtilities.dp(11); } } else { dialog_id = user.id; if (!LocaleController.isRTL) { nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); } else { nameLeft = AndroidUtilities.dp(11); } if (user.bot) { drawNameBot = true; if (!LocaleController.isRTL) { nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + botDrawable.getIntrinsicWidth(); } else { nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline + 2) - botDrawable.getIntrinsicWidth(); nameLeft = AndroidUtilities.dp(11); } nameLockTop = AndroidUtilities.dp(16.5f); } else { nameLockTop = AndroidUtilities.dp(17); } drawCheck = user.verified; } } if (currentName != null) { nameString = currentName; } else { String nameString2 = ""; if (chat != null) { nameString2 = chat.title; } else if (user != null) { nameString2 = UserObject.getUserName(user); } nameString = nameString2.replace('\n', ' '); } if (nameString.length() == 0) { if (user != null && user.phone != null && user.phone.length() != 0) { nameString = PhoneFormat.getInstance().format("+" + user.phone); } else { nameString = LocaleController.getString("HiddenName", R.string.HiddenName); } } if (encryptedChat != null) { currentNamePaint = nameEncryptedPaint; } else { currentNamePaint = namePaint; } int onlineWidth; int nameWidth; if (!LocaleController.isRTL) { onlineWidth = nameWidth = getMeasuredWidth() - nameLeft - AndroidUtilities.dp(14); } else { onlineWidth = nameWidth = getMeasuredWidth() - nameLeft - AndroidUtilities.dp(AndroidUtilities.leftBaseline); } if (drawNameLock) { nameWidth -= AndroidUtilities.dp(6) + lockDrawable.getIntrinsicWidth(); } else if (drawNameBroadcast) { nameWidth -= AndroidUtilities.dp(6) + broadcastDrawable.getIntrinsicWidth(); } else if (drawNameGroup) { nameWidth -= AndroidUtilities.dp(6) + groupDrawable.getIntrinsicWidth(); } else if (drawNameBot) { nameWidth -= AndroidUtilities.dp(6) + botDrawable.getIntrinsicWidth(); } if (drawCount) { TLRPC.TL_dialog dialog = MessagesController.getInstance().dialogs_dict.get(dialog_id); if (dialog != null && dialog.unread_count != 0) { lastUnreadCount = dialog.unread_count; String countString = String.format("%d", dialog.unread_count); countWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(countPaint.measureText(countString))); countLayout = new StaticLayout( countString, countPaint, countWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); int w = countWidth + AndroidUtilities.dp(18); nameWidth -= w; if (!LocaleController.isRTL) { countLeft = getMeasuredWidth() - countWidth - AndroidUtilities.dp(19); } else { countLeft = AndroidUtilities.dp(19); nameLeft += w; } } else { lastUnreadCount = 0; countLayout = null; } } else { lastUnreadCount = 0; countLayout = null; } CharSequence nameStringFinal = TextUtils.ellipsize( nameString, currentNamePaint, nameWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END); nameLayout = new StaticLayout( nameStringFinal, currentNamePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (chat == null || subLabel != null) { if (!LocaleController.isRTL) { onlineLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); } else { onlineLeft = AndroidUtilities.dp(11); } CharSequence onlineString = ""; TextPaint currentOnlinePaint = offlinePaint; if (subLabel != null) { onlineString = subLabel; } else if (user != null) { if (user.bot) { onlineString = LocaleController.getString("Bot", R.string.Bot); } else { onlineString = LocaleController.formatUserStatus(user); if (user != null && (user.id == UserConfig.getClientUserId() || user.status != null && user.status.expires > ConnectionsManager.getInstance().getCurrentTime())) { currentOnlinePaint = onlinePaint; onlineString = LocaleController.getString("Online", R.string.Online); } } } CharSequence onlineStringFinal = TextUtils.ellipsize( onlineString, currentOnlinePaint, onlineWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END); onlineLayout = new StaticLayout( onlineStringFinal, currentOnlinePaint, onlineWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); nameTop = AndroidUtilities.dp(13); if (subLabel != null && chat != null) { nameLockTop -= AndroidUtilities.dp(12); } } else { onlineLayout = null; nameTop = AndroidUtilities.dp(25); } int avatarLeft; if (!LocaleController.isRTL) { avatarLeft = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 13 : 9); } else { avatarLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.isTablet() ? 65 : 61); } avatarImage.setImageCoords( avatarLeft, AndroidUtilities.dp(10), AndroidUtilities.dp(52), AndroidUtilities.dp(52)); double widthpx; float left; if (LocaleController.isRTL) { if (nameLayout.getLineCount() > 0) { left = nameLayout.getLineLeft(0); if (left == 0) { widthpx = Math.ceil(nameLayout.getLineWidth(0)); if (widthpx < nameWidth) { nameLeft += (nameWidth - widthpx); } } } if (onlineLayout != null && onlineLayout.getLineCount() > 0) { left = onlineLayout.getLineLeft(0); if (left == 0) { widthpx = Math.ceil(onlineLayout.getLineWidth(0)); if (widthpx < onlineWidth) { onlineLeft += (onlineWidth - widthpx); } } } } else { if (nameLayout.getLineCount() > 0) { left = nameLayout.getLineRight(0); if (left == nameWidth) { widthpx = Math.ceil(nameLayout.getLineWidth(0)); if (widthpx < nameWidth) { nameLeft -= (nameWidth - widthpx); } } } if (onlineLayout != null && onlineLayout.getLineCount() > 0) { left = onlineLayout.getLineRight(0); if (left == onlineWidth) { widthpx = Math.ceil(onlineLayout.getLineWidth(0)); if (widthpx < onlineWidth) { onlineLeft -= (onlineWidth - widthpx); } } } } }
public void build(MessageWireframe wireframe, int desiredWidth, StelsApplication application) { Logger.d(TAG, "Build layout start"); checkResources(application); senderPaint = initTextPaint(); senderPaint.setTypeface(FontController.loadTypeface(application, "regular")); senderPaint.setTextSize(bodyPaint.getTextSize()); senderPaint.setColor(0xff000000); forwardingPaint = initTextPaint(); forwardingPaint.setTypeface(FontController.loadTypeface(application, "light")); forwardingPaint.setTextSize(bodyPaint.getTextSize()); forwardingPaint.setColor(0xff000000); this.layoutDesiredWidth = desiredWidth; this.isOut = wireframe.message.isOut(); this.showState = isOut; this.isGroup = wireframe.message.getPeerType() == PeerType.PEER_CHAT && !isOut; if (isGroup) { User user = wireframe.senderUser; this.senderName = user.getDisplayName(); if (!wireframe.message.isForwarded()) { senderPaint.setColor( Placeholders.USER_PLACEHOLDERS_COLOR[ wireframe.message.getSenderId() % Placeholders.USER_PLACEHOLDERS_COLOR.length]); forwardingPaint.setColor( Placeholders.USER_PLACEHOLDERS_COLOR[ wireframe.message.getSenderId() % Placeholders.USER_PLACEHOLDERS_COLOR.length]); } } if (wireframe.message.isForwarded()) { isForwarded = true; this.forwarderName = wireframe.forwardUser.getDisplayName(); if (isOut) { forwardingPaint.setColor(0xff739f53); senderPaint.setColor(0xff739f53); } else { forwardingPaint.setColor(0xff4884cf); senderPaint.setColor(0xff4884cf); } } else { isForwarded = false; } if (isGroup) { User user = application.getEngine().getUser(wireframe.message.getSenderId()); this.senderName = user.getDisplayName(); } if (wireframe.message.isForwarded()) { isForwarded = true; this.forwarderName = wireframe.forwardUser.getDisplayName(); } else { isForwarded = false; } layoutDesiredWidth = desiredWidth; long start = SystemClock.uptimeMillis(); this.spannable = application .getEmojiProcessor() .processEmojiCompatMutable( wireframe.message.getMessage(), EmojiProcessor.CONFIGURATION_BUBBLES); // spannable = new SpannableString(wireframe.message.getMessage()); Logger.d(TAG, "Emoji processed in " + (SystemClock.uptimeMillis() - start) + " ms"); start = SystemClock.uptimeMillis(); Linkify.addLinks( this.spannable, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS | Linkify.EMAIL_ADDRESSES); fixLinks(spannable); Logger.d(TAG, "Added links in " + (SystemClock.uptimeMillis() - start) + " ms"); start = SystemClock.uptimeMillis(); layout = new StaticLayout( spannable, bodyPaint, desiredWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true); Logger.d(TAG, "Built base layout in " + (SystemClock.uptimeMillis() - start) + " ms"); if (layout.getLineCount() < 20) { int layoutTextWidth = 0; for (int i = 0; i < layout.getLineCount(); i++) { layoutTextWidth = (int) Math.max(layout.getLineWidth(i), layoutTextWidth); } if (layoutTextWidth < layout.getWidth() - px(10)) { layout = new StaticLayout( spannable, bodyPaint, layoutTextWidth + px(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true); } } layoutRealWidth = layout.getWidth(); timeWidth = (int) clockOutPaint.measureText(wireframe.date) + px((showState ? 23 : 0) + 6); if (layout.getLineCount() == 1) { boolean isLastRtl = layout.getParagraphDirection(0) == Layout.DIR_RIGHT_TO_LEFT; if (!isLastRtl && desiredWidth - layoutRealWidth > timeWidth) { layoutRealWidth += timeWidth; layoutHeight = layout.getHeight() + px(3); } else if (isLastRtl && desiredWidth - layout.getWidth() > timeWidth) { layoutRealWidth = layout.getWidth() + timeWidth; layoutHeight = layout.getHeight() + px(3); } else { if (isLastRtl) { layoutRealWidth = layout.getWidth(); } layoutHeight = layout.getHeight() + px(17); } } else { boolean isLastRtl = layout.getParagraphDirection(layout.getLineCount() - 1) == Layout.DIR_RIGHT_TO_LEFT; if (!isLastRtl && (desiredWidth - layout.getLineWidth(layout.getLineCount() - 1) > timeWidth)) { layoutRealWidth = (int) Math.max( layoutRealWidth, layout.getLineWidth(layout.getLineCount() - 1) + timeWidth); layoutHeight = layout.getHeight() + px(3); } else if (isLastRtl && (desiredWidth - layout.getWidth() > timeWidth)) { layoutRealWidth = (int) Math.max(layoutRealWidth, layout.getWidth() + timeWidth); layoutHeight = layout.getHeight() + px(3); } else { layoutHeight = layout.getHeight() + px(17); } } if (layoutRealWidth < timeWidth) { layoutRealWidth = timeWidth; } if (isForwarded) { layoutHeight += px(19) * 2; forwardOffset = (int) forwardingPaintBase.measureText("From "); layoutRealWidth = (int) Math.max(layoutRealWidth, forwardingPaintBase.measureText("Forwarded message")); forwarderNameMeasured = TextUtils.ellipsize( forwarderName, senderPaintBase, desiredWidth - forwardOffset, TextUtils.TruncateAt.END) .toString(); layoutRealWidth = (int) Math.max( layoutRealWidth, forwardOffset + senderPaintBase.measureText(forwarderNameMeasured)); } if (isGroup && !isOut && !isForwarded) { layoutHeight += px(19); senderNameMeasured = TextUtils.ellipsize(senderName, senderPaintBase, desiredWidth, TextUtils.TruncateAt.END) .toString(); int width = (int) senderPaintBase.measureText(senderNameMeasured); layoutRealWidth = Math.max(layoutRealWidth, width); } Logger.d(TAG, "Build layout end"); }
/** * 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; }
private void build(int width) { positions.clear(); width = width - getPaddingLeft() - getPaddingRight(); if (width <= 0 || TextUtils.isEmpty(text)) { truncatedLayout = expandedLayout = null; return; } for (BubbleSpan span : spans) { span.resetWidth(width); } try { truncatedLayout = expandedLayout = new StaticLayout( text, textPaint, width, Layout.Alignment.ALIGN_NORMAL, lineSpacing, 1, false); if (maxLines > 0 && truncatedLayout.getLineCount() > maxLines) { int lineEnd = truncatedLayout.getLineEnd(maxLines - 1); int offset = -1; StaticLayout sl = new StaticLayout( moreText, textPaint, width, Layout.Alignment.ALIGN_NORMAL, lineSpacing, 1, false); sl.getWidth(); while (truncatedLayout.getLineCount() > maxLines && lineEnd > 0) { if (offset == -1 && truncatedLayout.getLineWidth(maxLines - 1) + sl.getLineWidth(0) > width) { offset = truncatedLayout.getOffsetForHorizontal(maxLines - 1, width - sl.getLineWidth(0)); lineEnd = offset; } else if (offset > 0) { lineEnd--; } SpannableStringBuilder textTruncated = new SpannableStringBuilder(text.subSequence(0, lineEnd)); textTruncated.append(moreText); truncatedLayout = new StaticLayout( textTruncated, textPaint, width, Layout.Alignment.ALIGN_NORMAL, lineSpacing, 1, false); } } } catch (java.lang.ArrayIndexOutOfBoundsException e) { return; } if (truncated) { recomputeSpans((Spannable) truncatedLayout.getText()); } else { recomputeSpans((Spannable) expandedLayout.getText()); } for (BubbleSpan span : spans) { positions.put(span, span.rect(this)); } }
@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); }
public void build(int width, int height) { CharSequence nameString = ""; TextPaint currentNamePaint; drawNameBroadcast = false; drawNameLock = false; drawNameGroup = false; if (encryptedChat != null) { drawNameLock = true; if (!LocaleController.isRTL) { nameLockLeft = AndroidUtilities.dp(61 + (usePadding ? 11 : 0)); nameLeft = AndroidUtilities.dp(65 + (usePadding ? 11 : 0)) + lockDrawable.getIntrinsicWidth(); } else { nameLockLeft = width - AndroidUtilities.dp(63 + (usePadding ? 11 : 0)) - lockDrawable.getIntrinsicWidth(); nameLeft = usePadding ? AndroidUtilities.dp(11) : 0; } nameLockTop = AndroidUtilities.dp(15); } else { if (chat != null) { nameLockTop = AndroidUtilities.dp(26); if (chat.id < 0) { drawNameBroadcast = true; } else { drawNameGroup = true; } if (!LocaleController.isRTL) { nameLockLeft = AndroidUtilities.dp(61 + (usePadding ? 11 : 0)); nameLeft = AndroidUtilities.dp(65 + (usePadding ? 11 : 0)) + (drawNameGroup ? groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); } else { nameLockLeft = width - AndroidUtilities.dp(63 + (usePadding ? 11 : 0)) - (drawNameGroup ? groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); nameLeft = usePadding ? AndroidUtilities.dp(11) : 0; } } else { if (!LocaleController.isRTL) { nameLeft = AndroidUtilities.dp(61 + (usePadding ? 11 : 0)); } else { nameLeft = usePadding ? AndroidUtilities.dp(11) : 0; } } } if (currentName != null) { nameString = currentName; } else { String nameString2 = ""; if (chat != null) { nameString2 = chat.title; } else if (user != null) { nameString2 = ContactsController.formatName(user.first_name, user.last_name); } nameString = nameString2.replace("\n", " "); } if (nameString.length() == 0) { if (user != null && user.phone != null && user.phone.length() != 0) { nameString = PhoneFormat.getInstance().format("+" + user.phone); } else { nameString = LocaleController.getString("HiddenName", R.string.HiddenName); } } if (encryptedChat != null) { currentNamePaint = nameEncryptedPaint; } else { currentNamePaint = namePaint; } if (!LocaleController.isRTL) { onlineWidth = nameWidth = width - nameLeft - AndroidUtilities.dp(3 + (usePadding ? 11 : 0)); } else { onlineWidth = nameWidth = width - nameLeft - AndroidUtilities.dp(61 + (usePadding ? 11 : 0)); } if (drawNameLock) { nameWidth -= AndroidUtilities.dp(6) + lockDrawable.getIntrinsicWidth(); } else if (drawNameBroadcast) { nameWidth -= AndroidUtilities.dp(6) + broadcastDrawable.getIntrinsicWidth(); } CharSequence nameStringFinal = TextUtils.ellipsize( nameString, currentNamePaint, nameWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END); nameLayout = new StaticLayout( nameStringFinal, currentNamePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (chat == null) { if (!LocaleController.isRTL) { onlineLeft = AndroidUtilities.dp(61 + (usePadding ? 11 : 0)); } else { onlineLeft = usePadding ? AndroidUtilities.dp(11) : 0; } CharSequence onlineString = ""; TextPaint currentOnlinePaint = offlinePaint; if (subLabel != null) { onlineString = subLabel; } else { onlineString = LocaleController.formatUserStatus(user); if (user != null && (user.id == UserConfig.getClientUserId() || user.status != null && user.status.expires > ConnectionsManager.getInstance().getCurrentTime())) { currentOnlinePaint = onlinePaint; onlineString = LocaleController.getString("Online", R.string.Online); } } CharSequence onlineStringFinal = TextUtils.ellipsize( onlineString, currentOnlinePaint, nameWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END); onlineLayout = new StaticLayout( onlineStringFinal, currentOnlinePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); nameTop = AndroidUtilities.dp(12); } else { onlineLayout = null; nameTop = AndroidUtilities.dp(22); } if (!LocaleController.isRTL) { avatarLeft = usePadding ? AndroidUtilities.dp(11) : 0; } else { avatarLeft = width - AndroidUtilities.dp(50 + (usePadding ? 11 : 0)); } avatarImage.setImageCoords( avatarLeft, avatarTop, AndroidUtilities.dp(50), AndroidUtilities.dp(50)); double widthpx = 0; float left = 0; if (LocaleController.isRTL) { if (nameLayout.getLineCount() > 0) { left = nameLayout.getLineLeft(0); if (left == 0) { widthpx = Math.ceil(nameLayout.getLineWidth(0)); if (widthpx < nameWidth) { nameLeft += (nameWidth - widthpx); } } } if (onlineLayout != null && onlineLayout.getLineCount() > 0) { left = onlineLayout.getLineLeft(0); if (left == 0) { widthpx = Math.ceil(onlineLayout.getLineWidth(0)); if (widthpx < onlineWidth) { onlineLeft += (onlineWidth - widthpx); } } } } else { if (nameLayout.getLineCount() > 0) { left = nameLayout.getLineRight(0); if (left == nameWidth) { widthpx = Math.ceil(nameLayout.getLineWidth(0)); if (widthpx < nameWidth) { nameLeft -= (nameWidth - widthpx); } } } if (onlineLayout != null && onlineLayout.getLineCount() > 0) { left = onlineLayout.getLineRight(0); if (left == onlineWidth) { widthpx = Math.ceil(onlineLayout.getLineWidth(0)); if (widthpx < onlineWidth) { onlineLeft -= (onlineWidth - widthpx); } } } } }
@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; }
public void build(int width, int height) { CharSequence nameString = ""; TextPaint currentNamePaint; if (encryptedChat != null) { drawNameLock = true; if (!LocaleController.isRTL) { nameLockLeft = Utilities.dp(61 + (usePadding ? 11 : 0)); nameLeft = Utilities.dp(65 + (usePadding ? 11 : 0)) + lockDrawable.getIntrinsicWidth(); } else { nameLockLeft = width - Utilities.dp(63 + (usePadding ? 11 : 0)) - lockDrawable.getIntrinsicWidth(); nameLeft = usePadding ? Utilities.dp(11) : 0; } } else { drawNameLock = false; if (!LocaleController.isRTL) { nameLeft = Utilities.dp(61 + (usePadding ? 11 : 0)); } else { nameLeft = usePadding ? Utilities.dp(11) : 0; } } if (currentName != null) { nameString = currentName; } else { String nameString2 = ""; if (chat != null) { nameString2 = chat.title; } else if (user != null) { nameString2 = Utilities.formatName(user.first_name, user.last_name); } nameString = nameString2.replace("\n", " "); } if (nameString.length() == 0) { if (user.phone != null && user.phone.length() != 0) { nameString = PhoneFormat.getInstance().format("+" + user.phone); } else { nameString = LocaleController.getString("HiddenName", R.string.HiddenName); } } if (encryptedChat != null) { currentNamePaint = nameEncryptedPaint; } else { currentNamePaint = namePaint; } if (!LocaleController.isRTL) { onlineWidth = nameWidth = width - nameLeft - Utilities.dp(3 + (usePadding ? 11 : 0)); } else { onlineWidth = nameWidth = width - nameLeft - Utilities.dp(61 + (usePadding ? 11 : 0)); } if (drawNameLock) { nameWidth -= Utilities.dp(6) + lockDrawable.getIntrinsicWidth(); } CharSequence nameStringFinal = TextUtils.ellipsize( nameString, currentNamePaint, nameWidth - Utilities.dp(12), TextUtils.TruncateAt.END); nameLayout = new StaticLayout( nameStringFinal, currentNamePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (chat == null) { if (!LocaleController.isRTL) { onlineLeft = Utilities.dp(61 + (usePadding ? 11 : 0)); } else { onlineLeft = usePadding ? Utilities.dp(11) : 0; } String onlineString = ""; TextPaint currentOnlinePaint = offlinePaint; if (subLabel != null) { onlineString = subLabel; } else { if (user != null) { if (user.status == null) { onlineString = getResources().getString(R.string.Offline); } else { int currentTime = ConnectionsManager.getInstance().getCurrentTime(); if (user.id == UserConfig.clientUserId || user.status.expires > currentTime) { currentOnlinePaint = onlinePaint; onlineString = getResources().getString(R.string.Online); } else { if (user.status.expires <= 10000) { onlineString = getResources().getString(R.string.Invisible); } else { onlineString = LocaleController.formatDateOnline(user.status.expires); } } } } } CharSequence onlineStringFinal = TextUtils.ellipsize( onlineString, currentOnlinePaint, nameWidth - Utilities.dp(12), TextUtils.TruncateAt.END); onlineLayout = new StaticLayout( onlineStringFinal, currentOnlinePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); nameTop = Utilities.dp(12); } else { onlineLayout = null; nameTop = Utilities.dp(22); } if (!LocaleController.isRTL) { avatarLeft = usePadding ? Utilities.dp(11) : 0; } else { avatarLeft = width - Utilities.dp(50 + (usePadding ? 11 : 0)); } avatarImage.imageX = avatarLeft; avatarImage.imageY = avatarTop; avatarImage.imageW = Utilities.dp(50); avatarImage.imageH = Utilities.dp(50); double widthpx = 0; float left = 0; if (LocaleController.isRTL) { if (nameLayout.getLineCount() > 0) { left = nameLayout.getLineLeft(0); if (left == 0) { widthpx = Math.ceil(nameLayout.getLineWidth(0)); if (widthpx < nameWidth) { nameLeft += (nameWidth - widthpx); } } } if (onlineLayout != null && onlineLayout.getLineCount() > 0) { left = onlineLayout.getLineLeft(0); if (left == 0) { widthpx = Math.ceil(onlineLayout.getLineWidth(0)); if (widthpx < onlineWidth) { onlineLeft += (onlineWidth - widthpx); } } } } else { if (nameLayout.getLineCount() > 0) { left = nameLayout.getLineRight(0); if (left == nameWidth) { widthpx = Math.ceil(nameLayout.getLineWidth(0)); if (widthpx < nameWidth) { nameLeft -= (nameWidth - widthpx); } } } if (onlineLayout != null && onlineLayout.getLineCount() > 0) { left = onlineLayout.getLineRight(0); if (left == onlineWidth) { widthpx = Math.ceil(onlineLayout.getLineWidth(0)); if (widthpx < onlineWidth) { onlineLeft -= (onlineWidth - widthpx); } } } } }
/** * 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 void setMessageObject(MessageObject messageObject) { if (currentMessageObject != messageObject || isUserDataChanged()) { int uid = messageObject.messageOwner.media.user_id; contactUser = MessagesController.getInstance().getUser(uid); drawAddButton = contactUser != null && uid != UserConfig.getClientUserId() && ContactsController.getInstance().contactsDict.get(uid) == null; int maxWidth; if (AndroidUtilities.isTablet()) { maxWidth = (int) (AndroidUtilities.getMinTabletSide() * 0.7f); } else { maxWidth = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f); } maxWidth -= AndroidUtilities.dp(58 + (drawAddButton ? 42 : 0)); if (contactUser != null) { if (contactUser.photo != null) { currentPhoto = contactUser.photo.photo_small; } else { currentPhoto = null; } avatarDrawable.setInfo(contactUser); } else { currentPhoto = null; avatarDrawable.setInfo(uid, null, null, false); } avatarImage.setImage(currentPhoto, "50_50", avatarDrawable, null, false); String currentNameString = ContactsController.formatName( messageObject.messageOwner.media.first_name, messageObject.messageOwner.media.last_name); int nameWidth = Math.min((int) Math.ceil(namePaint.measureText(currentNameString)), maxWidth); CharSequence stringFinal = TextUtils.ellipsize( currentNameString.replace("\n", " "), namePaint, nameWidth, TextUtils.TruncateAt.END); nameLayout = new StaticLayout( stringFinal, namePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (nameLayout.getLineCount() > 0) { nameWidth = (int) Math.ceil(nameLayout.getLineWidth(0)); } else { nameWidth = 0; } String phone = messageObject.messageOwner.media.phone_number; if (phone != null && phone.length() != 0) { if (!phone.startsWith("+")) { phone = "+" + phone; } phone = PhoneFormat.getInstance().format(phone); } else { phone = LocaleController.getString("NumberUnknown", R.string.NumberUnknown); } int phoneWidth = Math.min((int) Math.ceil(phonePaint.measureText(phone)), maxWidth); stringFinal = TextUtils.ellipsize( phone.replace("\n", " "), phonePaint, phoneWidth, TextUtils.TruncateAt.END); phoneLayout = new StaticLayout( stringFinal, phonePaint, phoneWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (phoneLayout.getLineCount() > 0) { phoneWidth = (int) Math.ceil(phoneLayout.getLineWidth(0)); } else { phoneWidth = 0; } namesWidth = Math.max(nameWidth, phoneWidth); backgroundWidth = AndroidUtilities.dp(77 + (drawAddButton ? 42 : 0)) + namesWidth; super.setMessageObject(messageObject); } }