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

1750

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

<code>int px = screenWidth - m;
int py = screenHeight - n;
</code>

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

Не забудьте умножить на getResources (). GetDisplayMetrics (). Плотность, чтобы учесть масштабирование дисплея jmaculate
Другой способ получить DisplayMetrics:Resources.getSystem().getDisplayMetrics(), Вы не нуждаетесь вContext чтобы получить их. Täg
DisplayMetrics displaymetrics = new DisplayMetrics (); . GetWindowManager () getDefaultDisplay () getMetrics (displaymetrics). int height = displaymetrics.heightPixels; int width = displaymetrics.widthPixels; Azahar
Используйте dp вместо px. потому что это будет искажать ваш макет с другими устройствами .. Xar E Ahmer
Это доказывает, что ответ с наибольшим количеством голосов не всегда является лучшим (& много людей повторяют ответы для повторения). Вместо getSize и устаревшей комбинации getWidth / getHeight (игнорируя ошибки), попробуйте Balaji.K'sgetMetrics, Комментарий Ника в его ответе даже объясняетgetDisplayMetrics рассмотреть размер системы / строки состояния. Также вы можете использоватьdensity как объяснил Jmaculate и LoungeKatt иметьEXACT значение:DisplayMetrics dm = getResources().getDisplayMetrics(); float fwidth = dm.density * dm.widthPixels; Протестировано в Android v2.2 (API 8) и v4.0 с хорошими результатами иno errors/warnings. Armfoot

Ваш Ответ

30   ответов
359

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;
Также существует этот способ: getContext (). GetResources (). GetDisplayMetrics (). WidthPixels
Метрики будут возвращать размер дисплея, но HoneyComb и выше, ваша деятельность будет иметь меньше места, чем то, что возвращается из-за системной панели.
@ Да, это зависит от вашей реализации. Вы можете скрыть строку состояния: requestWindowFeature (Window.FEATURE_NO_TITLE); getWindow (). setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
окончательный масштаб с плавающей запятой = getResources (). getDisplayMetrics (). density; int width = (int) (metrics.widthPixels * scale + 0.5f); - При этом вы должны учитывать плотность устройства.
Обратите внимание, что метрики (ширина, высота) меняются в зависимости от поворота устройства.
5

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

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

3401

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

A structure describing general information about a display, such as its size, density, and font scaling. To access the DisplayMetrics members, initialize an object like this:

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);

Мы можем использоватьwidthPixels получить информацию для:

"The absolute width of the display in pixels."

Example:

Log.d("ApplicationTagName", "Display width in px is " + metrics.widthPixels);
try {display.getSize (size); ширина = размер.х; высота = размер. у; } catch (NoSuchMethodError e) {width = display.getWidth (); height = display.getHeight (); }
Я не понимаю, почему вы хотите использоватьtry/catch для такой проверки? Почему бы просто не использоватьif (android.os.Build.VERSION.SDK_INT >= 13) без каких-либо исключений? Я думаю оtry/catch в нормальном потоке приложений как плохая практика.
getWidth () или getSize ()? Что бы я использовал, если бы мне нужно, чтобы мое приложение работало как на API & lt; 13, так и на API & gt; 13?
Что делать, если вы хотите получить размер экрана, исключая панель навигации и / или панель уведомлений
14

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int wwidth = metrics.widthPixels;
9

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

которое имеетmatch_parent для его ширины & amp; рост. Это код в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 и различных типов устройств (телефонов и планшетов).

11

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

Первый:

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

Во-вторых:

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

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

17

quot; android: layout_weight & quot;

Приведенный ниже пример, модифицированный из ответа 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>
4

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

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+.

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

Это не вычитает пространство для экранных элементов управления (например, на планшетах или устройствах Nexus). Кроме того, я получаю другое значение (750 против 800) на своих 10 & quot; Планшет, в зависимости от того, активна ли активность после завершения расчета. Но для моих целей это более чем нормально. Спасибо!
8

так как он хотел, чтобы размеры дисплея были в реальных пикселях. Я хотел, чтобы размеры были в "независимых от устройства пикселях" и собирали ответы отсюдаhttps://stackoverflow.com/a/17880012/253938 и здесьhttps://stackoverflow.com/a/6656774/253938 Я придумал это:

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

(Ответ 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, это то, что нам осталось.

Да, это было еще в 2012 году.
извините, позвольте мне уточнить, что я имел в виду. Маловероятно, что кто-либо поддержит API & lt; 14 с 22.06.2015
15

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

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

11

Rect dim = new Rect();
getWindowVisibleDisplayFrame(dim);
Круто, но одна страшная вещь об этом методе в исходном коде:this comment
7

Вы можете получитьheight размер с помощью:

getResources().getDisplayMetrics().heightPixels;

иwidth размер с помощью

getResources().getDisplayMetrics().widthPixels; 
11
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);
    }
}
7

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

usable screen dimension безStatus Bar а такжеAction Bar (также благодаря ответу Свапнила):

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

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

30

findViewById()), а затем вы можете использоватьgetWidth() на само представление.

Это фактически то, как документация говорит вам сделать это ... но это немного бессмысленно, если вы НЕ используете представление. Вы можете использовать что-то другое, например, mglsurfaceview.
это лучше, поскольку родительский вид может не соответствовать размеру дисплея. Но убедитесь, что это сделано в точке, где представление, размер которого вы запрашиваете, уже выложено, что обычно не будет внутри onCreate (). Вы можете использовать пользовательский обратный вызов из onWindowFocusChanged (boolean hasFocus), который будет вызываться после того, как все виды были измерены и т. Д., Гарантируя, что вы не получите неправильные размеры для интересующего вас вида ...
46

 int screenHeight = getResources().getDisplayMetrics().heightPixels;
 int screenWidth = getResources().getDisplayMetrics().widthPixels; 
14
DisplayMetrics dimension = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dimension);
int w = dimension.widthPixels;
int h = dimension.heightPixels;
4

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() вернет высоту экрана.

нет ... он возвращает 0.
114

но было бы полезно знать (я искал его сам, когда пришел к этому вопросу), что если вам нужно измерение View, но ваш код выполняется, d, когда его макет не имеет был выложен еще (например, вonCreate() ) вы можете настроитьViewTreeObserver.OnGlobalLayoutListener сView.getViewTreeObserver().addOnGlobalLayoutListener() и поместите туда соответствующий код, который нуждается в измерении представления. Обратный вызов слушателя будет вызван, когда макет будет размечен.

@marsbear, где это говоритView.post() не гарантируется ли работа? Мне любопытно, потому что я также полагаюсь на этот метод для получения размера представления после макета и не знал, что он ненадежен.
или просто напишите view.post
Суть для быстрой реализации :)gist.github.com/doridori/9208247
view.post не гарантированно работает, хотя. Это просто обходной путь.
@ Turbo Я говорю, что: p Мы использовали этот обходной путь раньше, и он оказался ненадежным. Этот обходной путь основан на предположении, что первоначальное размещение выполняется в том же UIThread витке, что и инициализация. Следовательно, вы можете запланировать выполнение своего кода до следующего поворота пользовательского интерфейса с помощью post () и все будет в порядке. Оказалось, что верстка может занять еще больше времени при определенных обстоятельствах, и представление все еще не было выложено, когда запускался опубликованный код. Теперь я добавляю ViewTreeObserver в onCreate и удаляю его после первого onLayout. Инициируйте свои вещи во время этого первого onLayout.
7

@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;
}
Это происходит сбой на эмуляторе под управлением Android 4.0 (API 14).
15

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

итаем программный способ получить ее:

Sample code
int resId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resId > 0) {
    result = getResources().getDimensionPixelSize(resId);
}

Переменнаяresult дает высоту в пикселе.

For quick access

Enter image description here

Для получения дополнительной информации о высотеTitle bar, Navigation bar а такжеContent Viewпожалуйста, посмотрите наРазмеры экрана устройства Android.

Этот подход устарел с Android Marshmallow. Высота строки состояния может меняться от версии устройства или Android. Лучше использоватьOnApplyWindowInsetsListener.
Как раз то, что мне нужно!getResources().getDisplayMetrics().heightPixels + result дает фактическую высоту полного экрана. Ответ Драгана Марджанови также работает, но я предпочитаю это более короткое и простое решение.
64

и я заметил, что Эллиот Хьюз » & quot; Dalvik Explorer & quot; Приложение всегда показывает правильные размеры на любом устройстве 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) {
}
Обратите внимание, что этот код распространяется по лицензии GPL v3, что имеет значение для использования в производственных приложениях.
Удивительно, но вы никогда не должны были ожидать исключений из бизнес-логики. Исключительная стрельба (даже когда ее поймали) ужасна для производительности. Кроме того, вы выполняете больше работы, чем необходимо, если SDK_INT равен & gt; 13. Вместо этого вы должны просто добавить некоторые if в Build.VERSION.SDK_INT.
Это единственный пост, который учитывает оформление окон (строка состояния / строка меню). отлично работал для меня.
GPL и в зависимости от отражения вызывать методы, которые могут отсутствовать в будущих версиях Android. Mhhh
@ Эрик Б, я согласен. Я добавил улучшенную версию. Тем не менее я оставил часть "начиная с SDK 1" просто на случай, если что-то пойдет не так в try / catch (я видел много плохих вещей в Android, особенно когда вы думаете, что что-то пойдет не так, поэтому я хотел бы сохранить это в безопасности :)). В любом случае не должно быть слишком больших накладных расходов, поскольку этот расчет должен выполняться только один раз (например, значения могут храниться в некоторых статических атрибутах).
5

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;
}
mContext.getResources () getDisplayMetrics () widthPixels..; ???
26

одна для отправки контекста, а другая для получения высоты и ширины в пикселях:

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;
}
Вам нужно добавить@SuppressLint("NewApi") чуть выше сигнатуры функции для возможности компиляции.
Я думаю, что лучше получить высоту и ширину за один раз, а не в отдельных вызовах API, потому что в противном случае они могут быть не синхронизированы. Это может произойти, если ориентация экрана меняется во время работы вашего кода.

Похожие вопросы