Problem Inflating Custom View for Alertdialog in Dialogfragment

Problem inflating custom view for AlertDialog in DialogFragment

The first error line gives me the hint that this is related to how you are creating your dialog - not the dialog itself.

Are you creating the dialog automatically (which could mean this gets called before the views are all set up) or in response to a button click? I initially had problems with fragments due to instantiation order.

I used the same code to set the view as you have, and my result works. I cut out the other setup to make this look cleaner, but it works with or without it.

@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();
}

StackOverflowError when trying to inflate a custom layout for an AlertDialog inside a DialogFragment

If found the problem. DialogFragment.getLayoutInflater() contains a call to onCreateDialog(), so calling onCreateDialog() from within getLayoutInflater() creates an infinite loop.

I found the solution in this answer: https://stackoverflow.com/a/10585164/2020340

I'm not exactly sure if this is good form, because it doesn't really seem like it, but I replaced

getLayoutInflater(savedInstanceState)

with

getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

Edit: They are the same. See this answer for details: https://stackoverflow.com/a/20995083/2020340

DialogFragment : Using AlertDialog with custom layout

I'm surprised that nobody answered. This is the solution:

public class PropDialogFragment extends DialogFragment {

private PropDialogFragment() { /*empty*/ }

/** creates a new instance of PropDialogFragment */
public static PropDialogFragment newInstance() {
return new PropDialogFragment();
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
//getting proper access to LayoutInflater is the trick. getLayoutInflater is a //Function
LayoutInflater inflater = getActivity().getLayoutInflater();

View view = inflater.inflate(R.layout.my_dialog, null);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(view);
builder.setTitle(getActivity().getString(R.string.sysinfo)).setNeutralButton(
getActivity().getString(R.string.okay), null);
return builder.create();
}
}

You can show the dialog using :

private void showDialog() {
// DialogFragment.show() will take care of adding the fragment
// in a transaction. We also want to remove any currently showing
// dialog, so make our own transaction and take care of that here.
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);

// Create and show the dialog.
DialogFragment newFragment = PropDialogFragment.newInstance();
newFragment.show(ft, "dialog");
}

DialogFragment onCreateView not returning custom layout view?

don't need to override onCreateView()

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
setRetainInstance(true);
Log.d(TAG, "onCreateDialog");
LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
return new AlertDialog.Builder(getActivity())
.setView(inflater.inflate(R.layout.dialog_edittext, null))
.setPositiveButton(android.R.string.ok, passDataListener)
.setNegativeButton(android.R.string.cancel, null)
.setCancelable(true)
.create();
}

Android: support DialogFragment with custom layout not shown

I ended up with this workaround, but I'd still want to understand WTF:

    // This is a workaround for the strange behavior of onCreateView (which doesn't show dialog's layout)
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getContext());
LayoutInflater inflater = LayoutInflater.from(getContext());
View dialogView = inflater.inflate(R.layout.dialog_info_prompt, null);
dialogBuilder.setView(dialogView);

initSubViews(dialogView);

populateSubViews();

setCancelable(false);

return dialogBuilder.create();
}

private void initSubViews(View rootView) {
mTxtTitle = (TextView) rootView.findViewById(R.id.txt_dialog_title);
mTxtMessage = (TextView) rootView.findViewById(R.id.txt_dialog_message);
mBtnPositive = (Button) rootView.findViewById(R.id.btn_dialog_positive);
mBtnNegative = (Button) rootView.findViewById(R.id.btn_dialog_negative);

mBtnPositive.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
mEventBus.post(new PromptDialogDismissedEvent(getDialogTag(), PromptDialogDismissedEvent.BUTTON_POSITIVE));
}
});

mBtnNegative.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
mEventBus.post(new PromptDialogDismissedEvent(getDialogTag(), PromptDialogDismissedEvent.BUTTON_NEGATIVE));
}
});
}

private void populateSubViews() {
String title = getArguments().getString(ARG_TITLE);
String message = getArguments().getString(ARG_MESSAGE);
String positiveButtonCaption = getArguments().getString(ARG_POSITIVE_BUTTON_CAPTION);
String negativeButtonCaption = getArguments().getString(ARG_NEGATIVE_BUTTON_CAPTION);

mTxtTitle.setText(TextUtils.isEmpty(title) ? "" : title);
mTxtMessage.setText(TextUtils.isEmpty(message) ? "" : message);
mBtnPositive.setText(positiveButtonCaption);
mBtnNegative.setText(negativeButtonCaption);
}

Custom DialogFragment with AlertDialog returns EditText as

You are adding the layout with a resource identifier, so your call to get the view is returning null. (Why? The view is inflated internally and just handled differently.) Since you are using the AlertDialog to collect data, you will have to add an inflated view.

I am also going to suggest that you change the interface to hide the details of the dialog; There is no reason for the main activity to know the internal structure of the dialog. It just needs the song title and BPM and maybe some other stuff. You will find the code a little easier to understand and maintain.

Here is a slight rework. This code just captures the song title, but it can easily be extended to include other data as well.

In NewSongFragment:

interface NewSongListener {
fun onDialogPositiveClick(songTitle: String)
fun onDialogNegativeClick(dialog: DialogFragment)
}

val inflater = requireActivity().layoutInflater;
val view = inflater.inflate(R.layout.fragment_new_song, null)
builder
.setView(view)
.setCancelable(true)
.setNegativeButton(R.string.cancel, DialogInterface.OnClickListener { dialog, id ->
dialog?.cancel()
})
.setPositiveButton(R.string.button_save)
{ dialog, _ ->
Log.d("Applog", view.toString())
val songTitle = view?.findViewById<EditText>(R.id.newSongTitle)?.text
listener.onDialogPositiveClick(songTitle.toString())
}

In MainActivity.kt

override fun onDialogPositiveClick(songTitle: String) {
// songTitle has the song title string
}

Android dialogs have some quirks. Here are a number of ways to do fragment/activity communication.

Android: Custom layout for DialogFragment is not showing fully in it's width like AlertDialog

Have tried the code you have and it turns out that you just really need to override the Dialog theme,

from your ConfirmationDialogFragment class

override fun getTheme() = R.style.AppTheme_Alert

and from your styles just add this but colorAccent is just optional, hehe.

<style name="AppTheme.Alert" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="colorAccent">@color/black</item>
</style>


Related Topics



Leave a reply



Submit