【问题标题】:Get height and width of a layout programmatically以编程方式获取布局的高度和宽度
【发布时间】:2014-02-21 06:13:20
【问题描述】:

我设计了一个布局,其中LinearLayout 有两个孩子LinearLayout 和FrameLayout,我在每个孩子中放置不同的视图。

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

在我正在使用的程序中

int height,width;

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

返回值为0

即使我尝试使用以下代码 int 高度,宽度;

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

返回相同的值0

最后我尝试了以下代码, int 高度,宽度;

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

回复我-2 和-1

我希望解决方案以编程方式获取任何布局的高度和宽度?

【问题讨论】:

标签: android android-layout


【解决方案1】:

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

  • 附上

  • 测量

  • 布局

  • 画

因此,根据您何时尝试获取宽度/高度,您可能看不到您期望看到的内容,例如,如果您在 onCreate 期间执行此操作,那么到那时甚至可能还没有测量视图,on另一方面,如果您在按钮的 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(); 

    } 
});

【讨论】:

  • 请注意,removeGlobalOnLayoutListener 已被弃用,因此您必须编写 this.layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);在最近的android api中。
  • 如果上面的代码解决方案给你零高度/宽度,检查这个答案:stackoverflow.com/a/31515283/1735603
  • 您没有使用 var ViewTreeObserver vto,那么分配该方法调用有什么意义?
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    只是想在这里添加一个答案,因为 Koltin 有一些方便的方法可以做到这一点,这些方法比添加和删除 onGlobalLayoutListener 要丑得多:

    view.doOnLayout {
        it.measuredWidth
        it.measuredHeight
    }
    

    你可以看到更多方便的方法here。

    【讨论】:

    • 像魅力一样工作。谢谢你,你让我很开心
    【解决方案4】:

    我认为您在 OnCreate() 方法中获得了高度和宽度,这就是为什么您总是获得 0 值的原因,因为那时您的视图仍未创建。

    尝试在单击某个按钮时获取高度和宽度,否则......

    【讨论】:

    • 我有几乎同样的问题。我是android的初学者。那么做这些事情的最佳/方式是什么?目前我在 onCreate 中创建了几个按钮并想要定位它们。最好的地方在哪里?
    【解决方案5】:

    只要给出你的身高,如果需要,你会得到高度甚至宽度。

    /** * 在视图渲染之前获取视图高度 * @param 查看要测量的视图 * @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();
    }
    

    【讨论】:

      【解决方案6】:

      在 Kotlin 中,您可以简单地这样做:

      fr.post {
          height=fr.height
          width=fr.width
      }
      

      【讨论】:

        【解决方案7】:

        如果您得到 -1 或 -2,它也可能是 LayoutParams.WRAP_CONTENT (-2) 或 LayoutParams.MATCH_PARENT (-1) 的数值。

        【讨论】:

        • 如何以像素或 dp 为单位获取此值?
        【解决方案8】:

        我有同样的问题,但不想在测量之前在屏幕上绘图,所以我在尝试获取高度和宽度之前使用了这种测量视图的方法。

        使用示例:

        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());
        }
        

        【讨论】:

          【解决方案9】:

          最简单的方法是使用 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();
          
                          }
                      });
                  }
          

          如果你需要使用 this on 方法,像这样使用并保存你可以使用全局变量的值。

          【讨论】:

            【解决方案10】:

            试试这个方法:

            int width = mView.getMeasuredWidth();
            
            int height = mView.getMeasuredHeight();
            

            或者

            int width = mTextView.getMeasuredWidth();
            
            int height = mTextView.getMeasuredHeight();
            

            【讨论】:

            • 除非onDraw() 被调用,否则你永远不会得到这些值。
            【解决方案11】:

            尝试来自this链接的类似代码

            ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
            if (viewTreeObserver.isAlive()) {
             viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
              view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
              viewWidth = view.getWidth();
              viewHeight = view.getHeight();
            }
             });
            }
            

            希望这会有所帮助。

            【讨论】:

              【解决方案12】:

              因为我刚遇到这个问题,我想我会为 kotlin 写它,

              my_view.viewTreeObserver.addOnGlobalLayoutListener {
                     // here your view is measured
                     // get height using my_view.height
                     // get width using my_view.width
                  }
              

              或

              my_view.post {
                     // here your view is measured
                     // get height using my_view.height
                     // get width using my_view.width
                  }
              

              【讨论】:

                【解决方案13】:

                第一个 sn-p 是正确的,但您需要在 onMeasure() 被执行后调用它。否则,尚未测量视图的大小。

                【讨论】:

                • 此外,您可以覆盖 onMeasure 并在每次调用此方法时获取新的测量值。
                【解决方案14】:

                对于框架:

                height=fr.getHeight();
                width=fr.getWidth();
                

                对于屏幕:

                width = getWindowManager().getDefaultDisplay().getWidth();
                height = getWindowManager().getDefaultDisplay().getHeight();
                

                【讨论】:

                  【解决方案15】:

                  我使用 DisplayMetrics 来获取屏幕尺寸,然后我可以将宽度/高度分配给 %age 中的元素

                  会是这样的

                  DisplayMetrics dmetrics = new DisplayMetrics();
                  int widthPixels=dmetrics.widthPixels;
                  int heightPixels=dmetrics.heightPixels;       
                  
                  //setting the height of the button 
                  button_nextPuzzle.setMinHeight((int) ((heightPixels/3)*.30));
                  

                  非常适合我!!!

                  【讨论】:

                  • 它不会给你所需的高度FrameLayout
                  【解决方案16】:

                  如果您在 Kotlin 中编写代码,请使用这个不错的扩展函数:

                  inline fun View.getDimensions(crossinline onDimensionsReady: (Int, Int) -> Unit) {
                      lateinit var layoutListener: ViewTreeObserver.OnGlobalLayoutListener
                      layoutListener = ViewTreeObserver.OnGlobalLayoutListener {
                          viewTreeObserver.removeOnGlobalLayoutListener(layoutListener)
                          onDimensionsReady(width, height)
                      }
                      viewTreeObserver.addOnGlobalLayoutListener(layoutListener)
                  }
                  

                  用法:

                  view.getDimensions { width, height ->
                      println("width = $width")
                      println("height = $height")
                  }
                  

                  【讨论】:

                    【解决方案17】:

                    检查行为 非常简单的解决方案

                      override fun onCreate(savedInstanceState: Bundle?) {
                            super.onCreate(savedInstanceState)
                            setContentView(R.layout.activity_main)
                            Log.d(LOG, "MainActivity - onCreate() called")
                    
                            fragments_frame.post {
                                Log.d(LOG, " fragments_frame.height:${fragments_frame.width}")
                                Log.d(LOG, " fragments_frame.height:${fragments_frame.measuredWidth}")
                            }
                    }
                    

                    【讨论】:

                      【解决方案18】:

                      getDefaultDisplay().getHeight 已弃用。所以更好用

                      getResources().getDisplayMetrics().heightPixels;

                      【讨论】:

                        【解决方案19】:

                        你也可以使用协程,比如这个:

                        CoroutineScope(Dispatchers.Main).launch {
                                delay(10)
                                val width = view.width()
                                val height= view.height()
                                // do your job ....
                            }
                        

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2016-06-23
                          • 2014-02-22
                          • 1970-01-01
                          • 1970-01-01
                          • 2013-09-16
                          • 1970-01-01
                          • 1970-01-01
                          • 2013-12-14
                          相关资源
                          最近更新 更多