Ho implementato una finestra di dialogo personalizzata per la mia applicazione. Voglio implementare che quando l'utente fa clic al di fuori della finestra di dialogo, la finestra di dialogo verrà chiusa. Cosa devo fare per questo?
Ho implementato una finestra di dialogo personalizzata per la mia applicazione. Voglio implementare che quando l'utente fa clic al di fuori della finestra di dialogo, la finestra di dialogo verrà chiusa. Cosa devo fare per questo?
Risposte:
È possibile utilizzare dialog.setCanceledOnTouchOutside(true);
ciò che chiuderà la finestra di dialogo se si tocca al di fuori della finestra di dialogo.
Qualcosa di simile a,
Dialog dialog = new Dialog(context)
dialog.setCanceledOnTouchOutside(true);
O se la tua finestra di dialogo non è modello allora,
1 - Imposta il flag - FLAG_NOT_TOUCH_MODAL
per l'attributo della finestra della tua finestra di dialogo
Window window = this.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
2 - Aggiungi un altro flag alle proprietà di Windows, FLAG_WATCH_OUTSIDE_TOUCH
- questo è per la finestra di dialogo per ricevere l'evento touch al di fuori della sua area visibile.
3 - Sostituisci la onTouchEvent()
finestra di dialogo e controlla il tipo di azione. se il tipo di azione è ' MotionEvent.ACTION_OUTSIDE
' significa che l'utente sta interagendo al di fuori dell'area di dialogo. Quindi, in questo caso, puoi ridimensionare la finestra di dialogo o decidere cosa vuoi eseguire. visualizzare il testo in chiaro?
public boolean onTouchEvent(MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_OUTSIDE){
System.out.println("TOuch outside the dialog ******************** ");
this.dismiss();
}
return false;
}
Per maggiori informazioni guarda Come chiudere una finestra di dialogo personalizzata basata su punti di contatto? e Come chiudere la finestra di dialogo non modale quando viene toccata al di fuori dell'area di dialogo
Basta usare
dialog.setCanceledOnTouchOutside(true);
È possibile utilizzare questa implementazione di onTouchEvent. Impedisce di reagire al di sotto dell'attività all'evento touch (come detto howettl).
@Override
public boolean onTouchEvent ( MotionEvent event ) {
// I only care if the event is an UP action
if ( event.getAction () == MotionEvent.ACTION_UP ) {
// create a rect for storing the window rect
Rect r = new Rect ( 0, 0, 0, 0 );
// retrieve the windows rect
this.getWindow ().getDecorView ().getHitRect ( r );
// check if the event position is inside the window rect
boolean intersects = r.contains ( (int) event.getX (), (int) event.getY () );
// if the event is not inside then we can close the activity
if ( !intersects ) {
// close the activity
this.finish ();
// notify that we consumed this event
return true;
}
}
// let the system handle the event
return super.onTouchEvent ( event );
}
Fonte: http://blog.twimager.com/2010/08/closing-activity-by-touching-outside.html
Oppure, se stai personalizzando la finestra di dialogo usando un tema definito nel tuo stile xml, inserisci questa linea nel tuo tema:
<item name="android:windowCloseOnTouchOutside">true</item>
dialog.setCanceledOnTouchOutside(true);
funziona meravigliosamente.
Questo metodo dovrebbe evitare completamente le attività al di sotto dell'area grigia che recupera eventi di clic.
Rimuovi questa linea se ce l'hai:
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
Metti questo sulla tua attività creata
getWindow().setFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
quindi sovrascrivere l'evento touch con questo
@Override
public boolean onTouchEvent(MotionEvent ev)
{
if(MotionEvent.ACTION_DOWN == ev.getAction())
{
Rect dialogBounds = new Rect();
getWindow().getDecorView().getHitRect(dialogBounds);
if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) {
// You have clicked the grey area
displayYourDialog();
return false; // stop activity closing
}
}
// Touch events inside are fine.
return super.onTouchEvent(ev);
}
Questo codice viene utilizzato per quando si fa clic sulla finestra di dialogo in quel momento nasconde l'inserimento e quando l'utente fa clic sul lato esterno della finestra in quel momento sia l'input software che la finestra di dialogo sono vicini.
dialog = new Dialog(act) {
@Override
public boolean onTouchEvent(MotionEvent event) {
// Tap anywhere to close dialog.
Rect dialogBounds = new Rect();
getWindow().getDecorView().getHitRect(dialogBounds);
if (!dialogBounds.contains((int) event.getX(),
(int) event.getY())) {
// You have clicked the grey area
InputMethodManager inputMethodManager = (InputMethodManager) act
.getSystemService(act.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(dialog
.getCurrentFocus().getWindowToken(), 0);
dialog.dismiss();
// stop activity closing
} else {
InputMethodManager inputMethodManager = (InputMethodManager) act
.getSystemService(act.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(dialog
.getCurrentFocus().getWindowToken(), 0);
}
return true;
}
};
Un'altra soluzione, questo codice è stato preso dal codice sorgente Android di Window
Devi solo aggiungere questi due metodi al codice sorgente della finestra di dialogo.
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isShowing() && (event.getAction() == MotionEvent.ACTION_DOWN
&& isOutOfBounds(getContext(), event) && getWindow().peekDecorView() != null)) {
hide();
}
return false;
}
private boolean isOutOfBounds(Context context, MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
final int slop = ViewConfiguration.get(context).getScaledWindowTouchSlop();
final View decorView = getWindow().getDecorView();
return (x < -slop) || (y < -slop)
|| (x > (decorView.getWidth()+slop))
|| (y > (decorView.getHeight()+slop));
}
Questa soluzione non presenta questo problema:
Funziona benissimo tranne che l'attività sottostante reagisce anche all'evento touch. C'è un modo per impedirlo? - howettl
Di seguito ha funzionato per me:
myDialog.setCanceledOnTouchOutside(true);
Ecco il codice
dialog.getWindow().getDecorView().setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent ev) {
if(MotionEvent.ACTION_DOWN == ev.getAction())
{
Rect dialogBounds = new Rect();
dialog. getWindow().getDecorView().getHitRect(dialogBounds);
if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) {
// You have clicked the grey area
UiUtils.hideKeyboard2(getActivity());
return false; // stop activity closing
}
}
getActivity().dispatchTouchEvent(ev);
return false;
}
});
Prova questo . puoi nascondere la tastiera quando tocchi fuori