3

I want to create a DialogFragment subclass that can be reused accross my app. So when an Activity wants to create a DialogFragment, it can set its own texts and attach its own listeners for the positive and negative buttons. For the texts inside the DialogFragment, I pass them to the fragment using the arguments bundle to make sure they are persisted when the configuration changes. However, the listeners for the buttons cannot be passed to the fragment with these arguments.

What would be best practice to attach these listeners to the DialogFragment, without losing them when the configuration changes?

Mark Buikema
  • 2,211
  • 26
  • 51
  • you can pass buttons as interfaces to your dialog fragment class. and their states can also be saved on configuration changes. – Umair Jun 05 '18 at 07:43

3 Answers3

3

BaseDialogFragment.java

public abstract class BaseDialogFragment extends AppCompatDialogFragment {
public AppCompatDialog dialog;

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(getLayoutResource(), null);
    ButterKnife.bind(this, view);
    return view;
}


@Override
public void onStart() {
    super.onStart();
    dialog = (AppCompatDialog) getDialog();
    if (dialog != null) {
        WindowManager windowManager =
                (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        int width = size.x;

        dialog.getWindow().setLayout(width - 75, ViewGroup.LayoutParams.WRAP_CONTENT);
        WindowManager.LayoutParams params = dialog.getWindow().getAttributes();
        dialog.getWindow().setAttributes(params);
        dialog.getWindow().setBackgroundDrawable(ContextCompat.getDrawable(getContext(), R.drawable.dialog_rounded_back));
    }

}

protected abstract int getLayoutResource();

@Override
public void show(FragmentManager manager, String tag) {

    try {
        FragmentTransaction ft = manager.beginTransaction();
        ft.add(this, tag);
        ft.commitAllowingStateLoss();
    } catch (IllegalStateException e) {

    }
}

}

Child fragment dialog:

public class InvitationAcceptRejectDialog extends BaseDialogFragment {
public InvitationAcceptRejectDialog() {

}

@Override
protected int getLayoutResource() {
    return R.layout.invite_accept_reject_dialog;
}

protected OnDialogClickListener alertListener;


@BindView(R.id.tvDialogTitle)
AppCompatTextView tvDialogTitle;
@BindView(R.id.tvDialogMessage)
AppCompatTextView tvDialogMessage;
int requestCode;
public String dialogTitle;
public String dialogMessage;
public Bundle bundle;

@OnClick({R.id.imgCloseDialog, R.id.btnYes, R.id.btnNo})
public void dialgClick(View view) {
    switch (view.getId()) {
        case R.id.imgCloseDialog:
            break;
        case R.id.btnYes:
            alertListener.onPositiveClick(dialog, requestCode, bundle);
            break;
        case R.id.btnNo:
            alertListener.onNegativeClick(dialog, requestCode, bundle);
            break;
    }
    dialog.dismiss();
}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    tvDialogTitle.setText(dialogTitle);
    tvDialogMessage.setText(dialogMessage);
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return super.onCreateView(inflater, container, savedInstanceState);

}

public static class Builder {

    InvitationAcceptRejectDialog alertDialogFragment;

    public Builder() {
        alertDialogFragment = new InvitationAcceptRejectDialog();
    }

    public Builder setTitle(String title) {
        alertDialogFragment.dialogTitle = title;
        return this;
    }

    public Builder setMessage(String message) {
        alertDialogFragment.dialogMessage = message;
        return this;
    }

    public Builder setBundel(Bundle bundel) {
        alertDialogFragment.bundle = bundel;
        return this;
    }

    public Builder setCallback(OnDialogClickListener mListener, int code) {
        alertDialogFragment.alertListener = mListener;
        alertDialogFragment.requestCode = code;
        return this;
    }

    public InvitationAcceptRejectDialog build() {
        return alertDialogFragment;
    }
}
}

Implementation in activity or fragmnet:

  InvitationAcceptRejectDialog build = new InvitationAcceptRejectDialog.Builder()
            .setCallback(this, Constant.DialogConstant.ACCEPET_INVITE)
            .setTitle(getString(R.string.logout))
            .setMessage(getString(R.string.logout_message))
            .build();
    build.show(getSupportFragmentManager(), "TAG");

Interface for handle positive and negative button click:

public interface OnDialogClickListener {

void onPositiveClick(DialogInterface dialog, int id, Bundle bundle);

void onNegativeClick(DialogInterface dialog, int id, Bundle bundle);

}
pRaNaY
  • 21,330
  • 22
  • 85
  • 134
Milan Pansuriya
  • 2,249
  • 1
  • 13
  • 28
1

Regarding passing the listeners, you can create an interface with two functions one each for the positive and the negative button in your DialogFragment. Inside click listeners of your positive and negative buttons, you can call these interface methods accordingly. Create a method inside your DialogFragment to set this Interface.

Rajen Raiyarela
  • 5,050
  • 4
  • 18
  • 39
1

I would do something like this, Use buttons with as interfaces and you can call this class any where you want in your project. and you can save it's instance too on configuration change :

public class MyDialogFragment extends DialogFragment  {

// the fragment initialization parameters,
private static final String DIALOG_TITLE = "DIALOG_TITLE";
private static final String DIALOG_MESSAGE = "DIALOG_MESSAGE";
private static final String DIALOG_BUTTON_POSITIVE = "DIALOG_BUTTON_POSITIVE";
private static final String DIALOG_BUTTON_NEGATIVE = "DIALOG_BUTTON_NEGATIVE";

private String Title;
private String Message;
private String btnPositive;
private String btnNegative;

public interface DialogFragmentButtonPressedListener {
    void onPositiveButtonClick();

    void onNegativeButtonClick();

}


public static MyDialogFragment newInstance(String title, String message, String btnPositiveText, String btnNegativeText) {
    MyDialogFragment fragment = new MyDialogFragment();
    Bundle args = new Bundle();
    args.putString(DIALOG_TITLE, title);
    args.putString(DIALOG_MESSAGE, message);
    args.putString(DIALOG_BUTTON_POSITIVE, btnPositiveText);
    args.putString(DIALOG_BUTTON_NEGATIVE, btnNegativeText);

    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        Title = getArguments().getString(DIALOG_TITLE);
        Message = getArguments().getString(DIALOG_MESSAGE);
        btnPositive = getArguments().getString(DIALOG_BUTTON_POSITIVE);
        btnNegative = getArguments().getString(DIALOG_BUTTON_NEGATIVE);

    }

}

// updated this method. before update it was onAttach(Activity activity)
@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (!(context instanceof DialogFragmentButtonPressedListener)) {
        throw new ClassCastException(context.toString() + " must implement DialogFragmentButtonPressedListener");
    }
}

static Handler handler = new Handler(Looper.getMainLooper());

final Runnable runnable = new Runnable( ) {
    @Override
    public void run() {
        if (mAlertDialog.isShowing()) {
            mAlertDialog.dismiss();

        }
    }
};

AlertDialog mAlertDialog = null;
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {

//        return new AlertDialog.Builder(getActivity())
//                .setTitle(Title)
//                .setMessage(Message)
//                .setPositiveButton(btnPositive, new DialogInterface.OnClickListener() {
//
//                    @Override
//                    public void onClick(DialogInterface dialog, int which) {
//                        ((DialogFragmentButtonPressedListener) getActivity()).onPositiveButtonClick();
//                    }
//                })
//                .setNegativeButton(btnNegative, new DialogInterface.OnClickListener() {
//
//                    @Override
//                    public void onClick(DialogInterface dialog, int which) {
//                        ((DialogFragmentButtonPressedListener) getActivity()).onNegativeButtonClick();
//                    }
//                })
//                .create();


    return mAlertDialog;
}
 }

And in my calling activity I would do like this:

 new MyDialogFragment();
 myDialogFragment = MyDialogFragment.newInstance("successfull", "Please follow the instructions", " OK ", "negativeButtonText");
  myDialogFragment.show(getSupportFragmentManager(), "MyDialogFragment");
Umair
  • 5,756
  • 15
  • 39
  • 47