Получить размеры экрана в пикселях
Я создал некоторые пользовательские элементы, и я хочу программно поместить их в верхний правый угол (n
пикселей от верхнего края и m
пикселей от правого края). Поэтому мне нужно получить ширину экрана и высоту экрана, а затем установить положение:
int px = screenWidth - m;
int py = screenHeight - n;
Как мне получить screenWidth
и screenHeight
в основном мероприятии?
- 1
- 2
Если вы хотите размеры экрана в пикселях, вы можете использовать getSize
:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
Если вы не в Activity
вы можете получить Display
по умолчанию через WINDOW_SERVICE
:
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Если вы находитесь во фрагменте и хотите выполнить это, просто используйте Activity.WindowManager (в Xamarin.Android) или getActivity(). GetWindowManager() (в java).
Перед введением getSize
(на уровне API 13) вы могли использовать методы getWidth
и getHeight
, которые сейчас не рекомендуются:
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth(); // deprecated
int height = display.getHeight(); // deprecated
Однако для описываемого вами варианта использования поле/отступ в макете кажется более подходящим.
Другой способ: DisplayMetrics
Структура, описывающая общую информацию об отображении, такую как его размер, плотность и масштабирование шрифта. Чтобы получить доступ к членам DisplayMetrics, инициализируйте объект следующим образом:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
Мы можем использовать widthPixels
чтобы получить информацию для:
"Абсолютная ширина дисплея в пикселях."
Пример:
Log.d("ApplicationTagName", "Display width in px is " + metrics.widthPixels);
Одним из способов является:
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
Это устарело, и вместо этого вы должны попробовать следующий код. Первые две строки кода дают вам объекты DisplayMetrics
. Этот объект содержит поля, такие как heightPixels
, widthPixels
.
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int width = metrics.widthPixels;
Похожие вопросы
Он может не отвечать на ваш вопрос, но было бы полезно знать (я сам искал его, когда пришел к этому вопросу), что если вам нужно измерение View, но ваш код выполняется, когда его макет не был (например, в onCreate()
) вы можете установить ViewTreeObserver.OnGlobalLayoutListener
с помощью View.getViewTreeObserver().addOnGlobalLayoutListener()
и поместить соответствующий код, для которого требуется измерение вида. Обратный вызов слушателя будет вызываться, когда макет будет выложен.
(ответ 2012 года, может быть устаревшим). Если вы хотите поддержать pre Honeycomb, вам нужно будет установить обратную совместимость до API 13. Что-то вроде:
int measuredWidth = 0;
int measuredHeight = 0;
WindowManager w = getWindowManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
Point size = new Point();
w.getDefaultDisplay().getSize(size);
measuredWidth = size.x;
measuredHeight = size.y;
} else {
Display d = w.getDefaultDisplay();
measuredWidth = d.getWidth();
measuredHeight = d.getHeight();
}
Конечно, устаревшие методы в конечном итоге будут выведены из самых последних SDK, но пока мы по-прежнему полагаемся на большинство наших пользователей, имеющих Android 2.1, 2.2 и 2.3, это то, с чем мы остались.
Я пробовал все возможные "решения" безуспешно, и я заметил, что приложение "Dalvik Explorer" Elliott Hughes всегда показывает правильное измерение на любой версии Android/OS. В итоге я посмотрел его проект с открытым исходным кодом, который можно найти здесь: https://code.google.com/p/enh/
Здесь весь соответствующий код:
WindowManager w = activity.getWindowManager();
Display d = w.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
d.getMetrics(metrics);
// since SDK_INT = 1;
widthPixels = metrics.widthPixels;
heightPixels = metrics.heightPixels;
try {
// used when 17 > SDK_INT >= 14; includes window decorations (statusbar bar/menu bar)
widthPixels = (Integer) Display.class.getMethod("getRawWidth").invoke(d);
heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(d);
} catch (Exception ignored) {
}
try {
// used when SDK_INT >= 17; includes window decorations (statusbar bar/menu bar)
Point realSize = new Point();
Display.class.getMethod("getRealSize", Point.class).invoke(d, realSize);
widthPixels = realSize.x;
heightPixels = realSize.y;
} catch (Exception ignored) {
}
EDIT: немного улучшенная версия (избегайте исключений об обстреле в версии, не поддерживаемой ОС):
WindowManager w = activity.getWindowManager();
Display d = w.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
d.getMetrics(metrics);
// since SDK_INT = 1;
widthPixels = metrics.widthPixels;
heightPixels = metrics.heightPixels;
// includes window decorations (statusbar bar/menu bar)
if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 17)
try {
widthPixels = (Integer) Display.class.getMethod("getRawWidth").invoke(d);
heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(d);
} catch (Exception ignored) {
}
// includes window decorations (statusbar bar/menu bar)
if (Build.VERSION.SDK_INT >= 17)
try {
Point realSize = new Point();
Display.class.getMethod("getRealSize", Point.class).invoke(d, realSize);
widthPixels = realSize.x;
heightPixels = realSize.y;
} catch (Exception ignored) {
}
Для доступа к высоте строки состояния для устройств Android мы предпочитаем программный способ ее получения:
Пример кода
int resId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resId > 0) {
result = getResources().getDimensionPixelSize(resId);
}
Переменная result
дает высоту в пикселе.
Для быстрого доступа
Для получения дополнительной информации о высоте Title bar
, Navigation bar
и Content View
, любезно посмотрите на Размеры экрана устройства Android.
Простейший способ:
int screenHeight = getResources().getDisplayMetrics().heightPixels;
int screenWidth = getResources().getDisplayMetrics().widthPixels;
Сначала получите представление (например, findViewById()
), а затем вы можете использовать getWidth() на просмотра самого себя.
У меня есть две функции: одна для отправки контекста, а другая высота и ширина в пикселях:
public static int getWidth(Context mContext){
int width=0;
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
if(Build.VERSION.SDK_INT>12){
Point size = new Point();
display.getSize(size);
width = size.x;
}
else{
width = display.getWidth(); // Deprecated
}
return width;
}
и
public static int getHeight(Context mContext){
int height=0;
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
if(Build.VERSION.SDK_INT>12){
Point size = new Point();
display.getSize(size);
height = size.y;
}
else{
height = display.getHeight(); // Deprecated
}
return height;
}
Для динамического масштабирования с использованием XML существует атрибут "android: layout_weight"
В приведенном ниже примере, измененном от синхронного ответа на этот поток, отображается кнопка, которая занимает 75% экрана (вес =.25) и текстовое представление заняв оставшиеся 25% экрана (вес =.75).
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight=".25"
android:text="somebutton">
<TextView android:layout_width="fill_parent"
android:layout_height="Wrap_content"
android:layout_weight=".75">
</LinearLayout>
Это код, который я использую для задачи:
// `activity` is an instance of Activity class.
Display display = activity.getWindowManager().getDefaultDisplay();
Point screen = new Point();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
display.getSize(screen);
} else {
screen.x = display.getWidth();
screen.y = display.getHeight();
}
Кажется достаточно чистым и, тем не менее, заботится об устаревании.
Разве это не лучшее решение? DisplayMetrics поставляется со всем необходимым и работает с API 1.
public void getScreenInfo(){
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
heightPixels = metrics.heightPixels;
widthPixels = metrics.widthPixels;
density = metrics.density;
densityDpi = metrics.densityDpi;
}
Вы также можете получить фактический дисплей (включая декодеры экрана, такие как строка состояния или панель навигации программного обеспечения) с помощью getRealMetrics, но это работает только с 17+.
Я что-то пропустил?
Просто добавив к Франческо ответ. Другой наблюдатель, более подходящий, если вы хотите узнать местоположение в окне или местоположении на экране, ViewTreeObserver.OnPreDrawListener()
Это также можно использовать для поиска других атрибутов представления, которое в большинстве случаев неизвестно в onCreate(), например. прокрученное положение, масштабированное положение.
Найдите ширину и высоту экрана:
width = getWindowManager().getDefaultDisplay().getWidth();
height = getWindowManager().getDefaultDisplay().getHeight();
Используя это, мы можем получить последний и выше SDK 13.
// New width and height
int version = android.os.Build.VERSION.SDK_INT;
Log.i("", " name == "+ version);
Display display = getWindowManager().getDefaultDisplay();
int width;
if (version >= 13) {
Point size = new Point();
display.getSize(size);
width = size.x;
Log.i("width", "if =>" +width);
}
else {
width = display.getWidth();
Log.i("width", "else =>" +width);
}
Используя следующий код в Activity.
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int wwidth = metrics.widthPixels;
DisplayMetrics dimension = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dimension);
int w = dimension.widthPixels;
int h = dimension.heightPixels;
Я нашел, что это сделало трюк.
Rect dim = new Rect();
getWindowVisibleDisplayFrame(dim);
public class AndroidScreenActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
String str_ScreenSize = "The Android Screen is: "
+ dm.widthPixels
+ " x "
+ dm.heightPixels;
TextView mScreenSize = (TextView) findViewById(R.id.strScreenSize);
mScreenSize.setText(str_ScreenSize);
}
}
Нужно сказать, что если вы не находитесь в Activity
, но в View
(или имеете переменную типа View
в своей области), нет необходимости использовать WINDOW_SERVICE
. Затем вы можете использовать как минимум два способа.
Во-первых:
DisplayMetrics dm = yourView.getContext().getResources().getDisplayMetrics();
Во-вторых:
DisplayMetrics dm = new DisplayMetrics();
yourView.getDisplay().getMetrics(dm);
Все эти методы, которые мы называем здесь, не устарели.
Для получения размеров экрана используйте отображаемые метрики
DisplayMetrics displayMetrics = new DisplayMetrics();
if (context != null)
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display defaultDisplay = windowManager.getDefaultDisplay();
defaultDisplay.getRealMetrics(displayMetrics);
}
Получить высоту и ширину в пикселях
int width =displayMetrics.widthPixels;
int height =displayMetrics.heightPixels;
Это не ответ для OP, так как он хотел отображать размеры в реальных пикселях. Мне нужны размеры в "device-independent-pixels" и собраны ответы отсюда fooobar.com/questions/2415/... и здесь fooobar.com/questions/2416/... Я придумал это:
DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
int dpHeight = (int)(displayMetrics.heightPixels / displayMetrics.density + 0.5);
int dpWidth = (int)(displayMetrics.widthPixels / displayMetrics.density + 0.5);
Существует не устаревший способ сделать это с помощью DisplayMetrics (API 1), что позволяет избежать беспорядка try/catch:
// initialize the DisplayMetrics object
DisplayMetrics deviceDisplayMetrics = new DisplayMetrics();
// populate the DisplayMetrics object with the display characteristics
getWindowManager().getDefaultDisplay().getMetrics(deviceDisplayMetrics);
// get the width and height
screenWidth = deviceDisplayMetrics.widthPixels;
screenHeight = deviceDisplayMetrics.heightPixels;
Я бы обернул код getSize следующим образом:
@SuppressLint("NewApi")
public static Point getScreenSize(Activity a) {
Point size = new Point();
Display d = a.getWindowManager().getDefaultDisplay();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
d.getSize(size);
} else {
size.x = d.getWidth();
size.y = d.getHeight();
}
return size;
}
Вы можете получить размер высота, используя:
getResources().getDisplayMetrics().heightPixels;
и размер ширина, используя
getResources().getDisplayMetrics().widthPixels;
Сначала загрузите файл XML, а затем напишите этот код:
setContentView(R.layout.main);
Display display = getWindowManager().getDefaultDisplay();
final int width = (display.getWidth());
final int height = (display.getHeight());
Покажите ширину и высоту в соответствии с разрешением экрана.
Для тех, кто ищет размер экрана без использования Строка состояния и Панель действий (также благодаря ответу Swapnil):
DisplayMetrics dm = getResources().getDisplayMetrics();
float screen_w = dm.widthPixels;
float screen_h = dm.heightPixels;
int resId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resId > 0) {
screen_h -= getResources().getDimensionPixelSize(resId);
}
TypedValue typedValue = new TypedValue();
if(getTheme().resolveAttribute(android.R.attr.actionBarSize, typedValue, true)){
screen_h -= getResources().getDimensionPixelSize(typedValue.resourceId);
}
Следуйте приведенным ниже методам:
public static int getWidthScreen(Context context) {
return getDisplayMetrics(context).widthPixels;
}
public static int getHeightScreen(Context context) {
return getDisplayMetrics(context).heightPixels;
}
private static DisplayMetrics getDisplayMetrics(Context context) {
DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics;
}
Бывают случаи, когда вам нужно знать точные размеры доступного пространства для макета, когда в действии onCreate. Подумав, я решил это сделать.
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startActivityForResult(new Intent(this, Measure.class), 1);
// Return without setting the layout, that will be done in onActivityResult.
}
@Override
protected void onActivityResult (int requestCode, int resultCode, Intent data) {
// Probably can never happen, but just in case.
if (resultCode == RESULT_CANCELED) {
finish();
return;
}
int width = data.getIntExtra("Width", -1);
// Width is now set to the precise available width, and a layout can now be created. ...
}
}
public final class Measure extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Create a LinearLayout with a MeasureFrameLayout in it.
// Just putting a subclass of LinearLayout in works fine, but to future proof things, I do it this way.
LinearLayout linearLayout = new LinearLayout(this);
LinearLayout.LayoutParams matchParent = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
MeasureFrameLayout measureFrameLayout = new MeasureFrameLayout(this);
measureFrameLayout.setLayoutParams(matchParent);
linearLayout.addView(measureFrameLayout);
this.addContentView(linearLayout, matchParent);
// measureFrameLayout will now request this second activity to finish, sending back the width.
}
class MeasureFrameLayout extends FrameLayout {
boolean finished = false;
public MeasureFrameLayout(Context context) {
super(context);
}
@SuppressLint("DrawAllocation")
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (finished) {
return;
}
finished = true;
// Send the width back as the result.
Intent data = new Intent().putExtra("Width", MeasureSpec.getSize(widthMeasureSpec));
Measure.this.setResult(Activity.RESULT_OK, data);
// Tell this activity to finish, so the result is passed back.
Measure.this.finish();
}
}
}
Если по какой-то причине вы не хотите добавлять другую активность в манифест Android, вы можете сделать это следующим образом:
public class MainActivity extends Activity {
static Activity measuringActivity;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras();
if (extras == null) {
extras = new Bundle();
}
int width = extras.getInt("Width", -2);
if (width == -2) {
// First time in, just start another copy of this activity.
extras.putInt("Width", -1);
startActivityForResult(new Intent(this, MainActivity.class).putExtras(extras), 1);
// Return without setting the layout, that will be done in onActivityResult.
return;
}
if (width == -1) {
// Second time in, here is where the measurement takes place.
// Create a LinearLayout with a MeasureFrameLayout in it.
// Just putting a subclass of LinearLayout in works fine, but to future proof things, I do it this way.
LinearLayout linearLayout = new LinearLayout(measuringActivity = this);
LinearLayout.LayoutParams matchParent = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
MeasureFrameLayout measureFrameLayout = new MeasureFrameLayout(this);
measureFrameLayout.setLayoutParams(matchParent);
linearLayout.addView(measureFrameLayout);
this.addContentView(linearLayout, matchParent);
// measureFrameLayout will now request this second activity to finish, sending back the width.
}
}
@Override
protected void onActivityResult (int requestCode, int resultCode, Intent data) {
// Probably can never happen, but just in case.
if (resultCode == RESULT_CANCELED) {
finish();
return;
}
int width = data.getIntExtra("Width", -3);
// Width is now set to the precise available width, and a layout can now be created.
...
}
class MeasureFrameLayout extends FrameLayout {
boolean finished = false;
public MeasureFrameLayout(Context context) {
super(context);
}
@SuppressLint("DrawAllocation")
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (finished) {
return;
}
finished = true;
// Send the width back as the result.
Intent data = new Intent().putExtra("Width", MeasureSpec.getSize(widthMeasureSpec));
MainActivity.measuringActivity.setResult(Activity.RESULT_OK, data);
// Tell the (second) activity to finish.
MainActivity.measuringActivity.finish();
}
}
Если вы не хотите накладных расходов на WindowManagers, Points или Displays, вы можете захватить атрибуты высоты и ширины самого верхнего элемента View в вашем XML, при условии, что его высота и ширина установлены на match_parent. (Это верно, если ваш макет занимает весь экран.)
Например, если ваш XML начинается с чего-то вроде этого:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/entireLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
Затем findViewById(R.id.entireLayout).getWidth()
вернет ширину экрана, а findViewById(R.id.entireLayout).getHeight()
вернет высоту экрана.
У меня есть активность заставки с LinearLayout как корневое представление, которое имеет match_parent для его ширины и высоты. Это код в методе onCreate()
этого действия. Я использую эти меры во всех других действиях приложения.
int displayWidth = getRawDisplayWidthPreHoneycomb();
int rawDisplayHeight = getRawDisplayHeightPreHoneycomb();
int usableDisplayHeight = rawDisplayHeight - getStatusBarHeight();
pf.setScreenParameters(displayWidth, usableDisplayHeight);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
LinearLayout myView = (LinearLayout) findViewById(R.id.splash_view);
myView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (left == 0 && top == 0 && right == 0 && bottom == 0) {
return;
}
int displayWidth = Math.min(right, bottom);
int usableDisplayHeight = Math.max(right, bottom);
pf.setScreenParameters(displayWidth, usableDisplayHeight);
}
});
}
Ниже перечислены реализации описанных выше методов:
private int getRawDisplayWidthPreHoneycomb() {
WindowManager windowManager = getWindowManager();
Display display = windowManager.getDefaultDisplay();
DisplayMetrics displayMetrics = new DisplayMetrics();
display.getMetrics(displayMetrics);
int widthPixels = displayMetrics.widthPixels;
int heightPixels = displayMetrics.heightPixels;
return Math.min(widthPixels, heightPixels);
}
private int getRawDisplayHeightPreHoneycomb() {
WindowManager w = getWindowManager();
Display d = w.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
d.getMetrics(metrics);
int widthPixels = metrics.widthPixels;
int heightPixels = metrics.heightPixels;
return Math.max(widthPixels, heightPixels);
}
public int getStatusBarHeight() {
int statusBarHeight = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight = getResources().getDimensionPixelSize(resourceId);
}
return statusBarHeight;
}
Это приводит к росту и ширине используемого дисплея, исключая любые типы баров (строка состояния, панель навигации) для всех версий API и различных типов устройств (телефонов и планшетов).
- 1
- 2
Посмотрите другие вопросы по меткам android layout screen pixel dimensions или Задайте вопрос