web-dev-qa-db-ja.com

Android PopupWindowがアクティブな場合に背景をぼかすまたは暗くする

popup.showAtLocationを使用してポップアップウィンドウを表示するときに背景をぼかしまたは薄暗くし、popup.dismissが呼び出されたときに背景をぼかし/薄暗くできるようにします。

レイアウトパラメータFLAG_BLUR_BEHINDおよびFLAG_DIM_BEHINDをアクティビティに適用しようとしましたが、これはアプリを起動するとすぐに背景がぼやけて暗くなるように見えます。

ポップアップだけでぼかし/暗くするにはどうすればよいですか?

76
k_day

質問はPopupwindowクラスに関するものでしたが、誰もがDialogクラスを使用する回答を出しました。 PopupwindowクラスにはgetWindow()メソッドがないため、Popupwindowクラスを使用する必要がある場合はほとんど役に立ちません。

実際にPopupwindowで機能するソリューションを見つけました。バックグラウンドアクティビティに使用するxmlファイルのルートがFrameLayoutであることのみが必要です。 Framelayout要素に_Android:foreground_タグを付けることができます。このタグが行うことは、アクティビティ全体の上に階層化される描画可能リソースを指定することです(つまり、Framelayoutがxmlファイルのルート要素である場合)。次に、前景のドロアブルの不透明度(setAlpha())を制御できます。

任意の描画可能リソースを使用できますが、調光効果だけが必要な場合は、_<shape>_タグをルートとして使用して、描画可能フォルダーにxmlファイルを作成します。

_<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:shape="rectangle" >
    <solid Android:color="#000000" />
</shape>
_

shape要素の詳細については、 http://developer.Android.com/guide/topics/resources/drawable-resource.html#Shape を参照してください)。ドローアブルアイテムを透明にするカラータグにアルファ値を指定しなかったことに注意してください(例_#ff000000_)。この理由は、ハードコードされたアルファ値は、コードのsetAlpha()を介して設定した新しいアルファ値をオーバーライドするように見えるため、それを望まないからです。ただし、これは、描画可能なアイテムが最初は不透明(固体、非透明)になることを意味します。そのため、アクティビティのonCreate()メソッドで透明にする必要があります。

Framelayout xml要素のコードは次のとおりです。

_<FrameLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/mainmenu"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent"
    Android:foreground="@drawable/shape_window_dim" >
...
... your activity's content
...
</FrameLayout>
_

アクティビティのonCreate()メソッドは次のとおりです。

_public void onCreate( Bundle savedInstanceState)
{
  super.onCreate( savedInstanceState);

  setContentView( R.layout.activity_mainmenu);

  //
  // Your own Activity initialization code
  //

  layout_MainMenu = (FrameLayout) findViewById( R.id.mainmenu);
  layout_MainMenu.getForeground().setAlpha( 0);
}
_

最後に、アクティビティを暗くするコード:

_layout_MainMenu.getForeground().setAlpha( 220); // dim

layout_MainMenu.getForeground().setAlpha( 0); // restore
_

アルファ値は_0_(不透明)から_255_(不可視)になります。 Popupwindowを閉じるときは、アクティビティを暗くする必要があります。

Popupwindowを表示したり閉じたりするためのコードは含めていませんが、それを行う方法へのリンクを次に示します。 http://www.mobilemancer.com/2011/01/08/popup-window-in- Android /

102
uhmdown

PopupWindowViewWindowManagerに追加するだけなので、updateViewLayout (View view, ViewGroup.LayoutParams params)を使用してLayoutParamsPopupWindowを更新できます。 contentViewはshow ..()を呼び出した後。

ウィンドウフラグ_FLAG_DIM_BEHIND_を設定すると、ウィンドウの背後のすべてが暗くなります。 dimAmountを使用して、減光の量を制御します(完全に不透明な場合は1.0、減光しない場合は0.0)。

バックグラウンドをPopupWindowに設定すると、contentViewがコンテナに格納されるため、親を更新する必要があることに注意してください。

背景付き:

_PopupWindow popup = new PopupWindow(contentView, width, height);
popup.setBackgroundDrawable(background);
popup.showAsDropDown(anchor);

View container = (View) popup.getContentView().getParent();
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams p = (WindowManager.LayoutParams) container.getLayoutParams();
// add flag
p.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
p.dimAmount = 0.3f;
wm.updateViewLayout(container, p);
_

背景なし:

_PopupWindow popup = new PopupWindow(contentView, width, height);
popup.setBackgroundDrawable(null);
popup.showAsDropDown(anchor);

WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams p = (WindowManager.LayoutParams) contentView.getLayoutParams();
// add flag
p.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
p.dimAmount = 0.3f;
wm.updateViewLayout(contentView, p);
_

マシュマロの更新:

Mでは、PopupWindowはmDecorViewと呼ばれるFrameLayout内にcontentViewをラップします。 PopupWindowソースを調べると、createDecorView(View contentView)のようなものが見つかります。mDecorViewの主な目的は、イベントディスパッチとコンテンツ移行を処理することです。これは、Mに新しく追加されたものです。 ()コンテナにアクセスします。

次のような変更が必要なバックグラウンド:

_View container = (View) popup.getContentView().getParent().getParent();
_

API 18+のより良い代替

ViewGroupOverlayを使用したハッキン​​グの少ないソリューション:

1)目的のルートレイアウトを取得する

_ViewGroup root = (ViewGroup) getWindow().getDecorView().getRootView();
_

2)applyDim(root, 0.5f);またはclearDim()を呼び出します

_public static void applyDim(@NonNull ViewGroup parent, float dimAmount){
    Drawable dim = new ColorDrawable(Color.BLACK);
    dim.setBounds(0, 0, parent.getWidth(), parent.getHeight());
    dim.setAlpha((int) (255 * dimAmount));

    ViewGroupOverlay overlay = parent.getOverlay();
    overlay.add(dim);
}

public static void clearDim(@NonNull ViewGroup parent) {
    ViewGroupOverlay overlay = parent.getOverlay();
    overlay.clear();
}
_
68
Markus Rubey

Xmlファイルに、幅と高さを「match_parent」としてこのようなものを追加します。

<RelativeLayout
        Android:id="@+id/bac_dim_layout"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:background="#C0000000"
        Android:visibility="gone" >
</RelativeLayout>

作成中のアクティビティで

//setting background dim when showing popup
back_dim_layout = (RelativeLayout) findViewById(R.id.share_bac_dim_layout);

最後に、popupwindowを表示するときに表示し、popupwindowを終了するときに表示を非表示にします。

back_dim_layout.setVisibility(View.VISIBLE);
back_dim_layout.setVisibility(View.GONE);
28
user2257590

もう1つの方法は、1つではなく2つのポップアップウィンドウを使用することです。最初のポップアップウィンドウは、薄暗い効果を提供する半透明の背景を持つダミービューになります。 2番目のポップアップウィンドウは、目的のポップアップウィンドウです。

ポップアップウィンドウの作成中のシーケンス:ダミーのポップアップウィンドウを最初に表示し、次に目的のポップアップウィンドウを表示します。

破壊中のシーケンス:目的のポップアップウィンドウを閉じてから、ダミーのポップアップウィンドウを閉じます。

これら2つをリンクする最良の方法は、 OnDismissListener を追加し、ダミーポップアップウィンドウを削除することを目的としたonDismiss()メソッドをオーバーライドすることです。

ダミーのポップアップウィンドウのコード:

fadepopup.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical" 
    Android:id="@+id/fadePopup"
    Android:background="#AA000000">
</LinearLayout>

フェードポップアップを表示して背景を暗くします

private PopupWindow dimBackground() {

    LayoutInflater inflater = (LayoutInflater) EPGGRIDActivity.this
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    final View layout = inflater.inflate(R.layout.fadepopup,
            (ViewGroup) findViewById(R.id.fadePopup));
    PopupWindow fadePopup = new PopupWindow(layout, windowWidth, windowHeight, false);
    fadePopup.showAtLocation(layout, Gravity.NO_GRAVITY, 0, 0);
    return fadePopup;
}
11
Abhishek Nandi

私はこれに対する解決策を見つけました

カスタムの透明なダイアログを作成し、そのダイアログ内でポップアップウィンドウを開きます。

dialog = new Dialog(context, Android.R.style.Theme_Translucent_NoTitleBar);
emptyDialog = LayoutInflater.from(context).inflate(R.layout.empty, null);

/* blur background*/
WindowManager.LayoutParams lp = dialog.getWindow().getAttributes();  
lp.dimAmount=0.0f;  
dialog.getWindow().setAttributes(lp);  
dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND); 
dialog.setContentView(emptyDialog);
dialog.setCanceledOnTouchOutside(true);
dialog.setOnShowListener(new OnShowListener()
{
    @Override
    public void onShow(DialogInterface dialogIx)
    {
        mQuickAction.show(emptyDialog); //open the PopupWindow here
    }
});
dialog.show();

ダイアログのxml(R.layout.empty):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
     Android:layout_height="match_parent" Android:layout_width="match_parent"
     style="@Android:style/Theme.Translucent.NoTitleBar" />

ポップアップウィンドウが閉じたときにダイアログを閉じます。そう

mQuickAction.setOnDismissListener(new OnDismissListener()
{
    @Override
    public void onDismiss()
    {
        if(dialog!=null)
        {
            dialog.dismiss(); // dismiss the empty dialog when the PopupWindow closes
            dialog = null;
        }
    }
});

注:ここでPopupWindowを作成するために NewQuickAction プラグインを使用しました。ネイティブのポップアップウィンドウでも実行できます。

5
PC.

Android:theme="@Android:style/Theme.Dialog"を使用してそれを行うことができます。アクティビティを作成し、AndroidManifest.xmlでアクティビティを次のように定義します。

    <activity Android:name=".activities.YourActivity"
              Android:label="@string/your_activity_label"
              Android:theme="@Android:style/Theme.Dialog">
0
Macarse

わかりましたので、私は hmdown's ポップウィンドウが開いているときにバックグラウンドアクティビティを暗くするための回答に従います。しかし、それは私にとって問題を引き起こします。アクティビティを暗くしてポップアップウィンドウを表示しました(アクティビティとポップアップの両方に薄暗黒のレイヤーがあり、それらを分離することはできません)。

だから私はこのようにしてみました、

調光効果のためにdimming_black.xmlファイルを作成し、

 <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:shape="rectangle">
    <solid Android:color="#33000000" />
</shape>

backgroundFrameLayoutとしてルートxmlタグとして追加し、他のコントロールもLinearLayoutにこのlayout.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical"
    Android:background="@drawable/ff_drawable_black">

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:orientation="vertical"
        Android:layout_gravity="bottom"
        Android:background="@color/white">

        // other codes...
    </LinearLayout>

</FrameLayout>

最後に、MainActivityにポップアップを表示し、追加のパラメーターを以下のように設定します。

           //instantiate popup window
            popupWindow = new PopupWindow(viewPopup, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT, true);

            //display the popup window
            popupWindow.showAtLocation(layout_ff, Gravity.BOTTOM, 0, 0);

結果:enter image description here

それは私のために機能し、BaDoによってコメントされた問題も解決しました。これにより、Actionbarも暗くすることができます。

P.s私はuhmdown'sが間違っていると言っていません。私は彼の答えから学び、私の問題のために進化しようとします。また、これが良い方法であるかどうかもわかりません。

私の英語が下手でごめんなさい。

0
Sahil M.

私にとっては、Abdelhak Mouaamouの答えのようなものが機能し、APIレベル16および27でテストされています。

popupWindow.getContentView().getParent()を使用して結果をViewにキャストする代わりに(APIレベル16でクラッシュすると、ViewRootImplオブジェクトのView)既にビューを返す.getRootView()を使用しているだけなので、キャストは必要ありません。

それが誰かを助けることを願っています:)

他のstackoverflowの投稿からスクランブルされた完全な作業例を、たとえばボタンのonClickリスナーにコピーアンドペーストするだけです:

// inflate the layout of the popup window
LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
if(inflater == null) {
    return;
}
//View popupView = inflater.inflate(R.layout.my_popup_layout, null); // this version gives a warning cause it doesn't like null as argument for the viewRoot, c.f. https://stackoverflow.com/questions/24832497 and https://stackoverflow.com/questions/26404951
View popupView = View.inflate(MyParentActivity.this, R.layout.my_popup_layout, null);

// create the popup window
final PopupWindow popupWindow = new PopupWindow(popupView,
        LinearLayout.LayoutParams.WRAP_CONTENT,
        LinearLayout.LayoutParams.WRAP_CONTENT,
        true // lets taps outside the popup also dismiss it
        );

// do something with the stuff in your popup layout, e.g.:
//((TextView)popupView.findViewById(R.id.textview_popup_helloworld))
//      .setText("hello stackoverflow");

// dismiss the popup window when touched
popupView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            popupWindow.dismiss();
            return true;
        }
});

// show the popup window
// which view you pass in doesn't matter, it is only used for the window token
popupWindow.showAtLocation(view, Gravity.CENTER, 0, 0);
//popupWindow.setOutsideTouchable(false); // doesn't seem to change anything for me

View container = popupWindow.getContentView().getRootView();
if(container != null) {
    WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
    WindowManager.LayoutParams p = (WindowManager.LayoutParams)container.getLayoutParams();
    p.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND;
    p.dimAmount = 0.3f;
    if(wm != null) {
        wm.updateViewLayout(container, p);
    }
}
0
chrisi1698

たぶん、このレポはあなたに役立つでしょう: BasePopup

これは私のレポで、PopupWindowのさまざまな問題を解決するために使用されます。

ライブラリを使用する場合、背景をぼかす必要がある場合は、setBlurBackgroundEnable(true).を呼び出すだけです

詳細については、Wikiを参照してください。(zh-cnの言語)

BasePopup:wiki

0
razerdp