मूल समस्या यह है, कि आपको वास्तविक माप (विशेषकर wrap_content
या जैसे गतिशील मूल्यों के साथ match_parent
) के लिए ड्राइंग चरण की प्रतीक्षा करनी होगी , लेकिन आमतौर पर यह चरण समाप्त नहीं हुआ है onResume()
। इसलिए आपको इस चरण की प्रतीक्षा करने के लिए वर्कअराउंड की आवश्यकता है। इसके विभिन्न संभावित समाधान हैं:
1. ड्रा / लेआउट इवेंट्स को देखें: ViewTreeObserver
एक ViewTreeObserver अलग-अलग ड्राइंग घटनाओं के लिए निकाल दिया जाता है। आमतौर पर OnGlobalLayoutListener
आप माप प्राप्त करने के लिए क्या चाहते हैं, इसलिए श्रोता में कोड को लेआउट चरण के बाद कहा जाएगा, इसलिए माप निम्न हैं:
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
view.getHeight(); //height is ready
}
});
नोट: श्रोता को तुरंत हटा दिया जाएगा क्योंकि अन्यथा यह हर लेआउट ईवेंट पर आग लगाएगा। यदि आपको श्रोताओं को अपंजीकृत करने के लिए एसडीके लवल <16 का उपयोग करना है
public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim)
2. लेआउट कतार में एक रननेबल जोड़ें: View.post ()
बहुत अच्छी तरह से ज्ञात नहीं है और मेरा पसंदीदा समाधान है। मूल रूप से बस अपने स्वयं के चलने योग्य के साथ दृश्य की पोस्ट विधि का उपयोग करें। यह मूल रूप से रोमेन गाइ द्वारा बताए गए दृश्य के माप, लेआउट आदि के बाद आपके कोड को कतार में खड़ा करता है :
UI ईवेंट कतार घटनाओं को क्रम में संसाधित करेगा। SetContentView () के आने के बाद, इवेंट कतार में एक संदेश होगा जिसमें एक रिलेटआउट के लिए पूछा जाएगा, इसलिए जो भी आप कतार में पोस्ट करेंगे वह लेआउट पास के बाद होगा
उदाहरण:
final View view=//smth;
...
view.post(new Runnable() {
@Override
public void run() {
view.getHeight(); //height is ready
}
});
पर लाभ ViewTreeObserver
:
- आपका कोड केवल एक बार निष्पादित किया गया है और आपको निष्पादन के बाद ऑब्जर्वर को निष्क्रिय करने की आवश्यकता नहीं है जो एक परेशानी हो सकती है
- कम क्रिया वाक्यविन्यास
संदर्भ:
3. दृश्य के ओवरलैट विधि को अधिलेखित करें
यह केवल कुछ स्थितियों में ही व्यावहारिक होता है जब तर्क को दृश्य में ही समझाया जा सकता है, अन्यथा यह एक काफी क्रियात्मक और बोझिल वाक्यविन्यास है।
view = new View(this) {
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
view.getHeight(); //height is ready
}
};
यह भी ध्यान रखें, कि onLayout को कई बार बुलाया जाएगा, इसलिए विचार करें कि आप इस विधि में क्या करते हैं, या पहली बार अपना कोड अक्षम करें
4. जाँच करें कि क्या लेआउट चरण के माध्यम से किया गया है
यदि आपके पास ऐसा कोड है जो ui बनाते समय कई बार निष्पादित हो रहा है तो आप निम्नलिखित समर्थन v4 कार्य विधि का उपयोग कर सकते हैं:
View viewYouNeedHeightFrom = ...
...
if(ViewCompat.isLaidOut(viewYouNeedHeightFrom)) {
viewYouNeedHeightFrom.getHeight();
}
यह देखने के बाद कि यह अंतिम रूप से कम से कम एक लेआउट के माध्यम से वापस आ गया हो या खिड़की से अलग किया गया हो, यह सच है।
अतिरिक्त: स्थिर रूप से परिभाषित माप प्राप्त करना
यदि यह केवल सांख्यिकीय रूप से परिभाषित ऊँचाई / चौड़ाई प्राप्त करने के लिए पर्याप्त है, तो आप इसके साथ बस कर सकते हैं:
लेकिन आप ध्यान रखें, यह ड्राइंग के बाद वास्तविक चौड़ाई / ऊंचाई के लिए भिन्न हो सकता है। Javadoc पूरी तरह से अंतर का वर्णन करता है:
एक दृश्य का आकार चौड़ाई और ऊंचाई के साथ व्यक्त किया गया है। एक दृश्य वास्तव में चौड़ाई और ऊंचाई मूल्यों के दो जोड़े हैं।
पहली जोड़ी को मापा चौड़ाई और मापा ऊंचाई के रूप में जाना जाता है। ये आयाम परिभाषित करते हैं कि एक दृश्य अपने माता-पिता के भीतर कितना बड़ा होना चाहता है (अधिक विवरण के लिए लेआउट देखें।) मापा आयाम getMeasuredWidth () और getMeasuredHeight () कहकर प्राप्त किया जा सकता है।
दूसरी जोड़ी को केवल चौड़ाई और ऊंचाई के रूप में जाना जाता है, या कभी-कभी चौड़ाई और ड्राइंग की ऊँचाई को खींचा जाता है। ये आयाम स्क्रीन पर दृश्य के वास्तविक आकार, ड्राइंग समय पर और लेआउट के बाद परिभाषित करते हैं। ये मान हो सकते हैं, लेकिन मापा चौड़ाई और ऊंचाई से भिन्न नहीं हैं। चौड़ाई और ऊंचाई getWidth () और getHeight () कहकर प्राप्त की जा सकती है।