Как получить высоту экрана в Android?
Как получить доступную высоту экрана в Android? Мне нужна высота за вычетом строки состояния или строки меню или любых других украшений, которые могут быть на экране, и мне нужно, чтобы она работала на всех устройствах. Кроме того, мне нужно знать это в функции onCreate. Я знаю, что этот вопрос задавали раньше, но я уже пробовал их решения, и никто из них не работает. Вот некоторые из вещей, которые я пробовал:
Это не учитывает строку состояния/строку меню:
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;
Это не работает:
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 10.
Ответы
Ответ 1
Вот как мне удалось получить правильные размеры экрана для всех устройств:
public class MainActivity extends Activity
{
static int ScreenWidth;
static int ScreenHeight;
static int ScreenWidthLandscape;
static int ScreenHeightLandscape;
private RelativeLayout layout;
private RelativeLayout.LayoutParams params;
private View top;
private View bottom;
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
layout = new RelativeLayout(this);
top = new View(this);
bottom = new View(this);
RelativeLayout.LayoutParams viewParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1);
viewParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
top.setLayoutParams(viewParams);
viewParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1);
viewParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
bottom.setLayoutParams(viewParams);
layout.addView(top);
layout.addView(bottom);
setContentView(layout);
final Intent intent = new Intent(this, myPackage.learnSpanishVerbs.Start.class);
final View view = getWindow().getDecorView().getRootView();
ViewTreeObserver vto = view.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
int topLoc[] = new int[2];
top.getLocationOnScreen(topLoc);
int BottomLoc[] = new int[2];
bottom.getLocationOnScreen(BottomLoc);
boolean portrait = getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE;
if (portrait)
{
ScreenWidth = top.getWidth();
ScreenHeight = BottomLoc[1] - topLoc[1];
}
else
{
ScreenWidthLandscape = top.getWidth();
ScreenHeightLandscape = BottomLoc[1] - topLoc[1];
}
if (Build.VERSION.SDK_INT < 16)
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
else
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
startActivity(intent);
finish();
}
});
}
}
Ответ 2
Лучшим решением, которое мне удалось придумать, является следующее:
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);
Я тестировал его на API 7 - 17. К сожалению, на API 13 есть дополнительное пространство внизу как по горизонтали, так и по вертикали, а на API 10, 8 и 7 недостаточно места внизу и горизонтально, и вертикально. (Я не тестировал устаревшие API).
Ответ 3
Пробовали ли вы выполнять вычисления высоты в onWindowFocusChanged класса Activity? Это устраняет проблемы API, вычисляя то, что вы действительно хотите, не возитесь с барами меню и т.д.
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
View content = getWindow().findViewById(Window.ID_ANDROID_CONTENT);
screenHeight=content.getHeight();
}