J'essaie de créer un DialogFragment
en utilisant une vue personnalisée dans un AlertDialog
. Cette vue doit être gonflée à partir de xml. Dans ma classe DialogFragment
, j'ai:
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
.setTitle("Title")
.setView(getActivity().getLayoutInflater().inflate(R.layout.dialog, null))
.setPositiveButton(Android.R.string.ok, this)
.setNegativeButton(Android.R.string.cancel, null)
.create();
}
J'ai essayé d'autres méthodes de gonflage pour .setView()
telles que:
.setView(getActivity().getLayoutInflater().inflate(R.layout.dialog, (ViewGroup) getView(), false))
et
.setView(getActivity().getLayoutInflater().inflate(R.layout.dialog, (ViewGroup) getTargetFragment().getView(), false))
Après avoir défini le fragment cible dans le fragment qui affiche cette boîte de dialogue.
Toutes ces tentatives pour gonfler ma vue personnalisée entraînent l'exception suivante:
E/AndroidRuntime(32352): Android.util.AndroidRuntimeException: requestFeature() must be called before adding content
E/AndroidRuntime(32352): at com.Android.internal.policy.impl.PhoneWindow.requestFeature(PhoneWindow.Java:214)
E/AndroidRuntime(32352): at com.Android.internal.app.AlertController.installContent(AlertController.Java:248)
E/AndroidRuntime(32352): at Android.app.AlertDialog.onCreate(AlertDialog.Java:314)
E/AndroidRuntime(32352): at Android.app.Dialog.dispatchOnCreate(Dialog.Java:335)
E/AndroidRuntime(32352): at Android.app.Dialog.show(Dialog.Java:248)
E/AndroidRuntime(32352): at Android.support.v4.app.DialogFragment.onStart(DialogFragment.Java:339)
E/AndroidRuntime(32352): at Android.support.v4.app.Fragment.performStart(Fragment.Java:1288)
E/AndroidRuntime(32352): at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:873)
E/AndroidRuntime(32352): at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:1041)
E/AndroidRuntime(32352): at Android.support.v4.app.BackStackRecord.run(BackStackRecord.Java:625)
E/AndroidRuntime(32352): at Android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.Java:1360)
E/AndroidRuntime(32352): at Android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.Java:411)
E/AndroidRuntime(32352): at Android.os.Handler.handleCallback(Handler.Java:587)
E/AndroidRuntime(32352): at Android.os.Handler.dispatchMessage(Handler.Java:92)
E/AndroidRuntime(32352): at Android.os.Looper.loop(Looper.Java:132)
E/AndroidRuntime(32352): at Android.app.ActivityThread.main(ActivityThread.Java:4028)
E/AndroidRuntime(32352): at Java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(32352): at Java.lang.reflect.Method.invoke(Method.Java:491)
E/AndroidRuntime(32352): at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:844)
E/AndroidRuntime(32352): at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:602)
E/AndroidRuntime(32352): at dalvik.system.NativeStart.main(Native Method)
Tandis que si j'essaie d'utiliser le DialogFragment
's getLayoutInflator(Bundle)
comme ceci:
.setView(getLayoutInflater(savedInstanceState).inflate(R.layout.dialog, null))
Je reçois un StackOverflowError
.
Est-ce que quelqu'un sait comment gonfler une vue personnalisée pour un AlertDialog
dans un DialogFragment
?
La première ligne d'erreur m'indique que cela est lié à la façon dont vous créez votre dialogue - pas au dialogue lui-même.
Créez-vous la boîte de dialogue automatiquement (ce qui pourrait signifier que cette option est appelée avant que toutes les vues soient configurées) ou en réponse à un clic de bouton? J'ai d'abord eu des problèmes avec les fragments en raison de l'ordre d'instanciation.
J'ai utilisé le même code pour définir la vue que vous avez, et mon résultat fonctionne. J'ai coupé l'autre configuration pour rendre ce look plus propre, mais cela fonctionne avec ou sans.
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_layout, null);
builder.setView(view);
return builder.create();
}
Je suis surpris par ces réponses car aucune d’entre elles ne résout le problème.
Un DialogFragment vous permet de réutiliser la même interface utilisateur à la fois pour un dialogue et de l'intégrer à votre application ailleurs en tant que fragment. Une fonctionnalité très utile. Selon la documentation de Google, vous pouvez y parvenir en remplaçant onCreateDialog et onCreateView . http://developer.Android.com/reference/Android/app/DialogFragment.html
Il y a trois scénarios ici:
Solution: La classe AlertDialog appelle une autre classe qui appelle requestFeature. Pour résoudre ce problème .. N'utilisez pas AlertDialog, utilisez plutôt un dialogue en clair ou tout autre retour de super.onCreateDialog. C'est la solution que j'ai trouvée qui fonctionne le mieux.
Avertissement: D'autres boîtes de dialogue telles que DatePickerDialog, ProgressDialog, TimePickerDialog héritent toutes de AlertDialog et provoqueront probablement la même erreur.
Bottom Line: DialogFragment est utile si vous devez créer une interface très personnalisée qui doit être utilisée à plusieurs endroits. Il ne semble pas fonctionner pour réutiliser les dialogues Android existants.
Evitez le crash de la fonctionnalité de demande et utilisez la même présentation:
public class MyCombinedFragment extends DialogFragment
{
private boolean isModal = false;
public static MyCombinedFragment newInstance()
{
MyCombinedFragment frag = new MyCombinedFragment();
frag.isModal = true; // WHEN FRAGMENT IS CALLED AS A DIALOG SET FLAG
return frag;
}
public MyCombinedFragment()
{
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
if(isModal) // AVOID REQUEST FEATURE CRASH
{
return super.onCreateView(inflater, container, savedInstanceState);
}
else
{
View view = inflater.inflate(R.layout.fragment_layout, container, false);
setupUI(view);
return view;
}
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
AlertDialog.Builder alertDialogBuilder = null;
alertDialogBuilder = new AlertDialog.Builder(getActivity());
View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_layout, null);
alertDialogBuilder.setView(view);
alertDialogBuilder.setTitle(“Modal Dialog“);
alertDialogBuilder.setPositiveButton("Cancel", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
dialog.dismiss();
}
});
setupUI(view);
return alertDialogBuilder.create();
}
}
J'ai eu le même problème. Dans mon cas, c'est parce qu'Android Studio a créé un modèle onCreateView qui a regonflé une nouvelle vue au lieu de renvoyer la vue créée dans onCreateDialog. onCreateView étant appelé après onCreateDialog, la solution consistait simplement à rétablir la vue des fragments.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return this.getView();
}
Comme j'avais besoin de beaucoup de temps pour résoudre le même problème (Ouvrir une boîte de dialogue texte simple), j'ai décidé de partager ma solution:
Le fichier de configuration connectivity_dialog.xml contient un simple TextView avec le texte du message:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:gravity="center"
Android:layout_gravity="center">
<TextView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_marginStart="20dp"
Android:layout_marginEnd="20dp"
Android:layout_marginTop="20dp"
Android:layout_marginBottom="20dp"
Android:text="Connectivity was lost"
Android:textSize="34sp"
Android:gravity="center"
/>
</RelativeLayout>
L'activité affichant le "dialogue" implémente une classe interne (DialogFragment étant un fragment et non un dialogue; pour plus d'informations, voir https://stackoverflow.com/a/5607560/6355541 ). L'activité peut activer et désactiver le DialogFragment via deux fonctions. Si vous utilisez Android.support.v4, vous souhaiterez peut-être utiliser getSupportFragmentManager ():
public static class ConnDialogFragment extends DialogFragment {
public static ConnDialogFragment newInstance() {
ConnDialogFragment cdf = new ConnDialogFragment();
cdf.setRetainInstance(true);
cdf.setCancelable(false);
return cdf;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.connectivity, container, false);
}
}
private void dismissConn() {
DialogFragment df = (DialogFragment) getFragmentManager().findFragmentByTag("conn");
if (df != null) df.dismiss();
}
private void showConn() {
FragmentTransaction ft = getFragmentManager().beginTransaction();
Fragment prev = getFragmentManager().findFragmentByTag("conn");
if (prev != null) ft.remove(prev);
ft.addToBackStack(null);
ConnDialogFragment cdf = ConnDialogFragment.newInstance();
cdf.show(ft, "conn");
}
Je n'ai pas gonflé à partir de XML mais j'ai réussi à générer une vue dynamique dans un DialogFragment:
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
m_editText = new EditText(getActivity());
return new AlertDialog.Builder(getActivity())
.setView(m_editText)
.setPositiveButton(Android.R.string.ok,null)
.setNegativeButton(Android.R.string.cancel, null);
.create();
}
Dans votre code où vous appelez
create().
Remplacer par
show().
Au lieu de cela, vous souhaitez créer votre vue personnalisée dans la méthode onCreateView comme vous le feriez normalement. Si vous voulez faire quelque chose comme changer le titre de la boîte de dialogue, faites-le dans onCreateView.
Voici un exemple pour illustrer ce que je veux dire:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
getDialog().setTitle("hai");
View v = inflater.inflate(R.layout.fragment_dialog, container, false);
return v;
}
Ensuite, vous appelez simplement:
DialogFragment df = new MyDialogFragment();
df.show(..);
Et voila, un dialogue avec votre propre vue personnalisée.