Android TextView显示不下问题

539 阅读2分钟

不知道你们在写需求的时候,会不会碰到这么一个UI问题,就是一个文本,然后文本右边还有个标签,或者几个标签,标签必须挨着文字左侧,然后标签的宽度是固定的,文本是服务器请求的数据,所以宽度不能固定,但是他们的父布局是有一个固定的宽度的。

然后问题就是当文字过长,超过父布局固定的宽度,这样的话标签就会被挤出去,UI需要如果文字的宽度过长,文字自动缩小。

为了实现这样的效果,就特地弄个扩展的TextView,这个TextView必须是在一个父容器有固定宽度,且标签有固定宽度的场景使用,至于那种给TextView给定宽度然后超出宽度文字自动缩小的场景,因为项目中已经有这种控件了,就不再写出来了,这边思路的话分以下几个步骤

  1. 获取当前TextView的父容器的宽度
  2. 获取当前父容器所有子View,并且遍历,获取所有子View的宽度 外边距 内边距,(当然要把当前的TextView剔除出去) 然后用父容器的宽度减去刚刚得到的所有宽度,就是TextView能展示的最大宽度
  3. 当前已经有了TextView的最大宽度,接下来就是,测量当前TextView文本的宽度
  4. 循环调用检测的方法,如果文字宽度一直超过最大宽度,文字大小就一直减小,如果怕陷入死循环可以定一个最大数值,超过这个值就不执行循环了
  5. 如果是在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);
    }
}