我有一个
DialogFragment
来展示一个像弹出屏幕一样的View
。
窗口总是出现在屏幕的中间。
是否有一种方法可以设置DialogFragment
窗口的位置?
我已经查看了源代码,但尚未找到任何内容。DialogFragment
来展示一个像弹出屏幕一样的View
。
窗口总是出现在屏幕的中间。
是否有一种方法可以设置DialogFragment
窗口的位置?
我已经查看了源代码,但尚未找到任何内容。尝试像这样:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
getDialog().getWindow().setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP);
WindowManager.LayoutParams p = getDialog().getWindow().getAttributes();
p.width = ViewGroup.LayoutParams.MATCH_PARENT;
p.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE;
p.x = 200;
...
getDialog().getWindow().setAttributes(p);
...
或者使用getDialog().getWindow()
的其他方法。
调用set-content
后,请务必设置位置。
没错,在这个问题上我花了一两个小时的时间撞墙,最后终于把DialogFragment
放在了我想要的位置。
我正在借鉴Steelight的回答。这是我找到的最简单、最可靠的方法。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle b) {
Window window = getDialog().getWindow();
// set "origin" to top left corner, so to speak
window.setGravity(Gravity.TOP|Gravity.LEFT);
// after that, setting values for x and y works "naturally"
WindowManager.LayoutParams params = window.getAttributes();
params.x = 300;
params.y = 100;
window.setAttributes(params);
Log.d(TAG, String.format("Positioning DialogFragment to: x %d; y %d", params.x, params.y));
}
注意,params.width
和params.softInputMode
(在Steelight的答案中使用)与此无关。
下面是一个更完整的示例。我真正需要的是将“确认框”DialogFragment与“源”或“父”视图对齐,在我的情况下是一个ImageButton。
我选择使用DialogFragment而不是任何自定义Fragment,因为它免费提供“对话框”功能(当用户在其外部单击时关闭对话框等)。
上面是“源”ImageButton(垃圾桶)的示例ConfirmBox
/**
* A custom DialogFragment that is positioned above given "source" component.
*
* @author Jonik, https://dev59.com/Dmkw5IYBdhLWcg3ws873#20419231
*/
public class ConfirmBox extends DialogFragment {
private View source;
public ConfirmBox() {
}
public ConfirmBox(View source) {
this.source = source;
}
public static ConfirmBox newInstance(View source) {
return new ConfirmBox(source);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NO_FRAME, R.style.Dialog);
}
@Override
public void onStart() {
super.onStart();
// Less dimmed background; see https://dev59.com/cWYr5IYBdhLWcg3wQYFa
Window window = getDialog().getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.dimAmount = 0.2f; // dim only a little bit
window.setAttributes(params);
// Transparent background; see https://dev59.com/ZWUp5IYBdhLWcg3w1qMi
// (Needed to make dialog's alpha shadow look good)
window.setBackgroundDrawableResource(android.R.color.transparent);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Put your dialog layout in R.layout.view_confirm_box
View view = inflater.inflate(R.layout.view_confirm_box, container, false);
// Initialise what you need; set e.g. button texts and listeners, etc.
// ...
setDialogPosition();
return view;
}
/**
* Try to position this dialog next to "source" view
*/
private void setDialogPosition() {
if (source == null) {
return; // Leave the dialog in default position
}
// Find out location of source component on screen
// see https://dev59.com/uHA65IYBdhLWcg3wzyH8#6798093
int[] location = new int[2];
source.getLocationOnScreen(location);
int sourceX = location[0];
int sourceY = location[1];
Window window = getDialog().getWindow();
// set "origin" to top left corner
window.setGravity(Gravity.TOP|Gravity.LEFT);
WindowManager.LayoutParams params = window.getAttributes();
// Just an example; edit to suit your needs.
params.x = sourceX - dpToPx(110); // about half of confirm button size left of source view
params.y = sourceY - dpToPx(80); // above source view
window.setAttributes(params);
}
public int dpToPx(float valueInDp) {
DisplayMetrics metrics = getActivity().getResources().getDisplayMetrics();
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);
}
}
通过添加构造函数参数或必要的setter方法,可以很容易地使上述更普适化。(我的最终ConfirmBox
有一个样式化的按钮(在一些边框内等),其文本和View.OnClickListener
可以在代码中自定义。)
source
按钮(下面是要显示对话框片段的位置)在屏幕方向改变时位置会发生变化,因此在更改方向时,对话框片段不会根据source
的位置更新位置。您能否给我一些提示如何解决这个问题? - Doryandroid.support.v7.app.AppCompatDialogFragment
中的AppCompatDialogFragment
,我想将对话框片段与屏幕底部对齐,并删除所有边框,特别是我需要设置内容宽度以匹配父级。以上的解决方案都没有起作用。所以,我做了这个:
fun AppCompatDialogFragment.alignToBottom() {
dialog.window.apply {
setGravity(Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL)
decorView.apply {
// Get screen width
val displayMetrics = DisplayMetrics().apply {
windowManager.defaultDisplay.getMetrics(this)
}
setBackgroundColor(Color.WHITE) // I don't know why it is required, without it background of rootView is ignored (is transparent even if set in xml/runtime)
minimumWidth = displayMetrics.widthPixels
setPadding(0, 0, 0, 0)
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
invalidate()
}
}
}
dialog?.window?.setLayout(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT)
。 - Mikhail Sharin@Override
public void onResume() {
final Window dialogWindow = getDialog().getWindow();
WindowManager.LayoutParams lp = dialogWindow.getAttributes();
lp.x = 100; // set your X position here
lp.y = 200; // set your Y position here
dialogWindow.setAttributes(lp);
super.onResume();
}
Window window = getDialog().getWindow();
// 将“原点”设置为左上角
window.setGravity(Gravity.TOP|Gravity.LEFT);
如果您不设置原点,则x和y位置将相对于屏幕中心。 - Kenneth ArgogetDialog().getWindow()
在使用DialogFragment
时不起作用,因为如果托管的活动不可见,getWindow()
将返回null,而在基于片段的应用程序中,它是不可见的。尝试调用getAttributes()
时,您将收到一个NullPointerException
。DialogFragment
类,那么切换不会太难。只需用构造并返回PopupWindow
的方法替换onCreateDialog
方法即可。然后,您应该能够重用供给AlertDialog.builder.setView()
的视图,并调用(PopupWindow object).showAtLocation()
。PopupWindow
在旋转时会发生内存泄漏,而操作系统会为我们处理 DialogFragment
。 - zaitsman如果有人想要将对话框移到屏幕底部并使其全宽,这是我的解决方案:
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// the content
final RelativeLayout root = new RelativeLayout(getActivity());
root.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
// creating the fullscreen dialog
final Dialog dialog = new Dialog(getActivity());
Window dialogWindow = dialog.getWindow();
dialog.setContentView(root);
dialogWindow.setBackgroundDrawable(new ColorDrawable(Color.WHITE));
WindowManager.LayoutParams params = dialogWindow.getAttributes();
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
dialogWindow.setAttributes(params);
dialogWindow.setGravity(Gravity.BOTTOM);
return dialog;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = new Dialog(mActivity, R.style.BottomDialog);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); //
dialog.setContentView(R.layout.layout_video_live);
dialog.setCanceledOnTouchOutside(true);
Window window = dialog.getWindow();
assert window != null;
WindowManager.LayoutParams lp = window.getAttributes();
lp.gravity = Gravity.BOTTOM; //psotion
lp.width = WindowManager.LayoutParams.MATCH_PARENT; // fuill screen
lp.height = 280;
window.setAttributes(lp);
return dialog;
}