I have a custom dialog which extends the Dialog Class, I would like to bind an event to execute some code after the Dialog is closed when the user presses the BACK button of the device. How can I do that? I found a post where someone says that the .addWindowListener() should be used when working with Dialogs and other Window widgets. But the dialog class doesn't have the addWindowListener method, so I cannot use it. Is there another way without using fragments cause I shouldn't re-write the MyCustomDialog class?
This is the code:
public class MyCustomDialog extends Dialog {
public MyCustomDialog(Context context, int layoutResourceId) {
super(context);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(layoutResourceId);
}
}
Thanks for the attention!
EDIT: i found this on the android developers site, is there a way to use it with MyCustomDialog class?
onDismiss DialogInterface
Since you are extending android Dialog class you can implement a Dismiss Listener in your Activity's and set it when you create the Dialog, and then in the listener implement any functionality you want depending on the button that was used to dismiss the Dialog.
Hope this will solve your problem.
Edit You can use dialog.setCanceledOnTouchOutside(false); which will stop closing the dialog if you touch outside of the dialog.
Something like,
Dialog dialog = new Dialog(context)
dialog.setCanceledOnTouchOutside(false);
OR Alternatively
Override onTouchEvent() of dialog and check for action type. if the action type is
'MotionEvent.ACTION_OUTSIDE' means, user is interacting outside the dialog region. So in this case, you can dimiss your dialog or decide what you wanted to perform.
view plainprint?
dialog.setOnTouchListener(new View.OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_OUTSIDE){
Toast.make(getApplicationContext(), "TOuched outside the dialog", Toast.LENGTH_LONG).show();
this.dismiss();
}
return false;
}
});
And for back press you can do dialog.setCancelable(false); which will prevent dialog getting cancelled from backpress event.
OR you can alternatively override setOnKeyListener event and put your own code into it.
Edit
dialog.setOnKeyListener(new Dialog.OnKeyListener() {
#Override
public boolean onKey(DialogInterface arg0, int keyCode,
KeyEvent event) {
// TODO Auto-generated method stub
if (keyCode == KeyEvent.KEYCODE_BACK) {
finish();
dialog.dismiss();
}
return true;
}
});
Happy Coding!!!
You need to Override onBackPressed inside Dialog class. Also make sure to close dialog after override OnBackPressed .
Try this
public class MyCustomDialog extends Dialog {
public MyCustomDialog(Context context, int layoutResourceId) {
super(context);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(layoutResourceId);
}
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
dismiss(); // make sure to call dismiss to close dialog
// put your code here
}
}
If you want to trigger an event if user clicked/touched outside the dialog and close it or used the back button to close then use
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
//your trigger goes here
Toast.makeText(IntroductoryActivity.this, "on cancel", Toast.LENGTH_SHORT).show();
}
});
But if you want to trigger an event if something dismisses the dialog, like some other event then use
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
//your trigger goes here
Toast.makeText(IntroductoryActivity.this, "on dismiss", Toast.LENGTH_SHORT).show();
}
});
Related
I have an activity where the whole screen is dedicated to sending one message. Being one EditText on the top half, and the SoftKeyboard always visible on the bottom half.
When i press back, the SoftKeyboard hides and i have to press back again to leave the activity.
The behavior that i'm struggling to get is : finishing the activity right away when i press the back button, instead of hiding the keyboard.
You can find this behavior in the twitter app for example, when writing a new tweet.
I tried with overriding the onBackPressed() function, but seems like when the keyboard is visible, the function is not called.
#Override
public void onBackPressed() {
finish();
}
Any help would be really appreciated!
So after trying many things, here something that worked :
Subclass EditText and override the onKeyPreIme() function to send a call back.
Here's the code for the subclass :
OnKeyPreImeListener onKeyPreImeListener;
public void setOnKeyPreImeListener(OnKeyPreImeListener onKeyPreImeListener) {
this.onKeyPreImeListener = onKeyPreImeListener;
}
#Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
if(onKeyPreImeListener != null)
onKeyPreImeListener.onBackPressed();
Log.d(TAG, "HIDING KEYBOARD");
return false;
}
return super.dispatchKeyEvent(event);
}
public interface OnKeyPreImeListener {
void onBackPressed();
}
Then in your activity for each of your TextView :
EditTextGraphee.OnKeyPreImeListener onKeyPreImeListener =
new EditTextGraphee.OnKeyPreImeListener() {
#Override
public void onBackPressed() {
Log.d(TAG, "CALL BACK RECEIVED");
MyActivity.this.onBackPressed();
}
};
editText.setOnKeyPreImeListener(onKeyPreImeListener);
new answer:
so apparently you don't receive the onBackPressed callback, but that doesn't mean you can't detect the keyboard closing.
Using the technique described here: How to check visibility of software keyboard in Android?
you can detect when the keyboard open/close, so when the keyboard closes you call finish();
deprecated, original answer:
simply override the back press event in the activity:
#Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
I assume that since the soft keyboard is visible probably an edittext has a focus. So you can catch the back pressed event by adding an OnEditorActionListener on that EditText and finish activity.
yourEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP){
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK){
finish();
}
}
return false;
}
});
You nee to extend EdtText class and implement onKeyPreIme method.
public class MyEditText extends EditText {
/* Must use this constructor in order for the layout files to instantiate the class properly */
public MyEditText(Context context, AttributeSet attrs)
{
super(context, attrs);
// TODO Auto-generated constructor stub
}
#Override
public boolean onKeyPreIme (int keyCode, KeyEvent event)
{
// do your stuff here.
return true;
}
}
Override onBackPressed() method like this :
#Override
public void onBackPressed() {
hideKeyboard();
finish();
}
For hideKeyboard() function please search in the Internet .
When I click an Android button the Android's Software Keys are shown (hidden before) instead of firing the onClick() method for the actual button that I click.
I have two methods for showing or hiding the system UI:
1.
// Set up the user interaction to manually show or hide the system UI.
contentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (TOGGLE_ON_CLICK) {
mSystemUiHider.toggle();
} else {
mSystemUiHider.show();
}
}
});
and 2:
/**
* Touch listener to use for in-layout UI controls to delay hiding the
* system UI. This is to prevent the jarring behavior of controls going away
* while interacting with activity UI.
*/
View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (AUTO_HIDE) {
delayedHide(AUTO_HIDE_DELAY_MILLIS);
}
return false;
}
};
And I also have another method which a switch to get the onClick() event on buttons
public void onClick(View v) { switch() { } }
Is it possible to fix this behaviour and when I click the actual button will be fired and the System UI will be shown?
There is no workaround to overcome this behaviour until you have both touch listener and also a click listener inside the same view. Try using
View.SYSTEM_UI_FLAG_LOW_PROFILE|View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
instead. Add the below code before setcontentview() method.
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_LOW_PROFILE|View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
decorView.setSystemUiVisibility(uiOptions);
There are the 3 basic keys in an Android device.
1. Home button (middle button)
2. Menu button (left most button)
3. Back Button (right most button)
I'm trying to create a code the use will press the Back button and a AlertDialog will appear before return to the previous activity.
How can I handle the back button and do I have to insert it on the onCreate on the Java File of an Activity?
Thank You!
All (4) buttons are handled differently.
The home button and running apps buttons are completely outside your control.
To get the BackButton press, override this function.
#Override
public void onBackPressed(){
//Do Stuff
}
To get the Menu button key press, use the following
#Override
public boolean onKeyDown(int keycode, KeyEvent e) {
switch(keycode) {
case KeyEvent.KEYCODE_MENU:
doSomething();
return true;
}
return super.onKeyDown(keycode, e);
}
After you show the user your alert dialog, you can either send a real BackPress to the system using super.onBackPressed(), or you can manually finish() your activity.
#Override
public void onBackPressed(){
AlertDialog.Builder build=new AlertDialog.Builder(currentactivity.this);
build.setMessage("Are you sure you want to return?");
build.setCancelable(false);
build.setTitle("Note");
build.setPositiveButton("yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int arg1) {
Intent i =new Intent(currentactivity.this,anotheractivity.class);
startActivity(i);
//or just type finish();
}
});
build.setNegativeButton("no", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int arg1) {
dialog.cancel();
}
});
AlertDialog alert=build.create();
alert.show();
}
I have a simple AlertDialog that displays a list of some items and upon clicking one of them, the clicked item is passed back to the enclosing Activity. I also want to perform some default handling when the user cancels the dialog (using the back button) - more specifically, I want to pass an empty string to the activity in such case.
However, if I put the dialog in a DialogFragment (from the compatibility package), the OnCancelListener is not called when I close the dialog with the back button. What am I doing wrong?
public class SelectItemDialog extends DialogFragment {
public interface Callback {
void onItemSelected(String string);
}
private static final String ARG_ITEMS = "items";
private Callback callback;
public static SelectItemDialog fromItems(Collection<String> items) {
SelectItemDialog fragment = new SelectItemDialog();
fragment.setArguments(newArguments(items));
return fragment;
}
private static Bundle newArguments(Collection<String> items) {
Bundle arguments = new Bundle();
arguments.putStringArray(ARG_ITEMS, items.toArray(new String[items.size()]));
return arguments;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
callback = (Callback) activity;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final String[] items = getArguments().getStringArray(ARG_ITEMS);
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.dialog_select_email_title)
.setItems(items, new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
callback.onItemSelected(items[which]);
}
})
.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
// this code is not executed
callback.onItemSelected("");
throw new RuntimeException("dialog cancelled");
}
})
.create();
}
}
It might have to do with the fact that there is no explicit call to cancel() from your code.
The OnCancelListener documentation says:
This will only be called when the dialog is canceled
Which probably needs an explicit cancel() call.
Either make a positive/negative button with a OnClickListener that calls DialogInterface#cancel() or use a OnDismissListener() with an extra check to see if a list item was clicked.
Also, to listen for a back keypress and cancel the dialog, you can set up an OnKeyListener, like outlined in this SO answer
Also, once you have the Dialog set up, it would also be a good idea to use Dialog#setCanceledOnTouchOutside() in case the the user taps outside the Dialog.
Edit: The below part is the easy way to handle cancel events in a DialogFragment.
Since you are using a DialogFragment, this class has a very handy method, DialogFragment#onCancel() which gets called when the DialogFragment is cancelled. Do your logic in there.
DialogFragments are more complex, with a slightly different lifecycle than normal dialogs. Therefore, first check the documentation if you have a certain Dialog-based approach that you are trying to port to a DialogFragment, some methods may exist that allow your new implementation to function properly!
If you are using DialogFragment and want to listen back button then use this -
this.getDialog().setOnKeyListener(new Dialog.OnKeyListener() {
#Override
public boolean onKey(DialogInterface dialog, int keyCode,
KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (****) {
your logic
}
return true;
}
return false;
}
});
Note: DialogFragment own the Dialog.setOnCancelListener and Dialog.setOnDismissListener callbacks. You must not set them yourself.
To find out about these events, override onCancel(DialogInterface) and onDismiss(DialogInterface).
public class SelectItemDialog extends DialogFragment {
#Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
//your code hear
dialog.cancel();
}
}
And you should remove .setOnCancelListener()
Actually if you want to use DialogFragment, you can never add OnCancelListener or OnDismissListener to it, since the Dialog Fragment owns callbacks to these methods!
You have 3 options here:
1- go with regular dialogs.2- set your dialog fragment to cancellable(false) and add a cancel button to the dialog.3- check #Nikhil Pingle answer.
this is from the documentation of the Dialog Fragment
* <p><em>Note: DialogFragment own the {#link Dialog#setOnCancelListener
* Dialog.setOnCancelListener} and {#link Dialog#setOnDismissListener
* Dialog.setOnDismissListener} callbacks. You must not set them yourself.</em>
* To find out about these events, override {#link #onCancel(DialogInterface)}
* and {#link #onDismiss(DialogInterface)}.</p>
Cancel Listener or Dismiss listener in DialogFragment can achieve by onDismiss
DialogFragment newFragment = new DatePickerFragment();
newFragment.show(getFragmentManager(), "datePicker");
newFragment.onDismiss(new DialogInterface(){
#Override
public void cancel() {
// TODO Auto-generated method stub
}
#Override
public void dismiss() {
// TODO Auto-generated method stub
}
});
Hi stackoverflow friends
I recently faced an issue that how can i disable global search button in android while an alert is shown in the screen.I don't want to disappear the alert box by using search button. I need to user must click the alertbox button and disappears in that way.So I want to disable the search button while alert box is shown. But I can disable the back button using setCancable(false).How can I solve this ?
THanks in advance.
So, Your intention is to provide non-cancelable alert.
Suggesting to set OnDismissListener and just show alert again. It's not very good from visual perspective (alert get closed and opened again).
Below is some obvious example how to achieve such non-cancelable alert (code is inside Acctivity class):
/** reference to our alert */
private AlertDialog alert = null;
/** to indicate if alert dismissed by key */
private boolean alertKeyPressed = false;
#Override
protected void onResume() {
// Say, we need to show alert when activity resumed
if(true/*provide condition to show alert*/) {
showAlert();
}
}
/**
* Show non dismissable alert
*/
private void showAlert() {
if(null == this.alert) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(false);
builder.setTitle(R.string.str_alert_title);
builder.setMessage(R.string.str_alert_text);
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setNeutralButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
YourActivity.this.alertKeyPressed = true;
dialog.dismiss();
}
});
this.alert = builder.create();
this.alert.setOwnerActivity(this);
this.alert.show();
this.alert.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
// dialog is not allowed to be dismissed, so show it again
YourActivity.this.alert = null;
if(!YourActivity.this.alertKeyPressed) {
showAlert();
}
}
});
}
}
However, I don't think it's the right way to left such alert for the user, sometimes it might be needed for cases like evaluation restriction etc.
Override onSearchRequested in your Activity and have it return false while the dialog is being shown. This should block the request, as per the docs:
You can override this function to force global search, e.g. in
response to a dedicated search key, or to block search entirely (by
simply returning false).
Returns true if search launched, and false if activity blocks it. The
default implementation always returns true.
.setOnKeyListener(new DialogInterface.OnKeyListener()
{
#Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event)
{
//There you catch the key, do whatever you want to do.
//Return true if you handled the key event, so nothing will trigger.
//Return false if you want your activity to handle.
return true;
}
})
Just add the code above to alert dialog builder. Hope this snippet would help. Good luck.