2010-03-26 10 views
17

Một trong các chế độ xem của chúng tôi có bố cục gốc là ScrollView. Khi thiết bị được xoay và được gọi, chúng tôi muốn có thể có chiều rộng/chiều cao mới của ScrollView. mã của chúng tôi trông như thế này:Làm thế nào để có chiều rộng/chiều cao mới của bố cục gốc trong 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() + "'"); 
} 

Các phần có liên quan của AndroidManifest.xml của chúng tôi trông như thế này:

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

Và cuối cùng, phần liên quan của bố trí của chúng tôi trông như thế này:

<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" 
     > 

Trên Droid của chúng tôi, chúng tôi dự kiến ​​sẽ thấy chiều rộng của ScrollView chuyển sang 854 khi chuyển sang chế độ ngang và 480 khi được chuyển về chân dung (và chiều cao thực hiện công tắc tương đương, trừ thanh trình đơn) . Tuy nhiên, chúng ta đang thấy điều ngược lại. Đây là LogCat của chúng tôi:

// 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 

Rõ ràng, chúng tôi đang nhận được kích thước chân dung khi chuyển sang chế độ ngang và kích thước ngang khi chuyển sang chế độ dọc. Có điều gì chúng tôi đang làm sai? Chúng tôi có thể nhận được hacky và giải quyết điều này, nhưng tôi cảm thấy như có một giải pháp đơn giản mà chúng tôi đang mất tích.

Trả lời

7

getWidth() trả về chiều rộng khi Chế độ xem được đặt ra, nghĩa là bạn cần chờ cho đến khi nó được vẽ lên màn hình. onConfigurationChanged được gọi trước khi vẽ lại chế độ xem cho cấu hình mới và vì vậy tôi không nghĩ rằng bạn sẽ có thể nhận được chiều rộng mới cho đến sau này.

+0

Đó là những gì chúng tôi đã sợ. Giải pháp đầu tiên chúng ta có thể nghĩ đến là tạo ra một luồng, đợi 100ms hoặc một cái gì đó, và sau đó lấy chiều rộng/chiều cao. Có điều gì ít hacky chúng ta có thể làm hơn thế không? – jakeboxer

+12

Tạo ra một chuỗi? Ồ không, đừng làm thế! Bạn có thể chỉ cần gửi một Runnable trong một Handler (hoặc trên thread UI bằng cách sử dụng View.post() chẳng hạn.) Bạn cũng có thể đăng ký một Listener với ViewTreeObserver, chờ một sự kiện thay đổi kích thước trong một View tùy chỉnh, v.v. –

+0

Listening với ViewTreeObserver có vẻ như giải pháp tốt nhất đối với tôi khi tôi tìm phương pháp chờ đợi một chút hacky. – jqpubliq

34

Đối với những người tìm kiếm mô tả giải pháp chi tiết hơn: Bạn có thể sử dụng ViewTreeObserver chế độ xem của mình và đăng ký 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

Để tránh một vòng lặp vô hạn các cuộc gọi đến 'onGlobalLayout', tôi đã phải loại bỏ người nghe sau khi thực hiện các phép tính dựa trên các kích thước mới của khung nhìn:' view.getViewTreeObserver(). RemoveGlobalOnLayoutListener (this); ' –

+0

Có bạn đúng . Tôi đã cập nhật đoạn mã. Cảm ơn bạn. –

+1

cảm ơn bạn tôi đã quên về viewTreeObservers ... cũng cho những người khác làm rõ: removeGlobalOnLayoutListener không được chấp nhận.thay vào đó hãy sử dụng "removeOnGlobalLayoutListener". – j2emanue

10

Khi onGlobalLayout gọi nó là không chắc chắn rằng quan điểm has been resized phù hợp với định hướng bố trí mới, vì vậy đối với tôi chỉ là giải pháp dưới đây làm việc đúng cách:

@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

Cảm ơn, tôi cũng phải kiểm tra xem kích thước đã thay đổi trước khi xóa người nghe chưa. Bây giờ onGlobalLayout được gọi hai lần và tôi nhận được kích thước phù hợp chỉ lần thứ hai. Tôi không biết tại sao mặc dù:/ –

+0

Nên là câu trả lời được chấp nhận. Mặc dù kiểm tra cả chiều cao và chiều rộng là không cần thiết, một là đủ. – 0101100101

+0

chắc chắn cần thiết trong trường hợp người dùng đã tinh chỉnh với tốc độ hoạt ảnh trong cài đặt điện thoại – rupps