देखें का getWidth () और getHeight () रिटर्न 0


513

मैं अपने एंड्रॉइड प्रोजेक्ट में सभी तत्वों को गतिशील रूप से बना रहा हूं। मैं एक बटन की चौड़ाई और ऊंचाई प्राप्त करने की कोशिश कर रहा हूं ताकि मैं उस बटन को चारों ओर घुमा सकूं। मैं बस यह जानने की कोशिश कर रहा हूं कि एंड्रॉइड भाषा के साथ कैसे काम किया जाए। हालाँकि, यह 0 देता है।

मैंने कुछ शोध किया और मैंने देखा कि इसे onCreate()विधि के अलावा कहीं और करने की आवश्यकता है। अगर कोई मुझे ऐसा करने का उदाहरण दे सकता है, तो यह बहुत अच्छा होगा।

यहाँ मेरा वर्तमान कोड है:

package com.animation;

import android.app.Activity;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.Button;
import android.widget.LinearLayout;

public class AnimateScreen extends Activity {


//Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    LinearLayout ll = new LinearLayout(this);

    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
    layoutParams.setMargins(30, 20, 30, 0);

    Button bt = new Button(this);
    bt.setText(String.valueOf(bt.getWidth()));

    RotateAnimation ra = new RotateAnimation(0,360,bt.getWidth() / 2,bt.getHeight() / 2);
    ra.setDuration(3000L);
    ra.setRepeatMode(Animation.RESTART);
    ra.setRepeatCount(Animation.INFINITE);
    ra.setInterpolator(new LinearInterpolator());

    bt.startAnimation(ra);

    ll.addView(bt,layoutParams);

    setContentView(ll);
}

किसी भी मदद की सराहना की है।

जवाबों:


197

आप getWidth()बहुत जल्दी बुला रहे हैं । यूआई को अभी तक स्क्रीन पर आकार और निर्धारित नहीं किया गया है।

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

कहा जा रहा है, आप बटन के आकार को परिभाषित करने के लिए एक आयाम संसाधन का उपयोग कर सकते हैं , फिर इस समस्या से बचने के लिए अपनी लेआउट फ़ाइल और अपने स्रोत कोड से उस आयाम संसाधन का संदर्भ लें।


82
ngreenwood6, आपका अन्य समाधान क्या है?
एंड्रयू

12
@ और - यदि आप चाहते हैं कि निग्विनवुड 6 को आपके फॉलोअप के बारे में सूचित किया जाए, तो आपको अपना संदेश शुरू करना होगा जैसे मैंने आपको किया था (मुझे लगता है कि पहले तीन अक्षर पर्याप्त हैं) - कॉमन्सवेयर को स्वचालित रूप से सूचित किया जाता है, क्योंकि उसने यह प्रतिक्रिया लिखी थी, लेकिन ट्रिन नहीं करता है जब तक आप उन्हें संबोधित नहीं करेंगे।
पीटर अज़ताई

11
@Override सार्वजनिक शून्य onWindowFocusChanged (बूलियन हैफोकस) {// TODO ऑटो-जनरेटेड तरीका stub super.onWindowFocusChanged (hasFocus); // यहाँ आप आकार प्राप्त कर सकते हैं! }
सना

5
@ ngreenwood6 तो आपका समाधान क्या था?
निमा वज़िरी

5
आकार प्राप्त करने के लिए इस श्रोता का उपयोग करें, जब आपकी स्क्रीन तैयार हो। view.getViewTreeObserver ()। addOnGlobalLayoutListener (नया ViewTreeObserver.OnGlobalLayoutListener) () {}
सिनान

815

मूल समस्या यह है, कि आपको वास्तविक माप (विशेषकर 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 () कहकर प्राप्त की जा सकती है।


1
मैं एक टुकड़े में view.post का उपयोग कर रहा हूँ। मुझे उस दृश्य को मापने की आवश्यकता है, जिसकी माता-पिता की ऊंचाई 0dp है और उसका वजन सेट है। मैं जो कुछ भी कोशिश करता हूं वह शून्य की ऊंचाई देता है (मैंने वैश्विक लेआउट श्रोता की भी कोशिश की है)। जब मैंने 125 में देरी के साथ view.post कोड डाल दिया, तो यह काम करता है, लेकिन देरी के बिना नहीं। विचार?
Psest328

6
बहुत बुरा आप केवल एक बार उत्तर दे सकते हैं, वास्तव में अच्छी व्याख्या। अगर मुझे अपना ऐप छोड़ना पड़ा और हाल के ऐप्स से इसे फिर से शुरू किया तो मुझे व्यू रोटेशन की समस्या थी। अगर मैंने इसे वहां से स्वाइप किया और फिर से शुरू किया तो सबकुछ ठीक था। View.post () ने मेरा दिन बचाया!
मथायस

1
धन्यवाद। मैं आमतौर पर View.post () (2 डी विधि) का उपयोग करता हूं, लेकिन अगर इसे पृष्ठभूमि थ्रेड से कहा जाता है तो यह कभी-कभी काम नहीं करता है। इसलिए, लिखना न भूलें runOnUiThread(new Runnable() {...}। वर्तमान में मैं 1 विधि की एक भिन्नता का उपयोग करता हूं addOnLayoutChangeListener:। इसके बाद इसे निकालना न भूलें: RemoveOnLayoutChangeListener। यह बैकग्राउंड थ्रेड से भी काम करता है।
CoolMind

2
दुर्भाग्य से मेरे लिए 'View.post ()' हर समय काम नहीं कर रहा है। मेरे पास 2 परियोजनाएं हैं जो बहुत समान हैं। एक परियोजना में यह काम कर रहा है, दूसरे पर काम नहीं कर रहा है। :(। दोनों ही स्थिति में मैं किसी गतिविधि से 'onCreate ()' विधि से विधि
कहता हूं

1
मुझे मुद्दा मिल गया। एक परियोजना में दृश्य है android:visibility="gone", और दूसरी परियोजना पर दृश्यता संपत्ति थी invisible। यदि दृश्यता goneचौड़ाई है तो हमेशा 0.
एड्रियन ब्यूलेमैन

262

हम प्रयोग कर सकते हैं

@Override
 public void onWindowFocusChanged(boolean hasFocus) {
  super.onWindowFocusChanged(hasFocus);
  //Here you can get the size!
 }

10
तो हम कैसे काम कर सकते हैं? यह केवल गतिविधि में काम करता है?
ओल्कुन्मुस्तफा

8
यह बात करनी चाहिए लेकिन इसका जवाब नहीं होना चाहिए। एक उपयोगकर्ता खिड़की पर तैयार होने के बजाय किसी भी समय में आयाम प्राप्त करना चाहता है। साथ ही इस विधि को कई बार या हर बार कहा जाता है जब खिड़की में कोई परिवर्तन (दृश्य छिपाना, चला जाना, नए विचार जोड़ना आदि) होता है। इसलिए इसे सावधानी से इस्तेमाल करें :)
डॉ। एनडीआरओ

1
यह एक हैक है और ऐसा लगता है कि ViewTreeObserver का उपयोग करना बेहतर होगा।
i_am_jorf

असभ्य ध्वनि करने का मतलब यह नहीं है, लेकिन एक ऑटो उत्पन्न टिप्पणी (विशेष रूप से कोड की 2 पंक्तियों में) छोड़ने से इतना विश्वास नहीं होता है कि आप वास्तव में जानते हैं कि आप क्या कर रहे हैं।
Natix

दुर्भाग्य से, यह मेरे लिए काम नहीं किया। ViewTreeObserver मेरे लिए काम कर रहा है।
नरेंद्र सिंह

109

मैंने इस समाधान का उपयोग किया, जो मुझे लगता है कि onWindowFocusChanged () से बेहतर है। यदि आप एक DialogFragment खोलते हैं, तो फोन को घुमाएं, onWindowFocusChanged तभी कॉल किया जाएगा जब उपयोगकर्ता संवाद बंद कर देगा):

    yourView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {
            // Ensure you call it only once :
            yourView.getViewTreeObserver().removeGlobalOnLayoutListener(this);

            // Here you can get the size :)
        }
    });

संपादित करें: जैसे ही हटाएंग्लोऑनलेऊट लिस्टनर को पदावनत कर दिया जाता है, आपको अब यह करना चाहिए:

@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
@Override
public void onGlobalLayout() {

    // Ensure you call it only once :
    if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
        yourView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    }
    else {
        yourView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
    }

    // Here you can get the size :)
}

4
यह अब तक का सबसे अच्छा उपाय है! क्योंकि यह गतिशील समाधानों पर भी काम करता है जहां चौड़ाई और ऊंचाई ज्ञात नहीं है और गणना की जाती है। अन्य पदों के आकार / आकार के आधार पर एक सापेक्ष लेआउट में। बहुत बढ़िया!
जॉर्ज प्लिगोपुलोस

2
इसके लिए एपीआई 16 या उच्चतर (जेली बीन) की आवश्यकता है
tomsv

7
यह एपीआई 16 की आवश्यकता नहीं है! केवल एक ही तरीका है विधि 16 से एपीआई हटाए जाने वाले ग्लॉइलोनऑलआउट लिस्टनर, लेकिन सभी एपीआई स्तरों के साथ संगत सरल समाधान है - stackoverflow.com/questions/16189525/…
gingo

यदि आपको श्रोता को हटाने की आवश्यकता है, ताकि कई बार खुद को कॉल न करें और आपके पास अलग-अलग एपीआई के साथ समस्याएँ हैं, तो मैं आपको वर्ग के प्रमुख पर एक झूठी बूलियन सेट करने की सलाह देता हूं और फिर मान कैप्चर करने के बाद इसे सही पर सेट करता हूं ताकि यह फिर से मूल्यों पर कब्जा नहीं करता है।
मंसूर फहद

यदि आप पहले रन के बाद श्रोता को निकालते हैं तो आपको गलत आयाम मिल सकते हैं: 02-14 10: 18: 53.786 15063-15063 / पहेलीफ्रेम: ऊंचाई: 1647 चौड़ाई: 996 02-14 10: 18: 53.985 15063-15063 / पहेलीफ्रेम: ऊंचाई : 1500 चौड़ाई: 996
लेओस लिटरक

76

जैसा कि इयान एंड्रॉइड डेवलपर्स थ्रेड में बताता है :

किसी भी तरह, सौदा यह है कि एक खिड़की की सामग्री का लेआउट सभी तत्वों के निर्माण और उनके माता-पिता के विचारों को जोड़ने के बाद होता है । यह इस तरह से होना चाहिए, क्योंकि जब तक आप जानते हैं कि एक दृश्य में कौन से घटक शामिल हैं, और वे क्या होते हैं, और इसी तरह, कोई भी समझदार तरीका नहीं है जो आप इसे बाहर रख सकते हैं।

नीचे की रेखा, यदि आप एक निर्माता में getWidth () आदि कॉल करते हैं, तो यह शून्य वापस आ जाएगा। यह प्रक्रिया कंस्ट्रक्टर में आपके सभी व्यू एलिमेंट्स को बनाने के लिए है, फिर अपने व्यू के onSizeChanged () मेथड को कॉल करने की प्रतीक्षा करें - जब आप पहली बार अपने वास्तविक आकार का पता लगाते हैं, तो यह तब होता है जब आप अपने GUI एलिमेंट्स के साइज सेट करते हैं।

यह भी अवगत रहें कि onSizeChanged () को कभी-कभी शून्य के मापदंडों के साथ कहा जाता है - इस मामले की जांच करें, और तुरंत वापस लौटें (इसलिए आपको अपने लेआउट, आदि की गणना करते समय शून्य से भाग नहीं मिलता है)। कुछ समय बाद इसे वास्तविक मूल्यों के साथ कहा जाएगा।


8
onSizeChanged ने मेरे लिए काम किया। onWindowFocusedChanged को मेरे कस्टम दृश्य में कॉल नहीं किया जाता है।
अनारमोइनो

यह एक अच्छा समाधान दिखता है, लेकिन क्या मुझे हमेशा onSizeChanged पद्धति को ओवरराइड करने के लिए अपना कस्टम दृश्य बनाना चाहिए?
M.ElSaka

Bottom line, if you call getWidth() etc. in a constructor, it will return zero.यह एक बिंगो है। मेरे मुद्दों की जड़।
माइकनेर्सन

मैं टुकड़ों के लिए इस समाधान का सुझाव देता हूं, क्योंकि कुछ अन्य समाधान मेरे मामले में 0 देते हैं।
विंडराइडर

66

यदि आपको स्क्रीन पर प्रदर्शित होने से पहले कुछ विजेट की चौड़ाई प्राप्त करने की आवश्यकता है, तो आप getMeasuredWidth () या getMeasuredHeight () का उपयोग कर सकते हैं।

myImage.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
int width = myImage.getMeasuredWidth();
int height = myImage.getMeasuredHeight();

5
किसी कारण के लिए, यह एकमात्र उत्तर था जो मेरे लिए काम करता था - धन्यवाद!
फारबोड सलामत-ज़ादे

मेरे लिए, सबसे सरल समाधान, जो मेरे लिए काम करता है
Tima

एक आकर्षण की तरह काम!
मोरेल्स बतोव्स्की

1
@CommonsWare वैश्विक लेआउट कॉलबैक पर व्यू ट्री ऑब्जर्वर से पहले यह समाधान कैसे ऊंचाई और चौड़ाई देता है, एक स्पष्टीकरण सहायक होगा।
माइटियन

21

मैं नहीं बल्कि प्रयोग करेंगे OnPreDrawListener()बजाय addOnGlobalLayoutListener(), के बाद से यह थोड़ा अन्य श्रोताओं से पहले कहा जाता है।

    view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
    {
        @Override
        public boolean onPreDraw()
        {
            if (view.getViewTreeObserver().isAlive())
                view.getViewTreeObserver().removeOnPreDrawListener(this);

            // put your code here
            return true;
        }
    });

3
ध्यान दें कि वर्तमान ड्राइंग पास को रद्द करने काreturn false मतलब है । इसके return trueबजाय आगे बढ़ना है ।
पैंग

9

वैश्विक लेआउट पर निरीक्षण करने और दिए गए कार्य को करने के लिए एक कोटलिन एक्सटेंशन जब ऊंचाई गतिशील रूप से तैयार होती है।

उपयोग:

view.height { Log.i("Info", "Here is your height:" + it) }

कार्यान्वयन:

fun <T : View> T.height(function: (Int) -> Unit) {
    if (height == 0)
        viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
                function(height)
            }
        })
    else function(height)
}

6

AndroidX में कई तरह के विस्तार कार्य हैं जो इस तरह के काम में आपकी मदद करते हैं, अंदर androidx.core.view

इसके लिए आपको कोटलिन का उपयोग करने की आवश्यकता है।

यहाँ जो सबसे उपयुक्त है वह है doOnLayout:

इस दृश्य के निर्धारित होने पर दी गई क्रिया को पूरा करता है। यदि दृश्य निर्धारित किया गया है और इसने किसी लेआउट का अनुरोध नहीं किया है, तो कार्रवाई को तुरंत निष्पादित किया जाएगा अन्यथा, दृश्य के अगले सेट होने के बाद कार्रवाई की जाएगी।

अगले लेआउट पर केवल एक बार कार्रवाई की जाएगी और फिर हटा दी जाएगी।

आपके उदाहरण में:

bt.doOnLayout {
    val ra = RotateAnimation(0,360,it.width / 2,it.height / 2)
    // more code
}

निर्भरता: androidx.core:core-ktx:1.0.0


यह एकमात्र सही उत्तर है। android.googlesource.com/platform/frameworks/support/+/…
hrules6872

1
ये एक्सटेंशन वास्तव में महत्वपूर्ण और उपयोगी हैं
अहमद ना

5

एक लाइनर यदि आप RxJava और RxBindings का उपयोग कर रहे हैं । बॉयलरप्लेट के बिना भी इसी तरह का दृष्टिकोण। यह भी टिम Autin द्वारा जवाब के रूप में चेतावनी को दबाने के लिए हैक हल करती है ।

RxView.layoutChanges(yourView).take(1)
      .subscribe(aVoid -> {
           // width and height have been calculated here
      });

यह बात है। कभी नहीं कहा जाता है, भले ही सदस्यता समाप्त करने की आवश्यकता नहीं है।


4

ऐसा इसलिए होता है क्योंकि दृश्य को फुलाए जाने के लिए अधिक समय की आवश्यकता होती है। इसलिए कॉल करने के बजाय view.widthऔर view.heightमुख्य धागे पर, आपको view.post { ... }यह सुनिश्चित करने के लिए उपयोग करना चाहिए कि आपका viewपहले से ही फुलाया गया है। कोटलिन में:

view.post{width}
view.post{height}

जावा में आप भी कॉल कर सकते हैं getWidth()और getHeight()एक में तरीकों Runnableऔर पारित Runnableकरने के लिए view.post()विधि।

view.post(new Runnable() {
        @Override
        public void run() {
            view.getWidth(); 
            view.getHeight();
        }
    });

यह सही उत्तर नहीं है क्योंकि पोस्ट कोड निष्पादित होने पर दृश्य को मापा और निर्धारित नहीं किया जा सकता है। यह एक किनारे का मामला होगा, लेकिन .postयह देखने की गारंटी नहीं है कि इसे बाहर रखा जाएगा।
d.aemon

1
यह जवाब बहुत अच्छा था और मेरे लिए काम किया। बहुत बहुत धन्यवाद एहसान
एमएमजी

3

ऊँचाई और चौड़ाई शून्य है क्योंकि दृश्य उस समय तक नहीं बनाया गया है जब आप अनुरोध कर रहे हैं कि यह ऊँचाई और चौड़ाई है। एक सबसे सरल उपाय है

view.post(new Runnable() {
        @Override
        public void run() {
            view.getHeight(); //height is ready
            view.getWidth(); //width is ready
        }
    });

यह विधि अन्य विधियों की तुलना में अच्छी है क्योंकि यह छोटी और कुरकुरी है।


3

शायद यह किसी की मदद करता है:

व्यू क्लास के लिए एक एक्सटेंशन फंक्शन बनाएं

फ़ाइल नाम: ViewExt.kt

fun View.afterLayout(what: () -> Unit) {
    if(isLaidOut) {
        what.invoke()
    } else {
        viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
                what.invoke()
            }
        })
    }
}

इसके बाद किसी भी दृश्य पर इसका उपयोग किया जा सकता है:

view.afterLayout {
    do something with view.height
}

2

उत्तर postगलत है, क्योंकि आकार पुनर्गणना नहीं हो सकता है।
एक और महत्वपूर्ण बात यह है कि यह दृश्य और इसके सभी पूर्वजों को दिखाई देना चाहिए । उसके लिए मैं एक संपत्ति का उपयोग करता हूं View.isShown

यहाँ मेरा kotlin फंक्शन है, जिसे बर्तनों में कहीं रखा जा सकता है:

fun View.onInitialized(onInit: () -> Unit) {
    viewTreeObserver.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            if (isShown) {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
                onInit()
            }
        }
    })
}

और उपयोग है:

myView.onInitialized {
    Log.d(TAG, "width is: " + myView.width)
}

1

यदि आप कोटलिन का उपयोग कर रहे हैं

  leftPanel.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {

            override fun onGlobalLayout() {

                if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
                    leftPanel.viewTreeObserver.removeOnGlobalLayoutListener(this)
                }
                else {
                    leftPanel.viewTreeObserver.removeGlobalOnLayoutListener(this)
                }

                // Here you can get the size :)
                leftThreshold = leftPanel.width
            }
        })

0

अगर बैकग्राउंड में ऐप दिखाई दे तो ऊंचाई 0 मानती है। यह मेरा कोड (1oo% कार्य)

fun View.postWithTreeObserver(postJob: (View, Int, Int) -> Unit) {
    viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            val widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
            val heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
            measure(widthSpec, heightSpec)
            postJob(this@postWithTreeObserver, measuredWidth, measuredHeight)
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                @Suppress("DEPRECATION")
                viewTreeObserver.removeGlobalOnLayoutListener(this)
            } else {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
            }
        }
    })
}

0

हमें देखने के लिए इंतजार करने की आवश्यकता है। इस प्रयोजन के लिए OnPreDrawListener का उपयोग करें। कोटलिन उदाहरण:

val preDrawListener = object : ViewTreeObserver.OnPreDrawListener {

                override fun onPreDraw(): Boolean {
                    view.viewTreeObserver.removeOnPreDrawListener(this)

                    // code which requires view size parameters

                    return true
                }
            }

            view.viewTreeObserver.addOnPreDrawListener(preDrawListener)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.