your programing

Android PopupWindow가 활성화되었을 때 배경이 흐리거나 어둡습니다.

lovepro 2020. 10. 13. 08:18
반응형

Android PopupWindow가 활성화되었을 때 배경이 흐리거나 어둡습니다.


를 사용하여 팝업 창을 표시 할 때 배경을 흐리게하거나 어둡게 할 수 popup.showAtLocation있고을 popup.dismiss호출 할 때 배경을 흐리게하거나 어둡게 할 수 있기를 원합니다 .

레이아웃 매개 변수 FLAG_BLUR_BEHINDFLAG_DIM_BEHIND내 활동을 적용하려고 시도했지만 앱이 시작 되 자마자 배경이 흐리게 표시되고 어둡게 표시됩니다.

팝업만으로 블러 링 / 디밍을 어떻게 할 수 있습니까?


질문은 Popupwindow수업 에 관한 것이 었지만 모든 사람들이 Dialog수업 을 사용하여 대답했습니다 . 메서드 Popupwindow없기 때문에 클래스 를 사용해야하는 경우에는 거의 쓸모 Popupwindow가 없습니다 getWindow().

실제로 작동하는 솔루션을 찾았습니다 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>

( 요소 에 대한 자세한 내용은 http://developer.android.com/guide/topics/resources/drawable-resource.html#Shape 참조 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/


때문에 PopupWindow단지가 추가하는 ViewWindowManager당신이 사용할 수있는 updateViewLayout (View view, ViewGroup.LayoutParams params)업데이트하는 LayoutParams당신의 PopupWindow의를 contentView쇼를 호출 한 후 .. ().

창 플래그 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);

Marshmallow 업데이트 :

M PopupWindow는 mDecorView라는 FrameLayout 안에 contentView를 래핑합니다. PopupWindow 소스를 createDecorView(View contentView)살펴보면 .mDecorView의 주요 목적은 M에 새로운 이벤트 전달 및 콘텐츠 전환을 처리하는 것입니다. 즉, 컨테이너에 액세스하려면 .getParent ()를 하나 더 추가해야합니다.

다음과 같이 변경해야하는 배경으로 :

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();
}

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);

마지막으로 팝업창을 표시 할 때 표시하고 팝업창을 종료 할 때 표시되도록합니다.

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

또 다른 트릭은 하나가 아닌 2 개의 팝업 창을 사용하는 것입니다. 첫 번째 팝업 창은 희미한 효과를 제공하는 반투명 배경의 더미보기입니다. 두 번째 팝업 창은 의도 한 팝업 창입니다.

팝업 창 생성시 순서 : 더미 팝업 창 1 번을 표시 한 다음 원하는 팝업 창을 표시합니다.

파괴 중 시퀀스 : 의도 한 팝업 창을 닫은 다음 더미 팝업 창을 닫습니다.

이 두 가지를 연결하는 가장 좋은 방법은 추가하는 것입니다 한 OnDismissListener을 하고 오버라이드 (override) onDismiss()(가) 자신의에서 더미 팝업 창을 dimiss하도록 구성의 방법을.

더미 팝업 창의 코드 :

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;
}

이에 대한 해결책을 찾았습니다.

사용자 지정 투명 대화 상자를 만들고 해당 대화 상자에서 팝업 창을 엽니 다.

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;
        }
    }
});

참고 : NewQuickAction여기에서 PopupWindow를 만드는 플러그인을 사용 했습니다. 기본 팝업 창에서도 수행 할 수 있습니다.


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">

좋아, 그래서 팝업 창이 열릴 때 배경 활동을 흐리게하기위한 uhmdown의 대답을 따릅니다 . 그러나 그것은 나에게 문제를 일으킨다. 그것은 활동을 흐리게하고 팝업 창을 포함합니다 (활동과 팝업 모두에 희미한 검은 색 레이어가 있음을 의미하며 분리 할 수 ​​없음).

그래서 이렇게 해봤어요

디밍 효과를 위해 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>

그리고로 추가 background에서 FrameLayout또한 내 다른 컨트롤에 넣어, 루트 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);

결과: 여기에 이미지 설명 입력

그것은 나를 위해 작동하고 또한 BaDo가 언급 한 문제를 해결 했습니다 . 이것으로 Actionbar또한 흐리게 할 수 있습니다.

P.s i am not saying uhmdown's is wrong. i learnt form his answer and try to evolve for my problem. I also confused whether this is a good way or not.

Any suggestions is also appreciated also sorry for my bad English.


For me, something like Abdelhak Mouaamou's answer works, tested on API level 16 and 27.

Instead of using popupWindow.getContentView().getParent() and casting the result to View (which crashes on API level 16 cause there it returns a ViewRootImpl object which isn't an instance of View) I just use .getRootView() which returns a view already, so no casting required there.

Hope it helps someone :)

complete working example scrambled together from other stackoverflow posts, just copy-paste it, e.g., in the onClick listener of a button:

// 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);
    }
}

Maybe this repo will help for you:BasePopup

이것은 PopupWindow의 다양한 문제를 해결하는 데 사용되는 내 저장소입니다.

라이브러리를 사용하는 경우 배경을 흐리게해야한다면 setBlurBackgroundEnable(true).

자세한 내용은 위키를 참조하십시오. (zh-cn 언어)

BasePopup : wiki


이 코드는

        pwindo = new PopupWindow(layout, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
        pwindo.showAtLocation(layout, Gravity.CENTER, 0, 0);
        pwindo.setOutsideTouchable(false);

        View container = (View) pwindo.getContentView().getParent();
        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;
        wm.updateViewLayout(container, p);

참고 URL : https://stackoverflow.com/questions/3221488/blur-or-dim-background-when-android-popupwindow-active

반응형