फॉर्मूला px से dp, dp से px android


150

मैं स्वतंत्र पिक्सल और घनत्व के लिए पिक्सेल की एक चर राशि की गणना करने की कोशिश कर रहा हूं।

यह सूत्र (px to dp): dp = (int)(px / (displayMetrics.densityDpi / 160));छोटे उपकरणों पर काम नहीं करता है क्योंकि यह शून्य से विभाजित होता है।

यह px सूत्र में मेरा dp है:

px = (int)(dp * (displayMetrics.densityDpi / 160));

क्या कोई मुझे कुछ संकेत दे सकता है?


1
पिक्सेल इकाइयों के लिए dp इकाइयों को परिवर्तित करना डेवलपर
पद्म कुमार

@ ब्राम: मुझे लगता है कि आपका फॉर्मूला ठीक है। आप शून्य से एक विभाजन कैसे प्राप्त करेंगे? डिस्प्लेमेट्रिक्स.डेंसिटी डीपीआई या तो 120, 160, 240 या 320, कभी 0. नहीं होगा
ct_rob

मैं @ct_rob से सहमत हूं। displayMetrics.d घनत्वDpi / 160 न्यूनतम मान 0.75 होगा। आप गलत स्थान पर इंट करने के लिए कास्टिंग कर रहे होंगे।
टॉमटैला

जवाबों:


318

नोट: ऊपर व्यापक रूप से इस्तेमाल किया समाधान पर आधारित है displayMetrics.density। हालाँकि, डॉक्स बताते हैं कि यह मान एक गोल मूल्य है, जिसका उपयोग स्क्रीन 'बकेट' के साथ किया जाता है। उदाहरण के लिए। मेरे Nexus 10 पर यह 2 आता है, जहाँ वास्तविक मान 298dpi (वास्तविक) / 160dpi (डिफ़ॉल्ट) = 1.8625 होगा।

अपनी आवश्यकताओं के आधार पर, आपको सटीक परिवर्तन की आवश्यकता हो सकती है, जिसे इस प्रकार प्राप्त किया जा सकता है:

[संपादित करें] यह एंड्रॉइड की आंतरिक डीपी इकाई के साथ मिश्रित होने के लिए नहीं है, क्योंकि यह निश्चित रूप से स्क्रीन बाल्टी पर आधारित है। इसका उपयोग करें जहां आप एक इकाई चाहते हैं जो विभिन्न उपकरणों पर एक ही वास्तविक आकार प्रदान करना चाहिए।

पिक्सेल में कनवर्ट करें:

public int dpToPx(int dp) {
    DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
    return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));     
}

पिक्सेल को dp में बदलें:

public int pxToDp(int px) {
    DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
    return Math.round(px / (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}

ध्यान दें कि वहाँ xdpi और ydpi गुण हैं, आप अंतर करना चाहते हैं, लेकिन मैं एक समझदार प्रदर्शन की कल्पना नहीं कर सकता जहाँ ये मूल्य बहुत अधिक हैं।


8
यह कई उपकरणों पर dp / px के लिए सही मान की गणना नहीं करेगा (अपने Nexus 10 सहित)! जैसा कि आप कहते हैं कि DisplayMetrics.d घनत्व निकटतम स्क्रीन बाल्टी के लिए गोल है, लेकिन इतना dp इकाई है! एक ऐसी वस्तु को खींचने की कोशिश करें जो 160dp चौड़ी हो और इसके ठीक नीचे आप एक और वस्तु खींचें जो dpToPx (160) चौड़ी हो और आप देखेंगे कि दोनों वस्तुओं का आकार अलग-अलग है। इसके अलावा कुछ फोन (जैसे कि गैलेक्सी मिनी और गैलेक्सी एस 3 मिनी) पूरी तरह से xdpi / ydpi के लिए गलत मान रखते हैं, इसलिए इन फोनों पर आपके तरीके पूरी तरह से गलत परिणाम देंगे।
nibarius

@nibarius हाँ आप ऊपर के साथ Android के बॉक्सिंग डीपी गणना को नहीं मिला सकते हैं। उपरोक्त समाधान का अर्थ सटीक डिवाइस भौतिकी के आधार पर एक अलग घनत्व स्वतंत्र मूल्य के रूप में है। जरूरत है उदाहरण के लिए, जहां आप विभिन्न उपकरणों पर एक ही वास्तविक लंबाई की रेखा दिखाना चाहते हैं। बेशक अगर xdpi / ydpi निविष्टियाँ कुछ उपकरणों द्वारा सही ढंग से सेट नहीं की जाती हैं, तो यह वहाँ काम नहीं करेगा।
बच्ची

1
xdpi और ydpi का उपयोग नहीं किया जाना चाहिए, क्योंकि वे कई उपकरणों पर गलत होते हैं, कभी-कभी बहुत से। केवल DisplayMetrics.d घनत्वDpi विश्वसनीय है, जो दुर्भाग्यपूर्ण है, क्योंकि यह डिजाइन द्वारा अभेद्य है। अधिक जानकारी के लिए Google फ़ोरम थ्रेड देखें: group.google.com/forum/# ​​.topic
मार्क मैकलेलैंड

1
मुझे यह प्रतिक्रिया मिली और वास्तव में इसी तरह के कई समाधानों का उपयोग किया गया था, लेकिन मैं बस डॉक्स से गुजरा और पाया गया getDimensionPixelOffSet को दिए गए आयाम (डिप / डीपी में घोषित) के साथ हस्तनिर्मित कोड की तरह पिक्सल में ऑफसेट देता है। मैंने परीक्षण किया और निर्दोष रूप से काम किया। आशा करता हूँ की ये काम करेगा!
५२ को वियायम गॉव

1
महह, यह सही मूल्य नहीं देता है। प्रयास करें: संसाधन r = getResources (); float px = TypedValue.applyDimension (TypedValue.COMPLEX_UNIT_DIP, 14, r.getDisplayMetrics ()); जैसा कि यहाँ बताया गया है: stackoverflow.com/questions/4605527/converting-pixels-to-dp
Rik van Velzen

103

मैंने निम्न सूत्रों का उपयोग करके अपनी समस्या हल की। अन्य लोगों को इससे लाभ हो सकता है।

dp से px:

displayMetrics = context.getResources().getDisplayMetrics();
return (int)((dp * displayMetrics.density) + 0.5);

px से dp:

displayMetrics = context.getResources().getDisplayMetrics();
return (int) ((px/displayMetrics.density)+0.5);

27
@Vame 0.5 को जोड़ने का उपयोग निकटतम पूर्णांक मान के लिए UP को राउंड करने के लिए किया जाता है .. 0.5 जोड़ा जाता है और फिर गणना का परिणाम एक इंट के रूप में डाला जाता है, जिससे यह मंटिसा को अलग कर देता है और एक ठीक गोल पूर्णांक मान के रूप में विशेषता छोड़ देता है।
केली कोपले

3
यह हमेशा सही नहीं होता है। जब मेरे पास दो लेआउट होते हैं एक दूसरे के अंदर और फिर मैं प्रत्येक दृश्य के एक कोनों (एक डीपी का उपयोग करके, दूसरे को डीपी में परिवर्तित करके) कोनों का मिलान नहीं होता है!
मारेक

मुझे इस तकनीक से कोई समस्या नहीं थी। मैंने अलग-अलग लेआउट के लिए इसका इस्तेमाल किया और यह हमेशा उम्मीद के मुताबिक काम किया। बेशक मैंने कुछ साल पहले इसका उपयोग किया था और मुझे यकीन नहीं है कि यह अभी भी काम करता है। शायद आप PanaVTEC के जवाब में दूसरी तकनीक आज़मा सकते हैं। यह भी हो सकता है कि सिर्फ डीपी / पीएक्स गणना की तुलना में कोनों को गोल करना अधिक है।
ब्रम

5
यह वही समाधान है जो Android डेवलपर साइट पर अपनाया गया है, इसलिए मुझे लगता है कि यह सही है :)। http://developer.android.com/guide/practices/screens_support.html#dips-pels
alocaly

1
+1 धन्यवाद आदमी। एक जादू की तरह काम किया! इस समाधान को हमारे साथ साझा करने के लिए धन्यवाद।
सिमोन डोरोयाकॉक

34

px से dp:

int valueInpx = ...;
int valueInDp= (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, valueInpx , getResources()
                .getDisplayMetrics());

7
यह डीपी से पीएक्स तक है, लेकिन इस सुधार के साथ: typedValue.applyDimension( TypedValue.COMPLEX_UNIT_PX, valueInDp , getResources() .getDisplayMetrics());पीएक्स से डीपी तक है, यह भी सबसे अच्छा जवाब है
PaNaVTEC

1
@PaNaVTEC, dp से px के लिए आपके द्वारा संदर्भित समाधान गलत है। applyDimensionकेवल पैदावार पिक्सेल। देखें android.googlesource.com/platform/frameworks/base/+/refs/heads/… जिसमें कोई रूपांतरण नहीं किया जाता है COMPLEX_UNIT_PX
स्टीफन नेदिज़ेल्स्की

यह उत्तर स्पष्ट है। यह पिक्सेल में अंतिम मान देता है, कभी नहीं dp। यदि आप स्रोत कोड को देखते हैं, तो मामले के लिए TypedValue.COMPLEX_UNIT_DIP, value * metrics.densityवापस कर दिया जाता है, जहां आपको वास्तव में आवश्यकता होती है value * metrics.density। तो क्या आप valueInDp` getting` कर रहे हैं में नहीं है dpके लिए valueInPxमें px
बिटबबिट

^ टाइपो, मेरा मतलब था "... जहां आपको वास्तव में ज़रूरत है value / metrics.density"
बिटबबिट

31

कभी कुशल तरीका

डीपी से पिक्सेल:

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

पिक्सेल से डीपी:

private int pxToDp(int px)
{
    return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}

आशा है कि यह आपकी मदद करेगा।


4
बेहतर है क्योंकि प्रसंग का उपयोग करने की कोई आवश्यकता नहीं है :) धन्यवाद।
अयाज अलिफोव

2
सबसे बढ़िया उत्तर! दुर्भाग्य से "सही के रूप में चिह्नित" उत्तर गलत है। खासकर जब से यह उपयोग करता है displayMetrics.xdpiजो किसी भी डिवाइस पर अलग है। अफसोस की बात है, इस गलत जवाब में सबसे अधिक अपवित्रता है।
तोम

अच्छा। सबसे अच्छा जवाब के रूप में चिह्नित किया जाना चाहिए। kotlin:private fun dpToPx(dp: Int) = (dp * Resources.getSystem().displayMetrics.density).toInt()
राफेल C

28

बस इकाइयों से पिक्सेल में getResources().getDimensionPixelSize(R.dimen.your_dimension)बदलने के लिए कॉल करेंdp


3
प्रलेखन के अनुसार, यह getDimension () के समान है, सिवाय इसके कि लौटे मूल्य को आकार के रूप में उपयोग करने के लिए पूर्णांक पिक्सेल में परिवर्तित किया जाता है। एक आकार रूपांतरण में आधार मूल्य को गोल करना शामिल है, और यह सुनिश्चित करना कि गैर-शून्य आधार मूल्य कम से कम एक पिक्सेल आकार में है।
CJBS


6
px = dp * (dpi / 160)

dp = px * (160 / dpi)

हालाँकि, अब जब कि मैं इसके बारे में सोचता हूँ ... ब्रैम के मूल सूत्र में शून्य से विभाजन कैसे होगा? डिस्प्लेमेट्रिक्स। डेंसिटी डीपीआई या तो 120, 160, 240 या 320, कभी 0. नहीं होगा
ct_rob

2
(displayMetrics.densityDpi / 160)- यह भाग छोटे उपकरणों पर 0 प्राप्त कर सकता है, वहां यह उदाहरण के लिए गणना करता है 120/160, दोनों मान अंतर हैं, जिसके परिणामस्वरूप 0. जो समाप्त होता है (int) (px/0)

आह, तुम सही हो। इसलिए उसे केवल इतना करना है कि वह अपने सूत्र में एक लंबा प्रयोग करे: 160.0
ct_rob

यह उत्तर डिस्प्लेमेटिक्स के कारण ऊपरी के समान है। DENSITY_DEFAULT का मूल्य 160 है। लेकिन क्या आप हमें बता सकते हैं कि यहाँ DPI क्या है, हम इसकी गणना कैसे करते हैं।
जॉन

3

ज्यादातर मामलों में, रूपांतरण कार्यों को अक्सर कहा जाता है। हम इसे संस्मरण जोड़कर अनुकूलित कर सकते हैं। इसलिए, यह हर बार गणना नहीं करता है कि फ़ंक्शन कहा जाता है।

आइए एक हैशपॉप घोषित करें जो गणना किए गए मूल्यों को संग्रहीत करेगा।

private static Map<Float, Float> pxCache = new HashMap<>();

एक फ़ंक्शन जो पिक्सेल मानों की गणना करता है:

public static float calculateDpToPixel(float dp, Context context) {

        Resources resources = context.getResources();
        DisplayMetrics metrics = resources.getDisplayMetrics();
        float px = dp * (metrics.densityDpi / 160f);
        return px;

    }

एक संस्मरण समारोह जो हैशपॅप से मान लौटाता है और पिछले मानों का रिकॉर्ड रखता है।

ज्ञापन को जावा में विभिन्न तरीकों से लागू किया जा सकता है। जावा 7 के लिए :

public static float convertDpToPixel(float dp, final Context context) {

        Float f = pxCache.get(dp);
        if (f == null) {
            synchronized (pxCache) {
                f = calculateDpToPixel(dp, context);
                pxCache.put(dp, f);
            }

        }

        return f;
    }

जावा 8 लंबोदा फंक्शन का समर्थन करता है :

public static float convertDpToPixel(float dp, final Context context) {

        pxCache.computeIfAbsent(dp, y ->calculateDpToPixel(dp,context));
}

धन्यवाद।


दिए गए समाधानों के अलावा अच्छा है।
ब्राम

मुझे आश्चर्य होगा कि यदि रूपांतरण गणना कम से कम इतनी तेजी से एक मानचित्र लुकअप के रूप में नहीं थी, तो एक सिंक्रनाइज़ एक का उल्लेख करने के लिए नहीं। क्या आपके पास इस अनुकूलन को प्रदर्शित करने के लिए कोई परीक्षा परिणाम लाभदायक है? एंड्रॉइड पर जहां वर्किंग मेमोरी सीमित है, गणना प्रयास के लिए ट्रेडिंग मेमोरी कुछ ऐसा नहीं है जिसे आपको अच्छे कारण के बिना करना चाहिए।
लोर्ने लालटेते


2

नीचे funtions मेरे लिए उपकरणों के पार अच्छी तरह से काम किया।

यह https://gist.github.com/laaptu/7867851 से लिया गया है

public static float convertPixelsToDp(float px){
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float dp = px / (metrics.densityDpi / 160f);
    return Math.round(dp);
}

public static float convertDpToPixel(float dp){
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return Math.round(px);
}

1

आप [DisplayMatrics][1]स्क्रीन घनत्व का उपयोग और निर्धारित कर सकते हैं । कुछ इस तरह:

int pixelsValue = 5; // margin in pixels
float d = context.getResources().getDisplayMetrics().density;
int margin = (int)(pixelsValue * d);

जैसा कि मुझे याद है कि फ़र्श के लिए फ़र्श और चौड़ाई के लिए गोलाई का उपयोग करना बेहतर है।


1

यदि आप डीपी, एसपी, इंच, मिलीमीटर, अंक या पिक्सेल को एक दूसरे से और अलग-अलग स्क्रीन घनत्वों में परिवर्तित करने के लिए एक ऑनलाइन कैलकुलेटर की तलाश कर रहे हैं, तो यह सबसे संपूर्ण उपकरण है जिसे मैं जानता हूं


1

// दशमलव / फ्लोट के संदर्भ में प्राप्त करने के लिए

public static float convertPixelsToDp(float px, Context context) {

    Resources resources = context.getResources();
    DisplayMetrics metrics = resources.getDisplayMetrics();
    float dp = px / (metrics.densityDpi / 160f);
    return Math.round(dp);
}



public static float convertDpToPixel(float dp, Context context) {
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return Math.round(px);
}


// for  getting in terms of Integer

private int convertPxToDp(int px, Context context) {
    Resources resources = context.getResources();
    return Math.round(px / (resources.getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
}


private int convertDpToPx(int dp, Context context) {
    Resources resources = context.getResources();

    return Math.round(dp * (resources.getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));

}

________________________________________________________________________________

public static float convertPixelsToDp(float px){
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float dp = px / (metrics.densityDpi / 160f);
    return Math.round(dp);
}

public static float convertDpToPixel(float dp){
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return Math.round(px);
}


private int convertDpToPx(int dp){
    return Math.round(dp*(getResources().getDisplayMetrics().xdpi/DisplayMetrics.DENSITY_DEFAULT));

}

private int convertPxToDp(int px){
    return Math.round(px/(Resources.getSystem().getDisplayMetrics().xdpi/DisplayMetrics.DENSITY_DEFAULT));
}

1

इन कोटलिन एक्सटेंशन का उपयोग करें:

/**
 * Converts Pixel to DP.
 */
val Int.pxToDp: Int
    get() = (this / Resources.getSystem().displayMetrics.density).toInt()

/**
 * Converts DP to Pixel.
 */
val Int.dpToPx: Int
    get() = (this * Resources.getSystem().displayMetrics.density).toInt()

0

इस विधि का उपयोग करने के लिए बेझिझक मैंने लिखा:

int dpToPx(int dp)
{
    return (int) (dp * getResources().getDisplayMetrics().density + 0.5f);
}

0

ऊपर स्वीकार किया गया उत्तर पूरी तरह से सही नहीं है। Android स्रोत कोड का निरीक्षण करके प्राप्त जानकारी के अनुसार:

Resources.getDimension()और getDimensionPixelOffset()/ getDimensionPixelSize()केवल उस में पूर्व रिटर्न अलग है floatजबकि बाद के दो समान मूल्य वापसी के लिए intउपयुक्त है। उन सभी के लिए, रिटर्न वैल्यू कच्चे पिक्सल में है।

सभी तीन कार्य क्रमशः कॉल करके Resources.getValue()और इस प्रकार TypedValueकॉल करके TypedValue.complexToDimension(), TypedValue.complexToDimensionPixelOffset()और TypedValue.complexToDimensionPixelSize()क्रमशः प्राप्त करके कार्यान्वयन योग्य हैं।

इसलिए, यदि आप XML स्रोत में निर्दिष्ट इकाई के साथ "कच्चा" मूल्य प्राप्त करना चाहते हैं, तो कक्षा के Resources.getValue()तरीकों को कॉल और उपयोग करें TypedValue


0

अन्य उत्तरों की मदद से मैंने यह फ़ंक्शन लिखा।

public static int convertToPixels(Context context, int nDP)
{
        final float conversionScale = context.getResources().getDisplayMetrics().density; 
        return (int) ((nDP * conversionScale) + 0.5f) ;
}

0

कोटलिन एक्सटेंशन का उपयोग करने का एक और तरीका यहां दिया गया है:

val Int.dpToPx: Int
    get() = Math.round(this * Resources.getSystem().displayMetrics.density)

val Int.pxToDp: Int
    get() = Math.round(this / Resources.getSystem().displayMetrics.density)

और फिर इसे इस तरह से कहीं से भी इस्तेमाल किया जा सकता है

12.dpToPx

244.pxToDp

0
DisplayMetrics displayMetrics = contaxt.getResources()
            .getDisplayMetrics();

    int densityDpi = (int) (displayMetrics.density * 160f);
    int ratio = (densityDpi / DisplayMetrics.DENSITY_DEFAULT);
    int px;
    if (ratio == 0) {
        px = dp;
    } else {
        px = Math.round(dp * ratio);

    }

0

यदि आप पूर्णांक का उपयोग कर रहे हैं, तो ct_robs उत्तर पर भिन्नता, कि न केवल 0 से विभाजित होने से बचता है, बल्कि यह छोटे उपकरणों पर भी प्रयोग करने योग्य परिणाम उत्पन्न करता है:

पूर्णांक गणना में सबसे बड़ी परिशुद्धता के लिए विभाजन शामिल है जो ट्रंकेशन प्रभाव को कम करने के लिए विभाजित करने से पहले गुणा करता है।

px = dp * dpi / 160
dp = px * 160 / dpi

5 * 120 = 600 / 160 = 3

के बजाय

5 * (120 / 160 = 0) = 0

यदि आप चाहते हैं कि गोल परिणाम ऐसा करें

px = (10 * dp * dpi / 160 + 5) / 10
dp = (10 * px * 160 / dpi + 5) / 10

10 * 5 * 120 = 6000 / 160 = 37 + 5 = 42 / 10 = 4
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.