Skip to content

Instantly share code, notes, and snippets.

@ityancs
Created September 25, 2015 07:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ityancs/711e398587273ff2c0fa to your computer and use it in GitHub Desktop.
Save ityancs/711e398587273ff2c0fa to your computer and use it in GitHub Desktop.
A vertical TextView like Chinese old text style
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetrics;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class TextViewVertical extends View {
private Paint paint;
private int mTextPosx = 0;// x坐标
private int mTextPosy = 0;// y坐标
private int mTextWidth = 0;// 绘制宽度
private int mFontHeight = 0;// 绘制字体高度
private float mFontSize = 24;// 字体大小
private int mRealLine = 0;// 字符串真实的行数
private int mLineWidth = 0;//列宽度
private int TextLength = 0;//字符串长度
private int MaxHeight = 500;
private String text = "";//待显示的文字
private Matrix matrix;
private Align textStartAlign = Align.RIGHT;//draw start left or right.//default right
BitmapDrawable drawable = (BitmapDrawable) getBackground();
public TextViewVertical(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public TextViewVertical(Context context, AttributeSet attrs) {
super(context, attrs);
matrix = new Matrix();
paint = new Paint();//新建画笔
paint.setTextAlign(Align.CENTER);//文字居中
paint.setAntiAlias(true);//平滑处理
paint.setColor(Color.BLACK);//默认文字颜色
try {
mFontSize = Float.parseFloat(attrs.getAttributeValue(null, "textSize"));//获取字体大小属性
} catch (Exception e) {
}
}
//设置文字
public final void setText(String text) {
this.text = text;
this.TextLength = text.length();
}
//设置字体大小
public final void setTextSize(float size) {
if (size != paint.getTextSize()) {
mFontSize = size;
}
}
//设置字体颜色
public final void setTextColor(int color) {
paint.setColor(color);
}
//设置字体颜色
public final void setTextARGB(int a, int r, int g, int b) {
paint.setARGB(a, r, g, b);
}
//设置字体
public void setTypeface(Typeface tf) {
if (this.paint.getTypeface() != tf) {
this.paint.setTypeface(tf);
}
}
//设置行宽
public void setLineWidth(int LineWidth) {
mLineWidth = LineWidth;
}
//获取实际宽度
public int getTextWidth() {
return mTextWidth;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.v("TextViewVertical", "onDraw");
if (drawable != null) {
//画背景
Bitmap b = Bitmap.createBitmap(drawable.getBitmap(), 0, 0, mTextWidth, MaxHeight);
canvas.drawBitmap(b, matrix, paint);
}
//画字
draw(canvas, this.text);
}
private void draw(Canvas canvas, String thetext) {
char ch;
mTextPosy = 0;//初始化y坐标
mTextPosx = textStartAlign == Align.LEFT ? mLineWidth : mTextWidth - mLineWidth;//初始化x坐标
for (int i = 0; i < this.TextLength; i++) {
ch = thetext.charAt(i);
if (ch == '\n') {
if (textStartAlign == Align.LEFT) {
mTextPosx += mLineWidth;// 换列
} else {
mTextPosx -= mLineWidth;// 换列
}
mTextPosy = 0;
} else {
mTextPosy += mFontHeight;
if (mTextPosy > this.MaxHeight) {
if (textStartAlign == Align.LEFT) {
mTextPosx += mLineWidth;// 换列
} else {
mTextPosx -= mLineWidth;// 换列
}
i--;
mTextPosy = 0;
} else {
canvas.drawText(String.valueOf(ch), mTextPosx, mTextPosy, paint);
}
}
}
//调用接口方法
//activity.getHandler().sendEmptyMessage(TestFontActivity.UPDATE);
}
//计算文字行数和总宽
private void GetTextInfo(int heightMeasureSpec) {
Log.v("TextViewVertical", "GetTextInfo");
char ch;
int h = 0;
paint.setTextSize(mFontSize);
//获得字宽
if (mLineWidth == 0) {
float[] widths = new float[1];
paint.getTextWidths("正", widths);//获取单个汉字的宽度
mLineWidth = (int) Math.ceil(widths[0] * 1.1 + 2);
}
FontMetrics fm = paint.getFontMetrics();
mFontHeight = (int) (Math.ceil(fm.descent - fm.top) * 0.9);// 获得字体高度
String[] split = text.split("\n");
int maxTextLength = 0;
for (String aSplit : split) {
int length = aSplit.length();
if (length > maxTextLength) {
maxTextLength = length;
}
}
int measureHeight = MeasureSpec.getSize(heightMeasureSpec);
if (measureHeight > 0) {
int fontHeight = maxTextLength * mFontHeight;
if (fontHeight > measureHeight) {
MaxHeight = measureHeight;
} else {
MaxHeight = fontHeight;
}
}
//计算文字行数
mRealLine = 0;
for (int i = 0; i < this.TextLength; i++) {
ch = this.text.charAt(i);
if (ch == '\n') {
mRealLine++;// 真实的行数加一
h = 0;
} else {
h += mFontHeight;
if (h > (MaxHeight > 0 ? MaxHeight : 500)) {
mRealLine++;// 真实的行数加一
i--;
h = 0;
} else {
if (i == this.TextLength - 1) {
mRealLine++;// 真实的行数加一
}
}
}
}
mRealLine++;//额外增加一行
mTextWidth = mLineWidth * mRealLine;//计算文字总宽度
measure(mTextWidth, MaxHeight);//重新调整大小
layout(getLeft(), getTop(), getLeft() + mTextWidth, getTop() + MaxHeight);//重新绘制容器
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.v("宽高", mTextWidth + ":" + MaxHeight);
if (mTextWidth == 0 || MaxHeight == 0) {
GetTextInfo(heightMeasureSpec);
}
setMeasuredDimension(mTextWidth, MaxHeight);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment