17

次の動作/機能で PopupWindow を使用したいと思います。

  • フォーカス可能です(ボタンなどの内部にインタラクティブなコントロールがあります)
  • View 'under' popupwindow は、ポップアップの外側のタッチを適切に消費する必要があります
  • ..しかし、外側をクリックした後でも、ポップアップウィンドウは画面上にとどまる必要があります

PopupWindow に関する多くの投稿を見つけましたが、そのような状況に対処する方法について質問したものはありません..

setOutsideTouchable()、setFocusable()、setTouchable() のすべての可能な組み合わせを試したと思いますが、行き詰まっています。ポップアップはクリックを適切に処理しますが、外側に触れると常に閉じられます。

私の現在のコードは次のとおりです。

View.OnTouchListener customPopUpTouchListenr = new View.OnTouchListener(){

    @Override
    public boolean onTouch(View arg0, MotionEvent arg1) {
        Log.d("POPUP", "Touch false");
        return false;
    }

};


LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout layout= (LinearLayout)inflater.inflate(R.layout.insert_point_dialog, null);
PopupWindow pw = new PopupWindow(layout,400,200,true);
pw.setOutsideTouchable(true);
pw.setTouchable(true);
pw.setBackgroundDrawable(new BitmapDrawable());
pw.setTouchInterceptor(customPopUpTouchListenr);
pw.showAtLocation(frameLayout, Gravity.BOTTOM, 0, 0);

私の一般的な目標は、gimp のようなソフトウェアで「ツール パレット」のように動作するフローティング ウィンドウを作成することです。内部にいくつかのコントロールがあり、「X」ボタンで閉じるまで上に留まり、その下の外側のコントロールと対話できるようにします。 PopupWindow ではなく、これを行うためのより良い方法があるのではないでしょうか? しかし、私はまだより適切なコントロールを見つけていません。

4

9 に答える 9

6

削除するだけpw.setBackgroundDrawable(new BitmapDrawable());

于 2012-08-09T06:09:25.593 に答える
6

手遅れですが、このようなことをグーグルで検索する人は、行の順序を変更するだけです

pw.showAtLocation(frameLayout, Gravity.BOTTOM, 0, 0);
pw.setOutsideTouchable(true);
pw.setTouchable(true);
pw.setBackgroundDrawable(new BitmapDrawable());
pw.setTouchInterceptor(customPopUpTouchListenr);

それ以外の

pw.setOutsideTouchable(true);
pw.setTouchable(true);
pw.setBackgroundDrawable(new BitmapDrawable());
pw.setTouchInterceptor(customPopUpTouchListenr);
pw.showAtLocation(frameLayout, Gravity.BOTTOM, 0, 0);

showatlocation メソッドの後に何かを置くと、何もないようになります

于 2013-06-10T12:40:34.010 に答える
2

試す

pw.setBackgroundDrawable(null);
于 2012-10-04T08:41:39.667 に答える
1

解決策は次のとおりです。

popupWindow.setFocusable(真);

popupWindow.update();

ありがとう: http://android-er.blogspot.ch/2012/04/disable-outside-popupwindow-by.html

于 2014-05-13T08:36:30.100 に答える
1

まず、外側に触れたときに popupWindow が閉じられる理由を理解する必要があります。

PopupWindowのソースコードとリソースファイルstyles.xmlを読んだら、

<style name="Widget.PopupWindow">
    <item name="popupBackground">@drawable/editbox_dropdown_background_dark</item>
    <item name="popupAnimationStyle">@style/Animation.PopupWindow</item>
</style>
 <style name="Widget">
    <item name="textAppearance">?textAppearance</item>
</style>

したがって、ダイアログテーマのようなものはありません:

<style name="Theme.Dialog">
<item name="windowCloseOnTouchOutside">@bool/config_closeDialogWhenTouchOutside</item>
</style name="Theme.Dialog">

しかし、PopupWindow.setBackgroundDrawable() が呼び出されると何かが起こり、

private void preparePopup(WindowManager.LayoutParams p) {
    if (mContentView == null || mContext == null || mWindowManager == null) {
        throw new IllegalStateException("You must specify a valid content view by "
                + "calling setContentView() before attempting to show the popup.");
    }

    if (mBackground != null) {
        final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
        int height = ViewGroup.LayoutParams.MATCH_PARENT;
        if (layoutParams != null &&
                layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
            height = ViewGroup.LayoutParams.WRAP_CONTENT;
        }

        // when a background is available, we embed the content view
        // within another view that owns the background drawable
        PopupViewContainer popupViewContainer = new PopupViewContainer(mContext);
        PopupViewContainer.LayoutParams listParams = new PopupViewContainer.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, height
        );
        popupViewContainer.setBackgroundDrawable(mBackground);
        popupViewContainer.addView(mContentView, listParams);

        mPopupView = popupViewContainer;
    } else {
        mPopupView = mContentView;
    }
    mPopupViewInitialLayoutDirectionInherited =
            (mPopupView.getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT);
    mPopupWidth = p.width;
    mPopupHeight = p.height;
}

コンテナ ビュー「PopupViewContainer」が作成されます。

 private class PopupViewContainer extends FrameLayout {
    private static final String TAG = "PopupWindow.PopupViewContainer";

    public PopupViewContainer(Context context) {
        super(context);
    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (mTouchInterceptor != null && mTouchInterceptor.onTouch(this, ev)) {
            return true;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final int x = (int) event.getX();
        final int y = (int) event.getY();

        if ((event.getAction() == MotionEvent.ACTION_DOWN)
                && ((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) {
            dismiss();
            return true;
        } else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
            dismiss();
            return true;
        } else {
            return super.onTouchEvent(event);
        }
    }

}

これで、重要な理由がわかりました。そのため、外部に触れた後に PopupWindow が閉じられないようにする方法は 2 つあります。1.@Raagaがしたように。pw.setBackgroundDrawable(新しい BitmapDrawable()) を削除します。

  1. OnTouchListener を実装して、PopupWindow 外のタッチ イベントをフィルタリングできます。
于 2015-06-02T02:35:35.100 に答える
0

PopupWindow の setFocusable(false) が可能です

ボタンは引き続きクリック可能ですが、視覚的なクリック動作はありません (強制的にクリックを表示するカスタム ハンドラー?)

以下は、「常に手前に表示」オプションを使用したフローティング ウィンドウのサンプルです。

フローティング ウィンドウに近い元のレイアウトは、どちらの場合も完全に機能します。さらに、ウィンドウがまだフローティングしているときに、ダイアログやその他のポップアップを使用することができます。

また、ウィンドウは再利用可能です

final static int buttonAlpha = 0xDF;
final static float buttonTextSize = 12f;

public final void addPopupButton(LinearLayout linearLayout, String title, android.view.View.OnClickListener onClickListener)
{
    Button button = new Button(this.getContext());
    button.setText(title);
    button.setTextSize(buttonTextSize);
    button.getBackground().setAlpha(buttonAlpha);
    button.setOnClickListener(onClickListener);
    linearLayout.addView(button, LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
}

public final Button addPopupCheckbox(LinearLayout linearLayout, String title, boolean isChecked, android.view.View.OnClickListener onClickListener)
{
    final Button button = new Button(getContext());
    button.setText(title);
    button.setTextSize(buttonTextSize);
    final int buttonHeight = button.getHeight();
    setButtonChecked(button, isChecked);
    button.setHeight(buttonHeight);
    button.getBackground().setAlpha(buttonAlpha);
    button.setOnClickListener(onClickListener);
    linearLayout.addView(button, LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
    return button;
}

public final void setButtonChecked(Button button, boolean isChecked)
{
    button.setCompoundDrawablesWithIntrinsicBounds(Resources.getSystem().getIdentifier(isChecked ? "android:drawable/btn_check_on" : "android:drawable/btn_check_off", null, null), 0, 0, 0);
}

private boolean isMenuAlwaysOnTop = true;
private PopupWindow popupWindowMenuV2 = null;

public final void popupMenuNav2()
{
    if (popupWindowMenuV2 == null)
    {
        // [start] layout

        ScrollView scrollView = new ScrollView(this.getContext());

        final LinearLayout linearLayoutNavigation = new LinearLayout(this.getContext());
        linearLayoutNavigation.setOrientation(LinearLayout.VERTICAL);
        linearLayoutNavigation.setBackgroundColor(0x7FFFFFFF);
        linearLayoutNavigation.setPadding(20, 10, 20, 10);

        scrollView.addView(linearLayoutNavigation, LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);

        popupWindowMenuV2 = new PopupWindow(this);
        popupWindowMenuV2.setBackgroundDrawable(new BitmapDrawable());
        popupWindowMenuV2.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
        popupWindowMenuV2.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
        popupWindowMenuV2.setTouchable(true);
        popupWindowMenuV2.setOutsideTouchable(!isMenuAlwaysOnTop);
        popupWindowMenuV2.setFocusable(!isMenuAlwaysOnTop);
        popupWindowMenuV2.setTouchInterceptor(new OnTouchListener()
        {
            @Override
            public boolean onTouch(View v, MotionEvent event)
            {
                if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_OUTSIDE)
                {
                    if (!isMenuAlwaysOnTop)
                        popupWindowMenuV2.dismiss();
                    else
                        return false;
                    return true;
                }
                return false;
            }
        });
        popupWindowMenuV2.setContentView(scrollView);

        // [end] layout

        // [start] always on top checkbox

        final Button buttonMenuAlwaysOnTop = addPopupCheckbox(linearLayoutNavigation, "always on top", isMenuAlwaysOnTop, null);
        buttonMenuAlwaysOnTop.setOnClickListener(
                new OnClickListener()
                {
                    @Override
                    public void onClick(View vv)
                    {
                        isMenuAlwaysOnTop = !isMenuAlwaysOnTop;
                        setButtonChecked(buttonMenuAlwaysOnTop, isMenuAlwaysOnTop);
                        popupWindowMenuV2.dismiss();
                        popupWindowMenuV2.setOutsideTouchable(!isMenuAlwaysOnTop);
                        popupWindowMenuV2.setFocusable(!isMenuAlwaysOnTop);
                        popupWindowMenuV2.showAtLocation(((Activity) getContext()).getWindow().getDecorView(), Gravity.CENTER_VERTICAL + Gravity.RIGHT, 0, 0);
                    }
                });

        // [end] always on top checkbox

        addPopupButton(linearLayoutNavigation, "some button",
                new OnClickListener()
                {
                    @Override
                    public void onClick(View vv)
                    {
                        if (!isMenuAlwaysOnTop)
                            popupWindowMenuV2.dismiss();
                        someAction();
                    }
                });

    }

    popupWindowMenuV2.showAtLocation(((Activity) getContext()).getWindow().getDecorView(), Gravity.CENTER_VERTICAL + Gravity.RIGHT, 0, 0);
}

// somewhere in handler:
            if (someCondition)
            {
                if (popupWindowMenuV2 != null && popupWindowMenuV2.isShowing())
                    popupWindowMenuV2.dismiss();
                else
                    popupMenuNav2();
                return true;
            }
于 2014-03-26T21:39:29.387 に答える