Problème gonflant vue personnalisée pour AlertDialog dans DialogFragment
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 d'inflation pour .setView()
tels 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 ce dialogue.
Toutes ces tentatives pour gonfler mon résultat de vue personnalisée dans 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.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)
Alors 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
?
9 réponses
la première ligne d'erreur me donne l'indication que ceci est lié à la façon dont vous créez votre Dialogue - pas le dialogue lui-même.
est-ce que vous créez le dialogue automatiquement (ce qui pourrait signifier que cela est appelé avant que les vues soient toutes configurées) ou en réponse à un clic de bouton? J'ai d'abord eu des problèmes avec des fragments à cause 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 découpé les autres installation pour rendre cette apparence plus propre, mais il fonctionne avec ou sans elle.
@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'elles ne résout le problème.
un fragment de dialogue vous permet de réutiliser le même UI pour un dialogue et intégré dans votre application ailleurs comme fragment. Tout à fait d'une fonctionnalité utile. Comme dans la documentation de google, vous pouvez y parvenir en outrepassant onCreateDialog et onCreateView. http://developer.android.com/reference/android/app/DialogFragment.html
il y a trois scénarios ici:
- Remplacer onCreateDialog uniquement - Fonctionne comme un dialogue, mais ne peut pas être intégrée ailleurs.
- outrepasser onreateview seulement - ne fonctionne pas comme une boîte de dialogue, mais peut être intégrée ailleurs.
- outrepasse les deux-fonctionne comme une boîte de dialogue et peut être intégré ailleurs.
Solution: La classe AlertDialog appelle une autre classe qui appelle requestFeature. Pour résoudre ce problème.. N'utilisez pas le AlertDialog, à la place utilisez un dialogue simple ou n'importe quel super.onCreateDialog retourne. C'est la solution que j'ai trouvée qui fonctionne le mieux.
mise en garde: D'autres dialogues tels que DatePickerDialog, ProgressDialog, TimePickerDialog héritent tous D'AlertDialog et causeront probablement la même erreur.
: DialogFragment est bon si vous avez besoin de créer une interface très personnalisée qui doit être utilisé dans plusieurs endroits. Il ne semble pas fonctionner à réutiliser dialogues android existants.
éviter l'écrasement de la fonction request et utiliser la même disposition:
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 que Android Studio a créé un template surreateview qui a gonflé une nouvelle vue au lieu de retourner la vue créée dans onCreateDialog. onCreateView est appelé après onCreateDialog, de sorte que la solution était simplement de remplacer la vue des fragments.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return this.getView();
}
Face à la même question, et il a fallu beaucoup de temps pour se débarrasser de l'erreur. Finalement, passer l'ID de la ressource à la méthode setView () a résolu le problème. Ajouter set view comme suit:
.setView(R.layout.dialog)
dans le code où vous appelez
create().
remplacer par
show().
Je n'ai pas gonflé à partir de XML mais j'ai fait la génération de vue dynamique dans un fragment de dialogue avec succès:
@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();
}
ce que vous voulez faire à la place est de 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, vous n'avez qu'à 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;
}
alors vous n'avez qu'à appeler:
DialogFragment df = new MyDialogFragment();
df.show(..);
et voilà, un dialogue avec votre propre vue personnalisée.
comme j'avais besoin de beaucoup de temps pour résoudre le même problème (Pop up un simple dialogue de texte) j'ai décidé de partager ma solution:
La layoutfile connectivity_dialog.xml contient un TextView simple 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é montrant 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 ). activité peut activer et désactiver le fragment de dialogue via deux fonctions. Si vous utilisez android.soutien.v4, vous pouvez changer pour 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");
}