【问题标题】:Close PopupWindow upon tapping outside or back button在点击外部或返回按钮时关闭弹出窗口
【发布时间】:2021-01-17 07:20:55
【问题描述】:

我想通过在窗口外点击或按后退按钮来关闭 PopupWindow。现在你可以点击屏幕上的任何地方,然后窗口就会关闭,我不知道为什么。我还想为 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>

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

【问题讨论】:

    标签: android popup maps popupwindow


    【解决方案1】:

    您需要使用外部触摸true 设置背景可绘制对象

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

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

    要给PopupWindow 添加阴影,更简单的方法是将CardView 作为View 的根放在xml 中并更改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);
    

    【讨论】:

    • 在哪里实现 SetBackgroundDrawable 和 SetOutsideTouchable?我尝试将它添加到脚趾 OnTouchListener 之上,但它什么也没做。我还尝试删除 OnTouchListener 并保留新的代码行,但没有任何效果。
    • 糟糕,我忘记了一行setFocusable() 我已经编辑了我的答案。滚动查看。同时删除触摸监听器。完全没有
    • 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); popupWindow.setFocusable(true); popupWindow.setBackgroundDrawable(new ColorDrawable()); popupWindow.setOutsideTouchable(true);'仍然什么都不做。没有错误或任何东西——点击没有响应
    • 让我再试试看
    • 非常感谢。对不起,菜鸟问题,
    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

      在上面添加任何内容。 在关闭背景和窗口的背景上添加 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
              }
          };)
      

      // 这可以防止通过单击弹出窗口关闭窗口

      popup.setOnClickListener(null);
      

      【讨论】:

        【解决方案4】:

        在 Android 5 上,我的弹出窗口不会被返回按钮或在外部点击。我在较新的 Android 版本上工作得很好,只是在 Android 5、Lollipop、API 级别 21 上没有。

        在我的情况下,只需要:

        popupWindow.setBackgroundDrawable(new ColorDrawable())
        

        去看看!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-11-25
          • 1970-01-01
          • 2021-11-21
          • 1970-01-01
          • 1970-01-01
          • 2012-12-21
          • 2019-11-10
          相关资源
          最近更新 更多