Получить размеры экрана в пикселях

Я создал несколько пользовательских элементов и хочу программно поместить их в верхний правый угол (n пикселей от верхнего края и m пикселей от правого края). Поэтому мне нужно получить ширину экрана и высоту экрана, а затем установить положение:

int px = screenWidth - m;
int py = screenHeight - n;

Как я могу получить screenWidth а также screenHeight в основной деятельности?

47 ответов

Решение

Если вы хотите размеры экрана в пикселях, вы можете использовать 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 г., возможно, устарел). Если вы хотите поддерживать предварительно 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" Эллиотта Хьюза всегда показывает правильный размер на любом устройстве Android / версии ОС. В итоге я посмотрел на его проект с открытым исходным кодом, который можно найти здесь: 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) {
}

РЕДАКТИРОВАТЬ: слегка улучшенная версия (избегать исключений запуска на не поддерживаемой версии ОС):

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

Самый простой способ:

 int screenHeight = getResources().getDisplayMetrics().heightPixels;
 int screenWidth = getResources().getDisplayMetrics().widthPixels; 

Для доступа к высоте строки состояния для устройств 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.

Сначала получить представление (например, по 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"

Приведенный ниже пример, модифицированный по ответу synic в этой теме, показывает кнопку, занимающую 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>

Разве это не намного лучшее решение? 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+.

Я что-то пропустил?

Вот код, который я использую для задачи:

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

Кажется достаточно чистым и все же, заботится об амортизации.

Найдите ширину и высоту экрана:

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

Просто добавлю к ответу Франческо. Другим более подходящим наблюдателем, если вы хотите узнать местоположение в окне или местоположение на экране, является ViewTreeObserver.OnPreDrawListener()

Это также может быть использовано для поиска других атрибутов представления, которые в основном неизвестны во время onCreate(), например прокручиваемая позиция, масштабированная позиция.

DisplayMetrics dimension = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dimension);
int w = dimension.widthPixels;
int h = dimension.heightPixels;

Используя следующий код в Activity.

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int wwidth = metrics.widthPixels;
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);
    }
}

Я обнаружил, что сделал свое дело.

Rect dim = new Rect();
getWindowVisibleDisplayFrame(dim);

Это не ответ для ОП, так как он хотел, чтобы размеры дисплея были в реальных пикселях. Я хотел размеры в "независимых от устройства пикселях", и собирал ответы отсюда /questions/3091946/preobrazovanie-pikselej-v-dp/3091980#3091980 и вот /questions/10340693/android-konvertirovat-px-v-dp-sootnoshenie-storon-video/10340701#10340701 Я подошел с этим:

    DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
    int dpHeight = (int)(displayMetrics.heightPixels / displayMetrics.density + 0.5);
    int dpWidth = (int)(displayMetrics.widthPixels / displayMetrics.density + 0.5);

Для получения размеров экрана используйте метрики отображения

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;

Надо сказать, что если вы не в Activity, но в View (или иметь переменную View введите в своей области), нет необходимости использовать WINDOW_SERVICE, Тогда вы можете использовать как минимум два способа.

Первый:

DisplayMetrics dm = yourView.getContext().getResources().getDisplayMetrics();

Во-вторых:

DisplayMetrics dm = new DisplayMetrics();
yourView.getDisplay().getMetrics(dm);

Все эти методы, которые мы здесь называем, не устарели.

Вы можете получить размер высоты, используя:

getResources().getDisplayMetrics().heightPixels;

и размер ширины с помощью

getResources().getDisplayMetrics().widthPixels; 

Существует не осуждаемый способ сделать это с помощью DisplayMetrics (API 1), который позволяет избежать путаницы в попытках / отлове:

 // 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;
}

Для тех, кто ищет полезные размеры экрана без строки состояния и панели действий (также благодаря ответу 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);
}

Котлин

fun getScreenHeight(activity: Activity): Int {
    val metrics = DisplayMetrics()
    activity.windowManager.defaultDisplay.getMetrics(metrics)
    return metrics.heightPixels
}

fun getScreenWidth(activity: Activity): Int {
    val metrics = DisplayMetrics()
    activity.windowManager.defaultDisplay.getMetrics(metrics)
    return metrics.widthPixels
}

В Котлине намного проще.

      val displayMetrics = Resources.getSystem().displayMetrics
displayMetrics.heightPixels
displayMetrics.widthPixels

Следуйте методам ниже:

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

Сначала загрузите файл XML, а затем напишите этот код:

setContentView(R.layout.main);      
Display display = getWindowManager().getDefaultDisplay();
final int width = (display.getWidth());
final int height = (display.getHeight());

Показать ширину и высоту в соответствии с вашим разрешением экрана.

Есть моменты, когда вам нужно знать точные размеры доступного пространства для макета в 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();
    }
}    
Другие вопросы по тегам