2010-03-26 17 views
17

हमारे विचारों में से एक को इसके रूट लेआउट के रूप में ScrollView है। जब डिवाइस घुमाया जाता है और कहा जाता है, तो हम ScrollView की नई चौड़ाई/ऊंचाई प्राप्त करने में सक्षम होना चाहते हैं। हमारे कोड इस तरह दिखता है:कॉन्फ़िगरेशन में रूट लेआउट की नई चौड़ाई/ऊंचाई कैसे प्राप्त करें?

@Override 
public void onConfigurationChanged(Configuration newConfig) { 
    Log.d(TAG, "Width: '" + findViewById(R.id.scrollview).getWidth() + "'"); 
    Log.d(TAG, "Height: '" + findViewById(R.id.scrollview).getHeight() + "'"); 

    super.onConfigurationChanged(newConfig); 

    Log.d(TAG, "Width: '" + findViewById(R.id.scrollview).getWidth() + "'"); 
    Log.d(TAG, "Height: '" + findViewById(R.id.scrollview).getHeight() + "'"); 
} 

हमारे AndroidManifest.xml के प्रासंगिक अनुभाग इस तरह दिखता है:

<activity android:name=".SomeActivity" 
    android:configChanges="keyboardHidden|orientation"> 
    <intent-filter> 
     <action android:name="android.intent.action.MAIN" /> 
    </intent-filter> 
</activity> 

और अंत में, हमारे लेआउट के संबंधित भाग इस तरह दिखता है:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/scrollview" 
    android:layout_height="fill_parent" 
    android:layout_width="fill_parent" 
    > 
    <LinearLayout android:id="@+id/container" 
     android:orientation="vertical" 
     android:layout_height="fill_parent" 
     android:minHeight="200dip" 
     android:layout_width="fill_parent" 
     > 

हमारे Droid पर, हमें लगता है कि स्क्रॉलव्यू की चौड़ाई 854 पर लैंडस्केप में स्विच होने पर और 480 पर जब पोर्ट्रेट पर वापस स्विच की जाती है (और ऊंचाई बराबर स्विच करता है, मेनू बार को घटाता है) । हालांकि, हम विपरीत देख रहे हैं। यहाँ हमारे LogCat है:

// Switching to landscape: 
03-26 11:26:16.490: DEBUG/ourtag(17245): Width: '480' // Before super 
03-26 11:26:16.490: DEBUG/ourtag(17245): Height: '778' // Before super 
03-26 11:26:16.529: DEBUG/ourtag(17245): Width: '480' // After super 
03-26 11:26:16.536: DEBUG/ourtag(17245): Height: '778' // After super 

// Switching to portrait: 
03-26 11:26:28.724: DEBUG/ourtag(17245): Width: '854' // Before super 
03-26 11:26:28.740: DEBUG/ourtag(17245): Height: '404' // Before super 
03-26 11:26:28.740: DEBUG/ourtag(17245): Width: '854' // After super 
03-26 11:26:28.740: DEBUG/ourtag(17245): Height: '404' // After super 

जाहिर है, हम चित्र आयाम हो रही है जब हम परिदृश्य के लिए स्विच, और परिदृश्य आयाम जब हम चित्र पर स्विच करें। क्या कुछ ऐसा है जो हम गलत कर रहे हैं? हम हैकी प्राप्त कर सकते हैं और इसे हल कर सकते हैं, लेकिन मुझे लगता है कि एक आसान समाधान है जिसे हम याद कर रहे हैं।

उत्तर

7

getWidth() चौड़ाई देता है क्योंकि दृश्य बाहर रखा गया है, जिसका अर्थ है कि आपको स्क्रीन पर खींचे जाने तक प्रतीक्षा करने की आवश्यकता है। onConfigurationChanged को नई कॉन्फ़िगरेशन के दृश्य को दोबारा हटाने से पहले कहा जाता है और इसलिए मुझे नहीं लगता कि आप बाद में अपनी नई चौड़ाई प्राप्त कर पाएंगे।

+0

है यही कारण है कि हम से डरते थे। पहला समाधान जिसे हम सोच सकते हैं, थ्रेड को फेंकना, 100 एमएमएस या कुछ इंतजार करना है, और फिर चौड़ाई/ऊंचाई पकड़ना है। क्या कुछ कम हैकी हम उससे भी कर सकते हैं? – jakeboxer

+12

धागा फैलाना? अरे नहीं यह मत करो! आप बस हैंडलर में एक रननेबल पोस्ट कर सकते हैं (या उदाहरण के लिए View.post() का उपयोग करके यूआई थ्रेड पर पोस्ट कर सकते हैं।) आप ViewTreeObserver के साथ श्रोता भी पंजीकृत कर सकते हैं, एक कस्टम व्यू इत्यादि में आकार बदलने की घटना का इंतजार कर सकते हैं। –

+0

सुनना ViewTreeObserver को मेरे लिए सबसे अच्छा समाधान लगता है क्योंकि मुझे प्रतीक्षा विधि थोड़ा हैकी मिलती है। – jqpubliq

34

उन लोगों के लिए जो अधिक विस्तृत समाधान विवरण ढूंढ रहे हैं: आप अपने दृश्य के ViewTreeObserver का उपयोग कर सकते हैं और OnGlobalLayoutListener पंजीकृत कर सकते हैं।

@Override 
public void onConfigurationChanged(Configuration newConfiguration) { 
    super.onConfigurationChanged(newConfiguration); 
    final View view = findViewById(R.id.scrollview); 

    ViewTreeObserver observer = view.getViewTreeObserver(); 
    observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 

     @Override 
     public void onGlobalLayout() { 
      Log.v(TAG, 
        String.format("new width=%d; new height=%d", view.getWidth(), 
          view.getHeight())); 
      view.getViewTreeObserver().removeOnGlobalLayoutListener(this); 
     } 
    }); 
} 
+6

'onGlobalLayout' पर कॉल के अनंत लूप से बचने के लिए, मुझे दृश्यों के नए आकारों के आधार पर मेरी गणना करने के बाद श्रोता को हटाना पड़ा: 'view.getViewTreeObserver()। RemoveGlobalOnLayoutListener (this);' –

+0

हाँ आप सही हैं । मैंने कोड स्निपेट अपडेट किया। धन्यवाद। –

+1

धन्यवाद, मैं viewTreeObservers के बारे में भूल गया था ... दूसरों के स्पष्टीकरण के लिए भी: removeGlobalOnLayoutListener को बहिष्कृत किया गया है।इसके बजाय "removeOnGlobalLayoutListener" का उपयोग करें। – j2emanue

10

जब onGlobalLayout कहा जाता है यह निश्चित नहीं है कि दृश्य नए लेआउट उन्मुखीकरण के लिए तदनुसार आकार दिया गया है, इसलिए मेरे लिए केवल नीचे समाधान ठीक से काम किया:

@Override 
public void onConfigurationChanged(Configuration newConfig) { 
final int oldHeight = mView.getHeight(); 
final int oldWidth = mView.getWidth(); 

mView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 
     @Override 
     public void onGlobalLayout() { 
      if (mView.getHeight() != oldHeight && mView.getWidth() != oldWidth) { 
       mView.getViewTreeObserver().removeOnGlobalLayoutListener(this); 
       //mView now has the correct dimensions, continue with your stuff 
      } 
     } 
    }); 
    super.onConfigurationChanged(newConfig);} 
+0

के दौरान भी चिकना है धन्यवाद, मुझे यह भी देखना था कि श्रोता को हटाने से पहले आकार बदल गया था। अब GlobalLayout को दो बार बुलाया जाता है और मुझे केवल दूसरी बार सही आकार मिलता है। मुझे नहीं पता कि क्यों:/ –

+0

स्वीकृत उत्तर होना चाहिए। हालांकि ऊंचाई और चौड़ाई दोनों की जांच करना जरूरी नहीं है, एक पर्याप्त है। – 0101100101

+0

निश्चित रूप से उस मामले में जरूरी है जब उपयोगकर्ता ने फोन सेटिंग्स में एनीमेशन गति के साथ tweaked किया है – rupps