Я создал свое приложение с заданными высотой и шириной в пикселях для устройства Pantech, разрешение которого составляет 480x800.
Мне нужно преобразовать высоту и ширину для устройства G1. Я подумал, что преобразование в dp решит проблему и обеспечит одинаковое решение для обоих устройств.
**Есть ли простой способ преобразования пикселей в dp?
// Converts 14 dip into its equivalent px
float dip = 14f;
Resources r = getResources();
float px = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dip,
r.getDisplayMetrics()
);
/**
* This method converts dp unit to equivalent pixels, depending on device density.
*
* @param dp A value in dp (density independent pixels) unit. Which we need to convert into pixels
* @param context Context to get resources and device specific display metrics
* @return A float value to represent px equivalent to dp depending on device density
*/
public static float convertDpToPixel(float dp, Context context){
return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
/**
* This method converts device specific pixels to density independent pixels.
*
* @param px A value in px (pixels) unit. Which we need to convert into db
* @param context Context to get resources and device specific display metrics
* @return A float value to represent dp equivalent to px value
*/
public static float convertPixelsToDp(float px, Context context){
return px / ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
Желательно поместить в класс util.java
public static float dpFromPx(final Context context, final float px) {
return px / context.getResources().getDisplayMetrics().density;
}
public static float pxFromDp(final Context context, final float dp) {
return dp * context.getResources().getDisplayMetrics().density;
}
float density = context.getResources().getDisplayMetrics().density;
float px = someDpValue * density;
float dp = somePxValue / density;
плотность
равна
.75
на языки
(120
Дои) 1.0
на элемент
(160
Дои; базовый уровень)1.5
на поп
(240
Дои)2.0
на поставлю
(320
Дои) 3.0
на красный
(480
Дои) 4.0
на сода
(640
Дои) Используйте этот онлайн конвертер, чтобы поиграть с значениями DPI.
Редактировать:
Кажется, нет 1:1 отношения между ведро Дои
и плотности
. Похоже, Нексус 5х
быть красный
имеет плотность
стоимость 2.625
(вместо 3
). Посмотреть на себя в Параметры Устройства.
Если вы можете использовать размеры XML, он's очень просто!
В res/values/dimens.xml`:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="thumbnail_height">120dp</dimen>
...
...
</resources>
Тогда в вашем Java:
getResources().getDimensionPixelSize(R.dimen.thumbnail_height);
Вы можете использовать это .. вне контекста
public static int pxToDp(int px) {
return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
public static int dpToPx(int dp) {
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
Как @Стэн упомянул .. используя этот подход может вызвать проблемы, если изменения плотности системы. Так что знать об этом!
Лично я использую контекст для этого. Это's просто еще один подход, я хотел бы поделиться с вами
По руководство разработкой Андроид:
px = dp * (dpi / 160)
Но часто вы'll не хотите ли проанализировать это другой путь вокруг, когда вы получите дизайн, который's заявило в пикселях. Так:
dp = px / (dpi / 160)
Если вы'вновь на устройстве 240dpi этот коэффициент составляет 1,5 (как указано раньше), так это означает, что значок 60px равняется доска 40dp в приложении.
Без "контекст", элегантные статические методы:
public static int dpToPx(int dp)
{
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
public static int pxToDp(int px)
{
return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
Поэтому можно использовать следующие разработчиком, чтобы рассчитать нужное количество точек измерения, указанных в ДП
public int convertToPx(int dp) {
// Get the screen's density scale
final float scale = getResources().getDisplayMetrics().density;
// Convert the dps to pixels, based on density scale
return (int) (dp * scale + 0.5f);
}
Для всех, кто использует Котлин:
val Int.toPx: Int
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
val Int.toDp: Int
get() = (this / Resources.getSystem().displayMetrics.density).toInt()
Использование:
64.toPx
32.toDp
Есть по умолчанию утиль в SDK для Android: http://developer.android.com/reference/android/util/TypedValue.html
float resultPix = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics())
используя Котлин-расширение делает его лучше
fun Int.toPx(context: Context): Int = (this * context.resources.displayMetrics.density).toInt()
fun Int.toDp(context: Context): Int = (this / context.resources.displayMetrics.density).toInt()
Обновление:
Из-за displayMetrics
- часть глобальных общих ресурсов, мы можем использовать ресурсы.getSystem()
fun Int.toPx(): Int = (this * Resources.getSystem().displayMetrics.density).toInt()
fun Int.toDp(): Int = (this / Resources.getSystem().displayMetrics.density).toInt()
Это должно дать вам преобразование DP в пиксели:
public static int dpToPx(int dp)
{
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
Это должно дать вам преобразование пикселей в ДП:
public static int pxToDp(int px)
{
return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
fun convertDpToPixel(dp: Float, context: Context): Float {
return dp * (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
}
fun convertPixelsToDp(px: Float, context: Context): Float {
return px / (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
}
public static float convertDpToPixel(float dp, Context context) {
return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
public static float convertPixelsToDp(float px, Context context) {
return px / ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
Вероятно, лучший способ, если у вас есть измерение ценностей/измере-получить измерения прямо из getDimension() метод, он возвращает вам размер уже превращается в пиксельного значения.
context.getResources().getDimension(R.dimen.my_dimension)
Просто чтобы лучше объяснить это,
getDimension(int resourceId)
возвращает размер уже преобразованы в пиксель как поплавок.
getDimensionPixelSize(int resourceId)
вернется то же самое, но усе в int, так как Целое число.
Смотри [ссылка Андроид][1]
[1]: я http://developer.android.com/reference/android/content/res/Resources.html#getDimensionPixelSize(инт) &; андроид док"и
public static int dp2px(Resources resource, int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,resource.getDisplayMetrics());
}
public static float px2dp(Resources resource, float px) {
return (float) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px,resource.getDisplayMetrics());
}
где ресурс контексте.getResources().
Более элегантный подход, использующий Котлин'функция расширения с
/**
* Converts dp to pixel
*/
val Int.dpToPx: Int get() = (this * Resources.getSystem().displayMetrics.density).toInt()
/**
* Converts pixel to dp
*/
val Int.pxToDp: Int get() = (this / Resources.getSystem().displayMetrics.density).toInt()
Использование:
println("16 dp in pixel: ${16.dpToPx}")
println("16 px in dp: ${16.pxToDp}")
как это:
public class ScreenUtils {
public static float dpToPx(Context context, float dp) {
if (context == null) {
return -1;
}
return dp * context.getResources().getDisplayMetrics().density;
}
public static float pxToDp(Context context, float px) {
if (context == null) {
return -1;
}
return px / context.getResources().getDisplayMetrics().density;
}
}
в зависимости от контекста, возвращаемое значение типа float, статический метод
В случае, если вы развивать критическое для производительности приложения, пожалуйста, рассмотреть следующие оптимизированные класс:
public final class DimensionUtils {
private static boolean isInitialised = false;
private static float pixelsPerOneDp;
// Suppress default constructor for noninstantiability.
private DimensionUtils() {
throw new AssertionError();
}
private static void initialise(View view) {
pixelsPerOneDp = view.getResources().getDisplayMetrics().densityDpi / 160f;
isInitialised = true;
}
public static float pxToDp(View view, float px) {
if (!isInitialised) {
initialise(view);
}
return px / pixelsPerOneDp;
}
public static float dpToPx(View view, float dp) {
if (!isInitialised) {
initialise(view);
}
return dp * pixelsPerOneDp;
}
}