Как конвертировать DP, PX, SP между собой, особенно DP и SP?

Я знал разницу между DP, SP и PX. И после поиска этой темы я не нашел ничего полностью удовлетворяющего меня. Может быть, этот пост является дубликатом, но я все еще хочу знать, какова формула преобразования из DP в PX и DP в SP, из SP в PX, из PX в SP, из SP в DP, из DP в SP? Я знал некоторые коды для этого, но они несовершенны.

7 ответов

Решение

DP to PX:

public static int dpToPx(float dp, Context context) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
}

SP к PX:

public static int spToPx(float sp, Context context) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.getResources().getDisplayMetrics());
}

DP to SP:

public static int dpToSp(float dp, Context context) {
    return (int) (dpToPx(dp, context) / context.getResources().getDisplayMetrics().scaledDensity);
}

В принятом ответе отсутствуют несколько полезных преобразований.

SP к PX

float sp = 20;
float px = sp * getResources().getDisplayMetrics().scaledDensity;

или же

float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());

PX в SP

float px = 70;
float sp = px / getResources().getDisplayMetrics().scaledDensity;

DP to PX

float dp = 20;
float px = dp * getResources().getDisplayMetrics().density;

или же

float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());

PX в DP

float px = 70;
float dp = px / getResources().getDisplayMetrics().density;

Заметки

  • Поплавки я выбрал выше (20 а также 70) были произвольные значения. Вы можете подключить разные номера, если хотите.
  • px относится к пикселям. Количество пикселей, которое устройство имеет на дюйм экрана, называется плотностью.
  • dp означает независимые от плотности пиксели. То есть, независимо от того, какое устройство используется, фактический размер должен быть одинаковым. Например, если я установлю вид 100 dp Широкий, он будет иметь такую ​​же ширину на новом телефоне высокой плотности, как и на старом телефоне низкой плотности. (Если бы я установил ширину 100 pxс другой стороны, он будет выглядеть большим на телефоне с низкой плотностью и маленьким на телефоне с высокой плотностью.) Плотность измеряется в точках на дюйм (DPI). Формула px = dp * density, Таким образом, вы просто умножаете или делите на плотность для преобразования между px а также dp,
  • sp означает независимые от масштаба пиксели. Он используется только для шрифтов, а не для просмотра. Это похоже на dp кроме того, также факторы в пользовательских предпочтениях. Эта плотность с учетом пользовательских предпочтений называется масштабной плотностью. Настройка TextView шрифт размером с 30 spНапример, текст будет выглядеть одинаково физически на всех устройствах. Тем не менее, ваша бабушка может иметь максимальный размер шрифта в настройках телефона, поэтому 30 sp текст на ее телефоне будет выглядеть больше, чем на вашем. Формула px = sp * scaledDensity,
  • Значение ДП и СП
  • DP в SP преобразование обычно не полезно

Для преобразования Dimension в Integer или Pixel вам нужно использовать функцию "getDimensionPixelSize (R.dimen.your_dp_value)", например...

Сделать значение в измерениях. Xml

<dimen name="padding_10">10dp</dimen>

Теперь для этого значения в пикселях или целых числах вы можете использовать, как показано ниже:

int sizeInPixel = context.getResources().getDimensionPixelSize(R.dimen.padding_10);

За kotlin Я создал функцию расширения:

fun Number.spToPx(context: Context) = TypedValue.applyDimension(
    TypedValue.COMPLEX_UNIT_SP, this.toFloat(), context.resources.displayMetrics).toInt()

Вы можете использовать его как 16.spToPx(context) или же 16.5.spToPx(context)

(Я помещаю такие функции вKotlinExtensions.ktфайл)

Вы можете написать метод, который не требует context или resources:

public static int dpToPx(int dp) {
    return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}

public static int spToPx(int sp) {
    return (int) (sp * Resources.getSystem().getDisplayMetrics().scaledDensity);
}

По аналогии можно преобразовать другие количества.

Согласно исходному коду TypedValue#applyDimension и воспользуйтесь расширением Kotlin:

      val Float.toSp get() = this * Resources.getSystem().displayMetrics.scaledDensity

Другие расширения по ссылке

      val Float.toPx get() = this * Resources.getSystem().displayMetrics.density

val Float.toDp get() = this / Resources.getSystem().displayMetrics.density

у меня работает просто инвертирование applyDimension(), поэтому это решение должно работать для всех единиц.

      public static int unApplyDimension(int unit,float value){
    return (int)( b.getTextSize()/TypedValue.applyDimension(
        b.getTextSizeUnit(),1,
        getApplicationContext().getResources().getDisplayMetrics()));
}

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

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

Другие вопросы по тегам