2011-10-08 17 views
10

Hầu hết các ví dụ ngoài đó chỉ định chính xác chiều rộng và chiều cao của cửa sổ bật lên. Tôi muốn chúng là WRAP_CONTENT - vì nội dung được xác định theo thực tế, vì vậy trong hàm dựng mà tôi đặt -2 cho cả chiều rộng và chiều cao và hiển thị nó qua showAsDropDown (Xem neo)PopupWindow ra khỏi màn hình khi kích thước không được chỉ định

Thực hiện việc này, cửa sổ bật lên luôn được vẽ bên dưới chế độ xem neo, có nghĩa là nó có thể được vẽ ngoài màn hình. Đoạn mã sau minh họa sự cố. Hãy thử nhấp vào TextView cuối cùng và bạn sẽ không thấy bất kỳ PopupWindow nào, vì nó được hiển thị bên ngoài các giới hạn cửa sổ. Tại sao nó không hoạt động? Tôi nhận xét rằng chỉ định kích thước một cách rõ ràng (ví dụ 200, 100) không kích hoạt vấn đề. Thử nó cho mình

package com.zybnet.example.popupdemo; 

import android.app.Activity; 
import android.graphics.Color; 
import android.os.Bundle; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.LinearLayout; 
import android.widget.PopupWindow; 
import android.widget.TextView; 

public class PopupDemoActivity extends Activity implements OnClickListener { 
    private PopupWindow popup; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     // -2 means WRAP_CONTENT THIS TRIGGERS THE PROBLEM 
     popup = new PopupWindow(getPopupContent(), -2, -2); 
     // When you specify the dimensions everything goes fine 
     //popup = new PopupWindow(getPopupContent(), 200, 100); 

     LinearLayout layout = new LinearLayout(this); 
     layout.setOrientation(LinearLayout.VERTICAL); 

     // FILL_PARENT and same layout weight for all children 
     LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(-1, -1, 1); 
     for (int i = 0; i < 10; i++) { 
      TextView tv = new TextView(this); 
      tv.setText("Click to show popup"); 
      tv.setOnClickListener(this); 
      layout.addView(tv, params); 
     } 
     setContentView(layout); 
    } 

    @Override 
    public void onClick(View view) { 
     popup.dismiss(); 
     popup.showAsDropDown(view); 
    } 

    private View getPopupContent() { 
     TextView popupContent = new TextView(this); 
     popupContent.setText("Some text here"); 
     popupContent.setTextColor(Color.parseColor("#5000ae")); 
     popupContent.setBackgroundColor(Color.parseColor("#ff00ff")); 
     popupContent.setPadding(10, 20, 20, 10); 
     return popupContent; 
    } 
} 

Trả lời

16

tôi bắt đầu nghi ngờ rằng trong bối cảnh của một PopupWindow rằng -2, -2 thực sự có nghĩa WRAP_CONTENT thay vì tôi nghĩ rằng nó chỉ giải thích nó như width = -2 height = -2

Đây là từ Android Nguồn

public PopupWindow(View contentView, int width, int height, boolean focusable) { 
    if (contentView != null) { 
     mContext = contentView.getContext(); 
     mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 
    } 
    setContentView(contentView); 
    setWidth(width); 
    setHeight(height); 
    setFocusable(focusable); 
} 

nơi setWidth(int width) chỉ là một đơn giản mWidth = width; tôi nghĩ rằng những gì bạn đang tìm kiếm thay vì là phương pháp setWindowLayoutMode (int widthSpec, int heightSpec). Đó là nơi bạn nên vượt qua trong số WRAP_CONTENT

Nếu mọi thứ khác không thành công, hãy đo chiều rộng và chiều cao của TextView và sau đó sử dụng setWidthsetHeight như mong đợi.

Sửa:

Chỉ cần thử nó ra cho bản thân mình và thêm dòng mã này để làm cho nó hoạt

// -2 means WRAP_CONTENT THIS TRIGGERS THE PROBLEM 
    popup = new PopupWindow(getPopupContent(), 200, 100); 
    popup.setWindowLayoutMode(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 
    // When you specify the dimensions everything goes fine 
    //popup = new PopupWindow(getPopupContent(), 200, 100); 

    LinearLayout layout = new LinearLayout(this); 
    layout.setOrientation(LinearLayout.VERTICAL); 

tôi rời các ý kiến ​​ban đầu trong đó để bạn có thể xem cho chính mình nơi tất cả mọi thứ nên đi.

Chỉnh sửa 2: Được rồi, vì vậy tôi đã mã của bạn bạn được đăng và đúng nguyên văn thử nó trên điện thoại của tôi, và bạn đã đúng, nó đã không làm việc vì khi Android được xác định mà xem để bố trí để đặt nó trong , nó dựa trên chiều rộng và chiều cao bạn cung cấp. Điều đó có nghĩa là vì bạn đang sử dụng 0 và 0 làm chiều rộng và chiều cao của bạn, Android sẽ đến và nói, "Ôi, hộp chỉ là hộp 0 bằng 0 để tôi có thể hiển thị nó dưới dạng cửa sổ bật lên bên dưới nội dung". Đây không phải là điều mong muốn! Vấn đề là, bạn biết rằng hộp sẽ lớn hơn thế, vì vậy hãy bắt đầu đưa vào một số con số khác nhau và nhìn thấy kết quả đến từ nó.

popup = new PopupWindow(getPopupContent(), 1, 1); 

Bây giờ khi tôi đi và nhấp vào hộp dưới cùng, hãy lưu ý rằng nó nhảy ở trên. (Xem ảnh chụp màn hình) Đó là bởi vì Android BIẾT rằng chiều rộng và chiều cao là 1 (như tôi đặt trong hàm tạo) và không gian màn hình có sẵn bên dưới mục danh sách là 0. Vâng, nếu không có đủ chỗ để hiển thị nó ở đó, thì nó phải ở trên rồi!

enter image description here

Nhưng chờ đã! Điều gì sẽ xảy ra nếu như trong ví dụ hiện tại của tôi, chuỗi sẽ thêm vào nhiều nội dung hơn mỗi lần? Vâng, đây là nơi mọi thứ trở nên thú vị. Bạn thấy đấy, trong ảnh chụp màn hình tiếp theo của tôi rằng cửa sổ bật lên, mặc dù nó sẽ được hiển thị vì nó dài 6 dòng, được hiển thị ở phía dưới! Oh crap, đúng rồi!Đó là bởi vì nó được đo so với 1 1 Tôi đã sử dụng trong hàm tạo. Vậy thì một số giải pháp cho điều này là gì?

enter image description here

Giải pháp thứ nhất: cách ưa thích của tôi sẽ được tham gia một dự đoán vào những gì chiều cao tối đa trung bình của TextView sẽ và sau đó chỉ cần quăng trong một số quát lớn.

popup = new PopupWindow(getPopupContent(), 300, 300); //just guessing it won't get bigger than that 

Giải pháp Hai: Điều này thích hợp hơn, nhưng bạn đang hy sinh một chút tốc độ để làm điều đó. Sử dụng lớp Paint để đo kích thước nội dung văn bản sẽ là gì và chuyển số đó vào setWidth()setHeight() trước khi bạn hiển thị cửa sổ bật lên. Tôi đã đi trước và xây dựng một gần giải pháp hoàn chỉnh, nhưng tôi đã không đo lường trong đệm và các công cụ (xem chú thích)

private int maxWidth; 
private int maxHeight; 
private Paint p = new Paint(); 
private Rect bounds = new Rect(); 
private View getPopupContent() { 
    maxWidth = 0; 
    maxHeight = 0; 
    TextView popupContent = new TextView(this); 
    popupContent.setText(popupText += "\n" + DEMO); 
    popupContent.setTextColor(Color.parseColor("#5000ae")); 
    popupContent.setBackgroundColor(Color.parseColor("#ff00ff")); 
    popupContent.setPadding(10, 20, 20, 10); 
    //the measure can only work line by line so I split it up by line 
    String[] temp = popupText.split("\n"); 
    for (String s : temp){ 
     //measure each line of string and get its width and height 
     p.getTextBounds(s, 0, s.length(), bounds); 

     //keep a running total of the longest width 
     maxWidth = (bounds.width() > maxWidth) ? bounds.width() : maxWidth; 
     //add up each of the heights 
     maxHeight += bounds.height(); 
    } 

    //also take in account the padding too... if you REALLY want it to be completely robust 
    //probably adding another 20 or 30 to the maxHeight should be good 
    return popupContent; 
} 

Và sau đó trong onClick() tôi bổ sung thêm hai dòng sau

popup.setHeight(maxHeight); 
    popup.setWidth(maxWidth); 
+0

tôi đọc các nguồn quá, và có vẻ như nhiều hơn một điểm A lỗi ndroid, vì kích thước là chính xác, nhưng vị trí là sai. Bạn có thể tự mình kiểm tra vì tôi đã cung cấp bản trình diễn. Bây giờ tôi đang thử nghiệm với PopupWindow.showAtLocation() – Raffaele

+0

Cũng giống như tôi nghi ngờ bạn cần thêm vào 'setWindowLayoutMode' Tôi đã chỉnh sửa câu trả lời của mình và thêm vào mã làm việc chính xác mà bạn cần. Tôi đã thử nghiệm nó trên thiết bị Android của tôi và tất cả mọi thứ! :) – Bob

+0

Điều gì xảy ra nếu lần sau bạn gọi cửa sổ bật lên, chế độ xem nội dung thay đổi? Đó là lý do tại sao tôi cần WRAP_CONTENT – Raffaele

1

tôi giải quyết vấn đề này bằng cách gọi measure() phương pháp trong một cái nhìn nội dung popup:

View content = getPopupContent(); 

content.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 
int measuredHeight = content.getMeasuredHeight(); 

popup = new PopupWindow(content, ViewGroup.LayoutParams.WRAP_CONTENT, measuredHeight); 
Các vấn đề liên quan