Create a general class for custom Dialog in java Android
Solution 1
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 .
Solution 2
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.
Solution 3
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.
Related videos on Youtube
danigonlinea
The first idea is what matters to you. Do less. Think smarter involving today. --- Frontend Developer
Updated on August 23, 2020Comments
-
danigonlinea over 3 years
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
-
danigonlinea about 10 yearswhy anyone has voted -1? this is a reasonable question.
-
-
danigonlinea about 10 yearsbut it is not a custom dialog with a custom layout. The default theme of AlertDialog is really ugly.
-
danigonlinea about 10 yearsLibin, it is really good idea but it is not general. I mean that onClick events of setPositiveButton and setNegativeButton can change. Imagine that I have 10 dialogs thats looks the same but, depends where activity/screen are, when I click "yes" it is gonna be different in all of this activities.
-
Libin about 10 yearsOk. I will update the answer. Are you fine with Dialog Fragment ?
-
danigonlinea about 10 yearsit is the same idea like Libin. The Onclick events can not be changed. I want to be able to change the funcionality of yes or no events, but I want the same dialog in all of them. It is like to override the onclick functions and have abstract funcionts in the class... but i don't know how to get it.
-
danigonlinea about 10 yearsWell, I would like to work < 3.0 android versions but, I thing it is gonna be ok with Dialog Fragment. I mean, sooner or later, we will have to think on > 4.0 android versions.
-
danigonlinea about 10 yearsSorry I needed some time to eat it, it is a little hard when I saw it first time... Anyway it is a great approach that I was looking for, general code. The key is to link the onClick events to interfaces functions and have a base dialog... very wise. I don't check it yet but I will accepted it as a real answer. Thanks
-
peterh over 8 yearsAlthough the code is appreciated, it should always have an accompanying explanation. This doesn't have to be long, but it is expected.
-
Cliff almost 8 years@Libin how i use it on Fragment?
-
Jainam Jhaveri over 6 yearsOh great. This also handles the case of multiple dialogs in the same activity. Thanks:)
-
Faisal Mohammad over 5 yearsthe interface are not working in fragment .please any body tell me how use in fragment
-
Rafael Baptista almost 5 yearsThis was exactly what I needed... thank you so much!
-
Abigail La'Fay over 4 yearsThis is what I wanted: How to push OnClickListener as parameter. Thank you!
-
AlexS over 4 yearsAnybody can please tell me about why or where i should use activityInstance of BaseDialog?
-
steveOS about 4 yearsThis Worked for me, but I had to remove
requestWindowFeature(Window.FEATURE_NO_TITLE);
because it was producing an error -
nikhil123 about 4 yearsthanks, but there is a minor mistake in code it sould be
.setMessage(getArguments().getString("msg"))
instead of.setMessage(getArguments().getString("message"))