Comment régler la largeur et la hauteur de DialogFragment?
je spécifie la disposition de mon fragment de dialogue dans un fichier de mise en page xml (appelons-le layout_mydialogfragment.xml
), et ses attributs layout_width
et layout_height
en particulier (pour être 100dp
chaque disons). Je gonfle alors cette disposition dans la méthode de mon DialogFragment onCreateView(...)
comme suit:
View view = inflater.inflate(R.layout.layout_mydialogfragment, container, false);
malheureusement, je constate que lorsque ma boîte de dialogue (DialogFragment) apparaît, elle ne respecte pas les layout_width
et layout_height
spécifiés dans son fichier de mise en page xml. (et mon dialogue se rétrécit ou se développe de façon variable selon le contenu). Quelqu'un sait si ou comment je peux obtenir mon dialogue pour respecter les layout_width
et layout_height
spécifiés dans son fichier de mise en page xml? Pour le moment, je dois à nouveau spécifier la largeur et la hauteur de mon dialogue dans la méthode onResume()
de My DialogFragment comme suit...
getDialog().getWindow().setLayout(width, height);
... Et donc, de manière indésirable, doivent se rappeler de faire tout changement futur à la largeur et à la hauteur du dialogue dans deux endroits.
22 réponses
si vous convertissez directement les valeurs des ressources:
int width = getResources().getDimensionPixelSize(R.dimen.popup_width);
int height = getResources().getDimensionPixelSize(R.dimen.popup_height);
getDialog().getWindow().setLayout(width, height);
alors spécifiez match_parent dans votre mise en page pour la boîte de dialogue:
android:layout_width="match_parent"
android:layout_height="match_parent"
vous n'avez qu'à vous soucier d'un seul endroit (placez-le dans votre DialogFragment#onResume
). Ce n'est pas parfait, mais au moins cela fonctionne pour avoir une sortie relative comme la racine du fichier de mise en page de votre dialogue.
j'ai fini par dépasser Fragment.onResume()
et saisir les attributs de la boîte de dialogue sous-jacente, puis paramétrer les paramètres de largeur/hauteur. J'ai réglé la hauteur/largeur de la disposition extérieure à match_parent
. Notez que ce code semble respecter les marges que j'ai définies dans la mise en page xml.
@Override
public void onResume() {
super.onResume();
ViewGroup.LayoutParams params = getDialog().getWindow().getAttributes();
params.width = LayoutParams.MATCH_PARENT;
params.height = LayoutParams.MATCH_PARENT;
getDialog().getWindow().setAttributes((android.view.WindowManager.LayoutParams) params);
}
j'ai obtenu un DialogFragment de taille fixe définissant ce qui suit dans le schéma principal XML (LinearLayout dans mon cas):
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="1000dp"
android:minHeight="450dp"
la seule chose qui a fonctionné dans mon cas était la solution indiquée ici: http://adilatwork.blogspot.mx/2012/11/android-dialogfragment-dialog-sizing.html
extrait d'un billet du blog Adil:
@Override
public void onStart()
{
super.onStart();
// safety check
if (getDialog() == null)
return;
int dialogWidth = ... // specify a value here
int dialogHeight = ... // specify a value here
getDialog().getWindow().setLayout(dialogWidth, dialogHeight);
// ... other stuff you want to do in your onStart() method
}
une façon de contrôler la largeur et la hauteur de votre DialogFragment
est de s'assurer que son dialogue respecte la largeur et la hauteur de votre vue si leur valeur est WRAP_CONTENT
.
utilisant ThemeOverlay.AppCompat.Dialog
une façon simple d'y parvenir est de faire usage du style ThemeOverlay.AppCompat.Dialog
qui est inclus dans la bibliothèque de Soutien Android.
DialogFragment
avec Dialog
:
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = LayoutInflater.from(getContext());
View view = inflater.inflate(R.layout.dialog_view, null);
Dialog dialog = new Dialog(getContext(), R.style.ThemeOverlay_AppCompat_Dialog);
dialog.setContentView(view);
return dialog;
}
DialogFragment
avec AlertDialog
(mise en garde: minHeight="48dp"
):
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = LayoutInflater.from(getContext());
View view = inflater.inflate(R.layout.dialog_view, null);
AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), R.style.ThemeOverlay_AppCompat_Dialog);
builder.setView(view);
return builder.create();
}
vous pouvez également définir ThemeOverlay.AppCompat.Dialog
comme thème par défaut lors de la création de vos dialogues, en l'ajoutant au thème xml de votre application.
soyez prudent, car de nombreux dialogues ont besoin de la largeur minimale par défaut pour bien paraître.
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- For Android Dialog. -->
<item name="android:dialogTheme">@style/ThemeOverlay.AppCompat.Dialog</item>
<!-- For Android AlertDialog. -->
<item name="android:alertDialogTheme">@style/ThemeOverlay.AppCompat.Dialog</item>
<!-- For AppCompat AlertDialog. -->
<item name="alertDialogTheme">@style/ThemeOverlay.AppCompat.Dialog</item>
<!-- Other attributes. -->
</style>
DialogFragment
avec Dialog
, en utilisant android:dialogTheme
:
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = LayoutInflater.from(getContext());
View view = inflater.inflate(R.layout.dialog_view, null);
Dialog dialog = new Dialog(getContext());
dialog.setContentView(view);
return dialog;
}
DialogFragment
avec AlertDialog
, en utilisant android:alertDialogTheme
ou alertDialogTheme
(mise en garde: minHeight="48dp"
):
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = LayoutInflater.from(getContext());
View view = inflater.inflate(R.layout.dialog_view, null);
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setView(view);
return builder.create();
}
Bonus
sur les API Android plus anciennes, Dialog
s semblent avoir quelques problèmes de largeur, en raison de leur titre (même si vous ne mettez pas un).
Si vous ne souhaitez pas utiliser ThemeOverlay.AppCompat.Dialog
style et votre Dialog
n'a pas besoin d'un titre (ou personnalisé), vous pouvez le désactiver:
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = LayoutInflater.from(getContext());
View view = inflater.inflate(R.layout.dialog_view, null);
Dialog dialog = new Dialog(getContext());
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(view);
return dialog;
}
réponse périmée, ne fonctionnera pas dans la plupart des cas
j'essayais de faire en sorte que le dialogue respecte la largeur et la hauteur de ma mise en page, sans spécifier une taille fixe de façon programmatique.
I j'ai pensé que android:windowMinWidthMinor
et android:windowMinWidthMajor
étaient à l'origine du problème. Bien qu'ils n'aient pas été inclus dans le thème de mon Activity
ou Dialog
, ils étaient encore appliqués au thème Activity
, d'une manière ou d'une autre.
j'ai proposé trois solutions possibles.
Solution 1: créez un thème de dialogue personnalisé et utilisez-le lors de la création du dialogue dans le DialogFragment
.
<style name="Theme.Material.Light.Dialog.NoMinWidth" parent="android:Theme.Material.Light.Dialog">
<item name="android:windowMinWidthMinor">0dip</item>
<item name="android:windowMinWidthMajor">0dip</item>
</style>
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new Dialog(getActivity(), R.style.Theme_Material_Light_Dialog_NoMinWidth);
}
Solution 2: créer un thème personnalisé pour être utilisé dans un ContextThemeWrapper
qui servira de Context
pour le dialogue. Utilisez ceci si vous ne voulez pas créer un thème de dialogue personnalisé (par exemple, lorsque vous voulez utiliser le thème spécifié par android:dialogTheme
).
<style name="Theme.Window.NoMinWidth" parent="">
<item name="android:windowMinWidthMinor">0dip</item>
<item name="android:windowMinWidthMajor">0dip</item>
</style>
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new Dialog(new ContextThemeWrapper(getActivity(), R.style.Theme_Window_NoMinWidth), getTheme());
}
Solution 3 (avec un AlertDialog
): appliquer android:windowMinWidthMinor
et android:windowMinWidthMajor
dans le ContextThemeWrapper
créé par le AlertDialog$Builder
.
<style name="Theme.Window.NoMinWidth" parent="">
<item name="android:windowMinWidthMinor">0dip</item>
<item name="android:windowMinWidthMajor">0dip</item>
</style>
@Override
public final Dialog onCreateDialog(Bundle savedInstanceState) {
View view = new View(); // Inflate your view here.
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(view);
// Make sure the dialog width works as WRAP_CONTENT.
builder.getContext().getTheme().applyStyle(R.style.Theme_Window_NoMinWidth, true);
return builder.create();
}
Gotcha N ° 13: DialogFragment
Mises En Page
c'est un peu engourdissant.
lors de la création d'un DialogFragment
, vous pouvez choisir de remplacer onCreateView
(qui passe un ViewGroup
pour attacher votre .xml layout to) ou onCreateDialog
, ce qui n'est pas le cas.
vous ne devez pas outrepasser les deux méthodes tho, parce que vous allez très probablement confondre Android quand ou si la mise en page de votre dialogue a été gonflée! WTF?
Le choix de remplacer OnCreateDialog
ou OnCreateView
dépend de la façon dont vous avez l'intention d'utiliser la boîte de dialogue.
- si vous lancez le dialogue dans une fenêtre (le comportement normal), vous devez remplacer
OnCreateDialog
. - si vous avez l'intention d'intégrer le fragment de dialogue dans une configuration existante de L'interface utilisateur (beaucoup moins courante), alors vous devez remplacer
OnCreateView
.
c'est probablement la pire chose au monde.
"151980920 la" Folie
donc, vous supprimez onCreateDialog
dans votre DialogFragment
pour créer une instance personnalisée de AlertDialog
à afficher dans une fenêtre. Cool. Mais rappelez-vous, onCreateDialog
ne reçoit pas ViewGroup
pour attacher votre coutume .layout xml à . Pas de problème, il vous suffit de passer null
à la méthode inflate
.
que la folie commence.
Lorsque vous remplacez onCreateDialog
Android IGNORE COMPLÈTEMENT plusieurs attributs du nœud racine de l' .la mise en page xml que vous gonflez. Cela inclut, mais n'est probablement pas limité à:
-
background_color
-
layout_gravity
-
layout_width
-
layout_height
c'est presque comique, comme vous êtes tenus de mettre le
layout_width
etlayout_height
de chaque .xml Layout ou Android Studio vous giflera avec un joli petit badge rouge de honte.
juste le mot DialogFragment
me donne envie de vomir. Je pourrais écrire un roman rempli D'Androïde gotchas et de snafus, mais celui-ci est l'un des plus insidieux.
pour revenir À la santé mentale, la première, nous déclarons un style pour restaurer juste le background_color
et layout_gravity
nous attendons:
<style name="MyAlertDialog" parent="Theme.AppCompat.Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:layout_gravity">center</item>
</style>
le style ci-dessus hérite du thème de base pour les dialogues (dans le thème AppCompat
dans cet exemple).
ensuite, nous appliquer le style programmatique pour remettre les valeurs Android vient de jeter de côté et de restaurer la norme AlertDialog
look and feel:
public class MyDialog extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
View layout = getActivity().getLayoutInflater().inflate(R.layout.my_dialog_layout, null, false);
assert layout != null;
//build the alert dialog child of this fragment
AlertDialog.Builder b = new AlertDialog.Builder(getActivity());
//restore the background_color and layout_gravity that Android strips
b.getContext().getTheme().applyStyle(R.style.MyAlertDialog, true);
b.setView(layout);
return b.create();
}
}
le code ci-dessus votre AlertDialog
ressemblera à nouveau à un AlertDialog
. Peut-être que ce est assez bon.
mais attendez, il y a plus!
si vous cherchez à définir un spécifique layout_width
ou layout_height
pour votre AlertDialog
quand il est montré (très probable), alors devinez quoi, vous n'avez pas encore fait!
l'hilarité continue alors que vous réalisez que si vous tentez de définir un layout_width
ou layout_height
dans votre nouveau style de fantaisie, Android va complètement ignorer cela, aussi!:
<style name="MyAlertDialog" parent="Theme.AppCompat.Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:layout_gravity">center</item>
<!-- NOPE!!!!! --->
<item name="android:layout_width">200dp</item>
<!-- NOPE!!!!! --->
<item name="android:layout_height">200dp</item>
</style>
pour définir une largeur ou une hauteur de fenêtre spécifique, vous obtenez de la tête sur un tout 'méthode de la lettre et de traiter avec LayoutParams
:
@Override
public void onResume() {
super.onResume();
Window window = getDialog().getWindow();
if(window == null) return;
WindowManager.LayoutParams params = window.getAttributes();
params.width = 400;
params.height = 400;
window.setAttributes(params);
}
beaucoup de gens suivent le mauvais exemple D'Android de casting
WindowManager.LayoutParams
jusqu'à la plus généraleViewGroup.LayoutParams
, seulement pour tourner à droite autour et CastingViewGroup.LayoutParams
retour vers le bas àWindowManager.LayoutParams
quelques lignes plus tard. Java efficace soit damné, ce casting inutile n'offre rien d'autre que de rendre le code encore plus difficile à déchiffrer.Side note: Il ya une vingtaine de répétitions de
LayoutParams
à travers le SDK Android - un exemple parfait de conception radicalement mauvais.
En Résumé
pour DialogFragment
s qui remplacent onCreateDialog
:
- pour restaurer la norme
AlertDialog
look and feel de créer un style qui définitbackground_color
=transparent
etlayout_gravity
=center
et appliquez le styleonCreateDialog
. - pour définir un spécifique
layout_width
et / oulayout_height
, le faire programmatiquement dansonResume
avecLayoutParams
- pour maintenir la santé mentale, essayez de ne pas penser au SDK Android.
quand j'ai besoin de rendre le fragment de dialogue un peu plus large, je règle minWidth:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="320dp"
... />
la dimension dans la mise en page la plus externe ne fonctionne pas dans le dialogue. Vous pouvez ajouter une mise en page où placer la dimension au-dessous de l'extérieur.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="xxdp"
android:layout_height="xxdp"
android:orientation="vertical">
</LinearLayout>
Je l'ai fixé en réglant les paramètres de mise en page de l'élément racine.
int width = activity.getResources().getDisplayMetrics().widthPixels;
int height = activity.getResources().getDisplayMetrics().heightPixels;
content.setLayoutParams(new LinearLayout.LayoutParams(width, height));
Voici une façon de définir la largeur/hauteur du fragment en xml. Il suffit d'envelopper votre viewHierarchy dans un Framelayout (n'importe quelle mise en page fonctionnera) avec un fond transparent.
un fond transparent semble être un drapeau spécial, car il Centre automatiquement l'enfant de frameLayout dans la fenêtre lorsque vous faites cela. Vous obtiendrez toujours le plein écran assombrissement derrière votre fragment, en indiquant votre fragment est l'élément actif.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/transparent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="@color/background_material_light">
.....
vous pouvez utiliser le pourcentage pour la largeur.
<style name="Theme.Holo.Dialog.MinWidth">
<item name="android:windowMinWidthMajor">70%</item>
j'ai utilisé le thème Holo pour cet exemple.
je crée le dialogue en utilisant AlertDialog.Donc J'ai utilisé la réponse de Rodrigo dans un OnShowListener.
dialog.setOnShowListener(new OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics ();
display.getMetrics(outMetrics);
dialog.getWindow().setLayout((int)(312 * outMetrics.density), (int)(436 * outMetrics.density));
}
});
travaillant sur Android 6.0, a rencontré le même problème. AlertDialog
serait par défaut à prédéfinie width
défini dans le thème indépendamment de la réelle width
défini dans la racine de la vue personnalisée Layout
. J'ai pu le faire régler correctement en réglant le width
du loading_message
TextView
. Sans chercher plus loin, il semble que le dimensionnement des éléments réels et ayant la racine Layout
envelopper les fait fonctionner comme prévu. Vous trouverez ci-dessous une mise en page XML de un dialogue de chargement qui définit width
de la boîte de dialogue correctement. En utilisant le cette bibliothèque pour l'animation.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/custom_color"
android:padding="@dimen/custom_dimen">
<com.github.rahatarmanahmed.cpv.CircularProgressView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/progress_view"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_centerHorizontal="true"
app:cpv_color="@color/white"
app:cpv_animAutostart="true"
app:cpv_indeterminate="true" />
<TextView
android:id="@+id/loading_message"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_below="@+id/progress_view"
android:layout_centerHorizontal="true"
android:gravity="center"
android:textSize="18dp"
android:layout_marginTop="@dimen/custom_dimen"
android:textColor="@color/white"
android:text="@string/custom_string"/>
</RelativeLayout>
vous pouvez ci-dessous le code pour définir la largeur et la hauteur de la disposition de java.
final AlertDialog alertDialog = alertDialogBuilder.create();
final WindowManager.LayoutParams WMLP = alertDialog.getWindow().getAttributes();
WMLP.gravity = Gravity.TOP;
WMLP.y = mActionBarHeight;
WMLP.x = getResources().getDimensionPixelSize(R.dimen.unknown_image_width);
alertDialog.getWindow().setAttributes(WMLP);
alertDialog.show();
dans mon cas, il a été causé par align_parentBottom="true"
donné à une vue à l'intérieur d'un RelativeLayout
. Suppression de tous les alignparentbottom's et modification de toutes les mises en page à la verticale Linéairelayouts et problème disparu.
définit le layout Parent du LAYOUT de dialogue personnalisé à RelativeLayout , obtenir la largeur commune et la hauteur automatiquement .
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
facile et solide:
@Override
public void onResume() {
// Sets the height and the width of the DialogFragment
int width = ConstraintLayout.LayoutParams.MATCH_PARENT;
int height = ConstraintLayout.LayoutParams.MATCH_PARENT;
getDialog().getWindow().setLayout(width, height);
super.onResume();
}
C'est la solution la plus simple
la meilleure solution que j'ai trouvée est de remplacer onCreateDialog()
par onCreateView()
. setContentView () définira les dimensions correctes de la fenêtre avant de la gonfler. Il supprime le besoin de stocker/définir une dimension, couleur de fond, style, etc dans les fichiers de ressources et de les définir manuellement.
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = new Dialog(getActivity());
dialog.setContentView(R.layout.fragment_dialog);
Button button = (Button) dialog.findViewById(R.id.dialog_button);
// ...
return dialog;
}
l'Une des premières solutions a presque fonctionné. J'ai essayé quelque chose de légèrement différent et ça a fini par marcher pour moi.
(assurez-vous de regarder sa solution) C'était sa solution.. Cliquez Ici Il a fonctionné sauf pour: constructeur.getContext ().getTheme ().applyStyle (R. style.Theme_Window_NoMinWidth, true);
Je l'ai changé en
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get layout inflater
LayoutInflater layoutInflater = getActivity().getLayoutInflater();
// Set layout by setting view that is returned from inflating the XML layout
builder.setView(layoutInflater.inflate(R.layout.dialog_window_layout, null));
AlertDialog dialog = builder.create();
dialog.getContext().setTheme(R.style.Theme_Window_NoMinWidth);
la dernière ligne est ce qui est vraiment différent.
@Override
public void onStart() {
super.onStart();
Dialog dialog = getDialog();
if (dialog != null)
{
dialog.getWindow().setLayout(-1, -2);
dialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation;
Window window = getDialog().getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.dimAmount = 1.0f;
window.setAttributes(params);
window.setBackgroundDrawableResource(android.R.color.transparent);
}
}
Je ne vois pas de raison impérieuse pour outrepasser onResume
ou onStart
pour définir la largeur et la hauteur du Window
dans DialogFragment
's Dialog
-- ces méthodes de cycle de vie particulières peuvent être appelées et exécuter inutilement que redimensionner le code plus d'une fois en raison de choses comme le changement de fenêtre multiple, backgrounding puis foregrounding l'application, et ainsi de suite. Les conséquences de cette répétition sont assez insignifiantes, mais pourquoi s'en contenter?
le réglage de la largeur / hauteur à la place dans une méthode onActivityCreated()
dépassée sera une amélioration parce que cette méthode n'est appelée qu'une fois par instance de votre DialogFragment
. Par exemple:
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Window window = getDialog().getWindow();
assert window != null;
WindowManager.LayoutParams layoutParams = window.getAttributes();
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
window.setAttributes(layoutParams);
}
au-dessus, j'ai juste réglé la largeur à match_parent
quelle que soit l'orientation du dispositif. Si vous voulez que votre dialogue paysage ne soit pas aussi large, vous pouvez vérifier si getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT
à l'avance.
pour obtenir une boîte de dialogue qui couvre presque tout le Screen: d'abord définir une classe ScreenParameter
public class ScreenParameters
{
public static int Width;
public static int Height;
public ScreenParameters()
{
LayoutParams l = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
Width= l.width;
Height = l.height;
}
}
alors vous devez appeler le ScreenParamater avant votre getDialog.getWindow ().méthode de setLayout () 151930920"
@Override
public void onResume()
{
super.onResume();
ScreenParameters s = new ScreenParameters();
getDialog().getWindow().setLayout(s.Width , s.Height);
}