下面列出了android.text.StaticLayout#getHeight ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Sets the text size of a clone of the view's {@link TextPaint} object
* and uses a {@link StaticLayout} instance to measure the height of the text.
*
* @param source
* @param availableWidthPixels
* @param textSizePixels
* @return the height of the text when placed in a view
* with the specified width
* and when the text has the specified size.
*/
private int getTextHeightPixels(
CharSequence source,
int availableWidthPixels,
float textSizePixels) {
// Make a copy of the original TextPaint object
// since the object gets modified while measuring
// (see also the docs for TextView.getPaint()
// which states to access it read-only)
TextPaint textPaintCopy = new TextPaint(getPaint());
textPaintCopy.setTextSize(textSizePixels);
// Measure using a StaticLayout instance
StaticLayout staticLayout = new StaticLayout(
source,
textPaintCopy,
availableWidthPixels,
Layout.Alignment.ALIGN_NORMAL,
mLineSpacingMultiplier,
mLineSpacingExtra,
true);
return staticLayout.getHeight();
}
/**
* Sets the text size of a clone of the view's {@link TextPaint} object
* and uses a {@link StaticLayout} instance to measure the height of the text.
*
* @param source
* @param availableWidthPixels
* @param textSizePixels
* @return the height of the text when placed in a view
* with the specified width
* and when the text has the specified size.
*/
private int getTextHeightPixels(
CharSequence source,
int availableWidthPixels,
float textSizePixels) {
// Make a copy of the original TextPaint object
// since the object gets modified while measuring
// (see also the docs for TextView.getPaint()
// which states to access it read-only)
TextPaint textPaintCopy = new TextPaint(getPaint());
textPaintCopy.setTextSize(textSizePixels);
// Measure using a StaticLayout instance
StaticLayout staticLayout = new StaticLayout(
source,
textPaintCopy,
availableWidthPixels,
Layout.Alignment.ALIGN_NORMAL,
mLineSpacingMultiplier,
mLineSpacingExtra,
true);
return staticLayout.getHeight();
}
public boolean testSize(float suggestedSize, RectF availableSpace) {
paint.setTextSize(suggestedSize);
paint.setTypeface(getTypeface());
String text = getText().toString();
if (maxLines == 1) {
textRect.bottom = paint.getFontSpacing();
textRect.right = paint.measureText(text);
return availableSpace.width() >= textRect.right && availableSpace.height() >= textRect.bottom;
} else {
StaticLayout layout = new StaticLayout(text, paint, (int) availableSpace.right, Layout.Alignment.ALIGN_NORMAL, spacingMult, spacingAdd, true);
if (maxLines != -1 && layout.getLineCount() > maxLines)
return false;
return availableSpace.width() >= layout.getWidth() && availableSpace.height() >= layout.getHeight();
}
}
/**
* 获得单句歌词的高度,可能有多行
*/
private int getSingleLineHeight(String text) {
StaticLayout staticLayout = new StaticLayout(text, mPaintForOtherLrc,
getWidth() - getPaddingLeft() - getPaddingRight(), Layout.Alignment.ALIGN_CENTER,
DEFAULT_SPACING_MULTI, DEFAULT_SPACING_PADDING, true);
return staticLayout.getHeight();
}
private int getTextHeight(CharSequence source, TextPaint paint, int width, float textSize) {
// modified: make a copy of the original TextPaint object for measuring
// (apparently the object gets modified while measuring, see also the
// docs for TextView.getPaint() (which states to access it read-only)
TextPaint paintCopy = new TextPaint(paint);
// Update the text paint object
paintCopy.setTextSize(textSize);
// Measure using a static layout
StaticLayout layout = new StaticLayout(source, paintCopy, width, Alignment.ALIGN_NORMAL, mSpacingMult, mSpacingAdd, true);
return layout.getHeight();
}
/**
* 分割绘制歌词
*/
private void drawText(Canvas canvas, TextPaint textPaint, int availableWidth, String text) {
StaticLayout staticLayout = new StaticLayout(text, textPaint, availableWidth,
Layout.Alignment.ALIGN_CENTER,
DEFAULT_SPACING_MULTI, 0, true);
final int extra = staticLayout.getLineCount() > 1 ? DensityUtil.dip2px(getContext(), 10) : 0;
canvas.save();
canvas.translate(getPaddingLeft(), mRowY - staticLayout.getHeight() / 2 + extra);
staticLayout.draw(canvas);
canvas.restore();
mRowY += staticLayout.getHeight();
}
private void resetSize() {
textLayout = new StaticLayout(text, textPaint, textLayoutWidth,
Layout.Alignment.ALIGN_CENTER, 1.0F, 0.0F, true);
textWidth = minWidth;
textHeight = minHeight;
if (textWidth < textLayout.getWidth()) {
textWidth = textLayout.getWidth();
}
if (textHeight < textLayout.getHeight()) {
textHeight = textLayout.getHeight();
}
minScale = minWidth / textWidth;
}
protected void onDraw(Canvas canvas) {
if (mCache != null && mStrokeColor != Color.TRANSPARENT) {
if (mUpdateCachedBitmap) {
final int w = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
final int h = getMeasuredHeight();
final String text = getText().toString();
mCanvas.setBitmap(mCache);
mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
float strokeWidth = mStrokeWidth > 0 ? mStrokeWidth : (float)Math.ceil(getTextSize() / 11.5f);
mPaint.setStrokeWidth(strokeWidth);
mPaint.setColor(mStrokeColor);
mPaint.setTextSize(getTextSize());
mPaint.setTypeface(getTypeface());
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
StaticLayout sl = new StaticLayout(text, mPaint, w, Layout.Alignment.ALIGN_CENTER, 1, 0, true);
mCanvas.save();
float a = (h - getPaddingTop() - getPaddingBottom() - sl.getHeight()) / 2.0f;
mCanvas.translate(getPaddingLeft(), a + getPaddingTop());
sl.draw(mCanvas);
mCanvas.restore();
mUpdateCachedBitmap = false;
}
canvas.drawBitmap(mCache, 0, 0, mPaint);
}
super.onDraw(canvas);
}
public boolean testSize(float suggestedSize, RectF availableSpace) {
paint.setTextSize(suggestedSize);
paint.setTypeface(getTypeface());
String text = getText().toString();
if (maxLines == 1) {
textRect.bottom = paint.getFontSpacing();
textRect.right = paint.measureText(text);
return availableSpace.width() >= textRect.right && availableSpace.height() >= textRect.bottom;
} else {
StaticLayout layout = new StaticLayout(text, paint, (int) availableSpace.right, Layout.Alignment.ALIGN_NORMAL, spacingMult, spacingAdd, true);
if (maxLines != -1 && layout.getLineCount() > maxLines)
return false;
return availableSpace.width() >= layout.getWidth() && availableSpace.height() >= layout.getHeight();
}
}
private int getTextHeight(CharSequence source, TextPaint paint, int width, float textSize) {
// modified: make a copy of the original TextPaint object for measuring
// (apparently the object gets modified while measuring, see also the
// docs for TextView.getPaint() (which states to access it read-only)
TextPaint paintCopy = new TextPaint(paint);
// Update the text paint object
paintCopy.setTextSize(textSize);
// Measure using a static layout
StaticLayout layout = new StaticLayout(source, paintCopy, width, Alignment.ALIGN_NORMAL, mSpacingMult, mSpacingAdd, true);
return layout.getHeight();
}
@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;
}
}
protected void drawTextBackground(DanMuModel danMuView, Canvas canvas, DanMuChannel danMuChannel) {
CharSequence text = danMuView.text;
StaticLayout staticLayout = new StaticLayout(text,
paint,
(int) Math.ceil(StaticLayout.getDesiredWidth(text, paint)),
Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true);
int textBackgroundHeight = staticLayout.getHeight()
+ danMuView.textBackgroundPaddingTop
+ danMuView.textBackgroundPaddingBottom;
float top = danMuView.getY()
+ (danMuChannel.height - textBackgroundHeight) / 2;
float x = danMuView.getX()
+ danMuView.marginLeft
+ danMuView.avatarWidth
- danMuView.textBackgroundMarginLeft;
Rect rectF = new Rect((int)x,
(int)top,
(int)(x + danMuView.levelMarginLeft
+ danMuView.levelBitmapWidth
+ danMuView.textMarginLeft
+ danMuView.textBackgroundMarginLeft
+ staticLayout.getWidth()
+ danMuView.textBackgroundPaddingRight),
(int)(top + textBackgroundHeight));
danMuView.textBackground.setBounds(rectF);
danMuView.textBackground.draw(canvas);
}
/**
* 给图片添加带文字和图片的水印,水印会根据图片宽高自动缩放处理
*
* @param watermark 水印图片
* @param image 要加水印的图片
* @param srcWaterMarkImageWidth 水印对应的原图片宽度,即ui制作水印时候参考的图片画布宽度,应该是已知的图片最大宽度
* @param text 要添加的文字
* @param offsetX 添加水印的X轴偏移量
* @param offsetY 添加水印的Y轴偏移量
* @param addInLeft true 在左下角添加水印,false 在右下角添加水印
*/
public static void addWatermarkWithText(@NonNull Bitmap watermark, Bitmap image, int srcWaterMarkImageWidth, @NonNull String text, int offsetX, int offsetY, boolean addInLeft) {
float imageWidth = image.getWidth();
float imageHeight = image.getHeight();
if (0 == imageWidth || 0 == imageHeight) {
throw new RuntimeException("AlbumBuilder: 加水印的原图宽或高不能为0!");
}
float watermarkWidth = watermark.getWidth();
float watermarkHeight = watermark.getHeight();
float scale = imageWidth / (float) srcWaterMarkImageWidth;
if (scale > 1) scale = 1;
else if (scale < 0.4) scale = 0.4f;
float scaleWatermarkWidth = watermarkWidth * scale;
float scaleWatermarkHeight = watermarkHeight * scale;
Bitmap scaleWatermark = Bitmap.createScaledBitmap(watermark, (int) scaleWatermarkWidth, (int) scaleWatermarkHeight, true);
Canvas canvas = new Canvas(image);
TextPaint textPaint = new TextPaint();
textPaint.setAntiAlias(true);
textPaint.setColor(Color.WHITE);
float textsize = (float) (scaleWatermark.getHeight() * 2) / (float) 3;
textPaint.setTextSize(textsize);
StaticLayout staticLayout = new StaticLayout(text, textPaint, canvas.getWidth() / 3, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
int textWidth = staticLayout.getWidth();
int textHeight = staticLayout.getHeight();
canvas.save();
if (addInLeft) {
canvas.translate(scaleWatermarkWidth + offsetX + scaleWatermarkWidth / 6, imageHeight - textHeight - offsetY - scaleWatermarkHeight / 6);
} else {
canvas.translate(imageWidth - offsetX - textWidth, imageHeight - textHeight - offsetY - scaleWatermarkHeight / 6);
}
staticLayout.draw(canvas);
canvas.restore();
Paint sacleWatermarkPaint = new Paint();
sacleWatermarkPaint.setAntiAlias(true);
if (addInLeft) {
canvas.drawBitmap(scaleWatermark, offsetX, imageHeight - textHeight - offsetY - scaleWatermarkHeight / 6, sacleWatermarkPaint);
} else {
canvas.drawBitmap(scaleWatermark, imageWidth - textWidth - offsetX - scaleWatermarkWidth - scaleWatermarkWidth / 6, imageHeight - textHeight - offsetY - scaleWatermarkHeight / 6, sacleWatermarkPaint);
}
recycle(scaleWatermark);
}
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);
int maxWidth;
if (AndroidUtilities.isTablet()) {
maxWidth = (int) (AndroidUtilities.getMinTabletSide() * 0.7f);
} else {
maxWidth = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f);
}
String lines[] = text.split("\n");
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
String help = LocaleController.getString("BotInfoTitle", R.string.BotInfoTitle);
stringBuilder.append(help);
stringBuilder.append("\n\n");
for (int a = 0; a < lines.length; a++) {
stringBuilder.append(lines[a].trim());
if (a != lines.length - 1) {
stringBuilder.append("\n");
}
}
MessageObject.addLinks(false, stringBuilder);
stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), 0, help.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
Emoji.replaceEmoji(stringBuilder, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
try {
textLayout = new StaticLayout(stringBuilder, Theme.chat_msgTextPaint, maxWidth, 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)));
}
if (width > maxWidth) {
width = maxWidth;
}
} catch (Exception e) {
FileLog.e(e);
}
width += AndroidUtilities.dp(4 + 18);
}
public void setTime(int value) {
time = value;
String timeString;
if (time >= 1 && time < 60) {
timeString = "" + value;
if (timeString.length() < 2) {
timeString += "s";
}
} else if (time >= 60 && time < 60 * 60) {
timeString = "" + value / 60;
if (timeString.length() < 2) {
timeString += "m";
}
} else if (time >= 60 * 60 && time < 60 * 60 * 24) {
timeString = "" + value / 60 / 60;
if (timeString.length() < 2) {
timeString += "h";
}
} else if (time >= 60 * 60 * 24 && time < 60 * 60 * 24 * 7) {
timeString = "" + value / 60 / 60 / 24;
if (timeString.length() < 2) {
timeString += "d";
}
} else {
timeString = "" + value / 60 / 60 / 24 / 7;
if (timeString.length() < 2) {
timeString += "w";
} else if (timeString.length() > 2) {
timeString = "c";
}
}
timeWidth = timePaint.measureText(timeString);
try {
timeLayout = new StaticLayout(timeString, timePaint, (int)Math.ceil(timeWidth), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
timeHeight = timeLayout.getHeight();
} catch (Exception e) {
timeLayout = null;
FileLog.e(e);
}
invalidateSelf();
}
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);
int maxWidth;
if (AndroidUtilities.isTablet()) {
maxWidth = (int) (AndroidUtilities.getMinTabletSide() * 0.7f);
} else {
maxWidth = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f);
}
String lines[] = text.split("\n");
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
String help = LocaleController.getString("BotInfoTitle", R.string.BotInfoTitle);
stringBuilder.append(help);
stringBuilder.append("\n\n");
for (int a = 0; a < lines.length; a++) {
stringBuilder.append(lines[a].trim());
if (a != lines.length - 1) {
stringBuilder.append("\n");
}
}
MessageObject.addLinks(false, stringBuilder);
stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), 0, help.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
Emoji.replaceEmoji(stringBuilder, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
try {
textLayout = new StaticLayout(stringBuilder, Theme.chat_msgTextPaint, maxWidth, 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)));
}
if (width > maxWidth) {
width = maxWidth;
}
} catch (Exception e) {
FileLog.e(e);
}
width += AndroidUtilities.dp(4 + 18);
}
public void setTime(int value) {
time = value;
String timeString;
if (time >= 1 && time < 60) {
timeString = "" + value;
if (timeString.length() < 2) {
timeString += "s";
}
} else if (time >= 60 && time < 60 * 60) {
timeString = "" + value / 60;
if (timeString.length() < 2) {
timeString += "m";
}
} else if (time >= 60 * 60 && time < 60 * 60 * 24) {
timeString = "" + value / 60 / 60;
if (timeString.length() < 2) {
timeString += "h";
}
} else if (time >= 60 * 60 * 24 && time < 60 * 60 * 24 * 7) {
timeString = "" + value / 60 / 60 / 24;
if (timeString.length() < 2) {
timeString += "d";
}
} else {
timeString = "" + value / 60 / 60 / 24 / 7;
if (timeString.length() < 2) {
timeString += "w";
} else if (timeString.length() > 2) {
timeString = "c";
}
}
timeWidth = timePaint.measureText(timeString);
try {
timeLayout = new StaticLayout(timeString, timePaint, (int)Math.ceil(timeWidth), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
timeHeight = timeLayout.getHeight();
} catch (Exception e) {
timeLayout = null;
FileLog.e(e);
}
invalidateSelf();
}
private int getTextHeight(CharSequence source, TextPaint paint, int width, float textSize) {
paint.setTextSize(textSize);
StaticLayout layout = new StaticLayout(source, paint, width, Alignment.ALIGN_NORMAL, mSpacingMult, mSpacingAdd, true);
return layout.getHeight();
}
/**
* If reuseBmp is not null, and size of the new bitmap matches the size of the reuseBmp,
* new bitmap won't be created, reuseBmp it will be reused instead
*
* @param textLayer text to draw
* @param reuseBmp the bitmap that will be reused
* @return bitmap with the text
*/
@NonNull
private Bitmap createBitmap(@NonNull TextLayer textLayer, @Nullable Bitmap reuseBmp) {
int boundsWidth = canvasWidth;
// init params - size, color, typeface
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextSize(textLayer.getFont().getSize() * canvasWidth);
textPaint.setColor(textLayer.getFont().getColor());
textPaint.setTypeface(fontProvider.getTypeface(textLayer.getFont().getTypeface()));
// drawing text guide : http://ivankocijan.xyz/android-drawing-multiline-text-on-canvas/
// Static layout which will be drawn on canvas
StaticLayout sl = new StaticLayout(
textLayer.getText(), // - text which will be drawn
textPaint,
boundsWidth, // - width of the layout
Layout.Alignment.ALIGN_CENTER, // - layout alignment
1, // 1 - text spacing multiply
1, // 1 - text spacing add
true); // true - include padding
// calculate height for the entity, min - Limits.MIN_BITMAP_HEIGHT
int boundsHeight = sl.getHeight();
// create bitmap not smaller than TextLayer.Limits.MIN_BITMAP_HEIGHT
int bmpHeight = (int) (canvasHeight * Math.max(TextLayer.Limits.MIN_BITMAP_HEIGHT,
1.0F * boundsHeight / canvasHeight));
// create bitmap where text will be drawn
Bitmap bmp;
if (reuseBmp != null && reuseBmp.getWidth() == boundsWidth
&& reuseBmp.getHeight() == bmpHeight) {
// if previous bitmap exists, and it's width/height is the same - reuse it
bmp = reuseBmp;
bmp.eraseColor(Color.TRANSPARENT); // erase color when reusing
} else {
bmp = Bitmap.createBitmap(boundsWidth, bmpHeight, Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(bmp);
canvas.save();
// move text to center if bitmap is bigger that text
if (boundsHeight < bmpHeight) {
//calculate Y coordinate - In this case we want to draw the text in the
//center of the canvas so we move Y coordinate to center.
float textYCoordinate = (bmpHeight - boundsHeight) / 2;
canvas.translate(0, textYCoordinate);
}
//draws static layout on canvas
sl.draw(canvas);
canvas.restore();
return bmp;
}
public void setText(String text) {
if (text == null || text.length() == 0) {
setVisibility(GONE);
return;
}
if (text != null && text.equals(oldText)) {
return;
}
oldText = text;
setVisibility(VISIBLE);
int maxWidth;
if (AndroidUtilities.isTablet()) {
maxWidth = (int) (AndroidUtilities.getMinTabletSide() * 0.7f);
} else {
maxWidth = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f);
}
String[] lines = text.split("\n");
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
String help = LocaleController.getString("BotInfoTitle", R.string.BotInfoTitle);
stringBuilder.append(help);
stringBuilder.append("\n\n");
for (int a = 0; a < lines.length; a++) {
stringBuilder.append(lines[a].trim());
if (a != lines.length - 1) {
stringBuilder.append("\n");
}
}
MessageObject.addLinks(false, stringBuilder);
stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), 0, help.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
Emoji.replaceEmoji(stringBuilder, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
try {
textLayout = new StaticLayout(stringBuilder, Theme.chat_msgTextPaint, maxWidth, 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)));
}
if (width > maxWidth) {
width = maxWidth;
}
} catch (Exception e) {
FileLog.e(e);
}
width += AndroidUtilities.dp(4 + 18);
}