不知道你们在写需求的时候,会不会碰到这么一个UI问题,就是一个文本,然后文本右边还有个标签,或者几个标签,标签必须挨着文字左侧,然后标签的宽度是固定的,文本是服务器请求的数据,所以宽度不能固定,但是他们的父布局是有一个固定的宽度的。
然后问题就是当文字过长,超过父布局固定的宽度,这样的话标签就会被挤出去,UI需要如果文字的宽度过长,文字自动缩小。
为了实现这样的效果,就特地弄个扩展的TextView,这个TextView必须是在一个父容器有固定宽度,且标签有固定宽度的场景使用,至于那种给TextView给定宽度然后超出宽度文字自动缩小的场景,因为项目中已经有这种控件了,就不再写出来了,这边思路的话分以下几个步骤
- 获取当前TextView的父容器的宽度
- 获取当前父容器所有子View,并且遍历,获取所有子View的宽度 外边距 内边距,(当然要把当前的TextView剔除出去) 然后用父容器的宽度减去刚刚得到的所有宽度,就是TextView能展示的最大宽度
- 当前已经有了TextView的最大宽度,接下来就是,测量当前TextView文本的宽度
- 循环调用检测的方法,如果文字宽度一直超过最大宽度,文字大小就一直减小,如果怕陷入死循环可以定一个最大数值,超过这个值就不执行循环了
- 如果是在RecyclerView中使用的话 需要注意会出现一些本来文字很短的,然后它的文字大小也变的跟列表中缩小的文字大小一样了,这是因为RecyclerView使用的缓存,它使用的TextView还是你之前缩小的TextView,所以你换新数据后它的文字大小是不会变的,建议把每次测量后的文字大小与数据源绑定,这样就能有效避免了
贴上代码
public class SelfAdaptionTextView extends TextView {
public SelfAdaptionTextView(Context context) {
super(context);
}
public SelfAdaptionTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public SelfAdaptionTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (getParent() instanceof ViewGroup) {
int textViewIndex = -1;
int textViewMargin = 0;
int margin = 0;
ViewGroup viewGroup = (ViewGroup) getParent();
int totalWidth = viewGroup.getWidth();
for (int i = 0; i < viewGroup.getChildCount(); i++) {
View view = viewGroup.getChildAt(i);
ViewGroup.LayoutParams vlp = view.getLayoutParams();
if (vlp instanceof ViewGroup.MarginLayoutParams){
margin = ((ViewGroup.MarginLayoutParams) vlp).getMarginStart() + ((ViewGroup.MarginLayoutParams) vlp).getMarginEnd();
}
if (view.getTag() instanceof String && view instanceof SelfAdaptionTextView){
textViewIndex = i;
textViewMargin = margin;
}else {
totalWidth = totalWidth - (view.getWidth() + view.getPaddingLeft() + view.getPaddingRight() + margin);
}
}
if (textViewIndex != -1 && textViewIndex <= viewGroup.getChildCount() - 1){
View tView = viewGroup.getChildAt(textViewIndex);
if (tView instanceof TextView) {
//当前View的真实宽度
totalWidth = totalWidth - textViewMargin - tView.getPaddingLeft() - tView.getPaddingRight();
resetTextSize(totalWidth, (TextView) tView);
}
}
}
}
private void resetTextSize(int totalWidth,TextView textView){
float v = textView.getPaint().measureText(textView.getText().toString());
if (v > totalWidth){
float textSize = textView.getTextSize();
textSize = textSize - 1;
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX,textSize);
}else {
return;
}
resetTextSize(totalWidth, textView);
}
}