弹出窗口 window 关闭外部触摸无效
Popup window dismiss on outside touch not working
请检查我到目前为止所做的尝试,然后再对重复进行投票。
我试图在外部触摸时关闭弹出窗口 window。我已经尝试了所有可用的解决方案,但都没有用。
第一次尝试:
pwindo.setBackgroundDrawable(new BitmapDrawable());
pwindo.setFocusable(true);
pwindo.setOutsideTouchable(true);
第二次尝试:
pwindo.setBackgroundDrawable(new ColorDrawable());
pwindo.setFocusable(true);
pwindo.setOutsideTouchable(true);
第三次尝试:
pwindo.setBackgroundDrawable(new ColorDrawable());
pwindo.setFocusable(true);
pwindo.setOutsideTouchable(false);
第四次尝试:
pwindo.setFocusable(true);
pwindo.setOutsideTouchable(false);
第 5 次尝试:
pwindo.setOutsideTouchable(true);
第 6 次尝试:
pwindo.setOutsideTouchable(false);
第七次尝试:
pwindo.setFocusable(true);
没有任何效果。
已更新:
public void addFlyout()
{
try {
LayoutInflater inflater = TabActivity.this.getLayoutInflater();
Display display = getWindowManager().getDefaultDisplay();
Method mGetRawH = Display.class.getMethod("getRawHeight");
Method mGetRawW = Display.class.getMethod("getRawWidth");
int rawHeight = (Integer) mGetRawH.invoke(display);
View view = inflater.inflate(R.layout.flyout_list_layout,
(ViewGroup) findViewById(R.id.flyoutLayoutList));
Dialog dialog = new Dialog(TabActivity.this);
pwindo = new PopupWindow(view, 340, rawHeight- actionBar.getHeight(), true);
pwindo.showAtLocation(view, Gravity.RIGHT | Gravity.TOP, 0, actionBar.getHeight());
pwindo.setBackgroundDrawable(new ColorDrawable(Color.RED));
// pwindo.setTouchable(true);
pwindo.setOutsideTouchable(true);
pwindo.setTouchInterceptor(new View.OnTouchListener() {
@Override public boolean onTouch(View v, MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_OUTSIDE)
{
pwindo.dismiss();
//Log.e(TAG, "some event happened outside window: action outside");
return true;
}
// Log.e(TAG, "some event happened outside window");
return false;
}
});
listFlyout = (ListView) view.findViewById(R.id.list_slideList);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(TabActivity.this, R.layout.drawer_item, R.id.content, tabs);
listFlyout.setAdapter(adapter);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
和
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
try {
if(tab.getPosition() == 4)
{
addFlyout();
}
else
mViewPager.setCurrentItem(tab.getPosition());
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
您可以使用 dialog.setCanceledOnTouchOutside(true);
,如果您触摸 Dialog
的外部,它会关闭 Dialog
。
类似于:
Dialog dialog = new Dialog(context)
dialog.setCanceledOnTouchOutside(true);
对于弹出 windows:
popupWindow.setOutsideTouchable(true);
popupWindow.setTouchable(true);
popupWindow.setBackgroundDrawable(new BitmapDrawable());
popupWindow.setTouchInterceptor(new OnTouchListener() { @Override
public boolean onTouch(View v, MotionEvent event) {
if(AppContext.isDebugMode()) {
Log.d("POPUP_WINDOW", "v: "+v.getTag() + " | event: "+event.getAction());
popupWindow.dismiss();
return true;
}
});
}
尝试使用下面的代码。
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Inflate the view from a predefined XML layout
View layout = inflater.inflate(R.layout.test, (ViewGroup) findViewById(R.id.linearLayout));
pw = new PopupWindow(layout, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, true);
pw.setOutsideTouchable(true);
pw.setBackgroundDrawable(new ShapeDrawable());
pw.setTouchInterceptor(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// here I want to close the pw when clicking outside it but
// at all this is just an example of how it works and you can
// implement the onTouch() or the onKey() you want
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
pw.dismiss();
return true;
}
return false;
}
});
pw.showAtLocation(layout, Gravity.CENTER, 0, 0);
在 PopupWindow
上设置背景可确保在其范围外单击可将其关闭。
showAtLocation(...)
:
public void showAtLocation(IBinder token, int gravity, int x, int y) {
....
preparePopup(p);
....
}
preparePopup(...)
检查是否设置了背景。如果是,您传递的内容视图(在构造函数中)将添加到自定义 FrameLayout
。然后在这个自定义 FrameLayout
:
上设置背景
if (mBackground != null) {
....
// when a background is available, we embed the content view
// within another view that owns the background drawable
PopupViewContainer popupViewContainer = new PopupViewContainer(mContext);
PopupViewContainer.LayoutParams listParams = new PopupViewContainer.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, height
);
popupViewContainer.setBackground(mBackground);
popupViewContainer.addView(mContentView, listParams);
....
} else {
....
}
由于您在 setBackgroundDrawable(...)
showAtLocation(...)
之后调用,preparePopup(...)
不会将内容视图放在 PopupViewContainer
中。
PopupViewContainer
还覆盖 onTouchEvent(...)
以提供 'dismissed-when-touched-outside' 行为:
@Override
public boolean onTouchEvent(MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
if ((event.getAction() == MotionEvent.ACTION_DOWN)
&& ((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) {
dismiss();
return true;
} else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
dismiss();
return true;
} else {
return super.onTouchEvent(event);
}
}
显然,您只需要提供背景,并在调用 showAtLocation(...)
之前提供。
有效:
popup.setFocusable(false);
popup.setTouchable(true);
popup.setOutsideTouchable(false);
popup.setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
请检查我到目前为止所做的尝试,然后再对重复进行投票。
我试图在外部触摸时关闭弹出窗口 window。我已经尝试了所有可用的解决方案,但都没有用。
第一次尝试:
pwindo.setBackgroundDrawable(new BitmapDrawable());
pwindo.setFocusable(true);
pwindo.setOutsideTouchable(true);
第二次尝试:
pwindo.setBackgroundDrawable(new ColorDrawable());
pwindo.setFocusable(true);
pwindo.setOutsideTouchable(true);
第三次尝试:
pwindo.setBackgroundDrawable(new ColorDrawable());
pwindo.setFocusable(true);
pwindo.setOutsideTouchable(false);
第四次尝试:
pwindo.setFocusable(true);
pwindo.setOutsideTouchable(false);
第 5 次尝试:
pwindo.setOutsideTouchable(true);
第 6 次尝试:
pwindo.setOutsideTouchable(false);
第七次尝试:
pwindo.setFocusable(true);
没有任何效果。
已更新:
public void addFlyout()
{
try {
LayoutInflater inflater = TabActivity.this.getLayoutInflater();
Display display = getWindowManager().getDefaultDisplay();
Method mGetRawH = Display.class.getMethod("getRawHeight");
Method mGetRawW = Display.class.getMethod("getRawWidth");
int rawHeight = (Integer) mGetRawH.invoke(display);
View view = inflater.inflate(R.layout.flyout_list_layout,
(ViewGroup) findViewById(R.id.flyoutLayoutList));
Dialog dialog = new Dialog(TabActivity.this);
pwindo = new PopupWindow(view, 340, rawHeight- actionBar.getHeight(), true);
pwindo.showAtLocation(view, Gravity.RIGHT | Gravity.TOP, 0, actionBar.getHeight());
pwindo.setBackgroundDrawable(new ColorDrawable(Color.RED));
// pwindo.setTouchable(true);
pwindo.setOutsideTouchable(true);
pwindo.setTouchInterceptor(new View.OnTouchListener() {
@Override public boolean onTouch(View v, MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_OUTSIDE)
{
pwindo.dismiss();
//Log.e(TAG, "some event happened outside window: action outside");
return true;
}
// Log.e(TAG, "some event happened outside window");
return false;
}
});
listFlyout = (ListView) view.findViewById(R.id.list_slideList);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(TabActivity.this, R.layout.drawer_item, R.id.content, tabs);
listFlyout.setAdapter(adapter);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
和
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
try {
if(tab.getPosition() == 4)
{
addFlyout();
}
else
mViewPager.setCurrentItem(tab.getPosition());
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
您可以使用 dialog.setCanceledOnTouchOutside(true);
,如果您触摸 Dialog
的外部,它会关闭 Dialog
。
类似于:
Dialog dialog = new Dialog(context)
dialog.setCanceledOnTouchOutside(true);
对于弹出 windows:
popupWindow.setOutsideTouchable(true);
popupWindow.setTouchable(true);
popupWindow.setBackgroundDrawable(new BitmapDrawable());
popupWindow.setTouchInterceptor(new OnTouchListener() { @Override
public boolean onTouch(View v, MotionEvent event) {
if(AppContext.isDebugMode()) {
Log.d("POPUP_WINDOW", "v: "+v.getTag() + " | event: "+event.getAction());
popupWindow.dismiss();
return true;
}
});
}
尝试使用下面的代码。
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Inflate the view from a predefined XML layout
View layout = inflater.inflate(R.layout.test, (ViewGroup) findViewById(R.id.linearLayout));
pw = new PopupWindow(layout, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, true);
pw.setOutsideTouchable(true);
pw.setBackgroundDrawable(new ShapeDrawable());
pw.setTouchInterceptor(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// here I want to close the pw when clicking outside it but
// at all this is just an example of how it works and you can
// implement the onTouch() or the onKey() you want
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
pw.dismiss();
return true;
}
return false;
}
});
pw.showAtLocation(layout, Gravity.CENTER, 0, 0);
在 PopupWindow
上设置背景可确保在其范围外单击可将其关闭。
showAtLocation(...)
:
public void showAtLocation(IBinder token, int gravity, int x, int y) {
....
preparePopup(p);
....
}
preparePopup(...)
检查是否设置了背景。如果是,您传递的内容视图(在构造函数中)将添加到自定义 FrameLayout
。然后在这个自定义 FrameLayout
:
if (mBackground != null) {
....
// when a background is available, we embed the content view
// within another view that owns the background drawable
PopupViewContainer popupViewContainer = new PopupViewContainer(mContext);
PopupViewContainer.LayoutParams listParams = new PopupViewContainer.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, height
);
popupViewContainer.setBackground(mBackground);
popupViewContainer.addView(mContentView, listParams);
....
} else {
....
}
由于您在 setBackgroundDrawable(...)
showAtLocation(...)
之后调用,preparePopup(...)
不会将内容视图放在 PopupViewContainer
中。
PopupViewContainer
还覆盖 onTouchEvent(...)
以提供 'dismissed-when-touched-outside' 行为:
@Override
public boolean onTouchEvent(MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
if ((event.getAction() == MotionEvent.ACTION_DOWN)
&& ((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) {
dismiss();
return true;
} else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
dismiss();
return true;
} else {
return super.onTouchEvent(event);
}
}
显然,您只需要提供背景,并在调用 showAtLocation(...)
之前提供。
有效:
popup.setFocusable(false);
popup.setTouchable(true);
popup.setOutsideTouchable(false);
popup.setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));