最近看了老罗的锤子便签应用,感觉很清新,打开便签第一眼感觉每行文字的行分割线很漂亮。无聊之下,做了一个下划线效果,而且还处于不断修改中
效果图如下:
代码如下:
public class UnderlinedTextView extends TextView {
/** 默认的文字行上下间隔 */
private static final int paddingTop = 20;
private static final int paddingBottom = 30;
private static final int paddingLeft = 30;
private static final int paddingRight = 30;
/** 控件的宽度与高度 */
private int mCanvasWidth;
/** 垂直偏移量 */
private int offsetY = 0;
/** 根据屏幕容量,每行内容截取的初始位置 */
private int mStartIndex = 0;
/** 文本数组 */
private ArrayList<String> dataStr = new ArrayList<String>();
/** 文本 */
private String mText;
/** 文本画笔 */
private Paint mPaint;
/** 分割线画笔 */
private Paint mLPaint;
/** 预估一行可以容纳的字符量 */
private int mEstNumber;
/** 字符串总长度 */
private int mTextLen;
/** 字体高度 */
private int mTextHeight;
public UnderlinedTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public UnderlinedTextView(Context context) {
super(context);
init();
}
private void init() {
mLPaint = new Paint();
mLPaint.setColor(Color.parseColor("#FFF1EDE4"));
mLPaint.setAntiAlias(true);
mLPaint.setDither(true);
mLPaint.setStrokeWidth(3);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
mCanvasWidth = getWidth() - paddingLeft - paddingRight;
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
if (dataStr == null || dataStr.size() == 0) {
mText = getText().toString();
mPaint = getPaint();
mPaint.setColor(Color.parseColor("#FF62331D"));
// 以当前字体大小,衡量一个汉字的占位
float mPerCharLength = mPaint.measureText("A");
// 预估一行可显示多少个字符
mEstNumber = (int) (mCanvasWidth % mPerCharLength == 0 ? mCanvasWidth
/ mPerCharLength
: mCanvasWidth / mPerCharLength + 1);
// 文本总长度
mTextLen = mText.length();
// 字体高度
mTextHeight = getFontHeight();
offsetY = mTextHeight + paddingTop;
while (mStartIndex < mTextLen) {
getSingleLine();
}
}
if (dataStr != null) {
for (int i = 0; i < dataStr.size(); i++) {
drawLine(canvas, dataStr.get(i));
}
}
}
private void drawLine(Canvas canvas, String content) {
if (!TextUtils.isEmpty(content)) {
canvas.drawText(content, paddingLeft, offsetY, mPaint);
offsetY += paddingBottom;
canvas.drawLine(0, offsetY, mCanvasWidth, offsetY, mLPaint);
offsetY += paddingTop + mTextHeight;
}
}
/**
* 根据预估,取出最合适的一行内容
*/
private void getSingleLine() {
// 每次文本截取的末尾位置
int mTempLength = mStartIndex + mEstNumber;
if (mTempLength > mTextLen) {
String lastContent = mText.substring(mStartIndex);
dataStr.add(lastContent);
mStartIndex = mTextLen;
return;
}
// 取出一行预估文本
String content = mText.substring(mStartIndex, mTempLength);
// 预估文本的占位空间
int length = (int) mPaint.measureText(content);
if (length > mCanvasWidth) {
// 如果预估的位置偏大,往回缩
while (length > mCanvasWidth) {
mTempLength--;
if (mTempLength > mStartIndex && mTempLength > mStartIndex) {
content = mText.substring(mStartIndex, mTempLength - 2);
length = (int) mPaint.measureText(content);
}
}
} else if (length < mCanvasWidth) {
// 如果预估的位置偏小,往外伸
while (length < mCanvasWidth) {
mTempLength++;
if (mTempLength < mTextLen && mTempLength > mStartIndex) {
// 临时保持处理结果
String mTempContent = mText.substring(mStartIndex,
mTempLength - 2);
int mTempLen = (int) mPaint.measureText(mTempContent);
// 提前预判处理后是否超出条件,如果超出,保持当前
if (mTempLen < mCanvasWidth) {
content = mTempContent;
length = mTempLen;
} else {
break;
}
}
}
}
// 保存取出的本行内容
dataStr.add(content);
// 重置初始位置
mStartIndex = mTempLength;
}
/**
* 得到字体高度
*
* @return
*/
private int getFontHeight() {
FontMetrics fm = mPaint.getFontMetrics();
return (int) Math.ceil(fm.descent - fm.ascent);
}
}