2012-03-05 24 views
38

Đối với hoạt ảnh, tôi cần biết chiều cao từ Chế độ xem. Vấn đề là, phương thức getHeight() allways trả về 0 trừ khi View được vẽ. Vì vậy, có cách nào để có được chiều cao mà không cần vẽ nó?Android: nhận chiều cao của chế độ xem trước khi được vẽ

Trong trường hợp này, Chế độ xem là LinearLayout.

EDIT: tôi cố gắng thích nghi với sự mở rộng Animation từ https://github.com/Udinic/SmallExamples/blob/master/ExpandAnimationExample/src/com/udinic/expand_animation_example/ExpandAnimation.java

Với nó, tôi muốn mở rộng một số thông tin nhiều hơn cho một mục danh sách. Tôi không thể đạt được hiệu ứng tương tự qua xml. Hiện tại, Hoạt ảnh chỉ hoạt động khi bạn biết kích thước bố cục trước khi vẽ.

Trả lời

10

Về mặt kỹ thuật, bạn có thể gọi phương thức measure trên chế độ xem và sau đó nhận được chiều cao thông qua getMeasureHeight. Xem thông tin này để biết thêm thông tin: https://developer.android.com/guide/topics/ui/how-android-draws.html. Bạn sẽ cần phải cung cấp cho nó một mặc dù là MeasureSpec.

Nhưng trên thực tế, kích thước của khung nhìn bị ảnh hưởng bởi bố cục gốc, do đó bạn có thể có kích thước khác so với khi nó được vẽ thực sự.

Ngoài ra, bạn có thể thử sử dụng các giá trị RELATIVE_TO_SELF trong hoạt ảnh của mình.

+0

Thật vậy, chiều cao được trả về bởi getMeasuredSpec là khác nhau. Tại thời điểm này 34 so với 137. Tôi đã chỉnh sửa thông điệp đầu tiên của mình với một số thông tin khác. – anonymous

+1

Xem câu trả lời mới của tôi. – Fixpoint

+0

Câu trả lời này là câu trả lời đúng, nhưng thiếu mã là lý do đơn giản cho ít người trả lời hơn. – Warpzit

-5

Bạn có thể thử để bắt đầu với Life View nhìn thấy được, và sau đó thêm một cái gì đó như thế này:

view.post(new Runnable() {  
    @Override 
    public void run() { 
     // hide view here so that its height has been already computed 
     view.setVisibility(View.GONE); 
    } 
}); 

Bây giờ khi bạn sẽ gọi view.getHeight() nó sẽ trả về chiều cao mà bạn mong đợi.

Tôi không chắc đó có thực sự là một cách hay hay không, nhưng ít nhất nó cũng có tác dụng.

+0

Nếu bạn làm điều này thì nó sẽ hiển thị khung nhìn đầu tiên và sau đó làm điều này. Trong trường hợp chúng ta muốn thiết lập các tham số dựa trên các tham số của khung nhìn thì chúng ta sẽ muốn làm điều gì đó khác. – lokoko

0

Ok, về bài đăng được cập nhật, dưới đây là những gì sẽ giúp bạn: Animation#initialize. Bạn chỉ nên đặt khởi tạo ở đó thay vì hàm tạo và bạn sẽ có tất cả các kích thước bạn cần ở đó.

+0

Hm ... Tôi không hiểu. Có chiều cao cũng là 0 trừ khi View có thể nhìn thấy và không biến mất. – anonymous

+2

Thử sử dụng 'INVISIBLE' thay vì' GONE'. – Fixpoint

+0

Có thể là một gợi ý tốt. Nhưng bây giờ các hoạt hình không bắt đầu allways ngay lập tức. Đôi khi đầu tiên nếu tôi cuộn hoặc tương tác với ui theo một cách nào đó. – anonymous

112

Có vẻ như bạn muốn có chiều cao nhưng ẩn chế độ xem trước khi hiển thị.

Có khả năng hiển thị trong chế độ xem được đặt thành hiển thị hoặc ẩn để bắt đầu (chỉ để tạo chiều cao). Đừng lo lắng, chúng tôi sẽ thay đổi thành ẩn/đi trong mã như sau:

private int mHeight = 0; 
private View mView; 

class... 

// onCreate or onResume or onStart ... 
mView = findViewByID(R.id.someID); 
mView.getViewTreeObserver().addOnGlobalLayoutListener( 
    new OnGlobalLayoutListener(){ 

     @Override 
     public void onGlobalLayout() { 
      // gets called after layout has been done but before display 
      // so we can get the height then hide the view 


      mHeight = mView.getHeight(); // Ahaha! Gotcha 

      mView.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
      mView.setVisibility(View.GONE); 
     } 

}); 
+9

Cảm ơn bạn, nó hoạt động! Chỉ cần thêm một chút: removeGlobalOnLayoutListener() không còn được dùng kể từ API cấp 16, nó được thay thế bằng removeOnGlobalLayoutListener() –

+0

Cảm ơn đã giúp tôi rất nhiều. việc đo lường các lượt xem là lỗi. –

+1

Cảm ơn lời khuyên này, nó hoạt động rất tốt. Side lưu ý, thực tế là tên của đối số cho removeOnGlobalLayoutListener là "nạn nhân" là tuyệt vời. – Silmarilos

12

Tôi gặp vấn đề tương tự với tình huống tương tự.

Tôi đã phải tạo một bản chiếu mà tôi yêu cầu chiều cao của view tùy thuộc vào hoạt ảnh. Trong đó view, là LinearLayout có thể là chế độ xem con của loại TextView. Điều đó TextView là nhiều dòng và số dòng thực sự yêu cầu khác nhau.

Dù tôi đã làm gì, tôi chỉ có chiều cao được đo cho chế độ xem như thể TextView chỉ có một dòng để lấp đầy. Không có thắc mắc này làm việc tốt mỗi khi văn bản happend là đủ ngắn cho một dòng, nhưng nó không thành công khi văn bản đã được han dài trên đường dây.

Tôi coi câu trả lời này là: https://stackoverflow.com/a/6157820/854396 Nhưng điều đó không hoạt động tốt cho tôi vì tôi không thể truy cập trực tiếp vào số TextView được nhúng trực tiếp từ đây. (Tôi có thể lặp dù cây quan điểm con mặc dù.)

Có xem xét mã của tôi vì nó làm việc cho bây giờ:

view là quan điểm cho rằng là để được hoạt hình. Nó là LinearLayout (Giải pháp cuối cùng sẽ tiết kiệm hơn một chút ở đây) this là chế độ xem tùy chỉnh chứa view và thừa kế từ LinearLayout.

private void expandView(final View view) { 

     view.setVisibility(View.VISIBLE); 

     LayoutParams parms = (LayoutParams) view.getLayoutParams(); 
     final int width = this.getWidth() - parms.leftMargin - parms.rightMargin; 

     view.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), 
       MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 

     final int targetHeight = view.getMeasuredHeight(); 

     view.getLayoutParams().height = 0; 

     Animation anim = new Animation() { 
     @Override 
     protected void applyTransformation(float interpolatedTime, Transformation trans) { 
      view.getLayoutParams().height = (int) (targetHeight * interpolatedTime); 
      view.requestLayout(); 
     } 

     @Override 
     public boolean willChangeBounds() { 
      return true; 
     } 
     }; 

     anim.setDuration(ANIMATION_DURATION); 
     view.startAnimation(anim); 
    } 

Gần như vậy nhưng tôi đã mắc phải một sai lầm khác. Trong phân cấp khung nhìn có hai chế độ xem tùy chỉnh có liên quan là các lớp con của LinearLayout và xml của chúng được hợp nhất thành một thẻ merge dưới dạng thẻ gốc xml. Trong một trong các thẻ merge tôi bỏ qua này để đặt thuộc tính android:orientation thành vertical. Điều đó không làm phiền quá nhiều đối với bản thân bố cục, bởi vì trong số ViewGroup đã hợp nhất này chỉ là một đứa trẻ ViewGroup và do đó tôi không thể thực sự nhìn thấy sai hướng trên màn hình. Nhưng nó đã ở đó và loại vỡ logic đo lường bố cục này một chút.

Ngoài những điều trên, có thể cần phải loại bỏ tất cả các phần đệm được liên kết với LinearLayout s và các lớp con trong phân cấp chế độ xem. Thay thế chúng bằng lề, ngay cả khi bạn phải bọc một bố trí khác xung quanh nó để làm cho nó trông giống nhau.

+0

Cảm ơn bạn! Tôi mất nhiều giờ với điều này. –

0
static void getMeasurments(View v) { 

    v.measure(View.MeasureSpec.makeMeasureSpec(PARENT_VIEW.getWidth(), 
     View.MeasureSpec.EXACTLY), 
     View.MeasureSpec.makeMeasureSpec(0, 
     View.MeasureSpec.UNSPECIFIED)); 

    final int targetHeight = v.getMeasuredHeight(); 
    final int targetWidth = v.getMesauredWidth(); 
} 
Các vấn đề liên quan