【问题标题】:Generic DialogFragment with listeners带有侦听器的通用 DialogFragment
【发布时间】:2018-06-05 07:38:51
【问题描述】:

我想创建一个可以在我的应用程序中重复使用的 DialogFragment 子类。所以当Activity 想要创建一个DialogFragment 时,它可以设置自己的文本并为正负按钮附加自己的侦听器。对于DialogFragment 中的文本,我使用参数包将它们传递给片段,以确保它们在配置更改时保持不变。但是,按钮的侦听器不能通过这些参数传递给片段。

将这些侦听器附加到DialogFragment 而不在配置更改时丢失它们的最佳做法是什么?

【问题讨论】:

  • 您可以将按钮作为接口传递给您的对话框片段类。并且它们的状态也可以保存在配置更改中。

标签: android android-fragments android-dialogfragment dialogfragment


【解决方案1】:

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) {

    }
}

}

子片段对话框:

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

activityfragmnet 中的实现:

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

处理正负按钮点击界面:

public interface OnDialogClickListener {

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

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

}

【讨论】:

    【解决方案2】:

    我会做这样的事情,使用带有接口的按钮,您可以在项目中的任何位置调用此类。您也可以在配置更改时保存它的实例:

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

    在我的通话活动中,我会这样做:

     new MyDialogFragment();
     myDialogFragment = MyDialogFragment.newInstance("successfull", "Please follow the instructions", " OK ", "negativeButtonText");
      myDialogFragment.show(getSupportFragmentManager(), "MyDialogFragment");
    

    【讨论】:

      【解决方案3】:

      关于传递侦听器,您可以创建一个接口,其中包含两个函数,分别用于 DialogFragment 中的正按钮和负按钮。在正面和负面按钮的点击侦听器中,您可以相应地调用这些接口方法。在 DialogFragment 中创建一个方法来设置这个接口。

      【讨论】:

      • 配置改变时接口的实例会保留吗?
      • 没有。你需要重置它。
      • 你会怎么做?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-21
      • 2019-05-20
      • 2014-02-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多