写在前面的话
奇葩的需求造就奇葩代码!
需求是这样的:将描述信息只显示一行,而且内容要全部显示。一般这样的描述信息显示不了后面就直接写省略号,用TextView的属性直接可以搞定。如果一定要达到需求所说的那样,那只能将文本的字体缩小,如是程序员开始埋头写代码!
步骤
(1)获取文本的长度,textWidth;
(2)获取显示区域的长度,areaWidth;
(3)比较textWidth和areaWidth,如果textWidth>areaWidth,就缩小字体,直到textWidth<=areaWidth刚好显示字体为止。
实现
1.在values目录下创建attrs.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SingleLineTextView">
<attr name="textContent" format="string"></attr>
<attr name="textSize" format="dimension"></attr>
<attr name="textColor" format="color"></attr>
</declare-styleable>
</resources>
2.创建SingleLineTextView继承自TextView,在构造方法中利用TypedArray获取相应值:
public SingleLineTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray ta = context.obtainStyledAttributes(attrs,
R.styleable.SingleLineTextView, defStyle, 0);
//获取文本
textContent = ta.getString(R.styleable.SingleLineTextView_textContent);
//字体大小
textSize = ta.getDimensionPixelSize(R.styleable.SingleLineTextView_textSize, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
//字体颜色
textColor = ta.getColor(R.styleable.SingleLineTextView_textColor, Color.BLACK);
ta.recycle();
//初始化画笔
initPaint();
}
3.利用画笔Paint,获取文本的长度:
//初始化画笔
private void initPaint() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(textSize);
paint.setColor(textColor);
//获取文本的宽度
textWidth = paint.measureText(textContent);
//文本的高度
textHeight = paint.descent() - paint.ascent();
}
4.重写onMeasure()方法:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthsize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
if (widthMode == MeasureSpec.EXACTLY) {
width = widthsize;
} else {
width = getPaddingLeft() + (int)(textWidth+0.5) + getPaddingRight();
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {
height = getPaddingTop() + (int)(textHeight+0.5) + getPaddingBottom();
}
setMeasuredDimension(width, height);
}
onMeasure()方法的实现是一个常规写法,也可以说是一个固定写法,根据长宽的模式,确定长度和宽度。徐宜生的《Android群英传》里面讲这个很详细!以后可能会写一篇这方面的总结!
5.重写onDraw()方法:
@Override
protected void onDraw(Canvas canvas) {
//如果文本的宽度大于显示的宽度,将字体大小减小
while (textWidth > getWidth()) {
paint.setTextSize(textSize--);
textWidth = paint.measureText(textContent);
}
//让文本居中显示, 画出文本
float textBaseline = (getHeight() - (paint.descent() + paint.ascent())) / 2.0f;
canvas.drawText(textContent, (getWidth() - textWidth) / 2.0f, textBaseline, paint);
}
完全是按照步骤来实现的!
用法
<com.gyw.singlelinetextviewdemo.SingleLineTextView
android:background="#ff0000"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingTop="3dp"
android:singleLine="true"
gyw:textColor="#ffffff"
gyw:textContent="A好好学习好好学习A"
gyw:textSize="18sp" />
记住:
别忘记了命名空间
xmlns:gyw="http://schemas.android.com/apk/res-auto"
效果
源码
最终效果出来了,程序员拿着实现了功能高高兴兴找产品经理,产品经理看了后说:“还是用省略号吧…“。