I have popup window class like the following.
public class Popup extends PopupWindow {
Context context;
EditText et_bankname, et_banknumber;
String bank_name, account_number;
public Popup(Context ctx) {
super(ctx);
context = ctx;
setContentView(LayoutInflater.from(context).inflate(R.layout.bank_details, null));
setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
View popupView = getContentView();
setFocusable(true);
Button btn_close = (Button) popupView.findViewById(R.id.popupClose);
Button btn_submit = (Button) popupView.findViewById(R.id.popupSave);
et_bankname = (EditText) popupView.findViewById(R.id.bank_name);
et_banknumber = (EditText) popupView.findViewById(R.id.bankacc_no);
btn_submit.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
bank_name = et_bankname.getText().toString();
account_number = et_banknumber.getText().toString();
if (!bank_name.equals("") && !account_number.equals("")) {
Toast t1 = Toast.makeText(context,bank_name + " "+account_number , Toast.LENGTH_SHORT);
t1.setGravity(Gravity.TOP, 0, 100);
t1.show();
dismiss();
} else {
Toast t1 = Toast.makeText(context,
"Please provide valid details", Toast.LENGTH_SHORT);
t1.setGravity(Gravity.TOP, 0, 100);
t1.show();
}
}
});
}
public void show(View v) {
showAtLocation(v, Gravity.CENTER, 0, 0);
}
}
I will access this popup in my activity by
Popup popup = new Popup(getBaseContext());
popup.show(arg1);
This works perfectly. But I want to know when this popup window gets dismissed. for this purpose now I am using Thread concept like following.
if (isPopupShowing) {
Thread thread = new Thread() {
#Override
public void run() {
while (isPopupShowing) {
if (!popup.isShowing()) {
isPopupShowing = false;
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
loadDSP(type);
}
});
}
}
}
};
thread.start();
}
But this thread will run continuesly until the popup window gets dismissed. So I feel it is better to replace this solution by any other way.
What I want?
Just intimate to my activity like "popup is closed" when popup is dismissed.
Why I am use this way?
I will use this popup window in three activty. That is why I am create a separate class for popup window.
Any help will be highly appriciated.
Thank you.
PopupWindow already has its own dismiss listener, just use it as follows
Popup popup = new Popup(getBaseContext());
popup.show(arg1);
Change that to
Popup popup = new Popup(getBaseContext());
popup.setOnDismissListener(new PopupWindow.OnDismissListener() {
#Override
public void onDismiss() {
// Do your action
}
});
popup.show(arg1);
EDIT
I hadn't noticed you were extending a PopupWindow, which already has this implemented as shown in #Jayabal's answer. Anyway this is how you would do it if the PopupWindow didn't already have it's own onDismissListener.
Simply create your own OnDismissListener Interface.
public interface onDismissListener{
public void onDismiss();
}
Add a reference to a Listener in the PopUp class and a setter.
OnDismissListener listener;
public void setOnDismissListener(OnDismissListener listener){
this.listener = listener;
}
Then in your Activity
Popup popup = new Popup(getBaseContext());
popup.setOnDismissListener(new OnDismissListener(){
public void onDismiss(){
//do what you need to here
}
});
popup.show(arg1);
This pattern should be familiar to you, its used everywhere in Android.
Related
I have a custom dialog box that I am displaying in the following way:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.dict_add_word_dialog_box);
ok = findViewById(R.id.dictDialog_confirmButton);
cancel = (Button) findViewById(R.id.dictDialog_cancelButton);
ok.setOnClickListener(this);
cancel.setOnClickListener(this);
}
This displays when tapping the Floating Action Button, via:
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
DictCustomDialogBoxClass customDialog = new DictCustomDialogBoxClass(DictionaryActivity.this);
customDialog.show();
refreshRecyclerView();
}
});
I'd like the refreshRecyclerView(); to run only once the user has pressed the OK button on the dialog box. How would I go about doing this?
In addition, how would I go about running it only if the user has pressed OK, and not Cancel?
Create a runnable with your refreshRecyclerView method in it:
Runnable r = new Runnable() {
#Override
public void run() {
refreshRecyclerView();
}
}
then create a handler for that runnable:
Handler handler = new Handler();
inside your onClickListener for the ok button trigger the runnable by calling the following:
handler.post(r);
Why not add a listener to your custom dialog?
var listener: Listener
public interface Listener {
void onPositiveActionPressed();
}
Then in your custom dialog's ok.onClickListener you'd have the below;
if(listener != null) {
listener.onPositiveActionPressed();
}
Finally;
DictCustomDialogBoxClass customDialog = new DictCustomDialogBoxClass(DictionaryActivity.this)
customDialog.listener = self
Of course having implemented DictCustomDialogBoxClass.Listener
I am working on project, which simply validates through username and password.
I made some progress with using DialogFragments and AlertDialog. AlertDialog appears after starting the app over the mainactivity asking for username and password.
I must set the Alertdialog's setCanceledOnTouchOutside(false) and DialogFragment's setCancelable(false) because I don't want the users to dismiss it with pressing android's back button.
The problem is, after dismissing it programatically on successful login, if the activity becomes invisible and visible again , the Alertdialog's OnShowListener called, showing this AlertDialog again.
Can I somehow "detach" this AlertDialog from Activity? This popups also happen after unlocking the screen and getting back to activity which makes it very annoying...
Here is the code of interest:
MainActivity
public class MainActivity extends AppCompatActivity implements NoticeDialogFragment.NoticeDialogListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(GlobalInformations.getInstance().getUsername()==null){
shownoticeDialog();
}
}
public void shownoticeDialog(){
DialogFragment dialogFragment = new NoticeDialogFragment();
dialogFragment.show(getFragmentManager(), "NoticeDialogFragment");
}
#Override
public void onDismiss(DialogFragment dialog) {
//set the username on a TextView instance, etc...
}
NoticeDialogFragment extends DialogFragment
public class NoticeDialogFragment extends DialogFragment {
public interface NoticeDialogListener{
public void onDialogPositiveClick(DialogFragment dialog);
public void onDialogNegativeClick(DialogFragment dialog);
public void onDismiss(DialogFragment dialog);
}
NoticeDialogListener mListener;
static Activity activity = null;
//static String username;
#Override
public void onAttach(Context context) {
super.onAttach(context);
try{
activity = (Activity) context;
mListener = (NoticeDialogListener) activity;
} catch (ClassCastException e){
throw new ClassCastException(activity.toString() + "must implement NoticeDialogListener");
}
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.dialog_signin, null);
final AutoCompleteTextView actv_username = (AutoCompleteTextView) view.findViewById(R.id.username);
final EditText password = (EditText) view.findViewById(R.id.password);
getavailableusernames(actv_username);
final AlertDialog dialog = new AlertDialog.Builder(new ContextThemeWrapper(getContext(), R.style.AlertDialogCustom))
.setView(view)
.setTitle("Login")
.setPositiveButton("OK", null)
//.setNegativeButton("Cancel", null)
.create();
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialogInterface) {
final Button button =((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String passw = password.getText().toString();
String user = actv_username.getText().toString();
try{
if(user.length()<4 || passw.length()<4){
Toast.makeText(getContext(), "Username/password too short", Toast.LENGTH_SHORT).show();
dialog.show();
}
else {
//login to account, if success dismiss.
login(user, passw,dialog);
}
} catch(Exception e){
}
// dialog.dismiss();
}
});
}
});
dialog.setCanceledOnTouchOutside(false);
// set the DialogFragment to make the dialog unable to dismiss with back button
// (because not working if called on the dialog directly)
this.setCancelable(false);
return dialog;
}
public void login(final String username, String password, final AlertDialog dialog){
boolean login_success = false;
//query the credentials
login_success = dosomesqlquery(username, password);
if(login_success){
dialog.dismiss();
}
}
//passing the handling to activity...
#Override
public void onDismiss(DialogInterface dialog) {
mListener.onDismiss(NoticeDialogFragment.this);
}
}
Thank you for your help and patience.
Well this is that kind of situation where I end up heading my desk continously.
The source of the problem was I called dialog.dismiss() which dismisses the dialog, BUT not the dialogfragment itself, so will never, ever dismissed, even if the dialog disappeared from screen. Placing this.dismiss() in NoticeDialogFragment's onDismiss or anywhere else after login succeded will let the application act as it should.
#Override
public void onDismiss(DialogInterface dialog) {
mListener.onDismiss(NoticeDialogFragment.this);
this.dismiss(); //will dismiss the DialogFragment. Yeeey!
}
Thank you for your time and answers as they helped me point out the real problem. I will modify the code based on your suggestions.
An easier way is to use a static variable in your activity using two steps.
Declare a global static boolean
private static boolean session = false;
Check if the boolean has changed and if not, set the boolean to true when the dialog is shown
public void shownoticeDialog(){
if(session)return;
DialogFragment dialogFragment = new NoticeDialogFragment();
dialogFragment.show(getFragmentManager(), "NoticeDialogFragment");
session = true;
}
Set the value when the activity goes background
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean("authUser", GlobalInformations.getInstance().getUsername()==null)
}
and read it when it comes back
#Override
protected void onCreate(Bundle savedInstanceState) {
if(savedInstanceState != null && savedInstanceState.containsKey("authUser")) {
boolean authUser = savedInstanceState.getBoolean("authUser", false);
if(authUser) {
//show or don't show dialog
}
}
}
I want to close the popup window when I click a button, but it seems dismiss function doesn't work and the window is not closing. What did I wrong?
(I'm a beginner, so codes might be 'weird'. Please understand...)
public class AlarmPopup extends Activity {
private PopupWindow popup;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
onShowPopup();
}
public void onShowPopup(){
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View view = inflater.inflate(R.layout.alarm_popup, null, false);
final PopupWindow popup = new PopupWindow(view, 400, 300, true);
setContentView(R.layout.alarm_popup);
view.findViewById(R.id.button).post(new Runnable() {
#Override
public void run() {
popup.showAtLocation(view, Gravity.CENTER, 0, 0);
}
});
findViewById(R.id.button).setOnClickListener(mClickListener);
}
Button.OnClickListener mClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) { // dismiss and stop the alarm function on other class
Intent i = new Intent(AlarmPopup.this, AlarmService.class);
stopService(i); // this function is working...
popup.dismiss();
}
};
}
You have declared popup as global and inside your onShowPopup you are creating new object for popup so that local popup will never be accessible from listener so make the changes as below:
public void onShowPopup(){
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View view = inflater.inflate(R.layout.alarm_popup, null, false);
popup = new PopupWindow(view, 400, 300, true);
setContentView(R.layout.alarm_popup);
view.findViewById(R.id.button).post(new Runnable() {
#Override
public void run() {
popup.showAtLocation(view, Gravity.CENTER, 0, 0);
}
});
view.findViewById(R.id.button).setOnClickListener(mClickListener);
}
Popup variable that you are using to dismiss your popup window has not been initialized in the code that you have posted. Your final variable that you have created inside method is local and will not be accessible outside that method.
So initialize your variable or use same variable inside method too.
I have a Fragment. When the Fragment is created I want to show a Progress Dialog for 3 seconds, then dismiss it and show a pop up dialog. I attach below my code.
From the onCreate() of my Fragment:
final ProgressDialog myPd_ring=ProgressDialog.show(context, "Please wait", "text..", true);
myPd_ring.setCancelable(false);
new Thread(new Runnable() {
#Override
public void run() {
try
{
Thread.sleep(3000);
} catch(Exception e)
{
}
myPd_ring.dismiss();
}
}).start();
showPopup(0, 8, 1, "Next photo");
And my popup method:
public void showPopup(final int type, int photoNo, int currPhoto, String message) {
final Dialog dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.popup_erroare);
dialog.setCancelable(false);
TextView textHeader;
TextView textContent;
textHeader = (TextView) dialog.findViewById(R.id.text_titlu);
textContent = (TextView) dialog.findViewById(R.id.text_error);
textHeader.setText("Procedura fotografiere");
textContent.setText("Poza nr. " + currPhoto+ " of" + noPhoto+
". " + message);
if (type == 0) {
}
Button btn_nu = (Button) dialog.findViewById(R.id.button_nu);
if (type == 0) {
btn_nu.setText("NU");
}
btn_nu.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
btn_nu.setVisibility(View.GONE);
Button btn_da = (Button) dialog.findViewById(R.id.button_da);
btn_da.setText("Fotografiere");
btn_da.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (type == 0) {
captureImage();
}
dialog.dismiss();
}
});
dialog.show();
}
The problem is that my ProgressDialog doesn't appear, the popup appears directly. If I put my pop up invoking method in the new Thread() body I get an error. It seems that you can invoke a dialog from a Runnable.
you can use the below code:
final ProgressDialog myPd_ring=ProgressDialog.show(context, "Please wait",
"text..", true);
myPd_ring.setCancelable(false);
myPd_ring.show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
myPd_ring.dismiss();
showPopup(0, 8, 1, "Next photo");
}
}, 3000);
If you have any query please let me know.
Never use sleep() in final APP.
try this way, new a Runnable(), and call postDelay(runnable, delayTimes) on a Handle.
Android Handler has a handy method postDelay() that does what you need, for example:
final ProgressDialog myPd_ring=ProgressDialog.show(context, "Please wait", "text..", true);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
myPd_ring.dismiss();
// show popup
}
}, 3000);
In Android, all View related tasks must be executed in the main thread, doing it in other threads will result in error. If you want to do in inside a background task for example, you'll need to use myactivity.runOnUiThread()
runOnUiThread(new Runnable() {
#Override
public void run() {
// show my popup
}
});
I'm having the following issue developing in android 2.2 (API 8):
I have a customized Dialog class like this:
public AuthDialog(final Context context, OnDismissListener dismissListener, OnCancelListener cancelListener) {
super(context);
setOnDismissListener(dismissListener);
setOnCancelListener(cancelListener);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.userpassdialog);
setTitle("Enter email and password");
setCancelable(true);
setCanceledOnTouchOutside(true);
authEmail = (EditText) findViewById(R.id.authEmail);
authPass = (EditText) findViewById(R.id.authPass);
alertMessage = (TextView) findViewById(R.id.auth_alert);
Button authButton = (Button) findViewById(R.id.authButton);
View.OnClickListener onClickListener = new View.OnClickListener() {
public void onClick(View v) {
if (checkCredentials())
dismiss();
else
showAlert();
}
};
authButton.setOnClickListener(onClickListener);
}
private void showAlert() {
alertMessage.setText("Wrong user/pass");
authEmail.setText(null);
authPass.setText(null);
}
private boolean checkCredentials() {
// Empty user/pass for now
boolean checkEmail = authEmail.getText().toString().equals("");
boolean checkPassword = authPass.getText().toString().equals("");
return checkEmail && checkPassword;
}
#Override
public void onBackPressed() {
cancel();
}
And I create a new AuthDialog like this:
private void authenticateThenAccept() {
OnDismissListener dismissListener = new OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
accept();
}
};
OnCancelListener cancelListener = new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
cancel();
}
};
AuthDialog dialog = new AuthDialog(context, dismissListener, cancelListener);
dialog.show();
}
I'm using the debugger, and I see that when I cancel (using the back button or pressing outside the dialog) the app dismisses the dialog instead of cancelling.
Anybody has had this kind of issue with Dialogs?
Thanks in advanced.
onDismiss() is always fired when dialog closes. The documentation for setOnCancelListener() states: "This will only be invoked when the dialog is canceled, if the creator needs to know when it is dismissed in general, use setOnDismissListener", i.e. it's not either onCancel or onDismiss but both when a dialog is canceled. I agree though that it would have made more sense had that not been the case.
Assuming this dialog should be modal, make your dialog a new activity.
setCancelable(false) will prevent the back button from doing anything. Many developers just turn off the ability of the back button to close the dialog since it's unclear whether that is a cancel or ok action to the user.