如何在Android的自定义对话框中设置自定义侦听器?

时间:2018-08-23 23:38:14

标签: android dialog listener

我目前无法设置自定义监听器。我只想将字符串从对话框传递到片段(在其中设置对话框)。我试图遵循本教程:Properties and Configuration

在10:38分钟,他设置了听众。 唯一的问题是,他使用了DialogFragment,但是我正在扩展对话框,而且我不知道如何将上下文附加到侦听器。

我尝试在onAttachedToWindow()和对话框构造函数中进行设置,但是崩溃了。

我该怎么办?

如果有人能解释两者之间的区别,我也将不胜感激。

onAttachedToWindow()与onAttach(上下文上下文)。

谢谢!

我的自定义对话框:

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

3 个答案:

答案 0 :(得分:1)

在Android FragmentsActivity中具有生命周期。 Fragments托管在Activity内部,并通过onattach方法获取宿主活动的上下文。

另一方面,Dialog是从Object(上帝类)扩展而来的,没有任何生命周期,应将其作为对象使用。

如果您的活动正在实施NewListDialogListener,那么您可以

listener = (NewListDialogListener) a;

onAttachedToWindow:表示该对话框将很快显示在屏幕上

getApplicationContext()将为您提供应用程序的上下文对象(每个应用程序一个),该对象肯定与您的监听器无关,因此将无法正常工作

参考:

Android DialogFragment vs Dialog

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

答案 1 :(得分:1)

如果定义了一个自定义对话框,则可以声明一个方法,以允许其他组件调用此方法或在此对话框上侦听事件。将此方法添加到自定义对话框。

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

在其他组件中,例如必须实现NewListDialogListener的活动。

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

如果您不希望该活动实现NewListDialogListener,则可以通过侦听器代替。

NewListDialog dialog = new NewListDialog(this);
dialog.setNewListDialogListener(new NewListDialog.NewListDialogListener() {
    @Override
    public void createListName(String listname) {
        // TODO: Your code here
    }
});

答案 2 :(得分:0)

您可以使用RxAndroid代替侦听器,在这种情况下,我使用RxAndroid从对话框获取数据到活动或片段。

只需创建一个href并获取观察到的数据。关于活动或片段:

PublishSubject

您可以创建如下对话框:

公共类CustomDialog扩展了Dialog实现的View.OnClickListener {

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