Как да конвертирате DP, PX, SP един в друг, особено DP и SP?

Знам разликата между DP, SP и PX. И след като потърсих тази тема, не намерих нищо, което да ме удовлетворява напълно. Може би тази публикация е дубликат, но все пак искам да знам каква е формулата за преобразуване от DP в PX и DP в SP, от SP до PX, от PX до SP, от SP до DPот DP до SP? Знам някои кодове за това, но те са несъвършени.


person SilentKnight    schedule 16.04.2015    source източник
comment
погледнахте ли отговора на тази връзка stackoverflow.com/questions/8309354/   -  person surhidamatya    schedule 16.04.2015
comment
javapapers.com/android /   -  person surhidamatya    schedule 16.04.2015
comment
Не, мисля, че няма задоволителен отговор. Те са несъвършени. Казахте На този въпрос вече е отговорено хиляди пъти, тогава ми покажете.   -  person SilentKnight    schedule 16.04.2015


Отговори (6)


DP към 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 към SP:

public static int dpToSp(float dp, Context context) {
    return (int) (dpToPx(dp, context) / context.getResources().getDisplayMetrics().scaledDensity);
}
person AndroidEx    schedule 16.04.2015
comment
@Android777 Предишните ви два кодови сегмента изглеждат свежи. @DerGolem Но защо dp = sp, device-independent pixel е равно на scaled-pixel? - person SilentKnight; 16.04.2015
comment
@SilentKnight Извлечено от тази публикация (по-специално от изображението): stackoverflow.com/a/2025541/2649012 - person Phantômaxx; 16.04.2015
comment
Когато TextView се нарича setScaleX или setScaleY, и двете са равни? - person SilentKnight; 16.04.2015
comment
Когато android:scaleX = "integer" или android:scaleY = "integer" са определени от TextView, и двете са равни? - person SilentKnight; 16.04.2015
comment
@DerGolem, според моите познания, sp и dp могат да бъдат различни, защото sp взема предвид и предпочитанията за размера на шрифта на потребителя. Вярвам, че тази снимка описва само една възможна ситуация. - person AndroidEx; 16.04.2015
comment
@DerGolem Иска ми се да мога да намеря солиден пример, илюстриращ кога могат да бъдат еднакви и различни, но чувствам, че това е някак сива зона. Много хора (включително и аз) знаят какво е dp и sp и хипотетичните разлики между тях, но някои практически аспекти все още са на тъмно. - person AndroidEx; 16.04.2015
comment
@SilentKnight Забелязах, че променихте въпроса си. Искате ли да добавя други указания за преобразуване, които сте посочили? Защото мисля, че ще бъде някаква вариация (инверсия) на съществуващите, не много интересна. - person AndroidEx; 16.04.2015
comment
@Android777. Е, те са mostly еднакви. Като основно правило винаги използвайте dp за изгледи и sp за шрифтове. И никога няма да се провалиш. С уважение, никога не съм проучвал повече, тъй като следя този golden rule. - person Phantômaxx; 16.04.2015
comment
@DerGolem Напълно съм съгласен, но след това се натъкваме на въпрос относно преобразуването между dp и sp и не сме сигурни дали това е валидно нещо, което да разгледаме... - person AndroidEx; 16.04.2015
comment
Както и да е... рядко дори обмислям конвертиране на px в dp и обратно. Защото съм сигурен, че Android прави всичко възможно, за да мащабира правилно моите dps и sps. Въпреки че има случаи, в които трябва да мащабирам нещо, което е дадено в пиксели, или да предам параметър на някакъв метод, който очаква пиксели. - person Phantômaxx; 16.04.2015
comment
@AndroidEx Прав си. SP може да бъде различен от DP въз основа на потребителските предпочитания за размера на текста. Преобразуването от sp в px или dp би било необходимо например при персонализирано чертане, където искате размерът на графиката да съответства по някакъв начин на текста, начертан върху платно. - person Mitselplik; 29.05.2016
comment
"DP to SP: (why would you need it?)", напр. Задавам размер за фигури и текстове програмно (в зависимост от ширината на телефона), а текстът трябва да заема 50% от фигурата. Получавам размер-стойност на фигурата в dp и по някакъв начин трябва да изчисля sp, така че текстът да заема 50% от фигурата. Така че нищо странно.. - person user25; 11.09.2016
comment
p.s. ето официалната информация на Google за Converting dp units to pixel units: developer.android.com/guide/practices/screens_support. html Не, ако работи по същия начин като в отговора ви (използвам информацията на Google, работи правилно) - person user25; 11.09.2016
comment
@user25 Ако говорите за този ред final float scale = getResources().getDisplayMetrics().density; в документите, отколкото applyDimension() прави почти същото - person AndroidEx; 11.09.2016
comment
@anonymos Имам персонализирано оформление на Toast, което се появява в долната централна част на екрана с променлив текст. Изваждам 1/2 от ширината на текста от него, за да запазя центъра, защото знам необходимата стойност на DP, но трябва да взема предвид размера на текста. - person Abandoned Cart; 19.04.2017
comment
sp един е грешен правилният public static int convertDpToSp(float dp, Context context) { return (int) (convertDpToPixels(dp, context) / context.getResources().getDisplayMetrics().scaledDensity); } - person user49557; 05.10.2017
comment
Разликата между DP и SP е, че SP се мащабира въз основа на предпочитанията на потребителя за размер на шрифта. Не можете да третирате двете като еднакви, това е напълно погрешно. Ето защо целият текст трябва да бъде посочен в SP и (почти) всичко останало в DP. - person HughHughTeotl; 11.09.2018
comment
Не работи за мен: stackoverflow. com/questions/55972518/ - person Alex; 04.05.2019
comment
Тествах го и трябва да използвам COMPLEX_UNIT_PX, за да получа реалния размер в PX за SP. Не знам защо, но ако използвам COMPLEX_UNIT_SP, получих огромен и не реален размер на текста. Би трябвало да е чудесно, ако @AndroidEx може да ни потвърди дали това е правилно или е грешка в COMPLEX_UNIT_SP. - person JavierSegoviaCordoba; 16.06.2019

В приетия отговор липсват няколко полезни реализации.

SP to PX

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

or

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

PX to SP

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

DP to PX

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

or

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

PX to 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
  • Преобразуването на DP в SP обикновено не е полезно
person Suragch    schedule 08.02.2017

За конвертиране на Dimension в Integer или Pixel трябва да използвате функцията "getDimensionPixelSize(R.dimen.your_dp_value)", като...

Направете стойност в dimens.xml

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

Сега за тази стойност в пиксел или цяло число можете да използвате както по-долу:

int sizeInPixel = context.getResources().getDimensionPixelSize(R.dimen.padding_10);
person varotariya vajsi    schedule 22.01.2017
comment
Най-чистото решение IMHO, без да споменаваме, че разделянето на файла на стойности-* можете да получите различни стойности за различни плътности, ако е необходимо... - person Shockwaver; 01.08.2018
comment
Благодаря @Shockwaver - person varotariya vajsi; 01.08.2018

За 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 файл)

person vedant    schedule 06.06.2018

Можете да напишете метод, който не се нуждае от 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);
}

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

person Nicholas Oli    schedule 17.06.2020
comment
Resources.getSystem() не е конфигуриран за текущия екран и не може да използва мерни единици според документацията - person T - Gott; 17.10.2020

Според 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
person beigirad    schedule 12.07.2021