J'ai un DialogFragment
pour montrer un View
comme un écran Popup. La fenêtre apparaît toujours au milieu de l'écran. Existe-t-il un moyen de définir la position de la fenêtre DialogFragment
? J'ai regardé dans le code source mais je n'ai encore rien trouvé.
Essayez quelque chose comme ceci:
@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);
...
ou d'autres méthodes pour getDialog().getWindow()
.
assurez-vous de définir la position après avoir appelé set-content.
À droite, je me suis cogné la tête contre le mur pendant une heure ou deux avec ça, avant de finalement mettre DialogFragment
positionné comme je le voulais.
Je m'appuie sur réponse de Steelight ici. C'est l'approche la plus simple et la plus fiable que j'ai trouvée.
@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));
}
Notez que params.width
et params.softInputMode
(utilisé dans la réponse de Steelight) n'est pas pertinent pour cela.
Voici un exemple plus complet. Ce dont j'avais vraiment besoin était d'aligner un DialogFragment de "boîte de confirmation" à côté d'une vue "source" ou "parent", dans mon cas un ImageButton.
J'ai choisi d'utiliser DialogFragment, au lieu de tout fragment personnalisé, car il vous offre gratuitement des fonctionnalités de "dialogue" (fermer la boîte de dialogue lorsque l'utilisateur clique en dehors de celui-ci, etc.).
Exemple ConfirmBox au-dessus de sa "source" ImageButton (corbeille)
/**
* 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'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://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);
}
}
Il est assez facile de rendre l'utilisation ci-dessus plus générale en ajoutant des paramètres de constructeur ou des setters si nécessaire. (Mon dernier ConfirmBox
a un bouton stylisé (à l'intérieur de certaines bordures, etc.) dont le texte et View.OnClickListener
peut être personnalisé dans le code.)
Vous devez remplacer la méthode onResume () dans votre DialogFragment comme suit:
@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();
}
getDialog().getWindow()
ne fonctionnera pas pour un DialogFragment
car getWindow()
renverra null si l'activité d'hébergement n'est pas visible, ce qui n'est pas le cas si vous écrivez un fragment- application basée. Vous obtiendrez un NullPointerException
lorsque vous essayez getAttributes()
.
Je recommande la réponse de Mobistry. Si vous avez déjà une classe DialogFragment, il n'est pas trop difficile de basculer. Remplacez simplement la méthode onCreateDialog par une méthode qui construit et renvoie un PopupWindow. Vous devriez alors être en mesure de réutiliser la vue que vous fournissez à AlertDialog.builder.setView()
, et d'appeler (PopupWindow object).showAtLocation()
.
J'utilise la classe PopupWindow à cet effet, car vous pouvez spécifier l'emplacement et la taille de la vue.
J'utilise AppCompatDialogFragment
de Android.support.v7.app.AppCompatDialogFragment
et je souhaite aligner le fragment de boîte de dialogue en bas de l'écran et également supprimer toutes les bordures, en particulier j'avais besoin de définir la largeur du contenu pour qu'elle corresponde au parent.
Donc, je voulais de cela (le fond jaune vient de rootLayout du fragment de dialogue):
Obtenez ceci:
Aucune des solutions ci-dessus n'a fonctionné. J'ai donc réussi à faire ceci:
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()
}
}
}
@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;
}