2010-03-26 48 views
17

我們的觀點之一是其作爲其根部佈局。當設備旋轉並調用時,我們希望能夠獲得ScrollView的新寬度/高度。我們的代碼看起來是這樣的:如何在onConfigurationChanged中獲取新的寬度/高度的根佈局?

@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上,我們預計ScrollView的寬度在切換到橫向時會變爲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

這正是我們害怕的。我們可以想到的第一個解決方案是產生一個線程,等待100ms或其他東西,然後獲取寬度/高度。有什麼比我們能做的更簡單嗎? – jakeboxer 2010-03-26 18:07:00

+12

產生線程?哦,不,不要這樣做!您可以簡單地在處理程序中發佈Runnable(或在使用View.post()的UI線程中)。您還可以向ViewTreeObserver註冊偵聽器,在自定義視圖中等待調整大小更改事件等。 – 2010-03-26 18:51:46

+0

Listening到ViewTreeObserver聽起來像是對我最好的解決方案,因爲我確實發現等待方法有點冒失。 – jqpubliq 2010-03-26 19:06:03

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);' – 2012-08-25 14:18:19

+0

是的,您是對的。我更新了代碼片段。謝謝。 – 2012-08-27 14:05:58

+1

謝謝我已經忘記了關於viewTreeObservers ...也爲他人澄清:removeGlobalOnLayoutListener已棄用。改爲使用「removeOnGlobalLayoutListener」。 – j2emanue 2013-09-29 17:00:09

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

謝謝,我還必須檢查大小改變之前刪除監聽。現在onGlobalLayout被調用兩次,我第二次得到正確的大小。我不知道爲什麼:/ – 2015-06-08 20:29:56

+0

應該是被接受的答案。雖然檢查高度和寬度是沒有必要的,但一個就足夠了。 – 0101100101 2015-08-05 07:15:52

+0

肯定需要在用戶使用手機設置中的動畫速度進行調整的情況下 – rupps 2016-11-03 01:37:04

相關問題