63

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

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

4

11 に答える 11

150

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

拡張された難解な答え:

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

于 2010-06-26T04:24:19.353 に答える
39

次のように実行すると、正常に機能します。

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);
于 2011-11-16T06:34:27.403 に答える
8

新しいプロジェクトの場合は、を使用することをお勧めします

popupWindow.setBackgroundDrawable(new ColorDrawable());

それ以外の

popupWindow.setBackgroundDrawable(new BitmapDrawable());

BitmapDrawableは非推奨になっているため。また、この場合はShapeDrawableよりも優れています。PopupWindowが角の丸い長方形の場合、ShapeDrawableは角を黒で塗りつぶします。

于 2014-08-26T14:31:32.900 に答える
5

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

幸運を!

于 2010-11-08T08:10:26.257 に答える
5

新しいサーチャーの場合、aの作成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);
于 2014-05-22T09:12:01.580 に答える
4

これを使うだけ

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

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

于 2014-05-27T02:46:36.807 に答える
3

これがあなたのお役に立てば幸いです

 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;
        }
    });
于 2011-11-18T07:25:12.017 に答える
1

あなたはあなたのために追加する必要がありsetBackgroundDrawable(new BitmapDrawable())ますPopupWindow

于 2015-03-13T02:01:41.927 に答える
0
    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底層的消息机制决定的、因是的是応塞式的である。頑張ってください。

于 2013-08-22T02:48:19.417 に答える
0
pw.setBackgroundDrawable(new ColorDrawable());  

setContentViewの前にそれを書かなければなりません

これは私のために働きます。

于 2018-12-28T13:39:13.723 に答える
0

ポップアップウィンドウの閉じと[戻る]ボタンの適切な動作の組み合わせをお探しの場合は、以下の解決策を検討してください。

解決策の原則:ポップアップウィンドウの近くにあるすべてのボタンのクリックは傍受されますが、[戻る]ボタンは傍受されません。したがって、ポップアップウィンドウにアクションを実行するものがある場合は、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;
    }
});

ポップアップウィンドウ内にボタンがある場合は、setOnClickListener.onClickにisClickHandled = trueを設定してdismiss()を設定します。

onDismissListenerで、次のようにします。

popupWindow.setOnDismissListener(() -> {
        popupWindow.dismiss();
        if ( !isClickHandled) {
            MainActivity.mainActivity.getSupportFragmentManager().popBackStack();
        }
    });
于 2020-05-23T13:07:09.907 に答える