我想使用具有以下行为/功能的PopupWindow:
我发现了一些关于PopupWindow的帖子,但没有一个人质疑如何处理这种情况。
我想我尝试了setOutsideTouchable(),setFocusable(),setTouchable()的所有可能组合但是我被卡住了。 Popup正确地处理它的点击,但是当它在外面触摸时它总是被解雇。
我目前的代码是:
View.OnTouchListener customPopUpTouchListenr = new View.OnTouchListener(){
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
Log.d("POPUP", "Touch false");
return false;
}
};
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout layout= (LinearLayout)inflater.inflate(R.layout.insert_point_dialog, null);
PopupWindow pw = new PopupWindow(layout,400,200,true);
pw.setOutsideTouchable(true);
pw.setTouchable(true);
pw.setBackgroundDrawable(new BitmapDrawable());
pw.setTouchInterceptor(customPopUpTouchListenr);
pw.showAtLocation(frameLayout, Gravity.BOTTOM, 0, 0);
我的总体目标是创建一个浮动窗口,其行为类似于gimp等软件中的“工具调色板”:内部有一些控件,保持在顶部直到被“X”按钮关闭,并允许与外部控件进行交互它.. 也许有更好的方法来做到这一点,而不是PopupWindow?但我还是没有找到更合适的控制。
答案 0 :(得分:7)
现在为时已晚,但对于谷歌这些东西的人来说 只需更改行的顺序
pw.showAtLocation(frameLayout, Gravity.BOTTOM, 0, 0);
pw.setOutsideTouchable(true);
pw.setTouchable(true);
pw.setBackgroundDrawable(new BitmapDrawable());
pw.setTouchInterceptor(customPopUpTouchListenr);
而不是
pw.setOutsideTouchable(true);
pw.setTouchable(true);
pw.setBackgroundDrawable(new BitmapDrawable());
pw.setTouchInterceptor(customPopUpTouchListenr);
pw.showAtLocation(frameLayout, Gravity.BOTTOM, 0, 0);
在showatlocation方法之后放任何东西都会让它像什么
答案 1 :(得分:6)
只需删除pw.setBackgroundDrawable(new BitmapDrawable());
答案 2 :(得分:2)
pw.setOutsideTouchable(假);
答案 3 :(得分:2)
尝试
pw.setBackgroundDrawable(null);
答案 4 :(得分:2)
解决方案是:
popupWindow.setFocusable(真);
popupWindow.update();
感谢: http://android-er.blogspot.ch/2012/04/disable-outside-popupwindow-by.html
答案 5 :(得分:1)
首先,你必须弄明白当你触摸外面时popupWindow被解雇的原因。
阅读PopupWindow的源代码和资源文件styles.xml后,
if ($form->isValid()) {
$securePass = $this->getUsersTable()->getUserByUsername( $this->params()->fromPost('username') );
if( $securePass ){
$bcrypt = new Bcrypt();
if ($bcrypt->verify( $this->params()->fromPost( 'password' ) , $securePass->password ) ) {
$sm = $this->getServiceLocator();
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$authAdapter = new AuthAdapter(
$dbAdapter,
'users',
'username',
'password'
);
$authAdapter->setIdentity($securePass->username)
->setCredential($securePass->password);
$result = $authAdapter->authenticate($authAdapter);
$sesssionData = $authAdapter->getResultRowObject();
$auth = new AuthenticationService();
$storage = $auth->getStorage();
$storage->write($sesssionData);
return $this->redirect()->toRoute('user_list');
}
}
}
public function onBootstrap(MvcEvent $e)
{
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
$app = $e->getParam('application');
$app->getEventManager()->attach('render', array($this, 'setLayoutTitle'));
$eventManager->attach(MvcEvent::EVENT_DISPATCH, array($this, 'checkLogin'));
}
public function checkLogin(MvcEvent $e)
{
$iden = new AuthenticationService();
if( $iden->getIdentity() === NULL ){
$matches = $e->getRouteMatch();
$controller = $matches->getParam('controller');
$getController = explode( '\\', $controller );
if( isset( $getController[2] ) && $getController[2] != 'Login' ){
$controller = $e->getTarget();
return $controller->plugin('redirect')->toRoute('login');
}
}
}
所以没有像对话主题那样:
<style name="Widget.PopupWindow">
<item name="popupBackground">@drawable/editbox_dropdown_background_dark</item>
<item name="popupAnimationStyle">@style/Animation.PopupWindow</item>
</style>
<style name="Widget">
<item name="textAppearance">?textAppearance</item>
</style>
但是当调用PopupWindow.setBackgroundDrawable()时会发生某些事情,
<style name="Theme.Dialog">
<item name="windowCloseOnTouchOutside">@bool/config_closeDialogWhenTouchOutside</item>
</style name="Theme.Dialog">
容器视图&#34; PopupViewContainer&#34;已创建。
private void preparePopup(WindowManager.LayoutParams p) {
if (mContentView == null || mContext == null || mWindowManager == null) {
throw new IllegalStateException("You must specify a valid content view by "
+ "calling setContentView() before attempting to show the popup.");
}
if (mBackground != null) {
final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
int height = ViewGroup.LayoutParams.MATCH_PARENT;
if (layoutParams != null &&
layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
height = ViewGroup.LayoutParams.WRAP_CONTENT;
}
// 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.setBackgroundDrawable(mBackground);
popupViewContainer.addView(mContentView, listParams);
mPopupView = popupViewContainer;
} else {
mPopupView = mContentView;
}
mPopupViewInitialLayoutDirectionInherited =
(mPopupView.getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT);
mPopupWidth = p.width;
mPopupHeight = p.height;
}
}
现在你知道重要的原因了。 所以有两种方法可以让你在触摸外面后解除PopupWindow的解雇。 就像@Raaga那样。删除pw.setBackgroundDrawable(new BitmapDrawable());
答案 6 :(得分:0)
可以为PopupWindow
设置setFocusable(false)按钮仍然是可点击的,但没有可视点击行为(一些自定义处理程序强制显示点击?)
下面的是浮动窗口的示例,其中“always on top”选项
在浮动窗口附近的原始布局在两种情况下都是完全可操作的,而且,当窗口仍然浮动时,可以使用对话框和其他弹出窗口窗口也可以重复使用
final static int buttonAlpha = 0xDF;
final static float buttonTextSize = 12f;
public final void addPopupButton(LinearLayout linearLayout, String title, android.view.View.OnClickListener onClickListener)
{
Button button = new Button(this.getContext());
button.setText(title);
button.setTextSize(buttonTextSize);
button.getBackground().setAlpha(buttonAlpha);
button.setOnClickListener(onClickListener);
linearLayout.addView(button, LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
}
public final Button addPopupCheckbox(LinearLayout linearLayout, String title, boolean isChecked, android.view.View.OnClickListener onClickListener)
{
final Button button = new Button(getContext());
button.setText(title);
button.setTextSize(buttonTextSize);
final int buttonHeight = button.getHeight();
setButtonChecked(button, isChecked);
button.setHeight(buttonHeight);
button.getBackground().setAlpha(buttonAlpha);
button.setOnClickListener(onClickListener);
linearLayout.addView(button, LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
return button;
}
public final void setButtonChecked(Button button, boolean isChecked)
{
button.setCompoundDrawablesWithIntrinsicBounds(Resources.getSystem().getIdentifier(isChecked ? "android:drawable/btn_check_on" : "android:drawable/btn_check_off", null, null), 0, 0, 0);
}
private boolean isMenuAlwaysOnTop = true;
private PopupWindow popupWindowMenuV2 = null;
public final void popupMenuNav2()
{
if (popupWindowMenuV2 == null)
{
// [start] layout
ScrollView scrollView = new ScrollView(this.getContext());
final LinearLayout linearLayoutNavigation = new LinearLayout(this.getContext());
linearLayoutNavigation.setOrientation(LinearLayout.VERTICAL);
linearLayoutNavigation.setBackgroundColor(0x7FFFFFFF);
linearLayoutNavigation.setPadding(20, 10, 20, 10);
scrollView.addView(linearLayoutNavigation, LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
popupWindowMenuV2 = new PopupWindow(this);
popupWindowMenuV2.setBackgroundDrawable(new BitmapDrawable());
popupWindowMenuV2.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
popupWindowMenuV2.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
popupWindowMenuV2.setTouchable(true);
popupWindowMenuV2.setOutsideTouchable(!isMenuAlwaysOnTop);
popupWindowMenuV2.setFocusable(!isMenuAlwaysOnTop);
popupWindowMenuV2.setTouchInterceptor(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_OUTSIDE)
{
if (!isMenuAlwaysOnTop)
popupWindowMenuV2.dismiss();
else
return false;
return true;
}
return false;
}
});
popupWindowMenuV2.setContentView(scrollView);
// [end] layout
// [start] always on top checkbox
final Button buttonMenuAlwaysOnTop = addPopupCheckbox(linearLayoutNavigation, "always on top", isMenuAlwaysOnTop, null);
buttonMenuAlwaysOnTop.setOnClickListener(
new OnClickListener()
{
@Override
public void onClick(View vv)
{
isMenuAlwaysOnTop = !isMenuAlwaysOnTop;
setButtonChecked(buttonMenuAlwaysOnTop, isMenuAlwaysOnTop);
popupWindowMenuV2.dismiss();
popupWindowMenuV2.setOutsideTouchable(!isMenuAlwaysOnTop);
popupWindowMenuV2.setFocusable(!isMenuAlwaysOnTop);
popupWindowMenuV2.showAtLocation(((Activity) getContext()).getWindow().getDecorView(), Gravity.CENTER_VERTICAL + Gravity.RIGHT, 0, 0);
}
});
// [end] always on top checkbox
addPopupButton(linearLayoutNavigation, "some button",
new OnClickListener()
{
@Override
public void onClick(View vv)
{
if (!isMenuAlwaysOnTop)
popupWindowMenuV2.dismiss();
someAction();
}
});
}
popupWindowMenuV2.showAtLocation(((Activity) getContext()).getWindow().getDecorView(), Gravity.CENTER_VERTICAL + Gravity.RIGHT, 0, 0);
}
// somewhere in handler:
if (someCondition)
{
if (popupWindowMenuV2 != null && popupWindowMenuV2.isShowing())
popupWindowMenuV2.dismiss();
else
popupMenuNav2();
return true;
}
答案 7 :(得分:0)
这里或其他地方似乎没有任何建议对我有用。所以我这样做了:
popupWindow.setTouchInterceptor(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getX() < 0 || motionEvent.getX() > viewWidth) return true;
if (motionEvent.getY() < 0 || motionEvent.getY() > viewHight) return true;
return false;
}
});
如果触摸在popupWIndow的范围内,则不消耗触摸事件(因此按钮或滚动视图将起作用)。如果触摸超出范围,则触摸将被消耗并且不会传递给popupWindow,因此不会将其关闭。