在点击外部或后退按钮时关闭弹出窗口

Close PopupWindow upon tapping outside or back button

我想通过点击 window 外部或按后退按钮来关闭 PopupWindow。现在你可以点击屏幕上的任意位置,然后 window 关闭,我不明白为什么。我还想给 PopupWindow 添加一个阴影。谢谢!

MainActivity.Java:

public class MainActivity extends FragmentActivity implements OnMapReadyCallback, GoogleMap.OnMarkerClickListener{

LinearLayout mainLayout;

private GoogleMap mMap;
PlaceAutocompleteFragment placeAutoComplete;
private static final String TAG = "Main Activity";
List<Marker> list = new ArrayList<>();

Marker NY_MANHATTAN;
Marker NY_BROOKLYN;
Marker NY_BRONX;
Marker NY_QUEENS;
Marker NY_STATENISLAND;

private PopupWindow popupWindow;
private LayoutInflater layoutInflater;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //TODO:initialize startup stuff here:

    /*
    * layoutTest is the testing inflater for all popup windows.
    * here is where new popup windows will be added to the list.
    * */

    mainLayout = (LinearLayout) findViewById(R.id.mainLayout);



    placeAutoComplete = (PlaceAutocompleteFragment) getFragmentManager().findFragmentById(R.id.place_autocomplete);
    placeAutoComplete.setOnPlaceSelectedListener(new PlaceSelectionListener() {
        @Override
        public void onPlaceSelected(Place place) {

            Log.i(TAG, "Place Selected: " + place.getName());
            LatLng latLng = place.getLatLng();

            //move map camera
            mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 11));
        }

        @Override
        public void onError(Status status) {
            Log.d("Maps", "An error occurred: " + status);
        }
    });

    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
}

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;

    try {
        // Customise the styling of the base map using a JSON object defined
        // in a raw resource file.
        boolean success = googleMap.setMapStyle(
                MapStyleOptions.loadRawResourceStyle(
                        this, R.raw.style_json));

        if (!success) {
            Log.e(TAG, "Style parsing failed.");
        }
    } catch (Resources.NotFoundException e) {
        Log.e(TAG, "Can't find style. Error: ", e);
    }

    //TODO: DEFINE MARKER LOCATIONS HERE:

    LatLng manhattanLoc = new LatLng(40.754932, -73.984016);
    LatLng brooklynLoc = new LatLng(40.650002, -73.949997);
    LatLng bronxLoc = new LatLng(40.837048, -73.865433);
    LatLng queensLoc = new LatLng(40.742054, -73.769417);
    LatLng statenIslandLoc = new LatLng(40.579021, -74.151535);

    //TODO: INIT MARKERS HERE:


     NY_MANHATTAN = googleMap.addMarker(new MarkerOptions().position(manhattanLoc).title("Manhattan").snippet("test"));
    list.add(NY_MANHATTAN);

     NY_BROOKLYN = googleMap.addMarker(new MarkerOptions().position(brooklynLoc).title("Brooklyn").snippet("test"));
    list.add(NY_BROOKLYN);

     NY_BRONX = googleMap.addMarker(new MarkerOptions().position(bronxLoc).title("Bronx").snippet("test"));
    list.add(NY_BRONX);

     NY_QUEENS = googleMap.addMarker(new MarkerOptions().position(queensLoc).title("Queens").snippet("test"));
    list.add(NY_QUEENS);

     NY_STATENISLAND = googleMap.addMarker(new MarkerOptions().position(statenIslandLoc).title("Staten Island").snippet("test"));
    list.add(NY_STATENISLAND);

    googleMap.setOnCameraChangeListener(new
                                                GoogleMap.OnCameraChangeListener() {
                                                    @Override
                                                    public void onCameraChange(CameraPosition cameraPosition) {
                                                        for (Marker m : list) {
                                                            m.setVisible(cameraPosition.zoom > 10); // <-- define zoom level for markers here
                                                            /**
                                                             * Zoom level guidelines:
                                                             * 12 = zoomed in about 90%
                                                             * 1 = zommed in less than 5%
                                                             * Higher = higher zoom, Lower = lower zoom.
                                                             * Confusing. I know.
                                                             */
                                                        }
                                                    }
                                                });

    mMap.setOnMarkerClickListener(this);

}

//TODO: handle marker clicks below:
/*
* current placeholder code states that all markers
* will open the popup_test layout.
* */

public boolean onMarkerClick(Marker arg0) {

    PopupInit();

    return false;

}

public void PopupInit()
{

    layoutInflater = (LayoutInflater) getApplicationContext().getSystemService(LAYOUT_INFLATER_SERVICE);
    ViewGroup container = (ViewGroup) layoutInflater.inflate(R.layout.popup_test,null);

    /*
    *
    * set x/y locations here:
    *
    * */

    DisplayMetrics dm = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(dm);

    int popWidth = dm.widthPixels;
    int popHeight = dm.heightPixels;

    popupWindow = new PopupWindow(container,(int) (popWidth*.8),(int) (popHeight*.6),true);
    popupWindow.showAtLocation(mainLayout, Gravity.CENTER,0,0);

    container.setOnTouchListener(new View.OnTouchListener()
    {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent)
        {
            popupWindow.dismiss();
            return true;
        }
    });


}



}

Popup_Test.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="#fff55250"
    android:layout_width="match_parent" 
android:layout_height="match_parent">
</RelativeLayout>

抱歉这个菜鸟问题。我已经有一段时间了,无论我尝试多少,我似乎都无法弄清楚......我最大的两个担忧是在弹出 window 后面隐藏阴影并在按后退按钮或在弹出窗口外点击 window。首先十分感谢。谢谢。

您将需要使用 Outside touch 设置 Background Drawable true

popWindow.setFocusable(true);
popupWindow.setBackgroundDrawable(new ColorDrawable())
popupWindow.setOutsideTouchable(true);

方法通过传递任何 drawable。否则整个屏幕都是你的背景,点击外面将不起作用 backPressed 将使用这种方式自动工作!

要给你添加阴影 PopupWindow 更简单的方法是将 CardView 作为 xmlView 的根并更改 elevation属性。要使用 CardView,您可能还需要在 gradle 文件中添加一个依赖项

  <android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_gravity="center"
    android:layout_width="200dp"
    android:layout_height="200dp"
    card_view:cardElevation="4dp"
    card_view:cardCornerRadius="4dp">

    <!--YOUR RELATIVE LAYOUT SHOULD BE HERE!-->

</android.support.v7.widget.CardView>

您还必须在 app gradle 文件中添加依赖项,例如:

dependencies {
...
    compile 'com.android.support:cardview-v7:21.0.+'
}

CardView and elevation here 中有更多详细信息。

我的代码是这样的

    LayoutInflater layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    // inflate the custom popup layout
    final View inflatedView = layoutInflater.inflate(R.layout.pop_up_test, null,false);
    // get device size
    Display display = getWindowManager().getDefaultDisplay();
    final Point size = new Point();
    display.getSize(size);
    //mDeviceHeight = size.y; //Not in use just comment it off for now

    // set height depends on the device size
    popupWindow = new PopupWindow(inflatedView, size.x - 50,(WindowManager.LayoutParams.WRAP_CONTENT), true );
    // set a background drawable with rounders corners
    // make it focusable to show the keyboard to enter in `EditText`
    popupWindow.setFocusable(true);
    popupWindow.setBackgroundDrawable(new ColorDrawable());//This has no meaning than dismissal of the Pop Up Noni!!
    // make it outside touchable to dismiss the popup window
    popupWindow.setOutsideTouchable(true);

    // show the popup at bottom of the screen and set some margin at bottom ie,
    popupWindow.showAtLocation(v, Gravity.BOTTOM, 0,100);

我可以在您的 Activity 中覆盖您的 onBackPressed() 方法。话虽如此,如果您按下后退按钮,则会触发此方法。在该方法中,您可以检查弹出窗口是否显示,并在需要时关闭它,如下所示:

@Override
public void onBackPressed() {
    if (popupWindow != null && popupWindow.isShowing()) {
        popupWindow.dismiss();
    }
    super.onBackPressed();
}

您还可以使用您希望用户单击以取消弹出窗口的区域中的一些 onClickListeners 来实现 dismiss() 逻辑。

如果您出于任何原因不想使用 Xenolion asnwer,您可以手动创建覆盖整个屏幕的背景。

在上面添加任何内容。 在关闭背景和 window 的背景上添加 onclick 侦听器。 在 popupwindow 上添加 onclick 侦听器为 null,这将防止在其顶部单击时关闭弹出窗口。

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/backdrop"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

    </LinearLayout>

    <LinearLayout
        android:id="@+id/popUp"
        android:layout_width="500dp"
        android:layout_height="500dp"
        android:orientation="horizontal"
        app:layout_constraintBottom_toBottomOf="@+id/backdrop"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"></LinearLayout>


</androidx.constraintlayout.widget.ConstraintLayout>

backdrop.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // code to close backdrop and pop up
        }
    };)

// 这可以防止通过单击弹出 window

关闭 window
popup.setOnClickListener(null);

我有一些弹出窗口不会被后退按钮关闭或在 Android 5 上点击外部。我在较新的 Android 版本上工作得很好,只是在 Android 上不行 5,棒棒糖,API 21 级。

我的情况只需要:

popupWindow.setBackgroundDrawable(new ColorDrawable())

去看看吧!