如何在安卓系统中创建弹出窗口(PopupWindow)

78
创建一个简单的工作PopupWindow,需要执行以下步骤: popup_example.xml:
<?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:padding="10dip"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">

        <TextView         
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dip"
            android:text="Test Pop-Up" />

    </LinearLayout>

Java代码

LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

PopupWindow pw = new PopupWindow(inflater.inflate(R.layout.popup_example, null, false),100,100, true);

pw.showAtLocation(this.findViewById(R.id.main), Gravity.CENTER, 0, 0);

我的要求是我需要一个

<TEXTVIEW android:layout_height="wrap_content" android:layout_width="fill_parent" />

同时也

<BUTTON android:id="@+id/end_data_send_button" android:text="Cancel"/>
在我的popup_example.xml中,我如何在Java代码中处理这两个组件?

screenshot


9
根据你展示的内容,这些可能应该是对话框而不是弹出窗口。 - Mike dg
4
现在比以往任何时候都更加重要,因为DialogFragments已经可以使用。http://developer.android.com/guide/topics/ui/dialogs.html - samus
嘿,我能在列表视图中动态显示的图像上使用弹出窗口来展示放大后的图像吗?谢谢。 - Kaveesh Kanwal
8个回答

120

如何制作简单的Android弹出窗口

这是一个更详细的示例。它是一个补充答案,处理创建一般弹出窗口而不是OP问题的具体细节。(OP要求取消按钮,但这并不必要,因为用户可以点击屏幕上的任何位置来取消它。)它将看起来像下面的图片。

enter image description here

为弹出窗口制作布局

res/layout中添加一个布局文件,定义弹出窗口的外观。

popup_window.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#62def8">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_margin="30dp"
        android:textSize="22sp"
        android:text="This is a popup window."/>

</RelativeLayout>

弹出窗口的展开和显示

以下是我们示例的主要活动代码。每当单击按钮时,弹出窗口会被展开并显示在活动上方。在屏幕的任何地方触摸都会关闭弹出窗口。

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void onButtonShowPopupWindowClick(View view) {

        // inflate the layout of the popup window
        LayoutInflater inflater = (LayoutInflater)
                getSystemService(LAYOUT_INFLATER_SERVICE);
        View popupView = inflater.inflate(R.layout.popup_window, null);

        // create the popup window
        int width = LinearLayout.LayoutParams.WRAP_CONTENT;
        int height = LinearLayout.LayoutParams.WRAP_CONTENT;
        boolean focusable = true; // lets taps outside the popup also dismiss it
        final PopupWindow popupWindow = new PopupWindow(popupView, width, height, focusable);

        // show the popup window
        // which view you pass in doesn't matter, it is only used for the window tolken
        popupWindow.showAtLocation(view, Gravity.CENTER, 0, 0);

        // dismiss the popup window when touched
        popupView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                popupWindow.dismiss();
                return true;
            }
        });
    }
}

就是这样。你完成了。

继续

查看重力值如何影响PopupWindow

带偏移量的PopupWindow底部重力

你也可以添加阴影

带阴影的PopupWindow

进一步学习

以下资源对于学习如何制作弹出窗口也很有帮助:


1
@MartinezToni,我也不确定为什么。 - Suragch
1
非常好的和周到的回复!谢谢您发布这个。 - eric
1
对话框和弹出窗口有什么区别? - K Pradeep Kumar Reddy
Unable to add window -- token null is not valid; is your activity running? - f.trajkovski
无法使用按钮/其他可点击视图,应用程序崩溃并显示尝试在空对象引用上调用虚拟方法(NullPointerException)。 - Rudra Tiwari
显示剩余3条评论

80

这里,我为您提供一个演示示例。请查看并根据您的需要进行自定义。

public class ShowPopUp extends Activity {
    PopupWindow popUp;
    boolean click = true;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        popUp = new PopupWindow(this);
        LinearLayout layout = new LinearLayout(this);
        LinearLayout mainLayout = new LinearLayout(this);
        TextView tv = new TextView(this);
        Button but = new Button(this);
        but.setText("Click Me");
        but.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (click) {
                     popUp.showAtLocation(layout, Gravity.BOTTOM, 10, 10);
                     popUp.update(50, 50, 300, 80);
                     click = false;
                } else {
                     popUp.dismiss();
                     click = true;
                }
            }
        });

        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
            LayoutParams.WRAP_CONTENT);
        layout.setOrientation(LinearLayout.VERTICAL);
        tv.setText("Hi this is a sample text for popup window");
        layout.addView(tv, params);
        popUp.setContentView(layout);
        // popUp.showAtLocation(layout, Gravity.BOTTOM, 10, 10);
        mainLayout.addView(but, params);
        setContentView(mainLayout);
   }
}
希望这能解决您的问题。

有没有解决这个问题的方案?https://stackoverflow.com/questions/65623908/how-to-make-one-corner-as-a-horn-like-structure-to-point-an-icon-in-android-stud - sejn

9

您完成了布局填充吗?也许您可以尝试这个方法!!

View myPoppyView = pw.getContentView();
Button myBelovedButton = (Button)myPoppyView.findViewById(R.id.my_beloved_button);
//do something with my beloved button? :p

5

我构建了自己的类,并从我的活动中调用它,覆盖小方法如showAtLocation。当我在我的活动中有4到5个弹出窗口时,我发现这样做更容易。

public class ToggleValues implements OnClickListener{

    private View pView;
    private LayoutInflater inflater;
    private PopupWindow pop;
    private Button one, two, three, four, five, six, seven, eight, nine, blank;
    private ImageButton eraser;
    private int selected = 1;
    private Animation appear;

    public ToggleValues(int id, Context c, int screenHeight){
        inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        pop = new PopupWindow(inflater.inflate(id, null, false), 265, (int)(screenHeight * 0.45), true);
        pop.setBackgroundDrawable(c.getResources().getDrawable(R.drawable.alpha_0));
        pView = pop.getContentView();

        appear = AnimationUtils.loadAnimation(c, R.anim.appear);

        one = (Button) pView.findViewById(R.id.one);
        one.setOnClickListener(this);
        two = (Button) pView.findViewById(R.id.two);
        two.setOnClickListener(this);
        three = (Button) pView.findViewById(R.id.three);
        three.setOnClickListener(this);
        four = (Button) pView.findViewById(R.id.four);
        four.setOnClickListener(this);
        five = (Button) pView.findViewById(R.id.five);
        five.setOnClickListener(this);
        six = (Button) pView.findViewById(R.id.six);
        six.setOnClickListener(this);
        seven = (Button) pView.findViewById(R.id.seven);
        seven.setOnClickListener(this);
        eight = (Button) pView.findViewById(R.id.eight);
        eight.setOnClickListener(this);
        nine = (Button) pView.findViewById(R.id.nine);
        nine.setOnClickListener(this);
        blank = (Button) pView.findViewById(R.id.blank_Selection);
        blank.setOnClickListener(this);
        eraser = (ImageButton) pView.findViewById(R.id.eraser);
        eraser.setOnClickListener(this);
    }

    public void showAtLocation(View v) {
        pop.showAtLocation(v, Gravity.BOTTOM | Gravity.LEFT, 40, 40);
        pView.startAnimation(appear);
    }

    public void dismiss(){ 
        pop.dismiss();
    }

    public boolean isShowing() {
        if(pop.isShowing()){
            return true;
        }else{
            return false;
        }
    }

    public int getSelected(){
        return selected;
    }

    public void onClick(View arg0) {
        if(arg0 == one){
            Sudo.setToggleNum(1);
        }else if(arg0 == two){
            Sudo.setToggleNum(2);
        }else if(arg0 == three){
            Sudo.setToggleNum(3);
        }else if(arg0 == four){
            Sudo.setToggleNum(4);
        }else if(arg0 == five){
            Sudo.setToggleNum(5);
        }else if(arg0 == six){
            Sudo.setToggleNum(6);
        }else if(arg0 == seven){
            Sudo.setToggleNum(7);
        }else if(arg0 == eight){
            Sudo.setToggleNum(8);
        }else if(arg0 == nine){
            Sudo.setToggleNum(9);
        }else if(arg0 == blank){
            Sudo.setToggleNum(0);
        }else if(arg0 == eraser){
            Sudo.setToggleNum(-1);
        }
        this.dismiss();
    }

}

你如何从按钮点击操作中调用这个ToggleValues类? - Siva K

4
LayoutInflater inflater = (LayoutInflater) SettingActivity.this.getSystemService(SettingActivity.LAYOUT_INFLATER_SERVICE); 
PopupWindow pw = new PopupWindow(inflater.inflate(R.layout.gd_quick_action_slide_fontsize, null),LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT, true);
pw.showAtLocation(SettingActivity.this.findViewById(R.id.setting_fontsize), Gravity.CENTER, 0, 0);
View v= pw.getContentView();
TextView tv=v.findViewById(R.id.....);

4
Button endDataSendButton = (Button)findViewById(R.id.end_data_send_button);

同样地,通过添加一个 id,您可以获取文本视图。


@user746108 pw.showAtLocation(this.findViewById(R.id.text_view), Gravity.CENTER, 0, 0); TextView只在弹出窗口中显示。我该如何修复按钮的位置? - jennifer

0

这是我的代码示例,演示如何在弹出窗口中寻址小部件(按钮)

View v=LayoutInflater.from(getContext()).inflate(R.layout.popupwindow, null, false);
    final PopupWindow pw = new PopupWindow(v,500,500, true);
    final Button button = rootView.findViewById(R.id.button);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            pw.showAtLocation(rootView.findViewById(R.id.constraintLayout), Gravity.CENTER, 0, 0);


        }
    });
    final Button popup_btn=v.findViewById(R.id.popupbutton);

    popup_btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            popup_btn.setBackgroundColor(Color.RED);
        }
    });

希望这能帮到你


-3

使用以下代码编辑您的style.xml文件:

<style name="AppTheme" parent="Base.V21.Theme.AppCompat.Light.Dialog">

Base.V21.Theme.AppCompat.Light.Dialog 提供了一个 Android 弹出主题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接