最近项目里面RecyclerView做4列显示文字标签,但是按UI给的标注设置后,标签还是可能不止占一行,一些小屏手机时就不是预期效果了,于是自己摸索了一个view来根据宽高调节textSize:
代码贴出来,可能还不是很完善,一个思路:
/**
* use to do 如果限定textView的宽度,则根据宽度显示文字,字体大小改变
* 绘制只在居中绘制的样式,其他样式需要自己完善
*
* @author zhangdong on 2018/2/11 0011.
* @version 1.0
* @see .
* @since 1.0
*/
public class WrapContentTextView extends AppCompatTextView {
private static final String TAG = "WrapContentTextView";
private Paint mPaint;
private Boolean isWrapContent = false;//是否开启根据view的宽高调节字体大小
public void setWrapContent(Boolean wrapContent) {
isWrapContent = wrapContent;
invalidate();
}
public Boolean getWrapContent() {
return isWrapContent;
}
public WrapContentTextView(Context context) {
super(context);
init();
}
public WrapContentTextView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.getTheme()
.obtainStyledAttributes(attrs, R.styleable.WrapContentTextView, 0, 0);
isWrapContent = typedArray.getBoolean(R.styleable.WrapContentTextView_isWrapContent, false);
typedArray.recycle();
init();
}
public WrapContentTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
float density = getResources().getDisplayMetrics().density;
Log.d(TAG, "onDraw: ------- 屏幕密度系数density = " + density);
}
@Override
protected void onDraw(Canvas canvas) {
if (isWrapContent) {
int width = getWidth();
int height = getHeight();
Log.d(TAG, "onDraw: ------- View的width = " + width + "; View的height = " + height);
CharSequence text = getText();
if (!TextUtils.isEmpty(text)) {
//文字的字数
int length = text.length();
//view的内边距
int paddingLeft = getPaddingLeft();
int paddingRight = getPaddingRight();
int paddingTop = getPaddingTop();
int paddingBottom = getPaddingBottom();
Log.d(TAG, "onDraw: ------- paddingLeft = " + paddingLeft +
"; paddingTop = " + paddingTop +
"; paddingRight = " + paddingRight +
"; paddingBottom = " + paddingBottom);
//文字可绘制的宽高
int textWidth = width - paddingLeft - paddingRight;
int textHeight = height - paddingTop - paddingBottom;
//一个字可绘制的宽度
int oneWidth = textWidth / length;
//一个字可绘制的宽度与可绘制的高度取最小的值
int textSize = Math.min(oneWidth, textHeight);
Log.d(TAG, "onDraw: ------- 文字长度:" + length +
"; 可绘制的textWidth = " + textWidth +
"; oneWidth = " + oneWidth +
"; 可绘制的textHeight = " + textHeight);
//当前文字的size
float size = getTextSize();
float measureText = getPaint().measureText(text, 0, length);
Log.d(TAG, "onDraw: ------- 初始文字的size = " + size +
"; 初始文字的宽measureText = " + measureText);
//获取当前文字的高度
Paint.FontMetrics fontMetrics = getPaint().getFontMetrics();
float tHeight = fontMetrics.bottom - fontMetrics.top;
Log.d(TAG, "onDraw: ------- 初始文字的fontMetrics.bottom= " + fontMetrics.bottom +
"; 初始文字的fontMetrics.top= " + fontMetrics.top +
"; 初始文字的高度tHeight= " + tHeight);
float newSize = 0;
//新的文字大小根据宽度比例关系得到
float newSizeW = size * textSize * length / measureText;
//新的文字大小根据高度比例关系得到
float newSizeH = size * textHeight / tHeight;
Log.d(TAG, "onDraw: ------- 根据宽度比例关系得到newSizeW= " + newSizeW +
"; 根据高度比例关系得到newSizeH= " + newSizeH);
newSize = Math.min(newSizeW, newSizeH);
Log.d(TAG, "onDraw: ------- 取最小的文字大小设置给画笔newSize : " + newSize);
mPaint.setTextSize(newSize);
mPaint.setColor(getCurrentTextColor());
Rect textRect = new Rect();
mPaint.getTextBounds(text.toString(), 0, length, textRect);
Paint.FontMetrics mPaintFontMetrics = mPaint.getFontMetrics();
float top = mPaintFontMetrics.top;
float bottom = mPaintFontMetrics.bottom;
//文字绘制的x轴起点
int startX = (width - textRect.width() + paddingLeft - paddingRight) / 2;
//文字绘制的中心
int textCenterY = textHeight + paddingTop - textHeight / 2;
//文字绘制的基线 BaseLine
int startY = (int) (textCenterY - (bottom - top) / 2 - top);
Log.d(TAG, "onDraw: ------- textRect.width()= " + textRect.width() +
"; textRect.height()= " + textRect.height());
Log.d(TAG, "onDraw: ------- 绘制的起点:X = " + startX + "; Y = " + startY);
canvas.drawText(text, 0, length, startX, startY, mPaint);
}
} else super.onDraw(canvas);
}
}
需要的自定义属性:是否需要view根据宽高改变textSize
使用:
这一句代码是控制的:
app:isWrapContent="true"
当然也可以在代码里面动态设置,调用方法:
public void setWrapContent(Boolean wrapContent) {
isWrapContent = wrapContent;
invalidate();
}
eg:
wrapContentTextView.setText("好的的一个家,哎呀我大中华");
wrapContentTextView.setWrapContent(true);
运行效果还不错: