2013-06-27 94 views
17

如何獲取Android中屏幕的可用高度?我需要高度減去狀態欄/菜單欄或任何其他可能在屏幕上的裝飾,我需要它適用於所有設備。另外,我需要在onCreate函數中瞭解這一點。我知道這個問題以前已經問過,但我已經嘗試過他們的解決方案,而且他們都沒有工作。這裏有一些我已經嘗試過的東西:在Android中獲取屏幕高度

我已經在API 7 - 17上測試過這段代碼。不幸的是,在API 13上,水平和垂直方向上都有額外的空間,並且在API 10,8和7上水平和垂直底部空間不足。 (我還沒有過時的API測試):

Display display = getWindowManager().getDefaultDisplay(); 
DisplayMetrics metrics = new DisplayMetrics(); 
display.getMetrics(metrics); 
screenWidth = metrics.widthPixels; 
screenHeight = metrics.heightPixels; 

TypedValue tv = new TypedValue(); 
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 
{ 
    if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) 
     screenHeight -= TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics()); 
} 

int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); 
if (resourceId > 0) 
    screenHeight -= getResources().getDimensionPixelSize(resourceId); 

這並沒有考慮到狀態欄/菜單欄:

Display display = getWindowManager().getDefaultDisplay(); 
screenWidth = display.getWidth(); 
screenHeight = display.getHeight(); 

無論是做這個的:

Point size = new Point(); 
getWindowManager().getDefaultDisplay().getSize(size); 
screenWidth = size.x; 
screenHeight = size.y; 

這也不:

Point size = new Point(); 
getWindowManager().getDefaultDisplay().getRealSize(size); 
screenWidth = size.x; 
screenHeight = size.y; 

這不是窩RK:

Display display = getWindowManager().getDefaultDisplay(); 
DisplayMetrics metrics = new DisplayMetrics(); 
display.getMetrics(metrics); 
// since SDK_INT = 1; 
screenWidth = metrics.widthPixels; 
screenHeight = metrics.heightPixels; 
try 
{ 
    // used when 17 > SDK_INT >= 14; includes window decorations (statusbar bar/menu bar) 
    screenWidth = (Integer) Display.class.getMethod("getRawWidth").invoke(display); 
    screenHeight = (Integer) Display.class.getMethod("getRawHeight").invoke(display); 
} 
catch (Exception ignored) 
{ 
    // Do nothing 
} 
try 
{ 
    // used when SDK_INT >= 17; includes window decorations (statusbar bar/menu bar) 
    Point realSize = new Point(); 
    Display.class.getMethod("getRealSize", Point.class).invoke(display, realSize); 
    screenWidth = realSize.x; 
    screenHeight = realSize.y; 
} 
catch (Exception ignored) 
{ 
    // Do nothing 
} 

然後我用下面的代碼減去屏幕高度的狀態欄和菜單欄的高度:

int result = 0; 
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); 
if (resourceId > 0) 
    result = getResources().getDimensionPixelSize(resourceId); 
screenHeight -= result; 
result = 0; 
if (screenHeight >= screenWidth) 
    resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android"); 
else 
    resourceId = getResources().getIdentifier("navigation_bar_height_landscape", "dimen", "android"); 
if (resourceId > 0) 
    result = getResources().getDimensionPixelSize(resourceId); 
screenHeight -= result; 

在API 17它正確地計算狀態欄的高度和縱向菜單欄,但不是橫向。在API 10,則返回0。我需要它在所有設備上或最小API 7

+0

如果你真的需要在onCreate方法確切大小,你做某事是錯誤的。使用全局佈局偵聽器並在佈局階段完成時運行您的操作是正確的方式,例如@Carnal答案。在全局範圍回調中,您應該在View上使用getMessureadHeight而不是使用getHeight。 – Mikooos

+1

@DanBray - 請查看我提出的解決方案。它絕對有效。 –

+0

任何延遲使用「OnGlobalLayoutListener」獲取維度或將「Runnable」發佈到根視圖的消息隊列的方法都應該有效。 –

回答

5

工作液:

創建兩個虛擬的觀點:

<View 
    android:id="@+id/top" 
    android:layout_height="0dp" 
    android:layout_width="match_parent" 
    android:layout_alignParentTop="true" /> 

<View 
     android:id="@+id/bottom" 
     android:layout_height="0dp" 
     android:layout_width="match_parent" 
     android:layout_alignParentBottom="true" /> 

現在,你應該叫上這兩種觀點getLocationOnScreen(int [])接受他們的位置。這個函數返回一個2個整數的數組。第一個是x和第二個y。我們只需要y。另請注意,只有在創建了所有視圖並退出onCreate方法後,纔會返回正確的值。

我在從viewpager調用的常規片段上測試了此代碼。

該代碼位於我的片段的onCreateView方法中。我仍然必須使用postDelayed才能獲得正確的值。

final View top = (View) view.findViewById(R.id.top); 
    final View bottom = (View) view.findViewById(R.id.bottom); 
    new Handler().postDelayed(new Runnable() { 
     @Override 
     public void run() { 

      int topLoc[] = new int[2]; 
      top.getLocationOnScreen(topLoc); 
      int BottomLoc[] = new int[2]; 
      bottom.getLocationOnScreen(BottomLoc); 
      Log.d(Constants.debug, "topY: "+ topLoc[1]+" BottomY:" + BottomLoc[1]); 
     } 
    },4000); 

我的是Nexus 4.

在常規模式(狀態欄和軟按鈕示出):

07-05 02:28:23.367  565-565/com.torcellite.xx D/xx: topY: 50 BottomY:1182 

在(沒有示出狀態欄或軟按鈕)全屏模式:

07-05 02:29:17.360  707-707/com.torcellite.xx D/xx: topY: 0 BottomY:1280 

你現在要做的所有事情都是減去。

+0

這看起來像最有前途的解決方案,但我無法使它工作。我覺得我做錯了什麼。我創建了一個名爲screen.xml的XML文件,其中包含以下代碼: –

+0

<?xml version =「1.0」encoding =「utf-8」?> <查看 \t機器人:ID = 「@ + ID /頂部」 \t機器人:layout_height = 「0dp」 \t機器人:layout_width = 「match_parent」 \t機器人:layout_alignParentTop = 「真」/> \t <查看 機器人:ID = 「@ + ID /底」 機器人:layout_height = 「0dp」 android:layout_width =「match_parent」 android:layout_alignParentBottom =「true」/>

+0

然後,我將我的代碼從onCreate移動到公共'void run(){' 然後我將所有本地變量以避免錯誤,並使用此行'context = this;'擺脫在回調中使用'this'關鍵字的錯誤 –

2

理想的工作,爲顯示

DisplayMetrics displaymetrics = new DisplayMetrics(); 
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); 
int height = displaymetrics.heightPixels; 
int width = displaymetrics.widthPixels; 

狀態欄

public int getStatusBarHeight() { 
     int result = 0; 
     int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); 
     if (resourceId > 0) { 
      result = getResources().getDimensionPixelSize(resourceId); 
     } 
     return result; 
    } 
+0

這是我嘗試過的一件事,它不適用於所有設備。我在我的問題中展示了這一點。 –

+0

對於顯示器,它應該可以在所有設備上工作。 –

+0

@DanBray - 請看看我的解決方案,它適用於所有設備 –

1
Display currentDisplay = getWindowManager().getDefaultDisplay(); 
     float dw = currentDisplay.getWidth(); 
     float dh = currentDisplay.getHeight(); 

dh會給你屏幕高度。

+0

這是我試過的東西,但它沒有考慮到狀態欄/菜單欄。我在我的問題中展示了這一點。 –

+0

switch(displayMetrics.densityDpi){case displayMetrics.DENSITY_HIGH: \t statusBarHeight = HIGH_DPI_STATUS_BAR_HEIGHT; \t break; \t case DisplayMetrics.DENSITY_MEDIUM: \t statusBarHeight = MEDIUM_DPI_STATUS_BAR_HEIGHT; \t break; \t case DisplayMetrics.DENSITY_LOW: \t statusBarHeight = LOW_DPI_STATUS_BAR_HEIGHT; \t break; \t默認值: \t statusBarHeight = MEDIUM_DPI_STATUS_BAR_HEIGHT; \t}使用這個開關的情況下,你會得到不同屏幕密度的狀態欄高度。 –

2

我還沒有嘗試過不同的API,但我使用這些值來確定屏幕鍵盤是否啓動。也許你可以試試這個和寬度相近的東西來得到你需要的東西?

Rect r = new Rect(); 
view.getWindowVisibleDisplayFrame(r); 
int 
    screenHeight = view.getRootView().getHeight(), // height of the entire screen 
    appHeight = r.bottom - r.top, // height of the entire app 
    statusBarHeight = r.top, // height of the statusbar 
    pageHeight = view.getHeight(), // height of the app without title 
    appTitleHeight = appHeight - pageHeight, // height of the only the app title 
    topHeight = statusBarHeight + appTitleHeight; 
0

如何設置子類View作爲Activity的根。使該視圖填滿屏幕(它不會越過狀態欄)並覆蓋onSizeChanged()。存儲這些值併爲它們寫一個getter。

0

它可能不回答你的問題,但它可能是需要了解的(我是 找我吧,當我來到這個問題),如果你需要一個 查看的尺寸,但正在執行代碼時其佈局有 尚未佈局(例如在onCreate()),您可以設置 ViewTreeObserver.OnGlobalLayoutListener與 View.getViewTreeObserver()。addOnGlobalLayoutListener()並將 需要視圖的維度的相關代碼。當佈局已經佈局時,將會調用監聽器的回調函數 。

禮貌,弗朗西斯費爾特里內利

你可以嘗試這樣做。

2
final View view = findViewById(R.id.root); 
ViewTreeObserver vto = view.getViewTreeObserver(); 
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
    @Override 
    public void onGlobalLayout() { 
     // calculate the height in here... 

     ViewTreeObserver vto = view.getViewTreeObserver(); 
     vto.removeGlobalOnLayoutListener(this); 
    } 
}); 

onCreate(自api 1後可用)中使用此偵聽器。您需要將id @+id/root分配給xml佈局中的父級。大小無法返回0的結果,因爲只要佈局已經定位在視圖中,此偵聽器就會進行回調。

+0

如果我使用XML文件,這可能會起作用。我正在做我的佈局沒有XML文件。實際上,我的整個程序都有0個XML文件,因爲我寧願動態工作。 –

+0

我使用'final View view = getWindow()。getDecorView()。getRootView();'而不是'final View view = findViewById(R.id.root);'不幸的是,我仍然無法獲得屏幕高度減去任何裝飾。 'screenHeight = view.getMeasuredHeight();'或'screenHeight = view.getHeight();'不要在沒有狀態欄或菜單欄的情況下給高度。 –

+0

這不適用於onCreate。只有在執行完onCreate後發生的佈局後,纔會觸發此操作。 – AndroidDev

0

獲取活動加載的根佈局的高度。如果它沒有填充屏幕,則將其放入另一個高度爲fill_parent的佈局中。

6

如果你想在像素的顯示尺寸可以使用getSize

Display display = getWindowManager().getDefaultDisplay(); 
Point size = new Point(); 
display.getSize(size); 
int width = size.x; 
int height = size.y; 

如果您在Activity不是你可以通過WINDOW_SERVICE得到默認顯示:

WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE); 
Display display = wm.getDefaultDisplay(); 
display.getSize(size); 
int width = size.x; 
int height = size.y; 

之前getSize被引入(在API級別13中),您可以使用現在不推薦使用的getWidth和getHeight方法:

Display display = getWindowManager().getDefaultDisplay(); 
int width = display.getWidth(); // deprecated 
int height = display.getHeight(); // deprecated 

從推介:Get screen dimensions in pixels

+0

偉大的答案,謝謝 – Fattie