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