Подтвердить что ты не робот

Ввод плотности экрана в правильное ведро

Набор из шести обобщенных плотностей:

ldpi (low) ~120dpi
mdpi (medium) ~160dpi
hdpi (high) ~240dpi
xhdpi (extra-high) ~320dpi
xxhdpi (extra-extra-high) ~480dpi
xxxhdpi (extra-extra-extra-high) ~640dpi

На страницах вики каждого дисплея телефона

Масштабирование вниз в ведра i.e, если ppi - 300, которые войдут в ведро hdpi, так как оно меньше 320?

Galaxy S3 306ppi -> bucket hdpi
Nexus 4  318ppi -> bucket hdpi
Nexus 5  445ppi -> bucket xhdpi
Nexus 5X 432ppi -> bucket xhdpi
Nexus 6  493ppi -> bucket xxhdpi 
Nexus 6P 518ppi -> bucket xxhdpi

Это правильный способ выработать ведра для размеров экрана.

Я задал вопрос, потому что создал следующие ресурсы каталога значений:

values-hdpi/dimens
values-xhdpi/dimens
values-xxhdpi/dimens
values-xxxhdpi/dimens

В dimens.xml у меня разные поля и задано значение dp в зависимости от размера ведра i.e.

<dimen name="network_quantity_margin_top">100dp</dimen>

Мне интересно узнать, правильно ли это делается.

4b9b3361

Ответ 1

Причина, по которой я спрашивал, заключается в том, что я создал следующие ресурсы каталога значений. (...) В dimens.xml у меня разные поля и задано значение dp в зависимости от размера ведра. (...) Мне интересно узнать, правильно ли это делается.

Я не уверен, почему вам нужны разные поля, указанные в dp зависимости от плотности. Указание разницы как dp один раз, для базовой плотности, уже обрабатывает все другие плотности для вас, а это означает, что физический размер поля будет таким же, если он отображается на любом устройстве.

Если вы использовали px вместо dp (но не делаете этого), вам придется делать масштабирование для разных экранов самостоятельно.

Масштабирование в ведра, т.е. Если ppi 300, которые войдут в ведро hdpi, так как оно меньше 320?

Да, но не потому, что оно меньше 320. Если бы было правило, я бы сказал, что он округляется до ближайшей обобщенной плотности. См. Эту иллюстрацию того, как Android грубо отображает фактические плотности в обобщенных плотностях (цифра не является точной):

generalized densities

Соответствующая часть документации такова:

Каждый обобщенный размер и плотность охватывает диапазон фактических размеров экрана и плотности. Например, два устройства, которые сообщают размер экрана нормального, могут иметь фактические размеры экрана и пропорции, которые немного отличаются при измерении вручную. Аналогично, два устройства, которые сообщают плотность экрана hdpi, могут иметь реальную плотность пикселей, которые немного отличаются. Android делает эти различия абстрактными для приложений, поэтому вы можете предоставить пользовательский интерфейс, предназначенный для обобщенных размеров и плотности, и пусть система обрабатывает любые окончательные настройки по мере необходимости.

Так что вам не все равно, как Android это делает, если вы просто пишете приложение. Вы должны заботиться о:

  • укажите все значения размера макета в dp или с помощью wrap_content/match_parent, в зависимости от ситуации (текст может быть в sp для дополнительного соответствия предпочтениям пользователя, но не что иное, как текст),
  • подумайте о разных макетах в зависимости от физического размера и ориентации экрана,
  • предоставлять ресурсы битмапа для разных плотностей, чтобы избежать размытых или пиксельных артефактов (потому что Android будет масштабировать их, чтобы иметь правильный физический размер, если вы используете dp или wrap_content).

Android будет искать наилучший соответствующий ресурс, а затем прозрачно обрабатывать любое масштабирование блоков dp, если необходимо, исходя из фактической плотности используемого экрана. Преобразование блоков dp в пиксели экрана просто: px = dp * (dpi/160).

Обратите внимание на фактическую плотность в отличие от обобщенной плотности. Последнее является лишь удобством для разработчиков, поскольку невозможно было бы предоставить чертежи для каждого экрана. Таким образом, разработчикам необходимо предоставить только 3 или 4 набора графических элементов, в то время как Android выбирает наиболее подходящую и настраивает ее далее для нужд этого конкретного устройства. (В настоящее время можно использовать один вектор, который можно вырезать, а не много предварительно масштабированных растровых изображений, что означает лучшее качество и меньший размер.)

Это правильный способ разработки ведра для размеров экрана.

Нет. Согласно показателям устройства Google все перечисленные вами устройства попадают в ведра выше, чем вы ожидали:

Galaxy S3    NA        NA
Nexus 4     318     xhdpi
Nexus 5X    424    xxhdpi
Nexus 5     445    xxhdpi
Nexus 6     493   xxxhdpi
Nexus 6P    515   xxxhdpi

Я взял некоторые другие устройства из этого списка и описал, как разные устройства попадают в ведра плотности в зависимости от их реальной физической плотности.

density buckets of some Android devices

Chromebox 30            101      mdpi
Chromebook 11           135      mdpi
Samsung Galaxy Tab 10   149      mdpi
Nexus 7 '12             216     tvdpi
Android One             218      hdpi
Chromebook Pixel        239     xhdpi
Nexus 9                 288     xhdpi
Nexus 10                299     xhdpi
Moto X                  312     xhdpi
Nexus 4                 318     xhdpi
Nexus 7 '13             323     xhdpi 
Moto G                  326     xhdpi
Dell Venue 8            359     xhdpi
LG G2                   424    xxhdpi
Nexus 5X                424    xxhdpi
HTC One M8              441    xxhdpi
Nexus 5                 445    xxhdpi
Nexus 6                 493   xxxhdpi
Nexus 6P                515   xxxhdpi
LG G3                   534    xxhdpi

Вы можете видеть, что с некоторыми заметными исключениями выполняется правило, согласно которому выбирается ближайшая обобщенная плотность.

Исключение составляют Nexus 6 и 6P, которые перечислены как xxxhdpi, хотя LG G3 имеет более высокую физическую плотность и все еще далек от 640px/дюймов. Android One - hdpi но он только немного плотнее, чем Nexus 7 '12, который является tvdpi. Chromebox 30 и Chromebook Pixel (по общему признанию, а не Android) назначаются mdpi и xhdpi хотя они физически ниже, чем ldpi и hdpi, соответственно.

Ответ 2

Мне интересно узнать, правильно ли это делается.

В основном вы правы.

Проблема заключается в этой части:


Я задал вопрос, потому что создал следующие ресурсы каталога значений:

values-hdpi/dimens
values-xhdpi/dimens
values-xxhdpi/dimens
values-xxxhdpi/dimens

В dimens.xml у меня разные поля и задано значение dp в зависимости от размера ковша i.e.

<dimen name="network_quantity_margin_top">100dp</dimen>

Цель dp побеждает, определяя такие папки, как values-hdpi/dimens. Плотность пикселей, по дизайну, не зависит от устройства - 100dp на устройстве с dpi = 240 будет выглядеть столь же широко/длинно на устройстве с dpi = 480. Итак, если вы хотите, чтобы ваше приложение выглядело согласованным, не предоставляйте разные размеры для разных плотностей экрана.

Правильный способ подумать об этом - понять, что единственным ресурсом, на который влияет изменение плотности экрана, является drawable. A drawable на экране с разрешением dpi = 240 будет выглядеть вдвое большим по сравнению с экраном с плотностью = 480. Я уверен, что вы предоставляете папки типа drawable-hdpi, drawable-xhdpi и т.д. чтобы справиться с этим. Для всего остального и особенно измерений используйте dp. Для размеров текста используйте scaled-pixels - sp.

Что еще более важно, вам следует беспокоиться о диапазоне различных размеров экрана, доступных для Android. Как бы вы использовали всю дополнительную экранную недвижимость на 10-дюймовом устройстве по сравнению с 5-дюймовым телефоном? Квалификаторы, такие как -normal, -large, xlarge, должны представлять для вас большую заинтересованность.

Подводя итог:

  • рассмотрите все устройства определенного размера экрана одинаково - их плотность экрана не имеет значения при использовании density pixels.
  • для каждого используемого ресурса drawable, поместите свои масштабированные версии в ведра, которые вы хотите поддержать. Помните, что если вы не предоставите ресурсы для определенного ведра (скажем drawable-hdpi), андроид уменьшит ваши чертежи из папки drawable-xhdpi (если задано drawable-xhdpi). Также верно обратное: если вы разместили все свои чертежи в drawable-xhdpi, андроид масштабировал ваши чертежи на устройстве xxhdpi. Результатом будет размытая графика - из-за масштабирования.

Я знаю, что здесь немного крутого склона:). Итак, если вам нужно уточнить еще кое-что, оставьте мне комментарий.

Ответ 3

Из документации для Android:

Поддержка нескольких экранов

В некоторых случаях вам нужно будет выразить измерения в dp, а затем конвертировать их в пиксели. Представьте приложение, в котором свиток или бегущий жест распознается после перемещения пальца пользователя на не менее 16 пикселей. На базовом экране пользователь должен перемещаться на 16 пикселей /160 dpi, что составляет 1/10 дюйма (или 2,5 мм) до жест признается. На устройстве с дисплеем высокой плотности (240 точек на дюйм), пользователь должен перемещаться на 16 пикселей /240 точек на дюйм, что равно 1/15 дюймов (или 1,7 мм). Расстояние намного короче, и приложение становится более чувствительным к пользователю.

Чтобы исправить эту проблему, порог жестов должен быть выражен в коде в dp, а затем преобразуется в фактические пиксели. Например:

// The gesture threshold expressed in dp
private static final float GESTURE_THRESHOLD_DP = 16.0f;

// Get the screen density scale
final float scale = getResources().getDisplayMetrics().density;
// Convert the dps to pixels, based on density scale
mGestureThreshold = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f);

// Use mGestureThreshold as a distance in pixels...

В поле DisplayMetrics.density указан масштабный коэффициент, который вы должны использовать для преобразования единиц dp в пиксели в соответствии с текущим экраном плотность. На экране со средней плотностью DisplayMetrics.density равно 1,0; на экране с высокой плотностью он равен 1,5; на экране с повышенной плотностью он равен 2,0; и на экране с низкой плотностью он равен 0,75. Эта цифра является фактором, по которому вы должны умножить единицы dp на чтобы получить фактическое количество пикселей для текущего экрана. (Затем добавьте 0.5f для округления фигуры до ближайшего целого числа при преобразовании в целое число.) Для получения дополнительной информации см. DisplayMetrics класс.

Ответ 4

вам нужно обработать ресурсы, касающиеся ширины экрана в формате dp без точек на дюйм (точка на дюйм)

например, nexus 5 1920 X 1080 480 dpi использует xxhdpi и nexus 6p 2560 X 1440 560 dpi он использует xxhdpi тоже не xxxhdpi!!

чтобы обработать его, используйте самый маленький ресурс ширины "drawable-swXXXdp"


ширина в dp = ширина в пикселях /(dpi/160) dp = 1440/(560/160) = ~ 411

create drawable-sw411dp 

Ссылка

Ответ 5

Говоря об устройствах Android, PPI == DPI

PPI (пиксели на дюйм) и DPI (точки на дюйм) означают то же самое, поскольку они являются мерой плотности экрана; таким образом, ваш подход к PPI против DPI является правильным.

Подробное объяснение можно найти здесь. Ключевой частью статьи является следующее:

Плотность экрана указана как Пиксели на дюйм, PPI, и это количество пикселей, которые вписываются в дюйм. Чем выше число, тем на дисплее появляются более четкие изображения, поэтому потребители рассматривают высокий PPI имеет преимущество при покупке устройства. Иногда цифра цитируется как Точки на дюйм, DPI...

Ответ 6

Немного поздно, но это может быть полезно для других читателей. Плотность экрана и "ведро", используемое Android для выбора ресурса, могут сбить с толку. Документация Google довольно плотная, и она требует много работы, чтобы отделить ее до чего-то полезного при написании кода. Отчасти потому, что есть несколько факторов, и они рассказывают вам все о плотности экрана и провалах. Но короткий ответ таков.

В основном, ваш определяющий фактор - это твиттер (если вы полагаетесь на другие факторы, такие как малый/средний/большой), это не ваш ответ. В противном случае я нашел этот ответ довольно полезным и простым. Вот код, который я сопоставил из разных источников, которые я запускаю при запуске приложения, чтобы определить отображаемую информацию.

Плотность экрана говорит мне, какой уровень dpi поддерживается устройством.

float density = context.getResources().getDisplayMetrics().density;

Затем у меня есть простой метод измерения устройств, чтобы рассказать мне о экране. (Обратите внимание, я использую Logger).

protected static void checkDeviceSize(AppCompatActivity context) {
    DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
    Display display = context.getWindowManager().getDefaultDisplay();
    DisplayMetrics outMetrics = new DisplayMetrics();
    display.getMetrics(outMetrics);

    float density = context.getResources().getDisplayMetrics().density;
    float dpHeight = outMetrics.heightPixels / density;
    float dpWidth = outMetrics.widthPixels / density;
    String dpiName = getDpiName(density);
    Timber.e("density  :" + density + " [" + dpiName + "]");
    Timber.e("height dp:" + dpHeight + ", (" +outMetrics.heightPixels + "px)");
    Timber.e("width dp :" + dpWidth + ", (" + outMetrics.widthPixels + "px)");

}

У меня также есть этот простой вспомогательный метод, который определяет имя DPI для поддержки вышеописанного метода.

public static final String DPI_LDPI = "ldpi";
public static final String DPI_MDPI = "mdpi";
public static final String DPI_HDPI = "hdpi";
public static final String DPI_XHDPI = "xhdpi";
public static final String DPI_XXHDPI = "xxhdpi";
public static final String DPI_XXXHDPI = "xxxhdpi";
public static final String DPI_TVDPI = "tvdpi";

private static String getDpiName(float density) {
    String result = "undefined";
    if (density < 1.0) {
        result = DPI_LDPI;
    } else if (density == 1.0f) {
        result = DPI_MDPI;
    } else if (density <= 1.3f) {
        result = DPI_TVDPI;
    } else if (density <= 1.5f) {
        result = DPI_HDPI;
    } else if (density <= 2.0f) {
        result = DPI_XHDPI;
    } else if (density <= 3.0f) {
        result = DPI_XXHDPI;
    } else if (density <= 4.0f) {
        result = DPI_XXXHDPI;
    }
    return result;
}

Наконец, это видео с 2013 года по-прежнему актуально и сегодня.