У меня есть DialogFragment
, чтобы показать View
как всплывающее окно.
Окно появляется всегда посередине экрана.
Есть ли способ установить положение окна DialogFragment
?
Я просмотрел исходный код но ничего не смог найти.
Позиция DialogFragment в Android
Ответ 1
Попробуйте что-то вроде этого:
@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.
Ответ 2
Правильно, я ударил головой о стену в течение часа или двух с этим, прежде чем, наконец, получив 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) для этого не имеют значения.
Ниже приведен более полный пример. То, что мне действительно нужно, - выровнять флажок "подтвердить" диалогового окна "Диалоговое окно" рядом с "исходным" или "родительским" представлением, в моем случае - ImageButton.
Я решил использовать DialogFragment вместо любого пользовательского фрагмента, потому что он дает вам "диалоговые" функции бесплатно (закрывать диалог, когда пользователь щелкает за его пределами и т.д.).
Пример ConfirmBox над его "исходным" ImageButton (trashcan)
/**
* A custom DialogFragment that is positioned above given "source" component.
*
* @author Jonik, https://stackoverflow.com/a/20419231/56285
*/
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://stackoverflow.com/q/13822842/56285
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://stackoverflow.com/q/15007272/56285
// (Needed to make dialog 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://stackoverflow.com/a/6798093/56285
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);
}
}
Очень просто сделать вышеприведенное более общее использование, добавив параметры конструктора или сеттеры по мере необходимости. (Мой последний ConfirmBox
имеет стилизованную кнопку (внутри некоторых границ и т.д.), Текст которой и View.OnClickListener
можно настроить в коде.)
Ответ 3
getDialog().getWindow()
не будет работать для DialogFragment
, поскольку getWindow()
вернет значение null, если активность хоста не будет видна, а это не значит, что вы пишете приложение на основе фрагментов. Вы получите NullPointerException
при попытке getAttributes()
.
Я рекомендую ответ на Mobistry. Если у вас уже есть класс DialogFragment, его не так сложно переключить. Просто замените метод onCreateDialog тем, который создает и возвращает PopupWindow. Затем вы должны иметь возможность повторно использовать View, который вы поставляете, на AlertDialog.builder.setView()
и вызывать (PopupWindow object).showAtLocation()
.
Ответ 4
Я использую класс PopupWindow для этой цели, потому что вы можете указать местоположение и размер представления.
Ответ 5
Вам необходимо переопределить метод onResume() в вашем DialogFragment, как показано ниже:
@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();
}
Ответ 6
@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;
}
Ответ 7
Я использую AppCompatDialogFragment
из android.support.v7.app.AppCompatDialogFragment
и хочу выровнять фрагмент диалога по нижней части экрана, а также удалить все границы, особенно мне нужно было установить ширину содержимого в соответствии с родителем.
Итак, я хотел от этого (желтый фон происходит от rootLayout фрагмента диалога):
Взять это:
Ни одно из вышеуказанных решений не сработало. Итак, мне удалось сделать это:
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()
}
}
}