以编程方式获取布局的高度和宽度

91

我设计了一个布局,其中LinearLayout有2个子元素LinearLayoutFrameLayout,并在每个子元素中放置不同的视图。

我只想测量FrameLayout的高度和宽度,以便达到我的目的。

在程序中,我正在使用

int height,width;

FrameLayout fr=(FrameLayout)findviewbyid(R.id.fr);
height=fr.getHeight();
width=fr.getWidth();

返回值对于两者都是0

尝试以下代码后,甚至包括: int height, width;

FrameLayout fr=(FrameLayout)findviewbyid(R.id.fr);
height=fr.getMeasuredHeight();
width=fr.getMeasuredWidth();

返回相同的值0

最后我尝试了以下代码, int height,width;

FrameLayout fr=(FrameLayout)findviewbyid(R.id.fr);
height=fr.getgetLayoutParams().height();
width=fr.getLayoutParams().width;

返回给我的是 -2-1

我想要通过编程获取任何布局的高度和宽度的解决方案?


请查看以下问题:https://dev59.com/i2865IYBdhLWcg3whO3E - VinhNT
这是一篇很好的文章,可以帮助你了解安卓视图尺寸是如何设置的以及何时进行设置。https://cheesecakelabs.com/blog/understanding-android-views-dimensions-set/ - Krešimir Prcela
19个回答

174

视图本身有其自己的生命周期,基本如下所示:

  • 附加(Attached)

  • 测量(Measured)

  • 布局(Layout)

  • 绘制(Draw)

因此,根据您尝试获取宽度/高度的时间不同,您可能无法看到您期望看到的内容。例如,如果您在 onCreate 期间执行此操作,则该视图可能尚未被测量;另一方面,如果您在按钮的 onClick 方法中执行此操作,则该视图很可能已经被附加、测量、布局和绘制,因此您将看到预期的值。您应该实现一个 ViewTreeObserver 来确保在适当的时刻获取这些值。

LinearLayout layout = (LinearLayout)findViewById(R.id.YOUR VIEW ID);
ViewTreeObserver vto = layout.getViewTreeObserver(); 
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
    @Override 
    public void onGlobalLayout() { 
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                this.layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            } else {
                this.layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            } 
        int width  = layout.getMeasuredWidth();
        int height = layout.getMeasuredHeight(); 

    } 
});

6
请注意,removeGlobalOnLayoutListener已被弃用,因此在最新的Android API中,您需要编写this.layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);。 - Nicolas Massart
1
如果上面的代码解决方案给出了零高度/宽度,请检查此答案:https://dev59.com/XY3da4cB1Zd3GeqPwTHf#31515283 - Firzen
你并没有使用 var ViewTreeObserver vto,那么为什么要将它赋值给该方法调用呢? - Windgate

44

我想在这里添加一个答案,因为Kotlin有一些方便的方法来实现这个,这比添加和删除onGlobalLayoutListener要美观得多:

只是想要在这里添加一个答案,由于Kotlin有一些方便的方法可以做到这一点,这些方法比添加和删除onGlobalLayoutListener要好看得多:

view.doOnLayout {
    it.measuredWidth
    it.measuredHeight
}
你可以在这里查看更多的便捷方法:链接

2
工作得很顺利。谢谢你,你让我今天过得很愉快。 - Fazal Hussain

40

正如CapDroid所说,您正在尝试在视图绘制之前获取其大小,另一个可能的解决方案是在视图上使用可运行的Post方法:

mView.post(new Runnable() {
        @Override
        public void run() {
            int width = mView.getWidth();
            int height = mView.getHeight();
        }
}

15

我认为你在OnCreate()方法中获取高度和宽度,这就是为什么总是得到0值的原因,因为此时你的视图还没有创建。

尝试在某个按钮点击或其他事件中获取高度和宽度。


我几乎有同样的问题。我是Android的初学者。那么做事情的最佳/方式是什么地方呢?目前我正在onCreate中创建一些按钮并想要定位它们。最好在哪里做这件事呢? - Vlad E. Borovtsov

13

只需提供您的身高,您将获得身高甚至宽度(如果需要)。

/** * 在视图渲染之前获取视图的高度 * @param view 要测量的视图 * @return 视图的高度 */

public static int getViewHeight(View view) {
    WindowManager wm =
            (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();

    int deviceWidth;

    if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2){
        Point size = new Point();
        display.getSize(size);
        deviceWidth = size.x;
    } else {
        deviceWidth = display.getWidth();
    }

    int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(deviceWidth, View.MeasureSpec.AT_MOST);
    int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    view.measure(widthMeasureSpec, heightMeasureSpec);
    return view.getMeasuredHeight(); //        view.getMeasuredWidth();
}

11
在 Kotlin 中,您可以简单地这样做:
fr.post {
    height=fr.height
    width=fr.width
}

7
如果你得到了-1或-2,这也可能是LayoutParams.WRAP_CONTENT(-2)或LayoutParams.MATCH_PARENT(-1)的数字值。

1
如何以像素或 dp 的形式获取此值? - Arpit

7

我曾经遇到过同样的问题,但是在测量之前不想在屏幕上绘制,所以我使用了这种在获取高度和宽度之前先测量视图的方法。

使用示例:

layoutView(view);
int height = view.getHeight();

//...

void layoutView(View view) {
    view.setDrawingCacheEnabled(true);
    int wrapContentSpec = 
        MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
    view.measure(wrapContentSpec, wrapContentSpec);
    view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
}

5

最简单的方法是使用ViewTreeObserver,如果直接使用.height或.width,则会得到值为0,因为视图在绘制到屏幕上之前没有尺寸。以下示例将展示如何使用ViewTreeObserver。

ViewTreeObserver viewTreeObserver = YOUR_VIEW_TO_MEASURE.getViewTreeObserver();
        if (viewTreeObserver.isAlive()) {
            viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {

                    YOUR_VIEW_TO_MEASURE.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    int viewHeight = YOUR_VIEW_TO_MEASURE.getHeight();
                    int viewWeight = YOUR_VIEW_TO_MEASURE.getWidth();

                }
            });
        }

如果您需要使用这个 on 方法,请像这样使用,并且要保存值,可以使用全局变量。

3

尝试使用以下方法:

int width = mView.getMeasuredWidth();

int height = mView.getMeasuredHeight();

或者

int width = mTextView.getMeasuredWidth();

int height = mTextView.getMeasuredHeight();

除非调用onDraw()方法,否则您将永远无法获取这些值。 - Rohit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接