代码改变世界

Android获取TextView文本实际宽度

2015-10-10 14:49  一切尽在掌握  阅读(5480)  评论(0编辑  收藏  举报

转自:http://blog.csdn.net/lizzy115/article/details/7513552

float textWidth = textView.getPaint().measureText(text) + PaddingLeft + PaddingRight; 

 

另外:

 

1)问题
      在Android中实现自适应的TableCtrl控件显示文字信息时,碰到有一个问题,就是需要得到一列中最长的字符串的宽度值。在网上搜索后,发现Android下可以利用 sdk 中已经提供的Paint的 measureText(String text) 方法。于是尝试网上已经给出的代码:
Paint paint = new Paint();float strWidth = paint.measureText(String);
      控件中的各列按以上的调用并取得宽度的最大值,在设置后还是出现了字符串显示时被截断了,明显是返回的宽度值仍然偏小。难道与混杂的字体有关?有没有可能是这样产生的Paint实例只是用到了默认的值?

 

(2)解决的过程
     转念想到了Paint是画图时的重要元素,留意到熟悉的TextView中正是有这样的方法 getPaint() 返回的是TextPaint的实例(the base paint used for the text. Please use this only to consult the Paint's properties and not to change them.)  Paint的运用是与特定的Context中的资源相关联的,现在可以得到解决方案了。利用在TableCtrl中已经保存的Context(实际传入的 是Activity的实例),作如下调用:
view sourceprint?TextView textView = new TextView(mContext); 
Paint paint = textView .getPaint();
view sourceprint?float textWidth = paint.measureText(text);
经过测试,此时得到的textWidth值才是真正想要的。从而TableCtrl中单元格可以达到按最长的文字信息自动扩展显示。

 

(3)进一步的讨论
  

      现在我们可以把注意力转向TextView,在它的构造器里面有重要的一个参数Context,看到其父类View的构造器中对参数Context的 解释:context, The Context the view is running in, through which it can access the current theme, resources, etc. 至此容易看出View的显示是依赖于外部的Context的。
view sourceprint?public TextView (Context context, AttributeSet attrs, int defStyle) 

      super(context, attrs, defStyle); 
      ... 
      mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); 
      mTextPaint.density = getResource().getDisplayMetrics().density; 
      ... 
}

由以上TextView实现相关的部分源码,可以发现TextPaint与Context可用的资源实际上是紧密相关的,也就容易知道之前对measureText方法的调用出现了什么问题。

常常看到在Activity派生类的onCreate()方法中,我们通常需要调用setContentView()设置与当前的Activity相 关联的view进行显示,下面也大体看一下这个过程的发生:Activity的setContentView()方法实际交由其内部的成员 ---Window类别的实例 mWindow来完成(注意到Window为抽象类,实际的mWindow是经过工厂方法产生的PhoneWindow的实例)。继续挖出 PhoneWindow重写setContentView()方法的相关源码:
view sourceprint?@Override
    public void setContentView(View view, ViewGroup.LayoutParams params) { 
        if (mContentParent == null) { 
            installDecor(); 
        } else { 
            mContentParent.removeAllViews(); 
        } 
        mContentParent.addView(view, params); 
        final Callback cb = getCallback(); 
        if (cb != null) { 
            cb.onContentChanged(); 
        } 
    }

而mWindow是作为在Activity中的top-level view被加入进来的,另外可以看到在设置完view之后,PhoneWindow 获取了初始注册的外部回调方法,此时触发调用实现对应的更新操作。