繁体   English   中英

Android弹出窗口关闭

[英]Android popup window dismissal

单击列表活动中的项目时,会显示一个弹出窗口。 问题是后退键不会关闭它。 我尝试在我的列表活动中捕获返回键,但它没有注册它......然后我尝试将一个 onkeylistener 注册到我传递给我的弹出窗口的视图中。 像这样:

pop.setOnKeyListener(new View.OnKeyListener() {

        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            // TODO Auto-generated method stub
            boolean res=false;
            if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
                // do something on back.
                Log.e("keydown","back");
                if (pw.isShowing()) {
                    Log.e("keydown","pw showing");
                    pw.dismiss();
                    res = true;
                }
            } else {
                res = false;
            }
            return res;
        }
    });

它传递给这样的弹出窗口:

pw = new PopupWindow(
       pop, 
       240, 
       70, 
       true);

但是那个监听器也不会触发。 你能帮助我吗? 我没有想法:)

这是因为弹出窗口不会响应 onTouch 或 onKey 事件,除非它的背景为 != null。 查看我编写的一些代码来帮助解决这个问题。 在基本情况下,您可以调用PopupWindow#setBackgroundDrawable(new BitmapDrawable())以强制它按照您期望的方式运行。 您不需要自己的 onKey 侦听器。 如果您希望它在用户单击窗口边界外时消失,您可能还需要调用PopupWindow#setOutsideTouchable(true)

扩展深奥的答案:

背景不能为空的原因是因为PopupWindow#preparePopup发生的事情。 如果它检测到background != null它会创建一个PopupViewContainer的实例并调用setBackgroundDrawable并将您的内容视图放入其中。 PopupViewContainer基本上是一个FrameLayout ,它侦听触摸事件和KeyEvent.KEYCODE_BACK事件以关闭窗口。 如果 background == null,它不会执行任何操作,只会使用您的内容视图。 作为依赖PopupWindow处理该问题的替代方法,您可以扩展您的根ViewGroup以按照您想要的方式行事。

按照以下操作它工作正常:

PopupWindow pw;
LayoutInflater inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.weight_popup, (ViewGroup)findViewById(R.id.linlay_weight_popup));
pw = new PopupWindow(layout,LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT, true);
pw.setBackgroundDrawable(new BitmapDrawable());
pw.setOutsideTouchable(true);
pw.showAsDropDown(btnSelectWeight);

对于新项目,最好使用

popupWindow.setBackgroundDrawable(new ColorDrawable());

代替

popupWindow.setBackgroundDrawable(new BitmapDrawable());

因为 BitmapDrawable 已被弃用。 此外,在这种情况下,它比 ShapeDrawable 更好。 我注意到当 PopupWindow 是一个带圆角的矩形时,ShapeDrawable 用黑色填充角落。

对于新搜索者,由于现在不允许创建new BitmapDrawable (不The constructor BitmapDrawable() is deprecated ),因此您必须将其更改为new ShapeDrawable() ,以便您将更改:

pw.setBackgroundDrawable(new BitmapDrawable());

到 :

pw.setBackgroundDrawable(new ShapeDrawable());

整个工作将是这样的:

PopupWindow pw;
LayoutInflater inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.weight_popup, (ViewGroup)findViewById(R.id.linlay_weight_popup));
pw = new PopupWindow(layout,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT, true);
pw.setOutsideTouchable(true);
pw.setBackgroundDrawable(new ShapeDrawable());
pw.setTouchInterceptor(new OnTouchListener() { // or whatever you want
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            if(event.getAction() == MotionEvent.ACTION_OUTSIDE) // here I want to close the pw when clicking outside it but at all this is just an example of how it works and you can implement the onTouch() or the onKey() you want
            {
               pw.dismiss();
               return true;
            }
            return false;
        }

});
pw.showAtLocation(layout, Gravity.CENTER, 0, 0);

一个非常简单的解决方案是编写 pw.setFocusable(true),但您可能不想这样做,因为这样 MapActivity 将无法处理触摸事件。

更好的解决方案是覆盖后退键,例如:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {

    // Override back button
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        if (pw.isShowing()) {
            pw.dismiss();
            return false;
        }
    }
    return super.onKeyDown(keyCode, event);
} 

祝你好运!

就用这个

mPopupWindow.setBackgroundDrawable(new BitmapDrawable(null,""));

不推荐使用。 我会避免使用 new ShapeDrawable() ,因为它会在需要重绘屏幕时尝试绘制形状时渲染缓慢。

我希望这对你有帮助

 pw.setTouchInterceptor(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                pw.dismiss();
            }
            return true;
        }
    });

您需要为PopupWindow添加setBackgroundDrawable(new BitmapDrawable())

    private void initPopupWindow() {  
    // TODO Auto-generated method stub  

    View view = getLayoutInflater().inflate(R.layout.main_choice, null);  

    ListView main_menu_listview = (ListView) view.findViewById(R.id.main_menu_listview);  

    ShowMainChoice madapter = new ShowMainChoice(context);
    main_menu_listview.setAdapter(madapter);

    int width = (int)getWindowManager().getDefaultDisplay().getWidth()/2;
    popupWindow = new PopupWindow(view, width,WindowManager.LayoutParams.WRAP_CONTENT);  
    popupWindow.setBackgroundDrawable(new BitmapDrawable());//this is important,如果缺少这句将导致其他任何控件及监听都得不到响应
    popupWindow.setOutsideTouchable(true);
    popupWindow.setFocusable(true);

    main_menu_listview.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
            // TODO Auto-generated method stub

            Log.e("++++++>", arg2+"");

        }
    });
}

这个问题是popupwindow的消息机制决定的,因为它是真实式的。祝你好运

pw.setBackgroundDrawable(new ColorDrawable());  

必须在setContentView之前写

这对我有用。

您是否正在寻找弹出窗口关闭和BACK 按钮良好工作的组合,那么您可以考虑以下解决方案。

解决原理:弹窗附近的所有按钮点击都会被拦截,但不会拦截任何BACK按钮。 因此,如果您的弹出窗口中有任何需要采取行动的内容,请在您调用dismiss() 之前设置一个指示。 在您的 setOnDismissListener() 中执行一个额外的操作(如 getActivity().popupBackStack())。

此解决方案的优点是您可以创建自己的 CustomPopupWindow 并实施此策略。 您可以在自定义弹出窗口中隐藏此实现。

第 1 步:在弹出窗口的实例化附近添加:

boolean isClickHandled = false; 
popupWindow.setOutsideTouchable(true);
popupWindow.setBackgroundDrawable(new ShapeDrawable());
popupWindow.setTouchInterceptor(new View.OnTouchListener() { // or whatever you want
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        isClickHandled = true;
        return false;
    }
});

如果您的 popupWindow 中有按钮,请在 setOnClickListener.onClick 中设置 isClickHandled = true 和dismiss()。

在您的 onDismissListener 中执行以下操作:

popupWindow.setOnDismissListener(() -> {
        popupWindow.dismiss();
        if ( !isClickHandled) {
            MainActivity.mainActivity.getSupportFragmentManager().popBackStack();
        }
    });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM