Eduardo de Luna
Eduardo de Luna

Reputation: 491

Can't change a Custom DialogFragment layout dynamically

So reading through the Google API Guides I came across how to load a custom layout within an Alert Dialog Box here.

I wrote a class that extends a DialogFragment class like this:

    String product;
String description;
String company;
public void getAdInfo(String p, String d, String c)
{
    product = p;
    description = d;
    company = c;
}
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    LayoutInflater inflater = getActivity().getLayoutInflater();
    builder.setView(inflater.inflate(R.layout.ad_dialog, null));
            TextView pt = (TextView) getView().findViewById(R.id.product);
            pt.setText(product);
            TextView dt = (TextView) getView().findViewById(R.id.description);
            dt.setText(description);
            TextView ct = (TextView)getView().findViewById(R.id.company);
            ct.setText(company);
           builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                   // do something
               }
           });
           builder.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                   dismiss();
               }
           });
    return builder.create();
}

}

Here's the layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
    android:id="@+id/product"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textIsSelectable="false"
   />
<TextView
    android:id="@+id/company"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textIsSelectable="false"
   />  
<TextView
    android:id="@+id/description"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textIsSelectable="false"
   />

I instanciate the Dialog within an OnClickListener with these lines.

AdDialogFragment ad = new AdDialogFragment();
                        ad.getAdInfo(j.getAttribute("product"), j.getAttribute("description"), j.getAttribute("company"));
                        ad.show(getFragmentManager(), null);

j being an element from an xml node.

When I click on the button that's supposed to run the dialog I get this NullPointerException error from LogCat:

E/AndroidRuntime(10483):    at com.onix.mallard.android.guifrag.AdDialogFragment.onCreateDialog(AdDialogFragment.java:29)

The error refers to the line:

pt.setText(product);

Ultimately, it crashes the app completely. How can I change the layout of a DialogFragment dynamically? The Android API Guide says that DialogFragments are bound by the same lifecycle as Fragments, but that doesn't tell me much since they don't make use of FragmentTransactions (to my knowledge). If this is not possible and I need to instance the information as an Activity, no harm is done.

If it helps, the dialog is called from within a Fragment.

Upvotes: 3

Views: 6199

Answers (3)

Eduardo de Luna
Eduardo de Luna

Reputation: 491

I solved this issue a while ago by instead of recurring to the AlertDialog class I used a regular Activity. In AndroidManifest.xml, the activity specification has the following line.

android:theme="@styles/Theme.HoloLight.Dialog"

A word of advice, Linear Layout doesn't work. Try RelativeLayout.

Upvotes: 0

Martin Marconcini
Martin Marconcini

Reputation: 27236

Here's how I would do that (untested code) ;)

Your custom Dialog:

public class AdDialogFragment extends DialogFragment {
   String mProduct;
   String mDescription;
   String mCompany;
   TextView mProductTV;
   TextView mDescriptionTV;
   TextView mCompanyTV;

   public void setAdInfo(String product, String desc, String company)
   {
       mProduct = product;
       mDescription = desc;
       mCompany = company;
   }
   public AdDialogFragment() {
        super();
   }
   public static AdDialogFragment newInstance() {
        return new AdDialogFragment();
   }

public Dialog onCreateDialog(final Bundle savedInstanceState) {
   LayoutInflater factory = LayoutInflater.from(getActivity());
   final View content = factory.inflate(R.layout.ad_dialog, null);
   mProductTV = (TextView) content.findViewById(R.id.product);
   mDescriptionTV = (TextView) content.findViewById(R.id.description);
   mCompanyTV = (TextView) content.findViewById(R.id.company);

   fillTextViews();

   AlertDialog.Builder dialog;
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
      dialog = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.Theme.DeviceDefault.Dialog.)); //can't remember the name or create a custom theme.
   } else {
      dialog = new AlertDialog.Builder(getActivity());//anything below honeycomb can die :).
   }

   //  now customize your dialog
   dialog.setTitle(getActivity().getString(R.string.some_title_if_any))
      .setView(content)
      .setCancelable(true) //this is the default I think.
      .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                   // do something
               }
           });
      .setNegativeButton("Exit", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                   dismiss();
               }
           });
   return dialog.create();
}

private void fillTextViews() {
   mProductTV.setText(mProduct);
   mDescriptionTV.setText(mDescription);
   mCompanyTV.setText(mCompany);
}

And this is how you call it from an Activity for example:

public void showYourFancyDialog() {
   AdDialogFragment dialog = AdDialogFragment.newInstance();
   dialog.setAdInfo(yourProduct, yourDescription, yourCompany);
   dialog.show(getSupportFragmentManager(), "dialog");
}

Using patterns from Google's documentation

Upvotes: 4

TronicZomB
TronicZomB

Reputation: 8747

You could try the following, it has worked for me:

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View v = inflater.inflate(R.layout.ad_dialog, null));
builder.setView(v);

And then call findViewById like such:

v.findViewById();

Upvotes: 2

Related Questions