下面列出了android.text.StaticLayout#draw ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
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);
}
/**
* 画一行歌词
* @param y 歌词中心 Y 坐标
*/
private void drawText(Canvas canvas, StaticLayout staticLayout, float y) {
canvas.save();
canvas.translate(mLrcPadding, y - staticLayout.getHeight() / 2);
staticLayout.draw(canvas);
canvas.restore();
}
@Override
protected void onDraw(Canvas canvas) {
if (titleLayout != null) {
canvas.save();
canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), titleY);
titleLayout.draw(canvas);
canvas.restore();
}
if (descriptionLayout != null) {
descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
canvas.save();
canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), descriptionY);
descriptionLayout.draw(canvas);
canvas.restore();
}
if (descriptionLayout2 != null) {
descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
canvas.save();
canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), description2Y);
descriptionLayout2.draw(canvas);
canvas.restore();
}
if (!linkLayout.isEmpty()) {
descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkText));
int offset = 0;
for (int a = 0; a < linkLayout.size(); a++) {
StaticLayout layout = linkLayout.get(a);
if (layout.getLineCount() > 0) {
canvas.save();
canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), linkY + offset);
if (pressedLink == a) {
canvas.drawPath(urlPath, Theme.linkSelectionPaint);
}
layout.draw(canvas);
canvas.restore();
offset += layout.getLineBottom(layout.getLineCount() - 1);
}
}
}
letterDrawable.draw(canvas);
if (drawLinkImageView) {
linkImageView.draw(canvas);
}
if (needDivider) {
if (LocaleController.isRTL) {
canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline), getMeasuredHeight() - 1, Theme.dividerPaint);
} else {
canvas.drawLine(AndroidUtilities.dp(AndroidUtilities.leftBaseline), getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, Theme.dividerPaint);
}
}
}
/**
* 给图片添加带文字和图片的水印,水印会根据图片宽高自动缩放处理
*
* @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);
}
@Override
protected void onDraw(Canvas canvas) {
if (titleLayout != null) {
canvas.save();
canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), titleY);
titleLayout.draw(canvas);
canvas.restore();
}
if (descriptionLayout != null) {
descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
canvas.save();
canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), descriptionY);
descriptionLayout.draw(canvas);
canvas.restore();
}
if (descriptionLayout2 != null) {
descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
canvas.save();
canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), description2Y);
descriptionLayout2.draw(canvas);
canvas.restore();
}
if (!linkLayout.isEmpty()) {
descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkText));
int offset = 0;
for (int a = 0; a < linkLayout.size(); a++) {
StaticLayout layout = linkLayout.get(a);
if (layout.getLineCount() > 0) {
canvas.save();
canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), linkY + offset);
if (pressedLink == a) {
canvas.drawPath(urlPath, Theme.linkSelectionPaint);
}
layout.draw(canvas);
canvas.restore();
offset += layout.getLineBottom(layout.getLineCount() - 1);
}
}
}
letterDrawable.draw(canvas);
if (drawLinkImageView) {
linkImageView.draw(canvas);
}
if (needDivider) {
if (LocaleController.isRTL) {
canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline), getMeasuredHeight() - 1, Theme.dividerPaint);
} else {
canvas.drawLine(AndroidUtilities.dp(AndroidUtilities.leftBaseline), getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, Theme.dividerPaint);
}
}
}
@Override
protected void onDraw(Canvas canvas)
{
paint.setColor(Color.argb(255, colors[0] + (int) ((colors[1] - colors[0]) * bubbleProgress), colors[2] + (int) ((colors[3] - colors[2]) * bubbleProgress), colors[4] + (int) ((colors[5] - colors[4]) * bubbleProgress)));
int y = (int) Math.ceil((getMeasuredHeight() - AndroidUtilities.dp(24 + 30)) * progress);
rect.set(scrollX, AndroidUtilities.dp(12) + y, scrollX + AndroidUtilities.dp(5), AndroidUtilities.dp(12 + 30) + y);
canvas.drawRoundRect(rect, AndroidUtilities.dp(2), AndroidUtilities.dp(2), paint);
if ((pressed || bubbleProgress != 0))
{
paint.setAlpha((int) (255 * bubbleProgress));
int progressY = y + AndroidUtilities.dp(30);
y -= AndroidUtilities.dp(46);
float diff = 0;
if (y <= AndroidUtilities.dp(12))
{
diff = AndroidUtilities.dp(12) - y;
y = AndroidUtilities.dp(12);
}
float raduisTop;
float raduisBottom;
canvas.translate(AndroidUtilities.dp(10), y);
if (diff <= AndroidUtilities.dp(29))
{
raduisTop = AndroidUtilities.dp(44);
raduisBottom = AndroidUtilities.dp(4) + (diff / AndroidUtilities.dp(29)) * AndroidUtilities.dp(40);
}
else
{
diff -= AndroidUtilities.dp(29);
raduisBottom = AndroidUtilities.dp(44);
raduisTop = AndroidUtilities.dp(4) + (1.0f - diff / AndroidUtilities.dp(29)) * AndroidUtilities.dp(40);
}
if (LocaleController.isRTL && (radii[0] != raduisTop || radii[6] != raduisBottom) || !LocaleController.isRTL && (radii[2] != raduisTop || radii[4] != raduisBottom))
{
if (LocaleController.isRTL)
{
radii[0] = radii[1] = raduisTop;
radii[6] = radii[7] = raduisBottom;
}
else
{
radii[2] = radii[3] = raduisTop;
radii[4] = radii[5] = raduisBottom;
}
path.reset();
rect.set(LocaleController.isRTL ? AndroidUtilities.dp(10) : 0, 0, AndroidUtilities.dp(LocaleController.isRTL ? 98 : 88), AndroidUtilities.dp(88));
path.addRoundRect(rect, radii, Path.Direction.CW);
path.close();
}
StaticLayout layoutToDraw = letterLayout != null ? letterLayout : oldLetterLayout;
if (layoutToDraw != null)
{
canvas.save();
canvas.scale(bubbleProgress, bubbleProgress, scrollX, progressY - y);
canvas.drawPath(path, paint);
canvas.translate(textX, textY);
layoutToDraw.draw(canvas);
canvas.restore();
}
}
if ((pressed && letterLayout != null && bubbleProgress < 1.0f) || (!pressed || letterLayout == null) && bubbleProgress > 0.0f)
{
long newTime = System.currentTimeMillis();
long dt = (newTime - lastUpdateTime);
if (dt < 0 || dt > 17)
{
dt = 17;
}
lastUpdateTime = newTime;
invalidate();
if (pressed && letterLayout != null)
{
bubbleProgress += dt / 120.0f;
if (bubbleProgress > 1.0f)
{
bubbleProgress = 1.0f;
}
}
else
{
bubbleProgress -= dt / 120.0f;
if (bubbleProgress < 0.0f)
{
bubbleProgress = 0.0f;
}
}
}
}
@Override
protected void onDraw(Canvas canvas) {
if (letters.isEmpty()) {
return;
}
float height = letters.get(0).getHeight();
canvas.save();
canvas.translate(getPaddingLeft(), (getMeasuredHeight() - height) / 2);
int count = Math.max(letters.size(), oldLetters.size());
for (int a = 0; a < count; a++) {
canvas.save();
StaticLayout old = a < oldLetters.size() ? oldLetters.get(a) : null;
StaticLayout layout = a < letters.size() ? letters.get(a) : null;
if (progress > 0) {
if (old != null) {
textPaint.setAlpha((int) (255 * progress));
canvas.save();
canvas.translate(0, (progress - 1.0f) * height);
old.draw(canvas);
canvas.restore();
if (layout != null) {
textPaint.setAlpha((int) (255 * (1.0f - progress)));
canvas.translate(0, progress * height);
}
} else {
textPaint.setAlpha(255);
}
} else if (progress < 0) {
if (old != null) {
textPaint.setAlpha((int) (255 * -progress));
canvas.save();
canvas.translate(0, (1.0f + progress) * height);
old.draw(canvas);
canvas.restore();
}
if (layout != null) {
if (a == count - 1 || old != null) {
textPaint.setAlpha((int) (255 * (1.0f + progress)));
canvas.translate(0, progress * height);
} else {
textPaint.setAlpha(255);
}
}
} else if (layout != null) {
textPaint.setAlpha(255);
}
if (layout != null) {
layout.draw(canvas);
}
canvas.restore();
canvas.translate(layout != null ? layout.getLineWidth(0) : old.getLineWidth(0) + AndroidUtilities.dp(1), 0);
}
canvas.restore();
}
@Override
protected void onDraw(Canvas canvas) {
if (scrollable()) {
if (mShowIndicator) {
drawIndicator(canvas);
}
for (int i = 0; i < mLineCount; i++) {
float x = 0;
switch (mTextAlign) {
case LEFT:
x = INDICATOR_ICON_PLAY_MARGIN_LEFT + INDICATOR_LINE_MARGIN + mBtnPlayRect.width();
break;
case CENTER:
x = getWidth() * 0.5f;
break;
case RIGHT:
x = getWidth() - INDICATOR_LINE_MARGIN * 2 - mTimerRect.width() - INDICATOR_ICON_PLAY_MARGIN_LEFT;
break;
}
float y;
if (mEnableLineFeed && i > 0) {
y = getMeasuredHeight() * 0.5f + i * mLineHeight - mScrollY + mLineFeedRecord.get(i - 1);
} else {
y = getMeasuredHeight() * 0.5f + i * mLineHeight - mScrollY;
}
// float y = getHeight() * 0.5f + i * mLineHeight - mScrollY;
if (y < 0) {
continue;
}
if (y > getHeight()) {
break;
}
if (i == mCurrentPlayLine - 1) {
mTextPaint.setColor(mHighLightColor);
} else if (i == mLineNumberUnderIndicator && mShowIndicator) {
mTextPaint.setColor(Color.LTGRAY);
} else {
mTextPaint.setColor(mDefaultColor);
}
if (mIsShade && (y > getHeight() - mShaderWidth || y < mShaderWidth)) {
if (y < mShaderWidth) {
mTextPaint.setAlpha(26 + (int) (23000.0f * y / mShaderWidth * 0.01f));
} else {
mTextPaint.setAlpha(26 + (int) (23000.0f * (getHeight() - y) / mShaderWidth * 0.01f));
}
} else {
mTextPaint.setAlpha(255);
}
if (mEnableLineFeed) {
StaticLayout staticLayout = new StaticLayout(mLyricInfo.songLines.get(i).content, mTextPaint,
mMaxLength,
Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
canvas.save();
canvas.translate(x, y);
staticLayout.draw(canvas);
canvas.restore();
} else {
canvas.drawText(mLyricInfo.songLines.get(i).content, x, y, mTextPaint);
}
}
} else {
mTextPaint.setColor(mHintColor);
canvas.drawText(mDefaultHint, getMeasuredWidth() / 2, getMeasuredHeight() / 2, mTextPaint);
}
}
/**
* 给图片添加带文字和图片的水印,水印会根据图片宽高自动缩放处理
*
* @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 static void drawMultilineText(Canvas c, StaticLayout textLayout,
float x, float y,
TextPaint paint,
PointF anchor, float angleDegrees) {
float drawOffsetX = 0.f;
float drawOffsetY = 0.f;
float drawWidth;
float drawHeight;
final float lineHeight = paint.getFontMetrics(mFontMetricsBuffer);
drawWidth = textLayout.getWidth();
drawHeight = textLayout.getLineCount() * lineHeight;
// 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 += drawHeight;
// 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 -= drawWidth * 0.5f;
drawOffsetY -= drawHeight * 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(
drawWidth,
drawHeight,
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.translate(drawOffsetX, drawOffsetY);
textLayout.draw(c);
c.restore();
} else {
if (anchor.x != 0.f || anchor.y != 0.f) {
drawOffsetX -= drawWidth * anchor.x;
drawOffsetY -= drawHeight * anchor.y;
}
drawOffsetX += x;
drawOffsetY += y;
c.save();
c.translate(drawOffsetX, drawOffsetY);
textLayout.draw(c);
c.restore();
}
paint.setTextAlign(originalTextAlign);
}
private void drawTextLayout(Canvas canvas) {
StaticLayout layout = textLayout;
if (layout == null) {
// Nothing to draw.
return;
}
int saveCount = canvas.save();
canvas.translate(textLeft, textTop);
if (Color.alpha(windowColor) > 0) {
paint.setColor(windowColor);
canvas.drawRect(-textPaddingX, 0, layout.getWidth() + textPaddingX, layout.getHeight(),
paint);
}
if (Color.alpha(backgroundColor) > 0) {
paint.setColor(backgroundColor);
float previousBottom = layout.getLineTop(0);
int lineCount = layout.getLineCount();
for (int i = 0; i < lineCount; i++) {
lineBounds.left = layout.getLineLeft(i) - textPaddingX;
lineBounds.right = layout.getLineRight(i) + textPaddingX;
lineBounds.top = previousBottom;
lineBounds.bottom = layout.getLineBottom(i);
previousBottom = lineBounds.bottom;
canvas.drawRoundRect(lineBounds, cornerRadius, cornerRadius, paint);
}
}
if (edgeType == CaptionStyleCompat.EDGE_TYPE_OUTLINE) {
textPaint.setStrokeJoin(Join.ROUND);
textPaint.setStrokeWidth(outlineWidth);
textPaint.setColor(edgeColor);
textPaint.setStyle(Style.FILL_AND_STROKE);
layout.draw(canvas);
} else if (edgeType == CaptionStyleCompat.EDGE_TYPE_DROP_SHADOW) {
textPaint.setShadowLayer(shadowRadius, shadowOffset, shadowOffset, edgeColor);
} else if (edgeType == CaptionStyleCompat.EDGE_TYPE_RAISED
|| edgeType == CaptionStyleCompat.EDGE_TYPE_DEPRESSED) {
boolean raised = edgeType == CaptionStyleCompat.EDGE_TYPE_RAISED;
int colorUp = raised ? Color.WHITE : edgeColor;
int colorDown = raised ? edgeColor : Color.WHITE;
float offset = shadowRadius / 2f;
textPaint.setColor(foregroundColor);
textPaint.setStyle(Style.FILL);
textPaint.setShadowLayer(shadowRadius, -offset, -offset, colorUp);
layout.draw(canvas);
textPaint.setShadowLayer(shadowRadius, offset, offset, colorDown);
}
textPaint.setColor(foregroundColor);
textPaint.setStyle(Style.FILL);
layout.draw(canvas);
textPaint.setShadowLayer(0, 0, 0, 0);
canvas.restoreToCount(saveCount);
}
/**
* Share Button Click.
* get hadith text and create bitmap with hadith text and share it.
*/
private void onShareButtonClicked(String subject, String body) {
// check if app grant write external storage permission.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// check permission for marshmellow.
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Camera permission has not been granted.
// Camera permission has not been granted yet. Request it directly.
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
return;
}
}
// create image from hadith and try share it
Resources resources = getResources();
// Create background bitmap
Bitmap backgroundBitmap = BitmapFactory.decodeResource(resources, R.drawable.backgroundtile);
Bitmap.Config config = backgroundBitmap.getConfig();
if (config == null) {
config = Bitmap.Config.ARGB_8888;
}
int width = 600 + (body.length() / 512) * 50;//backgroundBitmap.getWidth();
// Create logo bitmap
Bitmap logoBitmap = BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher);
logoBitmap = Bitmap.createScaledBitmap(logoBitmap, 128, 128, false);
logoBitmap = logoBitmap.copy(config, false);
int padding = 15;
// Initiate text paint objects
TextPaint titleTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG);
titleTextPaint.setStyle(Paint.Style.FILL);
titleTextPaint.setTextSize(28);
titleTextPaint.setColor(Color.rgb(64, 0, 0));
titleTextPaint.setTypeface(Typeface.createFromAsset(getActivity().getAssets(), "fonts/simple.otf"));
StaticLayout titleStaticLayout = new StaticLayout("منظم المسلم" + "\n" + subject, titleTextPaint, width - 3 * padding - logoBitmap.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1.4f, 0.1f, false);
TextPaint matnTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG);
matnTextPaint.setStyle(Paint.Style.FILL);
matnTextPaint.setTextSize(30);
matnTextPaint.setColor(Color.BLACK);
matnTextPaint.setTypeface(Typeface.createFromAsset(getActivity().getAssets(), "fonts/simple.otf"));
StaticLayout matnStaticLayout = new StaticLayout(body + "\n", matnTextPaint, width - 2 * padding, Layout.Alignment.ALIGN_CENTER, 1.4f, 0.1f, false);
int height = padding + Math.max(titleStaticLayout.getHeight(), logoBitmap.getHeight()) + padding + matnStaticLayout.getHeight() + padding;
Bitmap bitmap = backgroundBitmap.copy(config, true);
bitmap = Bitmap.createScaledBitmap(bitmap, width, height, false);
// create canvas and draw text on image.
Canvas canvas = new Canvas(bitmap);
canvas.save();
tileBitmap(canvas, backgroundBitmap);
canvas.drawBitmap(logoBitmap, width - padding - logoBitmap.getWidth(), padding, null);
canvas.translate(padding, 2 * padding);
titleStaticLayout.draw(canvas);
canvas.translate(0, padding + logoBitmap.getHeight());
matnStaticLayout.draw(canvas);
canvas.restore();
// share bitmap.
shareImage(bitmap);
}
public Bitmap convertToBitmapFromText() {
if (mTextSize == 0.0F) {
throw new WaterMarkCreatorException("Did not provide the text size");
}
if (mTextColor == 0) {
throw new WaterMarkCreatorException("Did not provide the text color");
}
TextPaint paint = new TextPaint();
paint.setColor(mTextColor);
paint.setTextSize(mTextSize);
paint.setStrokeWidth(5);
paint.setTypeface(Typeface.MONOSPACE);
paint.setAntiAlias(true);
paint.setTextAlign(Paint.Align.LEFT);
//ascent : The recommended distance above the baseline for singled spaced text
float baseline = (int) (-paint.ascent() + 3f); // ascent() is negative
Log.e("test", " " + paint.ascent() + " baseline: " + baseline);
// First decode with Rect to check dimensions
Rect bounds = new Rect();
paint.getTextBounds(mText.toString(), 0, mText.length(), bounds);
int boundWidth = bounds.width() + MARGIN_RIGHT;
// mRequestWidth must be in pixels
if (boundWidth > mTextMaxWidth) {
boundWidth = mTextMaxWidth;
}
StaticLayout staticLayout = new StaticLayout(mText, 0, mText.length(),
paint, mTextMaxWidth, android.text.Layout.Alignment.ALIGN_NORMAL, 1.0f,
1.0f, false);
int lineCount = staticLayout.getLineCount();
//Descent: The recommended distance below the baseline for singled spaced text
int height = (int) (baseline + paint.descent() + 3) * lineCount + 10;
Bitmap image = Bitmap.createBitmap(boundWidth, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(image);
canvas.drawARGB(0xFF, 0xFF, 0xFF, 0xFF);
staticLayout.draw(canvas);
return image;
}
/**
* 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;
}
@SuppressWarnings("PMD.NPathComplexity") // TODO break this method up
private void drawTextLayout(Canvas canvas) {
StaticLayout layout = textLayout;
if (layout == null) {
// Nothing to draw.
return;
}
int saveCount = canvas.save();
canvas.translate(textLeft, textTop);
if (Color.alpha(windowColor) > 0) {
paint.setColor(windowColor);
canvas.drawRect(-textPaddingX, 0, layout.getWidth() + textPaddingX, layout.getHeight(),
paint);
}
if (Color.alpha(backgroundColor) > 0) {
paint.setColor(backgroundColor);
float previousBottom = layout.getLineTop(0);
int lineCount = layout.getLineCount();
for (int i = 0; i < lineCount; i++) {
lineBounds.left = layout.getLineLeft(i) - textPaddingX;
lineBounds.right = layout.getLineRight(i) + textPaddingX;
lineBounds.top = previousBottom;
lineBounds.bottom = layout.getLineBottom(i);
previousBottom = lineBounds.bottom;
canvas.drawRoundRect(lineBounds, cornerRadius, cornerRadius, paint);
}
}
if (edgeType == CaptionStyleCompat.EDGE_TYPE_OUTLINE) {
textPaint.setStrokeJoin(Join.ROUND);
textPaint.setStrokeWidth(outlineWidth);
textPaint.setColor(edgeColor);
textPaint.setStyle(Style.FILL_AND_STROKE);
layout.draw(canvas);
} else if (edgeType == CaptionStyleCompat.EDGE_TYPE_DROP_SHADOW) {
textPaint.setShadowLayer(shadowRadius, shadowOffset, shadowOffset, edgeColor);
} else if (edgeType == CaptionStyleCompat.EDGE_TYPE_RAISED
|| edgeType == CaptionStyleCompat.EDGE_TYPE_DEPRESSED) {
boolean raised = edgeType == CaptionStyleCompat.EDGE_TYPE_RAISED;
int colorUp = raised ? Color.WHITE : edgeColor;
int colorDown = raised ? edgeColor : Color.WHITE;
float offset = shadowRadius / 2;
textPaint.setColor(foregroundColor);
textPaint.setStyle(Style.FILL);
textPaint.setShadowLayer(shadowRadius, -offset, -offset, colorUp);
layout.draw(canvas);
textPaint.setShadowLayer(shadowRadius, offset, offset, colorDown);
}
textPaint.setColor(foregroundColor);
textPaint.setStyle(Style.FILL);
layout.draw(canvas);
textPaint.setShadowLayer(0, 0, 0, 0);
canvas.restoreToCount(saveCount);
}
@Override
protected void onDraw(Canvas canvas) {
if (letters.isEmpty()) {
return;
}
float height = letters.get(0).getHeight();
canvas.save();
canvas.translate(getPaddingLeft(), (getMeasuredHeight() - height) / 2);
int count = Math.max(letters.size(), oldLetters.size());
for (int a = 0; a < count; a++) {
canvas.save();
StaticLayout old = a < oldLetters.size() ? oldLetters.get(a) : null;
StaticLayout layout = a < letters.size() ? letters.get(a) : null;
if (progress > 0) {
if (old != null) {
textPaint.setAlpha((int) (255 * progress));
canvas.save();
canvas.translate(0, (progress - 1.0f) * height);
old.draw(canvas);
canvas.restore();
if (layout != null) {
textPaint.setAlpha((int) (255 * (1.0f - progress)));
canvas.translate(0, progress * height);
}
} else {
textPaint.setAlpha(255);
}
} else if (progress < 0) {
if (old != null) {
textPaint.setAlpha((int) (255 * -progress));
canvas.save();
canvas.translate(0, (1.0f + progress) * height);
old.draw(canvas);
canvas.restore();
}
if (layout != null) {
if (a == count - 1 || old != null) {
textPaint.setAlpha((int) (255 * (1.0f + progress)));
canvas.translate(0, progress * height);
} else {
textPaint.setAlpha(255);
}
}
} else if (layout != null) {
textPaint.setAlpha(255);
}
if (layout != null) {
layout.draw(canvas);
}
canvas.restore();
canvas.translate(layout != null ? layout.getLineWidth(0) : old.getLineWidth(0) + AndroidUtilities.dp(1), 0);
}
canvas.restore();
}
public static void drawMultilineText(Canvas c, StaticLayout textLayout,
float x, float y,
TextPaint paint,
MPPointF anchor, float angleDegrees) {
float drawOffsetX = 0.f;
float drawOffsetY = 0.f;
float drawWidth;
float drawHeight;
final float lineHeight = paint.getFontMetrics(mFontMetricsBuffer);
drawWidth = textLayout.getWidth();
drawHeight = textLayout.getLineCount() * lineHeight;
// 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 += drawHeight;
// 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 -= drawWidth * 0.5f;
drawOffsetY -= drawHeight * 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(
drawWidth,
drawHeight,
angleDegrees);
translateX -= rotatedSize.width * (anchor.x - 0.5f);
translateY -= rotatedSize.height * (anchor.y - 0.5f);
FSize.recycleInstance(rotatedSize);
}
c.save();
c.translate(translateX, translateY);
c.rotate(angleDegrees);
c.translate(drawOffsetX, drawOffsetY);
textLayout.draw(c);
c.restore();
} else {
if (anchor.x != 0.f || anchor.y != 0.f) {
drawOffsetX -= drawWidth * anchor.x;
drawOffsetY -= drawHeight * anchor.y;
}
drawOffsetX += x;
drawOffsetY += y;
c.save();
c.translate(drawOffsetX, drawOffsetY);
textLayout.draw(c);
c.restore();
}
paint.setTextAlign(originalTextAlign);
}
/**
* build a bitmap from a text.
*
* @return {@link Bitmap} the bitmap return.
*/
public static Bitmap textAsBitmap(Context context, WatermarkText watermarkText) {
TextPaint watermarkPaint = new TextPaint();
watermarkPaint.setColor(watermarkText.getTextColor());
watermarkPaint.setStyle(watermarkText.getTextStyle());
if (watermarkText.getTextAlpha() >= 0 && watermarkText.getTextAlpha() <= 255) {
watermarkPaint.setAlpha(watermarkText.getTextAlpha());
}
float value = (float) watermarkText.getTextSize();
int pixel = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
value, context.getResources().getDisplayMetrics());
watermarkPaint.setTextSize(pixel);
if (watermarkText.getTextShadowBlurRadius() != 0
|| watermarkText.getTextShadowXOffset() != 0
|| watermarkText.getTextShadowYOffset() != 0) {
watermarkPaint.setShadowLayer(watermarkText.getTextShadowBlurRadius(),
watermarkText.getTextShadowXOffset(),
watermarkText.getTextShadowYOffset(),
watermarkText.getTextShadowColor());
}
if (watermarkText.getTextFont() != 0) {
Typeface typeface = ResourcesCompat.getFont(context, watermarkText.getTextFont());
watermarkPaint.setTypeface(typeface);
}
watermarkPaint.setAntiAlias(true);
watermarkPaint.setTextAlign(Paint.Align.LEFT);
watermarkPaint.setStrokeWidth(5);
float baseline = (int) (-watermarkPaint.ascent() + 1f);
Rect bounds = new Rect();
watermarkPaint.getTextBounds(watermarkText.getText(),
0, watermarkText.getText().length(), bounds);
int boundWidth = bounds.width() + 20;
int mTextMaxWidth = (int) watermarkPaint.measureText(watermarkText.getText());
if (boundWidth > mTextMaxWidth) {
boundWidth = mTextMaxWidth;
}
StaticLayout staticLayout = new StaticLayout(watermarkText.getText(),
0, watermarkText.getText().length(),
watermarkPaint, mTextMaxWidth, android.text.Layout.Alignment.ALIGN_NORMAL, 2.0f,
2.0f, false);
int lineCount = staticLayout.getLineCount();
int height = (int) (baseline + watermarkPaint.descent() + 3) * lineCount;
Bitmap image = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
if (boundWidth > 0 && height > 0) {
image = Bitmap.createBitmap(boundWidth, height, Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(image);
canvas.drawColor(watermarkText.getBackgroundColor());
staticLayout.draw(canvas);
return image;
}
public static void drawMultilineText(Canvas c, StaticLayout textLayout,
float x, float y,
TextPaint paint,
MPPointF anchor, float angleDegrees) {
float drawOffsetX = 0.f;
float drawOffsetY = 0.f;
float drawWidth;
float drawHeight;
final float lineHeight = paint.getFontMetrics(mFontMetricsBuffer);
drawWidth = textLayout.getWidth();
drawHeight = textLayout.getLineCount() * lineHeight;
// 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 += drawHeight;
// 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 -= drawWidth * 0.5f;
drawOffsetY -= drawHeight * 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(
drawWidth,
drawHeight,
angleDegrees);
translateX -= rotatedSize.width * (anchor.x - 0.5f);
translateY -= rotatedSize.height * (anchor.y - 0.5f);
FSize.recycleInstance(rotatedSize);
}
c.save();
c.translate(translateX, translateY);
c.rotate(angleDegrees);
c.translate(drawOffsetX, drawOffsetY);
textLayout.draw(c);
c.restore();
} else {
if (anchor.x != 0.f || anchor.y != 0.f) {
drawOffsetX -= drawWidth * anchor.x;
drawOffsetY -= drawHeight * anchor.y;
}
drawOffsetX += x;
drawOffsetY += y;
c.save();
c.translate(drawOffsetX, drawOffsetY);
textLayout.draw(c);
c.restore();
}
paint.setTextAlign(originalTextAlign);
}
public static Bitmap textAsBitmap(StringBuilder text, Context context) {
TextPaint textPaint = new TextPaint();
textPaint.setColor(Color.GRAY);
textPaint.setAntiAlias(true);
textPaint.setTypeface(Typeface.MONOSPACE);
textPaint.setTextSize(12);
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels; //
StaticLayout layout = new StaticLayout(text, textPaint, width,
Layout.Alignment.ALIGN_CENTER, 1f, 0.0f, true);
Bitmap bitmap = Bitmap.createBitmap(layout.getWidth() + 20,
layout.getHeight() + 20, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.translate(10, 10);
canvas.drawColor(Color.WHITE);
// canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);//绘制透明色
layout.draw(canvas);
return bitmap;
}