下面列出了android.graphics.Paint#getTextBounds ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private static void setTextSizeForWidth(Paint paint, float desiredWidth, String text) {
// Pick a reasonably large value for the test. Larger values produce
// more accurate results, but may cause problems with hardware
// acceleration. But there are workarounds for that, too; refer to
// http://stackoverflow.com/questions/6253528/font-size-too-large-to-fit-in-cache
final float testTextSize = 48f;
// Get the bounds of the text, using our testTextSize.
paint.setTextSize(testTextSize);
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
// Calculate the desired size as a proportion of our testTextSize.
float desiredTextSize = testTextSize * desiredWidth / bounds.width();
// Set the paint for that size.
paint.setTextSize(desiredTextSize);
}
private boolean contentMayProtrudeFromLineTopOrBottom(CharSequence text, int start, int end) {
if (text instanceof Spanned) {
final Spanned spanned = (Spanned) text;
if (spanned.getSpans(start, end, ReplacementSpan.class).length > 0) {
return true;
}
}
// Spans other than ReplacementSpan can be ignored because line top and bottom are
// disjunction of all tops and bottoms, although it's not optimal.
final Paint paint = getPaint();
if (text instanceof PrecomputedText) {
PrecomputedText precomputed = (PrecomputedText) text;
precomputed.getBounds(start, end, mTempRect);
} else {
paint.getTextBounds(text, start, end, mTempRect);
}
final Paint.FontMetricsInt fm = paint.getFontMetricsInt();
return mTempRect.top < fm.top || mTempRect.bottom > fm.bottom;
}
@Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
//绘制文本的内容的背景
paint.setTextSize(mTextSize);
//测量文本的宽度和高度,通过mTextBound得到
paint.getTextBounds(text.toString(), start, end, mTextBound);
//设置文本背景的宽度和高度,传入的是left,top,right,bottom四个参数
maxWidth = maxWidth < mTextBound.width() ? mTextBound.width() : maxWidth;
maxHeight = maxHeight < mTextBound.height() ? mTextBound.height() : maxHeight;
//设置最大宽度和最大高度是为了防止在倒计时在数字切换的过程中会重绘,会导致倒计时边框的宽度和高度会抖动,
// 所以每次取得最大的高度和宽度而不是每次都去取测量的高度和宽度
getDrawable().setBounds(0,0, maxWidth+mPaddingLeft+mPaddingRight,mPaddingTop+mPaddingBottom+maxHeight);
//绘制文本背景
super.draw(canvas, text, start, end, x, top, y, bottom, paint);
//设置文本的颜色
paint.setColor(mTextColor);
//设置字体的大小
paint.setTextSize(mTextSize);
int mGapX = (getDrawable().getBounds().width() - maxWidth)/2;
int mGapY= (getDrawable().getBounds().height() - maxHeight)/2;
//绘制文本内容
canvas.drawText(text.subSequence(start, end).toString(), x + mGapX , y - mGapY + maxHeight/3, paint); }
@Override
public void processGenerated(@Nonnull Paint paint, @Nonnull Canvas canvas) {
paint.setTypeface(mTypeface);
paint.setAntiAlias(true);
paint.setColor(mColor);
paint.setTextAlign(Paint.Align.LEFT);
paint.setTextSize(PixelUtil.toPixelFromDIP(mFontSize));
Rect bounds = new Rect();
paint.getTextBounds(mText, 0, mText.length(), bounds);
canvas.drawText(
mText,
mWidth / 2.0f - bounds.width() / 2.0f - bounds.left,
mHeight / 2.0f + bounds.height() / 2.0f - bounds.bottom,
paint
);
}
private Bitmap makeFpsOverlay(Paint p, String text) {
Rect b = new Rect();
p.getTextBounds(text, 0, text.length(), b);
int bwidth = b.width()+2;
int bheight = b.height()+2;
Bitmap bm = Bitmap.createBitmap(bwidth, bheight, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bm);
p.setColor(overlayBackgroundColor);
c.drawRect(0, 0, bwidth, bheight, p);
p.setColor(overlayTextColor);
c.drawText(text, -b.left+1, (bheight/2)-((p.ascent()+p.descent())/2)+1, p);
return bm;
}
/**
*
* @param text
* @param key like ModifiersTS, ModifiersUnits, MilStdAttributes
* @param drawPoint
* @param paint
*/
public ModifierInfo(String text, String key, PointF drawPoint, Paint paint)
{
_key = key;
_text = text;
_drawPoint = drawPoint;
_paint = paint;
Rect rTemp = new Rect();
paint.getTextBounds(text, 0, text.length(), rTemp);
_bounds = new RectF(rTemp.left,rTemp.top,rTemp.width(),rTemp.height());
}
public static Rect getFobtWeightAndHeight(Paint paint, String text){
Rect rect = new Rect();
paint.getTextBounds(text, 0, text.length(), rect);
int width = rect.width();//文本的宽度
int height = rect.height();//文本的高度
return rect;
}
protected static int getWordWidth() {
Context context = getGDActivity();
String text = "W";
TextView textView = new TextView(context);
textView.setTextSize(ClickableMenuElement.TEXT_SIZE);
textView.setTypeface(Global.robotoCondensedTypeface);
Rect bounds = new Rect();
Paint textPaint = textView.getPaint();
textPaint.getTextBounds(text, 0, text.length(), bounds);
return bounds.width() + getDp(WORD_SPACE);
}
public void setColoredAdContent(TextView contentText, final ForumAdJson forumAd) {
String subject = StringUtils.get(forumAd.getContent());
Editable editable = contentText.getEditableText();
if (editable != null) {
editable.clear();
editable.clearSpans();
}
final String recomName = forumAd.getRecomName();
SpannableStringBuilder ssb = new SpannableStringBuilder(subject + recomName);
Drawable bg = context.getResources().getDrawable(R.drawable.bg_recom);
ImageSpan imageSpan = new ImageSpan(bg) {
@Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y,
int bottom, Paint paint) {
paint.setTypeface(Typeface.DEFAULT);
int textSize = DensityUtils.dip2px(context, 12);
paint.setTextSize(textSize);
Rect bounds = new Rect();
paint.getTextBounds(text.toString(), start, end, bounds);
getDrawable().setBounds(0, 0, bounds.width() + 10, bottom - top);
super.draw(canvas, text, start, end, x, top, y, bottom, paint);
paint.setColor(Color.TRANSPARENT);
canvas.drawText(text.subSequence(start, end).toString(), x + 5, y, paint);
}
};
ssb.setSpan(imageSpan, subject.length(), subject.length() + recomName.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
contentText.setText(ssb);
}
/**
* 添加文字水印
*
* @param src 源图片
* @param content 水印文本
* @param textSize 水印字体大小
* @param color 水印字体颜色
* @param alpha 水印字体透明度
* @param x 起始坐标x
* @param y 起始坐标y
* @param recycle 是否回收
* @return 带有文字水印的图片
*/
public static Bitmap addTextWatermark(Bitmap src, String content, int textSize, int color, int alpha, float x, float y, boolean recycle) {
if (isEmptyBitmap(src) || content == null) return null;
Bitmap ret = src.copy(src.getConfig(), true);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Canvas canvas = new Canvas(ret);
paint.setAlpha(alpha);
paint.setColor(color);
paint.setTextSize(textSize);
Rect bounds = new Rect();
paint.getTextBounds(content, 0, content.length(), bounds);
canvas.drawText(content, x, y, paint);
if (recycle && !src.isRecycled()) src.recycle();
return ret;
}
private Bitmap createBitmapFromText(String text) {
Bitmap out = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888);
out.eraseColor(0x00000000);
Paint textPaint = new Paint();
textPaint.setAntiAlias(true);
textPaint.setColor(0xffffffff);
textPaint.setTextSize(60);
textPaint.setStrokeWidth(2.f);
textPaint.setStyle(Paint.Style.FILL);
Rect textBoundaries = new Rect();
textPaint.getTextBounds(text, 0, text.length(), textBoundaries);
Canvas canvas = new Canvas(out);
for (int i = 0; i < 2; i++) {
canvas.drawText(text,
(canvas.getWidth() - textBoundaries.width()) / 2.f,
(canvas.getHeight() - textBoundaries.height()) / 2.f + textBoundaries.height(),
textPaint);
textPaint.setColor(0xff000000);
textPaint.setStyle(Paint.Style.STROKE);
}
// uncomment the following lines for debug information
// textPaint.setStyle(Paint.Style.STROKE);
// textPaint.setColor(0xffffffff);
// canvas.drawLine(0, 0, 512,0, textPaint);
// canvas.drawLine(0, 511, 512,511, textPaint);
// canvas.drawLine(0, 0, 0,511, textPaint);
// canvas.drawLine(511, 0, 511,511, textPaint);
return out;
}
public GraphStyle build() {
float density = context.getResources().getDisplayMetrics().density;
Rect rect = new Rect();
Paint namePaint = new Paint();
Paint amountPaint = new Paint();
Paint linePaint = new Paint();
namePaint.setColor(Color.WHITE);
namePaint.setAntiAlias(true);
namePaint.setTextAlign(Align.LEFT);
namePaint.setTextSize(spToPx(nameTextSize, density));
namePaint.setTypeface(Typeface.DEFAULT_BOLD);
namePaint.getTextBounds("A", 0, 1, rect);
int nameHeight = rect.height();
amountPaint.setColor(Color.WHITE);
amountPaint.setAntiAlias(true);
amountPaint.setTextSize(spToPx(amountTextSize, density));
amountPaint.setTextAlign(Align.CENTER);
amountPaint.getTextBounds("8", 0, 1, rect);
int amountHeight = rect.height();
linePaint.setStyle(Style.FILL);
return new GraphStyle(
spToPx(dy, density),
spToPx(textDy, density),
spToPx(indent, density),
spToPx(lineHeight, density),
nameHeight,
amountHeight,
namePaint,
amountPaint,
linePaint);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paintStokeLine.setColor(Color.BLACK);
canvas.drawLine(getWidth() / 2, 0, getWidth() / 2, getHeight(), paintStokeLine);
//键盘监听 开启 输入字符串
Paint paint = DrawUtils.getStrokePaint(Paint.Style.FILL);
paint.setTextSize(TextSize);
paint.setColor(Color.BLACK);
//必须有textSize不然测不出来
fm = paint.getFontMetricsInt();
System.out.println("heihei____FontMetricsInt:" + fm.toString());
Rect bounds = new Rect();
paint.getTextBounds(content, 0, content.length(), bounds);
StringBuilder sb = new StringBuilder();
int i = 0;
for (Paint.Align align : Paint.Align.values()) {
sb.append("—" + align.name());
paint.setTextAlign(align);
drawText_(canvas, paint, i);
i++;
}
sb.append("\n top:BLACK value:" + fm.top);
sb.append("\n ascent:MAGENTA value:" + fm.ascent);
sb.append("\n descent:GREEN value:" + fm.descent);
sb.append("\n bottom:RED value:" + fm.bottom);
sb.append("\n baseLine:BLUE 上边的值都是基于baseLine的值");
sb.append("\n bounds:" + bounds.toString());
System.out.println("heihei__bounds:" + bounds.toString());
sb.append("\n textSize:" + TextSize);
sb.append("\n 推断出:textSize=descent+bounds.top");
tv.setText(introduce + sb.toString());
}
private int getTextHeight(String str, Paint paint) {
Rect rect = new Rect();
paint.getTextBounds(str, 0, str.length(), rect);
return (int) (rect.height() / 33f * 29);
}
public static void drawTextCentredRight(Canvas canvas, String text, float cx, float cy, Paint paint, Rect textBounds) {
paint.getTextBounds(text, 0, text.length(), textBounds);
canvas.drawText(text, cx - textBounds.width(), cy - textBounds.exactCenterY(), paint);
}
public static void drawXAxisValue(Canvas c, String text, float x, float y,
Paint paint,
PointF anchor, float angleDegrees) {
float drawOffsetX = 0.f;
float drawOffsetY = 0.f;
final float lineHeight = paint.getFontMetrics(mFontMetricsBuffer);
paint.getTextBounds(text, 0, text.length(), mDrawTextRectBuffer);
// Android sometimes has pre-padding
drawOffsetX -= mDrawTextRectBuffer.left;
// Android does not snap the bounds to line boundaries,
// and draws from bottom to top.
// And we want to normalize it.
drawOffsetY += -mFontMetricsBuffer.ascent;
// To have a consistent point of reference, we always draw left-aligned
Paint.Align originalTextAlign = paint.getTextAlign();
paint.setTextAlign(Paint.Align.LEFT);
if (angleDegrees != 0.f) {
// Move the text drawing rect in a way that it always rotates around its center
drawOffsetX -= mDrawTextRectBuffer.width() * 0.5f;
drawOffsetY -= lineHeight * 0.5f;
float translateX = x;
float translateY = y;
// Move the "outer" rect relative to the anchor, assuming its centered
if (anchor.x != 0.5f || anchor.y != 0.5f) {
final FSize rotatedSize = getSizeOfRotatedRectangleByDegrees(
mDrawTextRectBuffer.width(),
lineHeight,
angleDegrees);
translateX -= rotatedSize.width * (anchor.x - 0.5f);
translateY -= rotatedSize.height * (anchor.y - 0.5f);
}
c.save();
c.translate(translateX, translateY);
c.rotate(angleDegrees);
c.drawText(text, drawOffsetX, drawOffsetY, paint);
c.restore();
} else {
if (anchor.x != 0.f || anchor.y != 0.f) {
drawOffsetX -= mDrawTextRectBuffer.width() * anchor.x;
drawOffsetY -= lineHeight * anchor.y;
}
drawOffsetX += x;
drawOffsetY += y;
c.drawText(text, drawOffsetX, drawOffsetY, paint);
}
paint.setTextAlign(originalTextAlign);
}
public static Bitmap getBitmap(final String text, int fillColor, final String arrow, final int width, final int height, final int margin, final boolean strike_through, boolean expandable, final boolean shadow) {
{
if ((text == null) || (text.length() > 4)) return null;
try {
if ((width > 2000) || height > 2000 || height < 16 || width < 16) return null;
final Paint paint = new Paint();
paint.setStrikeThruText(strike_through);
paint.setStyle(Paint.Style.FILL);
paint.setColor(fillColor);
paint.setAntiAlias(true);
//paint.setTypeface(Typeface.MONOSPACE);
paint.setTypeface(Typeface.SANS_SERIF); // TODO BEST?
paint.setTextAlign(Paint.Align.LEFT);
float paintTs = (arrow == null ? 17 : 17 - arrow.length());
paint.setTextSize(paintTs);
final Rect bounds = new Rect();
final String fullText = text + (arrow != null ? arrow : "");
paint.getTextBounds(fullText, 0, fullText.length(), bounds);
float textsize = ((paintTs - 1) * (width - margin)) / bounds.width();
paint.setTextSize(textsize);
paint.getTextBounds(fullText, 0, fullText.length(), bounds);
// cannot be Config.ALPHA_8 as it doesn't work on Samsung
final Bitmap bitmap = Bitmap.createBitmap(width, expandable ? Math.max(height, bounds.height() + 30) : height, Bitmap.Config.ARGB_8888);
final Canvas c = new Canvas(bitmap);
if (shadow) {
paint.setShadowLayer(10, 0, 0, getCol(ColorCache.X.color_number_wall_shadow));
}
c.drawText(fullText, 0, (height / 2) + (bounds.height() / 2), paint);
return bitmap;
} catch (Exception e) {
if (JoH.ratelimit("icon-failure", 60)) {
UserError.Log.e(TAG, "Cannot create number icon: " + e);
}
return null;
}
}
}
public float getFontHeight(Paint paint, String str) {
Rect rect = new Rect();
paint.getTextBounds(str, 0, str.length(), rect);
return rect.height();
}
public PicturePasswordView( Context context, AttributeSet attrs )
{
super( context, attrs );
setScaleType( ScaleType.CENTER_CROP );
mRandom = new Random();
mSeed = mRandom.nextInt();
mGridSize = DEFAULT_GRID_SIZE;
///////////////////////
// Initialize Paints //
///////////////////////
final DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
final float shadowOff = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 2, displayMetrics );
mPaint = new Paint( Paint.LINEAR_TEXT_FLAG );
mPaint.setColor( Color.WHITE );
mPaint.setShadowLayer( 10, shadowOff, shadowOff, Color.BLACK );
mPaint.setTextSize( TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, FONT_SIZE, displayMetrics ) );
mPaint.setAntiAlias( true );
mCirclePaint = new Paint( Paint.ANTI_ALIAS_FLAG );
mCirclePaint.setColor( Color.argb( 255, 0x33, 0xb5, 0xe5 ) );
mCirclePaint.setStyle( Paint.Style.STROKE );
mCirclePaint.setStrokeWidth( 5 );
mUnlockPaint = new Paint( Paint.ANTI_ALIAS_FLAG );
mTextBounds = new Rect();
mPaint.getTextBounds( "8", 0, 1, mTextBounds );
///////////////////////////
// Initialize animations //
///////////////////////////
mScale = 1.0f;
mAnimator = new ObjectAnimator();
mAnimator.setTarget( this );
mAnimator.setFloatValues( 0, 1 );
mAnimator.setPropertyName( "scale" );
mAnimator.setDuration( 200 );
mCircleAnimator = new ObjectAnimator();
mCircleAnimator.setTarget( this );
mCircleAnimator.setPropertyName( "internalUnlockProgress" ); // ugh!
mCircleAnimator.setDuration( 300 );
///////////////////////
// Hide/show numbers //
///////////////////////
mShowNumbers = true;
TypedArray a = context.getTheme().obtainStyledAttributes( attrs, R.styleable.PicturePasswordView, 0, 0 );
try
{
mShowNumbers = a.getBoolean( R.styleable.PicturePasswordView_showNumbers, true );
}
finally
{
a.recycle();
}
//////////////////////
// Initialize sizes //
//////////////////////
mCircleSize = ( int ) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 6, displayMetrics );
mCircleSpacing = ( int ) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 5, displayMetrics );
mCirclePadding = ( int ) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 10, displayMetrics );
}
/**
* calculates the approximate height of a text, depending on a demo text
* avoid repeated calls (e.g. inside drawing methods)
*
* @param paint
* @param demoText
* @return
*/
public static int calcTextHeight(Paint paint, String demoText) {
Rect r = new Rect();
paint.getTextBounds(demoText, 0, demoText.length(), r);
return r.height();
}