从另一个类中显示PopUpWindow - Android

3
基本上,我有两个类: - MyActivity.java - OtherClass.java
MyActivity.java 概览: 除了实例化 otherClass.java 所需的内容之外,没有什么有趣的东西...
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    context       = getApplicationContext()                 ;
    main_activity = this                                    ;
    layout        = (LinearLayout) findViewById(R.id.layout);
    /*
     * Do lot of stuff
     */
}

OtherClasse.java概述:

该类包含一个可点击的TextView。当我执行长按事件时,希望显示一个PopUpWindow(在UI线程上,因此与MyActivity相关...)

view.setOnLongClickListener( new OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {
        Log.d("TAG", "OnLongClick");
        PopupWindow popup = new PopupWindow(activity.getApplicationContext());
        //tried with new PopupWindow(MyActivity.context);
        popup.setWindowLayoutMode(150, 150);
        popup.setContentView( view );
        //view corresponds to the TextView.
        popup.showAtLocation(MyActivity.layout, Gravity.CENTER_HORIZONTAL, 10, 10);
        return true;
    }
});

日志显示我进入了 onLongClick() 方法,但是应用程序崩溃了...

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

但是MyActivity.layout是一个静态LinearLayout,所以我可以向其中添加视图... 有没有关于如何从另一个类的onClickListner中显示PopUpWindow的建议?
@Override
public boolean onLongClick(View v) {
    PopupWindow popup = new PopupWindow(BlaActivity.context);
    TextView tv = new TextView(BlaActivity.context);
    LayoutParams para = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    tv.setLayoutParams(para);
    tv.setText("My future text ...");
    popup.setContentView(tv);
    popup.setWidth(400);
    popup.setHeight(180);
    popup.showAtLocation(tv, Gravity.CENTER_HORIZONTAL, 10, 10);
    popup.update();

    return true;
}

返回一个

android.view.WindowManager$BadTokenException: 无法添加窗口--令牌为空无效; 您的活动是否正在运行?

因为popup.showAtLocation(tv, Gravity.CENTER_HORIZONTAL, 10, 10);调用了public IBinder getWindowToken()在tv上...显然没有令牌...

1个回答

2
您所提到的视图是指这里。
popup.setContentView( view );

可能的问题是每次都创建一个新的弹出窗口实例,但如果每次使用相同的文本视图,则会导致IllegalStateException异常。
以下代码只是一个活动和第二个类。onLongClick创建AnotherClass的一个实例并调用showPopUp。
AnotherClass的构造函数接受上下文作为参数,稍后用于实例化弹出窗口。
showPopUp接受一个视图,该视图用作弹出窗口的父级。
活动的onCreate方法。
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button b = (Button)findViewById(R.id.button1);
        final RelativeLayout parent = (RelativeLayout)findViewById(R.id.layout);
        b.setOnLongClickListener( new OnLongClickListener() {

                @Override
                public boolean onLongClick(View v) {
                    new AnotherClass(getApplicationContext()).showPopUp(parent);
                    return true;
                }
            });
    }

一个二级类

要在OtherClass中使用单击/触摸监听器,您可以像通常一样声明它们,但是要在监听器内创建弹出窗口,您需要提供活动的上下文。可以这样做:

public class AnotherClass {
    Context ctx;
    public AnotherClass(Context ctx){
        this.ctx = ctx;

        //***EXAMPLE*** wont actually be visible as its not added to a view
        Button b2 = new Button(ctx);
        b2.setText("show popup");
        b2.setOnLongClickListener( new OnLongClickListener() {

        @Override
        public boolean onLongClick(View v) {
            showPopUp(v);//View v can be used as the parent
            return true;
        }
    });
    }

    public void showPopUp(View parent) {

        PopupWindow popup = new PopupWindow(ctx);
        TextView tv = new TextView(ctx);
        LayoutParams para = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        tv.setLayoutParams(para);
        tv.setText("My future text ...");
        popup.setContentView(tv);
        popup.setWidth(400);
        popup.setHeight(180);
        popup.showAtLocation(parent, Gravity.CENTER_HORIZONTAL, 10, 10);
        popup.update();
    }

}

以及XML文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:background="@android:color/black" android:id="@+id/layout">
    <Button android:layout_height="wrap_content"
        android:layout_width="wrap_content" android:id="@+id/button1"
        android:text="Button" android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true" android:layout_marginLeft="51dp"
        android:layout_marginTop="28dp"></Button>

</RelativeLayout>

那么你建议如何解决这个问题? 即使使用onLongClick(View v)中的视图popup.setContentView(v);,我仍然遇到了IllegalStateException异常。 - Oromis L'ancien
事实上,我刚刚尝试在PopUpWindow上显示一些内容...我还尝试了使用刚创建的textView,但它不起作用...请查看添加的代码。 - Oromis L'ancien
在你更新的代码中,你将TextView tv作为showAtLocation的父视图传递,但是tv已经是弹出窗口的子视图了。我会编辑我的答案并提供一段对我有效的代码。 - triggs
那么,在OtherClass中使用onLongClick是可能的吗?并且仍然可以在UI线程中显示弹出窗口吗? 我应该在MyActivity中定义一个静态的LongClickListener,让OtherClass的textView监听它吗? - Oromis L'ancien
是的,只要弹出窗口在其构造函数中使用当前可见活动的上下文,就可以实现。我会再次编辑我的答案来解决这个问题。 - triggs
显示剩余4条评论

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