Какую единицу измерения использует Paint.setTextSize(float)?

Я хочу нарисовать текст определенной высоты (в пикселях) в представлении, используя Canvas. Можете ли вы просто использовать Paint.setTextSize(float) с количеством пикселей или это использование dp или sp?


person marzipankaiser    schedule 30.07.2012    source источник


Ответы (3)


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

double getDPFromPixels(double pixels) {
    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);
    switch(metrics.densityDpi){
     case DisplayMetrics.DENSITY_LOW:
                pixels = pixels * 0.75;
                break;
     case DisplayMetrics.DENSITY_MEDIUM:
                 //pixels = pixels * 1;
                 break;
     case DisplayMetrics.DENSITY_HIGH:
                 pixels = pixels * 1.5;
                 break;
    }
    return pixels;
}
person Todd Davies    schedule 30.07.2012
comment
Спасибо, что так быстро ответили. - person marzipankaiser; 30.07.2012
comment
@Todd Davies - как мне использовать это в пользовательском классе View? Не могу использовать getWindowManager() - person Neil; 04.03.2014
comment
@Neil - вы можете использовать метод View getContext() для получения Context, после чего вы можете вызвать Context.getSystemService(Context.WINDOW_SERVICE) для получения WindowManager. Подробнее об этом здесь developer.android.com/reference/android/view/WindowManager. HTML. - person Tzoiker; 27.03.2014
comment
Кстати, ответ неверный, dp это px/density. На самом деле это можно упростить, заменив switch на pixels /= metrics.density. - person Tzoiker; 27.03.2014
comment
@Tzoiker, не могли бы вы уточнить? Не понял что менять. - person natario; 23.02.2015
comment
@m iav, замени все switch на pixels /= metrics.density. - person Tzoiker; 28.02.2015
comment
ваша функция возвращает double, но она должна быть с плавающей запятой - person JuliaKo; 02.02.2017

Самый простой способ получить значение px для таких методов — просто определить соответствующее значение dp или sp в файле dimens.xml и получить его следующим образом:

int sizeInPx = context.getResources().getDimensionPixelSize(R.dimen.sizeInSp);

На самом деле у вас есть 3 метода, которые можно использовать в зависимости от ваших потребностей:

  • getDimension() Возвращает число с плавающей запятой в пикселях.

  • getDimensionPixelSize() Возвращает целое число в пикселях. Это то же самое, что и getDimension(), за исключением того, что возвращаемое значение ОКРУГЛЕНО до ближайшего целого числа, и это гарантирует, что ненулевое входное значение приводит к ненулевому выходному значению (например, 0,1 возвращается как 1, а не 0).

  • getDimensionPixelOffset() Возвращает целое число в пикселях. Это то же самое, что и getDimension(), за исключением того, что возвращаемое значение TRUNCATED (т.е. округлено в меньшую сторону). Результат может быть нулевым.

person TheIT    schedule 08.03.2015
comment
Это лучший ответ; он работает правильно на всех существующих устройствах И будет продолжать работать на будущих устройствах (в ответе Тодда Дэвиса отсутствуют более новые плотности, такие как xhdpi, xxhdpi и т. д.). Это также более гибко, вы можете предоставить альтернативный файл dimens.xml для разных размеров экрана (планшеты и т. д.) или при необходимости переключаться между dp и sp. - person NaxyMatt; 12.03.2015
comment
Да, этот ответ TheIT является лучшим ответом, как говорит WanderingLinguist, потому что решение Тодда Дэвиса должно быть обновлено, чтобы включать также случаи xHigh, xxhigh и xxxhigh и tv, а также любые случаи, которые когда-либо возникнут в будущем, показывая, что это сложно и будет легко сломано, а не Ответ ИТ, который будет работать сейчас и в будущем, даже если появятся какие-либо устройства, и решение будет работать, поскольку Android планирует обрабатывать всю плотность устройств. - person Reijo Korhonen; 19.07.2016
comment
Я попробовал это, но, похоже, это не работает должным образом: текст 22sp выглядит хорошо на большом экране (например, Pixel XL — 1440x2560, 560 точек на дюйм), но на маленьком (например, Nexus One — 480x800 hdpi = 240 точек на дюйм) он даже не удобочитаемый. Например, myPaint.setTextSize(80) текст выглядит хорошо на обоих экранах, а также имеет примерно одинаковый размер (всегда есть некоторая разница в размерах на разных устройствах, хотя обычно они очень маленькие). - person Neph; 14.05.2020
comment
@neph Я видел, как вы задавали тот же вопрос в другом ответе, единственное, о чем я могу думать, это то, что холст / растровое изображение, на котором вы рисуете, масштабируется, потому что метод setTextSize () принимает единицы пикселей, поэтому значение 80 должно выглядеть массивно на Nexus One. Удачи! - person TheIT; 19.05.2020
comment
@TheIT Да, я разместил информацию об этом по нескольким вопросам. А также да, изображение больше, чем холст на небольшом устройстве (около 2k x 2k). Я читал по другому вопросу, что холст автоматически масштабируется (в соответствии с dpi,...), если вы указываете ему размер текста напрямую (вместо использования R.dimen.textSize), и это единственное, что действительно сработало - ни одно из других предложений по вычислению размер текста сделал. - person Neph; 19.05.2020
comment
@Neph, холст определенно не масштабируется автоматически - я подозреваю, что происходит то, что вы создаете холст фиксированного размера (например, 2kx2k), затем визуализируете шрифт фиксированного размера (80), затем отображаете этот холст на представление, которое масштабирует холст, чтобы соответствовать размеру, соответствующему пространству экрана (например, 50% экрана или match_parent). Правильный подход заключается в создании холста, размер которого зависит от разрешения экрана (например, для устройств hdpi это может быть 512x512), для чего затем потребуется размер текста, зависящий от разрешения DPI. - person TheIT; 20.05.2020
comment
@TheIT Я создаю холст, используя растровое изображение из изображения, загруженного во время выполнения. Изображение, например. 2к х 2к (не мое изображение, так что не могу это изменить), как и холст. Я также использую то же растровое изображение в PhotoView (Chris Bane), чтобы иметь возможность масштабировать... изображение. Раньше я случайно использовал холст меньшего размера, но тогда он не рисовал в нужном месте. Спасибо за совет с правильным подходом, попробую, когда будет время, а пока оставлю так, потому что в итоге работает на разных устройствах, чего я и хотел. ;) - person Neph; 20.05.2020

Эти методы включают DisplayMetrics, которые могут быть добавлены в будущий Android SDK.

Пиксели для погружения:

public static float getDipFromPixels(float px) {
        return TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_PX,
                px,
                Resources.getSystem().getDisplayMetrics()
        );
}

Погружаемся в пиксели:

public static float getPixelsFromDip(float dip) {
        return TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP, 
                dip,
                Resources.getSystem().getDisplayMetrics()
        );
}
person Stanislav Bodnar    schedule 23.02.2015