-1

I'm currently having trouble setting up my custom listener. I just want to pass a string from my dialog to my fragment (where I set up the dialog). I was trying to follow this tutorial: https://www.youtube.com/watch?v=ARezg1D9Zd0.

At minute 10:38, he sets up the listener. This only problem is that in this, he uses DialogFragment, but I'm extending dialog and I don't know how to attach the context to the listener.

I've tried to set it up in onAttachedToWindow() and in the dialog constructor but it crashes.

What should I actually do?

I'd also appreciate it if someone could explain what the difference is between:

onAttachedToWindow() vs. onAttach(Context context).

Thanks!

MY CUSTOM DIALOG BOX:

public class NewListDialog extends Dialog implements View.OnClickListener {

    private Activity c;
    private TextInputLayout textInputLayout;
    private TextInputEditText editText;
    private LinearLayout dialog_root_view;
    private Animation fade_out;
    private String list_name;

    private NewListDialogListener listener;

    NewListDialog(Activity a) {
        super(a);
        this.c = a;

        //ANOTHER ATTEMPT TO ATTACH CONTEXT TO LISTENER
        //listener = (NewListDialogListener) a.getApplicationContext();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.new_list_dialog);

        MaterialButton cancel = findViewById(R.id.dialog_new_list_cancel_button);
        MaterialButton create = findViewById(R.id.dialog_new_list_create_button);
        textInputLayout = findViewById(R.id.dialog_text_input_layout);
        editText = findViewById(R.id.dialog_edit_text);
        dialog_root_view = findViewById(R.id.dialog_root);
        fade_out =  AnimationUtils.loadAnimation(c, R.anim.fade_out_dialog);

        editText.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View view, int i, KeyEvent keyEvent) {
                if (isTextValid(editText.getText())) {
                    textInputLayout.setError(null);
                    return true;
                }
                return false;
            }
        });


        cancel.setOnClickListener(this);
        create.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            //Cancel Button
            case R.id.dialog_new_list_cancel_button:
                dialog_root_view.startAnimation(fade_out);
                final Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        dismiss();
                    }
                }, 200);
                break;

            //Create Button
            case R.id.dialog_new_list_create_button:
                if (!isTextValid(editText.getText())) {
                    textInputLayout.setError(c.getString(R.string.dialog_error));
                } else {
                    textInputLayout.setError(null);

                    //record input string
                    list_name = editText.getText().toString();

                    //send information to parent activity
                    //What to put here?
                    listener.createListName(list_name);
                    dismiss();
                }
                break;

            default:
                break;
        }
    }

    private boolean isTextValid(@Nullable Editable text) {
        return text != null && text.length() > 0;
    }

    //ATTEMPT TO ATTACH CONTEXT TO LISTENER
    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();

        try {
            listener = (NewListDialogListener) c.getBaseContext();
        } catch (ClassCastException e) {
            throw new ClassCastException(c.getBaseContext().toString() + "must implement ExampleDialogListener");
        }
    }

    public interface NewListDialogListener {
        void createListName(String listname);
    }
}
Pavneet_Singh
  • 36,884
  • 5
  • 53
  • 68
Varun Govind
  • 983
  • 2
  • 12
  • 23

3 Answers3

2

In case you define a custom dialog then you can declare a method to allow other components call it or listen events on this dialog. Add this method to you custom dialog.

public void setNewListDialogListener(NewListDialogListener listener){
    this.listener = listener;
}

NewListDialog.java

public class NewListDialog extends Dialog implements View.OnClickListener {

    private Activity c;
    private TextInputLayout textInputLayout;
    private TextInputEditText editText;
    private LinearLayout dialog_root_view;
    private Animation fade_out;
    private String list_name;

    private NewListDialogListener listener;

    NewListDialog(Activity a) {
        super(a);
        this.c = a;
    }

    public void setNewListDialogListener(NewListDialogListener listener) {
        this.listener = listener;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.new_list_dialog);

        MaterialButton cancel = findViewById(R.id.dialog_new_list_cancel_button);
        MaterialButton create = findViewById(R.id.dialog_new_list_create_button);
        textInputLayout = findViewById(R.id.dialog_text_input_layout);
        editText = findViewById(R.id.dialog_edit_text);
        dialog_root_view = findViewById(R.id.dialog_root);
        fade_out =  AnimationUtils.loadAnimation(c, R.anim.fade_out_dialog);

        editText.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View view, int i, KeyEvent keyEvent) {
                if (isTextValid(editText.getText())) {
                    textInputLayout.setError(null);
                    return true;
                }
                return false;
            }
        });


        cancel.setOnClickListener(this);
        create.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            //Cancel Button
            case R.id.dialog_new_list_cancel_button:
                dialog_root_view.startAnimation(fade_out);
                final Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        dismiss();
                    }
                }, 200);
                break;

            //Create Button
            case R.id.dialog_new_list_create_button:
                if (!isTextValid(editText.getText())) {
                    textInputLayout.setError(c.getString(R.string.dialog_error));
                } else {
                    textInputLayout.setError(null);

                    //record input string
                    list_name = editText.getText().toString();

                    //send information to parent activity
                    //What to put here?
                    if (listener != null) {
                        listener.createListName(list_name);
                    }
                    dismiss();
                }
                break;

            default:
                break;
        }
    }

    private boolean isTextValid(@Nullable Editable text) {
        return text != null && text.length() > 0;
    }

    public interface NewListDialogListener {
        void createListName(String listname);
    }
}

In other components such as an activity which must implements NewListDialogListener.

NewListDialog dialog = new NewListDialog(this);
dialog.setNewListDialogListener(this);

If you don't want the activity implements NewListDialogListener then you can pass a listener instead.

NewListDialog dialog = new NewListDialog(this);
dialog.setNewListDialogListener(new NewListDialog.NewListDialogListener() {
    @Override
    public void createListName(String listname) {
        // TODO: Your code here
    }
});
Son Truong
  • 13,661
  • 5
  • 32
  • 58
1

In android Fragments and Activity has lifecycles. Fragments are hosted inside Activity and get the context of host activity via onattach method.

On the other hand Dialog is extended from Object (God class) without any lifecycle and should be treaded as an object.

If your activity is implementing NewListDialogListener then you can do

listener = (NewListDialogListener) a;

onAttachedToWindow : mean the dialog will be drawn on screen soon

and

getApplicationContext() will give you the context object of the application (one per app) which is surely not related with your listener and hence won't work

Reference :

Android DialogFragment vs Dialog

Difference between getContext() , getApplicationContext() , getBaseContext() and “this”

Pavneet_Singh
  • 36,884
  • 5
  • 53
  • 68
0

You can use RxAndroid instead of using listener, in this situation I use RxAndroid to get data from dialogs to activities or fragments.

Just need to create a PublishSubject and get the observed data. on activity or fragment :

    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    PublishSubject<String > objectPublishSubject = PublishSubject.create();
    objectPublishSubject.observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.newThread())
            .subscribe(this::onNext);
    CustomDialog customDialog = new CustomDialog(this, objectPublishSubject);
    customDialog.show();
}

private void onNext(String data) {
    Log.i("DIALOG_DATA", data);
}

and you can create dialog like this :

public class CustomDialog extends Dialog implements View.OnClickListener {

private PublishSubject<String> subject;
public CustomDialog(@NonNull Context context, PublishSubject<String> subject) {
    super(context);
    this.subject = subject;
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.custom_dialog);
    findViewById(R.id.button).setOnClickListener(this);

}

@Override
public void onClick(View v) {
    subject.onNext("Data");
    dismiss();
}
Vahid Rajabi
  • 191
  • 3
  • 3