簡體   English   中英

以編程方式獲取布局的高度和寬度

[英]Get height and width of a layout programmatically

我設計了一個布局,其中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

我希望解決方案以編程方式獲取任何布局的高度和寬度?

視圖本身有自己的生命周期,基本如下:

  • 隨附的

  • 實測

  • 布局

因此,根據您何時嘗試獲取寬度/高度,您可能看不到您期望看到的內容,例如,如果您在 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(); 

    } 
});

正如 CapDroid 所說,您正在嘗試在繪制視圖之前獲取大小,另一種可能的解決方案可能是在視圖上使用可運行對象執行 Post:

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

我認為您在 OnCreate() 方法中獲得 Height 和 Width 這就是為什么您始終獲得 0 值的原因,因為當時您的視圖仍未創建。

嘗試在單擊某些按鈕時獲取高度和寬度,否則..

只是想在這里添加一個答案,因為 Koltin 有一些方便的方法來做到這一點,這比添加和刪除onGlobalLayoutListener少得多:

view.doOnLayout {
    it.measuredWidth
    it.measuredHeight
}

您可以在此處查看更多便利方法。

只需給出您的高度,如果需要,您將獲得高度甚至寬度。

/** * 獲取視圖渲染前的視圖高度 * @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();
}

在 Kotlin 中,您可以簡單地執行以下操作:

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

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

我有同樣的問題,但不想在測量之前在屏幕上繪制,所以我在嘗試獲取高度和寬度之前使用了這種測量視圖的方法。

使用示例:

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

最簡單的方法是使用 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();

                }
            });
        }

如果你需要在方法上使用這個,像這樣使用並保存你可以使用全局變量的值。

試試這個方法:

int width = mView.getMeasuredWidth();

int height = mView.getMeasuredHeight();

或者

int width = mTextView.getMeasuredWidth();

int height = mTextView.getMeasuredHeight();

這個鏈接嘗試類似這樣的代碼

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

希望這可以幫助。

當我剛遇到這個問題時,我以為我會為 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
    }

第一個片段是正確的,但您需要onMeasure()執行調用它。 否則,視圖的大小尚未測量。

對於框架:

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

對於屏幕:

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

我使用 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));

為我工作得很好!!!

檢查行為非常簡單的解決方案

  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}")
        }
}

如果您在 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")
}

getDefaultDisplay().getHeight 已棄用。 所以更好地使用

getResources().getDisplayMetrics().heightPixels;

你也可以使用協程,就像這樣:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM