我的应用中有Fragment
,显示DialogFragment
我在片段中有一个关闭对话框的按钮。但是当我显示dialogFragment时,对话框外部的触摸什么都不做,我无法点击对话框片段外的按钮。
如何为DialogFragment提供外部触摸?
答案 0 :(得分:18)
为了做到这一点,应该打开允许外部触摸的Window
标志,并且为了良好的外观,应该清除背景暗淡标志。
由于必须在创建对话框后完成,因此我已通过Handler
实现了它。
@Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// This is done in a post() since the dialog must be drawn before locating.
getView().post(new Runnable() {
@Override
public void run() {
Window dialogWindow = getDialog().getWindow();
// Make the dialog possible to be outside touch
dialogWindow.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
getView().invalidate();
}
});
}
此时可以进行外部触摸。
如果我们想让它更好并且没有框架,可以添加以下代码:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Hide title of the dialog
setStyle(STYLE_NO_FRAME, 0);
}
答案 1 :(得分:4)
这是更通用的标志,允许任何动作不仅触及动作
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
答案 2 :(得分:1)
我找到了替代方法来处理外面的触摸。请检查以下代码示例,这肯定有用,
@Override
public void onStart() {
// mDialogView is member variable
mDialogView = getView();
mDialogView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
float eventX = event.getRawX();
float eventY = event.getRawY();
int location[] = new int[2];
mDialogView.getLocationOnScreen(location);
if (eventX < location[0] || eventX > (location[0] + mDialogView.getWidth()) || eventY < location[1]
|| eventY > location[1] + mDialogView.getHeight()) {
dismiss();
return true;
}
return false;
}
});
}
在我的情况下,我将getDialog()视为非null值,但是getDialog()。dismiss()无效。此外,标记为右上方的解决方案在我的情况下也不起作用。所以,我采用了这种方法。
答案 3 :(得分:1)
根据我上面的小调查,我真的认为这应该是公认的答案:
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
FragmentActivity act = getActivity();
AlertDialog.Builder builder = new AlertDialog.Builder(act);
// ... do your stuff here
Dialog dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
Window window = dialog.getWindow();
if( window!=null )
{
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
}
return dialog;
}
即将标志的设置移到onCreateDialog()的末尾,并添加setCancelOnTouchOutside(false)。
接受的答案不适用于运行Android 9和10(最有可能是11)的Samsung手机。看起来像在这些系统上,三星已经进行了一些更改,使得设置这些标志只能在设置得很早的情况下起作用。
以上方法适用于任何地方,包括Google模拟器,LG Nexus 5X,HTC Desire 12,Google Pixel 6,一些华为手机以及我测试过的所有(约20款)三星手机。
答案 4 :(得分:0)
答案 5 :(得分:0)
嗯,让我们具体一点。 如果你想使用外部视图,那么你不应该使用对话框片段,而是像这样使用片段。
FragmentTransaction transaction = fragmentManager.beginTransaction();
// For a little polish, specify a transition animation
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
// To make it fullscreen, use the 'content' root view as the container
// for the fragment, which is always the root view for the activity
transaction.add(android.R.id.content, newFragment)
.addToBackStack(null).commit();
制作布局wrap_content,显然看起来像Dialog,默认情况下它位于屏幕顶部。
有关详细信息,请访问here
答案 6 :(得分:0)
@yaniv提供了答案。但是,如果有需要,可以在以下代码段中获得相同的结果,但无需在根Runnable
上发布View
:
@NonNull
@Override
public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) {
final Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
return dialog;
}
答案 7 :(得分:-1)
我已经测试了接受的(Yaniv's)答案
Galaxy Tab A 9.7 Android 7.1.1: ok
Galaxy Tab A 8.0 Android 7 : ok
Galaxy Tab S4 Android 9 : no touch outside DialogFragment
Galaxy S5 Android 6.0.1 : ok
Galaxy Tab S2 Android 7 : ok
Galaxy Tab S3 Android 9 : no touch outside DialogFragment
Galaxy Tab S4 Android 9 : no touch outside DialogFragment
Galaxy Note Edge Android 6.0.1: ok
Galaxy Note4 Android 6.0.1 : ok
,实际上看起来它在Android 9上不起作用。当我说“不起作用”时,是指当我尝试单击DialogFragment之外的Button时,根本不会调用其onClick()方法。
编辑:根据我的发现(在评论中),我认为以下应该是可接受的答案。下面的代码在我测试过的所有地方都可以使用,包括模拟器,Google Pixel 6,LG Nexus 5X,HTC Desire 12,大约5部华为手机以及大约20部运行Android 5至10的三星手机。
public Dialog onCreateDialog(Bundle savedInstanceState)
{
FragmentActivity act = getActivity();
AlertDialog.Builder builder = new AlertDialog.Builder(act);
// ... do your stuff here....
Dialog dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
Window window = dialog.getWindow();
if( window!=null )
{
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
}
return dialog;
}