Search code examples
androidandroid-fragmentsandroid-dialogandroid-dialogfragment

Creating listener of a CustomDialog out of the class in Android


I am trying to create a listener of a button of a customdialog which extends DialogFragment class and I want to locate the listener of custom buttons out of customdialog fragment class .However when I try to call the view of CustomDialog Fragment then I am getting null exception. What I do is to create an new instance of the customdialog fragment in somewhere else and say

customdialog.getView().findViewById(R.id.custombutton);

but I am getting null.

public class CustomDialog extends DialogFragment {

public  final int RES_NONE = -1;
private  TextViewCustomFont dialogTitle, view2, dialogBodyBottom,
        dialogBodyTop;
private  EditTextCustomFont dialogEditText;
private  ButtonCustomFont dialogLeftButton;
private ButtonCustomFont dialogRightButton;
private  Typeface GothamBold, GothamMedium, GothamUltra;
private static  int title1, bodyTop1, bodyBottom1, EditTextHint1,
        leftButton1, rightButton1;
onSubmitListener mListener;

private  Dialog dialog;

interface onSubmitListener {
    void setOnSubmitListener(String arg);
}

public static CustomDialog newInstance(int title, int bodyTop,
        int bodyBottom, int EditTextHint, int leftButton, int rightButton) {

    title1 = title;
    bodyTop1 = bodyTop;
    bodyBottom1 = bodyBottom;
    EditTextHint1 = EditTextHint;
    leftButton1 = leftButton;
    rightButton1 = rightButton;

    CustomDialog frag = new CustomDialog();



    return frag;
}

public ButtonCustomFont getDialogLeftButton() {
    return dialogLeftButton;
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {

    dialog = new Dialog(getActivity());
    dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
    dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);

    //dialog.setContentView(R.layout.dialog_layout);
    //dialog.show();

    initLayout();

    return dialog;
}

private void initLayout(){
    dialog.setContentView(R.layout.dialog_layout);
    setDialogView();
    setCustomDialog();
}

public void setDialogView(){    

    //Create an java object of each dialog view item
    dialogTitle = (TextViewCustomFont) dialog.findViewById(R.id.custom_dialog_title);
    dialogBodyTop = (TextViewCustomFont) dialog.findViewById(R.id.custom_dialog_body_top);
    dialogBodyBottom = (TextViewCustomFont) dialog.findViewById(R.id.custom_dialog_body_bottom);
    dialogEditText = (EditTextCustomFont) dialog.findViewById(R.id.custom_dialog_body_et);
    dialogLeftButton = (ButtonCustomFont) dialog.findViewById(R.id.custom_dialog_body_btn_left);
    dialogRightButton = (ButtonCustomFont)  }

public class LoginSelectionFragment extends Fragment {


public static LoginSelectionFragment newInstance() {

    LoginSelectionFragment fragment = new LoginSelectionFragment();
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_loginselection,
            container, false);
}

I am trying to pull the dialogLeftButton of CustomDialog Fragment and assing a listener on it inside the LoginSelectionFragment.

Here is how it looks like after I added method 2. This a part of LoginSelectionFragment

private void TwoButtonTextEditTextDialog(){
    String title = getResources().getString(R.string.invalid_info_header);
    String body = getResources().getString(R.string.invalid_info_body);
    String body2 = getResources().getString(R.string.hint_newemail);
    String btn1 = getResources().getString(R.string.cancel_uppercase);
    String btn2 = getResources().getString(R.string.ok_alert);

    fragmentDialog = CustomDialog.newInstance(title, body, body2, RES_NONE, btn1, btn2);
    fragmentDialog.setCustomDialogFragmentListener(mDialogClickListener);
    fragmentDialog.show(getFragmentManager(), "");
}

private  CustomDialog.CustomDialogFragmentListener mDialogClickListener = new CustomDialog.CustomDialogFragmentListener(){ 

    @Override
    public void onNegativeClick() {
    // TODO Auto-generated method stub
    fragmentDialog.dismiss();
    }

    @Override
    public void onPositiveClick() {
    // TODO Auto-generated method stub
    fragmentDialog.dismiss();
    }

};


@Override
public void onNegativeClick() {
    // TODO Auto-generated method stub

}

@Override
public void onPositiveClick() {
    // TODO Auto-generated method stub

}

Solution

  • You could create a method as setDialogButtonClickListener(CustomDialog.OnButtonClickListener clickListener); where CustomDialog.OnButtonClickListener is an inner static interface , that way you could listen to click events of the buttons from anywhere.

    An example of this could look as below,

       public class CustomDialog extends DialogFragment {
    
           .....
         public static CustomDialog newInstance(int title, int bodyTop,
            int bodyBottom, int EditTextHint, int leftButton, int rightButton) {
    
            CustomDialog frag = new CustomDialog();
            Bundle args = new Bundle();
            args.putInt("title", title);
            ......
            frag.setArguments(args);
            return frag;
        }
    
    ...
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            int title = getArguments().getInt("title");
    
            return new AlertDialog.Builder(getActivity())
                    .setIcon(android.R.drawable.ic_dialog_alert)
                    .setTitle(title)
                    .setPositiveButton(android.R.string.ok, this)
                    .setNegativeButton(android.R.string.cancel, this)
                     ....
                    .create();
        }
    
        @Override
        public void onClick(DialogInterface dialog, int which) {
            if (listener != null) {
                switch (which) {
                case DialogInterface.BUTTON_POSITIVE:
                    listener.onRightButtonClick();
                default:
                    listener.onLeftButtonClick();
                }
            }
        }
    
        ...
        private CustomDialog.OnButtonClickListener mClickListener;
        ....
    
        public void setDialogButtonClickListener(CustomDialog.OnButtonClickListener clickListener){
             mClickListener = clickListener;
        }
    
        ...
        public static interface OnButtonClickListener {
           public void onLeftButtonClick();
           public void onRightButtonClick();
        }
        }
    

    If you notice from the above sample I posted , I have besides solving your problem of setting the click listener on buttons also have introduced you with the Factory Design Pattern on Android , You can see that instead of creating static fields for the button title and Dialog title I've set them in the Bundle Argument and then Retrieve them in the Dialogs onCreate() method.

    For more Best Practices of Fragment You can take a look here

    Edit

    Ok , for your help I am providing you a Glimpse of what your LoginSelectionFragment should look like.

    public class LoginSelectionFragment extends Fragment implements CustomDialog.OnButtonClickListener {
    
        ......// Method 1
        public void showDialog(String title , String message .....) {
             CustomDialog dialog = CustomDialog.getInstance(title , message...);
             dialog.setDialogButtonClickListener(this);
             dialog.show(getSupportFragmentManager(), null);
        }
    
            public void onLeftButtonClick(){
        ...// do something on left button click of dialog
        }
                   public void onRightButtonClick(){
        // do something on right button click of dialog
        ..
        }
    
        // Method 2
    public void showDialog2(String title , String message .....) {
             CustomDialog dialog = CustomDialog.getInstance(title , message...);
             dialog.setDialogButtonClickListener(mDialogClickListener);
             dialog.show(getSupportFragmentManager(), null);
    }
    
    private final CustomDialog.OnButtonClickListener mDialogClickListener = new CustomDialog.OnButtonClickListener() {
      public void onLeftButtonClick(){
            ...// do something on left button click of dialog
            }
                       public void onRightButtonClick(){
            // do something on right button click of dialog
            ..
            }
    }
        }
    

    Now If you look at Method 1 , we have given parameters to showDialog() method so that you could reuse it for showing multiple times with different arguments ie., you could use this approach when you want to show the same dialog with different title , message etc

    and in Method 2 we have provided an anonymous inner class for handling click events you could as many anonymous inner classes as you have different varieties of dialog ie dialog with different UI and different Event listeners in the same activity/fragment.

    Enjoy!