在点击外部或后退按钮时关闭弹出窗口
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
作为 xml
中 View
的根并更改 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())
去看看吧!
我想通过点击 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
作为 xml
中 View
的根并更改 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
关闭 windowpopup.setOnClickListener(null);
我有一些弹出窗口不会被后退按钮关闭或在 Android 5 上点击外部。我在较新的 Android 版本上工作得很好,只是在 Android 上不行 5,棒棒糖,API 21 级。
我的情况只需要:
popupWindow.setBackgroundDrawable(new ColorDrawable())
去看看吧!