Question

My app shows many custom dialog like Yes/No or Accept/Cancel decissions and, while I was coding, I realized that there are so much code repeated, following the same schema.

I want to build a general class but I don't know how to do it or, more exactly, the correct way that I have to do it(interfaces, abstract classes, inheritance, static classes, ...)

This is my current class:

public class DialogTwoOptions extends Dialog {

TextView title_tv;
// Button yes_btn, no_btn;

public DialogTwoOptions(Context context) 
{
    super(context);     
    setContentView(R.layout.dialogo_sino); // a simple layout with a TextView and Two Buttons

    title_tv = (TextView) findViewById(R.id.dialogo_titulo_sino);
    // yes_btn = (Button) findViewById(R.id.dialogo_aceptar); 
    // no_btn = (Button) findViewById(R.id.dialogo_cancelar);

    View v = getWindow().getDecorView();
    v.setBackgroundResource(android.R.color.transparent);
}

 public void quitDialog(View v) {
     if (isShowing()) dismiss();
 }

 public void setTitle(String title) {
     title_tv.setText(title);
 }

}

And this is what I am doing when I need to use this class:

final DialogTwoOptions dialog = new DialogTwoOptions(this);

    Button yes = (Button) dialog.findViewById(R.id.dialog_yes_btn);
    Button no = (Button) dialog.findViewById(R.id.dialog_no_btn);

    yes.setOnClickListener(new Button.OnClickListener() 
    {
        public void onClick(View v)     {
            dialog.dismiss();
            // Do something 
        }
    });

    no.setOnClickListener(new Button.OnClickListener() 
    {
        public void onClick(View v)     {
            dialog.dismiss();
            // Do something
        }
    });

    dialog.show();

I am sure that it is improvable, but how could you do this?

Thanks

Was it helpful?

Solution

First create an Base DialogFragment to keep hold of the instance of the Activity. So when the Dialog is attached to the Activity , you will know the instance of the Activity which created it.

public abstract class BaseDialogFragment<T> extends DialogFragment {
        private T mActivityInstance;

        public final T getActivityInstance() {
                return mActivityInstance;
        }

        @Override
        public void onAttach(Activity activity) {
                mActivityInstance = (T) activity;
            super.onAttach(activity);
        }

        @Override
        public void onDetach() {
                super.onDetach();
                mActivityInstance = null;
        }
}

Then, create a GeneralDialogFragment which extends the BaseDialogFragment

public class GeneralDialogFragment extends BaseDialogFragment<GeneralDialogFragment.OnDialogFragmentClickListener> {

        // interface to handle the dialog click back to the Activity
        public interface OnDialogFragmentClickListener {
            public void onOkClicked(GeneralDialogFragment dialog);
            public void onCancelClicked(GeneralDialogFragment dialog);
        }

        // Create an instance of the Dialog with the input
        public static GeneralDialogFragment newInstance(String title, String message) {
            GeneralDialogFragment frag = new GeneralDialogFragment();
            Bundle args = new Bundle();
            args.putString("title", title);
            args.putString("msg", message);
            frag.setArguments(args);
            return frag;
        }
        // Create a Dialog using default AlertDialog builder , if not inflate custom view in onCreateView
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {

            return new AlertDialog.Builder(getActivity())
                .setTitle(getArguments().getString("title"))
                .setMessage(getArguments().getString("message"))
                .setCancelable(false)
                .setPositiveButton("OK",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            // Positive button clicked
                            getActivityInstance().onOkClicked(GeneralDialogFragment.this);
                        }
                    }
                )
                .setNegativeButton("Cancel",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            // negative button clicked
                            getActivityInstance().onCancelClicked(GeneralDialogFragment.this);
                        }
                    }
                )
                .create();
        }

    }

If you need to use your own custom layout for dialog,then inflate a layout in onCreateView and remove onCreateDialog . But Add the click listeners in onCreateView like i explained in onCreateDialog

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

Then , In your Activity need to implement an interface to handle the action in dialog

public class TryMeActivity extends 
    FragmentActivity implements GeneralDialogFragment.OnDialogFragmentClickListener {

    @Override
        public void onOkClicked(GeneralDialogFragment dialog) {
                // do your stuff
        }

        @Override
        public void onCancelClicked(GeneralDialogFragment dialog) {
                // do your stuff
        }
}

Finally, Show the Dialog from your Activity when required, like this

    GeneralDialogFragment generalDialogFragment =
        GeneralDialogFragment.newInstance("title", "message");
    generalDialogFragment.show(getSupportFragmentManager(),"dialog");

Hope this helps. I am sure this approach is one of the optimized way, but there could be also different approaches .

OTHER TIPS

I faced a problem like you. And all in stackoverflow does not meet what I want. So I create my own Dialog Class and it can use like AlertDialog.Builder class.

In my dialogxml.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@drawable/drconner">

    <LinearLayout
        android:id="@+id/under"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    <TextView
        android:id="@+id/malertTitle"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:padding="5dp"
        android:textSize="25sp"
        android:textColor="#ffffff"
        android:drawablePadding="2dp"
        android:background="@color/colorPrimaryDark"
        />

    <TextView
        android:id="@+id/aleartMessage"
        android:layout_width="match_parent"
        android:layout_height="75dp"
        android:padding="5dp"
        android:textSize="18sp"
        android:textColor="@color/colorAccent"/>
    </LinearLayout>

    <LinearLayout
        android:layout_below="@+id/under"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="1dp"
        android:orientation="horizontal">

        <Button
            android:id="@+id/aleartYes"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            />

        <Button
            android:id="@+id/aleartNo"
            android:layout_marginLeft="30dp"
            android:layout_marginStart="30dp"
            android:layout_marginRight="3dp"
            android:layout_marginEnd="3dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />


    </LinearLayout>


</RelativeLayout>

For Dialog Shape I create just simple shape xml - drconner.xml

<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">

    <corners android:radius="5dp"/>
    <stroke android:color="@color/colorPrimaryDark" android:width="2dp"/>


</shape>

For custom Alert I create Alear.java as follow

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.TextView;



/**
 * Created by sanyatihan on 27-Dec-16.
 */

public class Alert extends Dialog {

    private String message;
    private String title;
    private String btYesText;
    private String btNoText;
    private int icon=0;
    private View.OnClickListener btYesListener=null;
    private View.OnClickListener btNoListener=null;

    public Alert(Context context) {
        super(context);
    }

    public Alert(Context context, int themeResId) {
        super(context, themeResId);
    }

    protected Alert(Context context, boolean cancelable, OnCancelListener cancelListener) {
        super(context, cancelable, cancelListener);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.dialogxml);
        TextView tv = (TextView) findViewById(R.id.malertTitle);
        tv.setCompoundDrawablesWithIntrinsicBounds(icon,0,0,0);
        tv.setText(getTitle());
        TextView tvmessage = (TextView) findViewById(R.id.aleartMessage);
        tvmessage.setText(getMessage());
        Button btYes = (Button) findViewById(R.id.aleartYes);
        Button btNo = (Button) findViewById(R.id.aleartNo);
        btYes.setText(btYesText);
        btNo.setText(btNoText);
        btYes.setOnClickListener(btYesListener);
        btNo.setOnClickListener(btNoListener);

    }



       public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public void setIcon(int icon) {
        this.icon = icon;
    }

    public int getIcon() {
        return icon;
    }

    public void setPositveButton(String yes, View.OnClickListener onClickListener) {
        dismiss();
        this.btYesText = yes;
        this.btYesListener = onClickListener;


    }

    public void setNegativeButton(String no, View.OnClickListener onClickListener) {
        dismiss();
        this.btNoText = no;
        this.btNoListener = onClickListener;


    }
}

To use this Alert class, just simple as the use of AlertDialog.Builder class

for example :

final Alert mAlert = new Alert(this);
        mAlert.setTitle("This is Error Warning");
        mAlert.setIcon(android.R.drawable.ic_dialog_alert);
        mAlert.setMessage("Do you want to delete?");
        mAlert.setPositveButton("Yes", new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mAlert.dismiss();
                //Do want you want
            }
        });

        mAlert.setNegativeButton("No", new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mAlert.dismiss();
                //Do want you want
            }
        });

        mAlert.show();

The main thing is you should call dismiss() function in your onClick. I hope this may help to you. And let me know if this is what you want or not. You can change the layout as you want in dialogxml.xml.

I have been using this for some time. Calling the alert dialog inside an activity, where alertDialog is a static function in a class called Misc:

    Misc.alertDlg(this, "Confirm", "Delete the file?", "Yes", null, "Cancel",
                    (DialogInterface dialog, int which) -> {
                        if(which == Misc.BTN_POS)
                            deleteYourFile()
                    });
}

And the alert dialog function (a static function in a class called Misc:

static public void alertDlg(Context context, String title, String msg, String btnPos, String btnNeutral, String btnNeg, DialogInterface.OnClickListener ocListener) {
    Builder db = new AlertDialog.Builder(context);
    db.setTitle(title);
    db.setMessage(msg);
    if (btnPos != null) db.setPositiveButton(btnPos, ocListener);
    if (btnNeutral != null) db.setNeutralButton(btnNeutral, ocListener);
    if (btnNeg != null) db.setNegativeButton(btnNeg, ocListener);
    db.setIcon(android.R.drawable.ic_dialog_alert);
    db.show();
}

But I have just recently converted it to kotlin. Calling the alert dialog (in Kotlin):

    Misc.alertDlg(this, "Confirm", "Delete the file?", "Yes", null, "Cancel"){
        which-> if(which == Misc.BTN_POS) deleteYourFile()
    }

And the alert dialog function (a function in an object called Misc):

fun alertDlg(context: Context, title: String, msg: String, btnNeg: String?, btnNeutral: String?, btnPos: String?,
             onClickCallback: (which: Int) -> Unit) {
    val ocListener = DialogInterface.OnClickListener() {dialog, which ->
        onClickCallback(which)
    }
    val db = AlertDialog.Builder(context)
    db.setTitle(title)
    db.setMessage(msg)
    if (btnPos != null) db.setPositiveButton(btnPos, ocListener)
    if (btnNeutral != null) db.setNeutralButton(btnNeutral, ocListener)
    if (btnNeg != null) db.setNegativeButton(btnNeg, ocListener)
    db.setIcon(android.R.drawable.ic_dialog_alert)
    db.show()
}

I have also been using a similar method to show a text input dialog.

You can use AlertDialog and AlertDialog.Builder.

new AlertDialog.Builder(context)
    .setTitle("some_title")
    .setMessge("some_message")
    .setNegativeButton("No", null)
    .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(int which) {
                // do some action
            }
        })
    .show();

try below code:

calling way

new CustomDialog().makeDialog(Activity.this,"pass value from diffrent-2 ");

class CustomDialog

public class CustomDialog
{

    public void makeDialog(Context con, String value)
    {
        final DialogTwoOptions dialog = new DialogTwoOptions(con);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        dialog.setContentView(R.layout.ur_xml);
        dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
        // set the custom dialog components - text, image
        // and button
        dialog.setCanceledOnTouchOutside(false);
        Button yes = (Button) dialog.findViewById(R.id.dialog_yes_btn);
        Button no = (Button) dialog.findViewById(R.id.dialog_no_btn);

        yes.setOnClickListener(new Button.OnClickListener()
        {
            public void onClick(View v)
            {
                dialog.dismiss();
                // Do something
                if (value.equals("1"))
                {
                }
                else if (value.equals("1"))
                {
                }
                // do more condition
            }
        });

        no.setOnClickListener(new Button.OnClickListener()
        {
            public void onClick(View v)
            {
                dialog.dismiss();
                // Do something
                if (value.equals("1"))
                {
                }
                else if (value.equals("1"))
                {
                }
                // do more condition
            }
        });

        dialog.show();
    }
}
package com.example.jojo.gridview;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
public class DialogClass extends Dialog {
 Bitmap b;
String n;
public DialogClass(Context context,Bitmap img,String name) {
    super(context);
    b=img;
    n=name;
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.dialog_style);
    ImageView image= (ImageView) findViewById(R.id.imageView2);
    TextView text= (TextView) findViewById(R.id.textView2);
    image.setImageBitmap(b);
    text.setText(n);

}

}

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top