700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 【Android】获取TextView宽度或高度

【Android】获取TextView宽度或高度

时间:2022-11-19 17:21:40

相关推荐

【Android】获取TextView宽度或高度

需要提前知道的一些东西

Android中获取View的宽度或者高度,可以通过View自带的方法getWidth()getHeight(),但这仅限于layout_widthlayout_height的值是具体的dp或者match_parent,如果值是wrap_content,那么直接调用getWidth()getHeight()方法,可能返回的会是0。直接调用getWidth()getHeight()可能返回0的原因是,View可能还没有被添加到界面上(这里添加到界面上是指View执行了onMeasure方法),View添加到界面上之后,才计算完宽度和高度,所以如果宽度或高度如果设置wrap_content,那么需要在View添加到界面上之后调用,才会返回具体的值。

计算View的宽度/高度

通过getMeasureWidth()/getMeasureHeight()计算

这里以计算高度为例如果高度设置为了wrap_content,可以通过getMeasureHeight()来计算高度

// 用post,表示将获取高度的任务放到TextView的消息队列尾部去做textView.post(new Runnable(){@Overridepublic void run(){// 宽度的测量模式int widthMeasureMode = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.EXACTLY);// 高度的测量模式int heightMeasureMode = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);// 进行宽高的测量textView.measure(widthMeasureMode, heightMeasureMode );// 测量后获取高度int measureHeight = textView.getMeasureHeight();}})

测量模式 Android的测量模式有三种,根据不同的测量模式,会按照不同的方式测量宽高EXACTLY:表示有具体数值,如果宽高设置为具体的数值或者match_parent,我们可以使用EXACTLY的测量模式AT_MOST:表示最大程度的增长,此时父布局将自身可用的最大宽度或者高度传给子View,用来代表子View的最大宽度或高度。如果宽高设置为wrap_content,那么此时表示宽度或者高度不确定,因此可以用AT_MOST模式,让Android去测量它的宽度或高度,但是它不会超过父布局的最大宽度或高度。UNSPECIFIED:表示可以无限增长。例如TextView如果按照这种方式去测量宽度,那么不管文本有多长,最终都会被当作单行去测量宽度。所以如果你想去测量TextView的高度,而你的宽度测量模式用了UNSPECIFIED,那么不管你文本有多长,它永远只返回单行的高度,因为Android认为它只有一行。 注意点 上面用post表示将Runnable放到TextView的消息队列尾部,在TextView添加到界面上之后,会执行这个Runnable上面的方式只适用于TextView高度设置成了wrap_content,而且文本内容不会发生变化或者只在初始化的时候变化一次的情况。如果TextView的文本在使用过程中会发生变化,那么getMeasureHeight()返回的值,只在第一次是正确的,后续文本内容发生变化,它永远返回上一次的高度。这个原因出于我自己的理解,可能是因为在第二次文本变化的时候,post的任务的执行,在TextView布局发生变化之前,所以导致获取的高度值是旧值。上面的方式需要在TextView在初始化的时候,就是visible的情况,如果初始化的时候是Gone,那么可能在第一次getMeasureHeight的时候,返回的值是0,后续变化返回正确的高度,原因同上。

通过ViewTreeObserver中计算高度

ViewTreeObserver可以addOnGlobalLayoutListener(),该方法有个onGlobalLayout回调,这个回调方法会在View添加到界面上之后调用也就是说,我们可以在onGlobalLayout中直接通过getHeight()getWidth()来获取高度或者宽度。

// 获取TextView的ViewTreeObserver对象ViewTreeObserver viewTreeObserver = textView.getViewTreeObserver();// 添加OnGlobalLayoutListenerviewTreeObserver .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {// 调用requestLayout()解决获取的高度是旧值的问题textView.requestLayout();// 获取高度float height = (float) textView.getHeight();topViewTreeObserver.removeOnGlobalLayoutListener(this);}});

requestLayout()一个View调用了requestLayout之后,会给当前View设置一个FORCE_LAYOUT标记,由此向ViewParent请求布局,这样从这个View开始向上一直requestLayout,最终到达ViewRootImpl。ViewRootImpl发现请求了布局,那么就会调用measure方法,确认当前View是否有FORCE_LAYOUT标记,如果有,则会直接进行重新布局。并且设置标记LAYOUT_REQUIRED。所以只要View调用了requestLayout方法,那么会同时去调用measure、onMeasure、layout、onLayout、draw、onDrawa方法(不会马上调用,请求到了ViewRootImpl之后,ViewRootImpl调用measure方法才会一一调用),重新去计算布局。 注意点 上面的方式,在TextView的文本内容发生变化的时候,能够实时获取到TextView的高度,就是因为调用了requestLayout方法,重新去布局、计算宽高,所以使得TextView在getHeight()的时候,获取到的就是最新的,而不是上一次的。如果去掉requestLayout方法,那么他会有和第一种方法一样的问题。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。