web-dev-qa-db-ja.com

Androidポップアップウィンドウの破棄

リストアクティビティでアイテムをクリックすると、ポップアップウィンドウが表示されます。問題は、バックキーが閉じないことです。リストアクティビティでバックキーをキャッチしようとしましたが、登録されません...それから、ポップアップウィンドウに渡すビューに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);

しかし、そのリスナーはどちらも起動しません。手伝って頂けますか?私はアイデアがありません:)

60
Bostjan

これは、ポップアップウィンドウの背景が!= nullでない限り、onTouchイベントまたはonKeyイベントに応答しないためです。 私が書いたコードをチェックしてください これを支援します。基本的なケースでは、PopupWindow#setBackgroundDrawable(new BitmapDrawable())を呼び出して、期待どおりに動作させることができます。独自のonKeyリスナーは必要ありません。また、ユーザーがウィンドウの境界の外側をクリックすると消える場合は、PopupWindow#setOutsideTouchable(true)を呼び出す必要があります。

拡張された難解な答え:

バックグラウンドをnullにできない理由は、PopupWindow#preparePopupで発生することです。 background != nullを検出すると、PopupViewContainerのインスタンスを作成し、その上でsetBackgroundDrawableを呼び出し、コンテンツビューをその中に配置します。 PopupViewContainerは基本的に、タッチイベントとKeyEvent.KEYCODE_BACKイベントをリッスンしてウィンドウを閉じるFrameLayoutです。 background == nullの場合、それは何もせず、コンテンツビューのみを使用します。 PopupWindowに依存してそれを処理する代わりに、ルートViewGroupを拡張して希望どおりに動作させることができます。

148
Rich Schuler

次のようにうまくいきます:

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);
38
Sunil Parmar

新しいプロジェクトの場合は、使用する方が良い

popupWindow.setBackgroundDrawable(new ColorDrawable());

の代わりに

popupWindow.setBackgroundDrawable(new BitmapDrawable());

bitmapDrawableは廃止されているため。また、この場合はShapeDrawableよりも優れています。 PopupWindowが角の丸い長方形の場合、ShapeDrawableは角を黒で塗りつぶすことに気付きました。

7
CoolMind

本当に簡単な解決策は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);
} 

がんばろう!

5
Vanja

新しいサーチャーの場合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);
4
Muhammed Refaat

これを使うだけ

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

非推奨ではありません。画面を再描画する必要があるときにシェイプを描画しようとするため、レンダリングが遅くなるため、新しいShapeDrawable()は避けたいと思います。

4
j2emanue

これがあなたの助けになることを願っています

 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;
        }
    });
3
Dwivedi Ji

PopupWindowsetBackgroundDrawable(new BitmapDrawable())を追加する必要があります。

1
Carl
pw.setBackgroundDrawable(new ColorDrawable());  

setContentViewの前に作成する必要があります

これは私のために動作します。

0
guptaatul91
    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+"");

        }
    });
}

この問題は、ポップアップウィンドウの最下層にあるメッセージマシンで発生します。

0
AlexChu