Eu implementei uma caixa de diálogo personalizada para o meu aplicativo. Quero implementar que, quando o usuário clicar fora da caixa de diálogo, a caixa de diálogo será descartada. O que eu tenho que fazer para isso?
Eu implementei uma caixa de diálogo personalizada para o meu aplicativo. Quero implementar que, quando o usuário clicar fora da caixa de diálogo, a caixa de diálogo será descartada. O que eu tenho que fazer para isso?
Respostas:
Você pode usar o dialog.setCanceledOnTouchOutside(true);
que fechará a caixa de diálogo se tocar fora dela.
Algo como,
Dialog dialog = new Dialog(context)
dialog.setCanceledOnTouchOutside(true);
Ou, se o seu Diálogo não for modelo,
1 - Defina o sinalizador FLAG_NOT_TOUCH_MODAL
para o atributo da janela da sua caixa de diálogo
Window window = this.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
2 - Adicione outro sinalizador às propriedades do Windows ,, FLAG_WATCH_OUTSIDE_TOUCH
- este é para o diálogo receber evento de toque fora de sua região visível.
3 - Substitua a onTouchEvent()
caixa de diálogo e verifique o tipo de ação. se o tipo de ação for ' MotionEvent.ACTION_OUTSIDE
' significa que o usuário está interagindo fora da região da caixa de diálogo. Portanto, nesse caso, você pode alterar o seu diálogo ou decidir o que deseja executar. ver impressão simples?
public boolean onTouchEvent(MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_OUTSIDE){
System.out.println("TOuch outside the dialog ******************** ");
this.dismiss();
}
return false;
}
Para obter mais informações, consulte Como descartar uma caixa de diálogo personalizada com base em pontos de contato? e Como descartar sua caixa de diálogo não modal, quando tocada fora da região da caixa de diálogo
Basta usar
dialog.setCanceledOnTouchOutside(true);
Você pode usar esta implementação do onTouchEvent. Impede reagir por baixo da atividade ao evento de toque (como mencionado anteriormente).
@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
Ou, se você estiver personalizando a caixa de diálogo usando um tema definido em seu estilo xml, coloque esta linha no seu tema:
<item name="android:windowCloseOnTouchOutside">true</item>
dialog.setCanceledOnTouchOutside(true);
funciona maravilhosamente.
Esse método deve evitar completamente as atividades abaixo da área cinza de recuperação de eventos de clique.
Remova esta linha, se a tiver:
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
Coloque isso em sua atividade criada
getWindow().setFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
substitua o evento de toque por este
@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);
}
Esse código é usado para quando o clique é usado na caixa de diálogo que oculta a entrada e quando o usuário clica no lado externo da caixa de diálogo na hora em que a entrada automática e a caixa de diálogo estão fechadas.
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;
}
};
Outra solução, esse código foi retirado do código-fonte android de Window
Você deve apenas adicionar esses dois métodos ao código-fonte do diálogo.
@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));
}
Esta solução não tem este problema:
Isso funciona muito bem, exceto que a atividade abaixo também reage ao evento de toque. Existe alguma maneira de evitar isso? - howettl
A seguir, trabalhou para mim:
myDialog.setCanceledOnTouchOutside(true);
Aqui está o código
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;
}
});
Tente este . você pode ocultar o teclado quando tocar fora