Sunday, November 7, 2010

How to dismiss a custom dialog based on touch points?


When we write a custom dialog class or set theme style/Theme.Dialog to activity, we might be interested in dismissing the dialog if user touches outside the dialog visible area.

This can be achieved through a special class, android.graphics.Region. It has a api contains(x,y) which is used to tell you if the passed x,y falls in the region defined.

1 - we need to override the public boolean onTouchEvent (MotionEvent event) function and get the current x,y the user touched on the screen.

2 - Define the region top left x,y and bottom right x,y of the rectangle region which you are interested in listening the touch events.

Region dialogRegion = new Region (10,12,183,179 );

3 - Dismiss the dialog using finish() if the touch points falls within this region() co-ordinates.

if( dialogRegion.contains(x, y) == true)
this.finish();

Here is the complete example.

This example shows that activity is set style - Theme.Dialog.


<activity android:name=".touch"
android:label="@string/app_name"
android:theme="@android:style/Theme.Dialog">


Size of the dialog is set using WindowManager layout params.

Depending on the height & width, i have set the region points.And in onTouchEvent() i check for the touch points, if within the region() points i simply call finish() which exits the activity.

touch.java
------------


package com.android.touch;

import android.app.Activity;
import android.graphics.Region;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.WindowManager;

public class touch extends Activity {
Region dialogRegion;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WindowManager.LayoutParams params = getWindow().getAttributes();

params.height = 200;
params.width = 200;


this.getWindow().setAttributes(params);

dialogRegion = new Region (10,12,183,179 );

}
public boolean onTouchEvent (MotionEvent event)
{

final int action = event.getAction();


final int x = (int) event.getX();
final int y = (int) event.getY();

switch (action & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN: {
System.out.println("Action down"+x +"::"+y);
if( dialogRegion.contains(x, y) == true)
this.finish();

}
}

return true;
}
}

6 comments:

  1. This is BBAAADDDDD don't do this. Just use:

    dialog.setCanceledOnTouchOutside(true);

    to cancel the dialog when touching outside of it

    ReplyDelete
  2. If your activity has set Theme as Dialog, you cannot use that Api in Activity instance. So the above said is valid.....!!!

    ReplyDelete
  3. My dialog does have a theme applied to it, so in the constructor of the class that extends dialog I put

    this.setCanceledOnTouchOutside(true);

    ReplyDelete
  4. Yes for customDialog it will work. For an activity which has theme dialog, we may need to handle differently.

    ReplyDelete
  5. Ohhh okay gotcha well either way great blog man!!! Keep up the good work!!!!

    ReplyDelete