Home > Development > Repositioning Toast Messages

Repositioning Toast Messages

I work on a large app that shows “business intelligence” reports. A feature of such reports allows the designer to add one or more images to the report along with more typical components like graphs and tables. The images can have “alt text”, and we want to show that in a Toast message if the user taps on the image. By default, Toast messages show up horizontally centered and near the bottom of the screen. Since that location may not be over the selected image, I decided to fix that by explicitly repositioning the Toast.

Two landscape images where the default Toast for the top image will show over the lower image.

In the screen shot above, you can see two images inside of horizontal rectangles. Prior to the fix, tapping on the image of the dog, causes the Toast with the “alt text” message to display on top of the fighter jet.

The Toast class has a method for adjusting the position:

toast.setGravity(Gravity.CENTER, xOffset, yOffset);

The x and y offsets are relative to the position determined by your choice for the gravity parameter. By starting from a centered gravity, I’ll be moving the position to be over the tapped image by changing the offsets. As near as I can tell, (Gravity.CENTER, 0,0) represents the center of the screen so negative and positive offsets are needed to correctly position the Toast.

We use an OnClickListener to detect the tap, and the ImageView is the view supplied to the onClick(View v) method in the listener. To obtain the coordinates of the RelativeLayout holding the ImageView, I obtained the parent view of the image view, then called getGlobalVisibleRect(Rect gvr) on the parent. The “gvr” rectangle contains the coordinates of the view over which we want to position the Toast. Calling getRootView() on the image view gives us the outermost view of the app, and we can use its coordinates to represent the limits of the viewable area.

Now it is a matter of calculating the “center” of the image and expressing that as an appropriate x and y offset. I determined the center of the viewable area by dividing the root view’s right and bottom values in half. The center of the image’s parent view was trickier. Look at the comments in the code below to see how I did it.

public void onClick(View v) {
   int xOffset = 0;
   int yOffset = 0;
   Rect gvr = new Rect();

  View parent = (View) v.getParent();// v is the image,
    //parent is the rectangle holding it.

  if (parent.getGlobalVisibleRect(gvr)) {
     	Log.v("image left", Integer.toString(gvr.left));
	Log.v("image right", Integer.toString(gvr.right));
	Log.v("image top", Integer.toString(gvr.top));
	Log.v("image bottom", Integer.toString(gvr.bottom));
	View root = v.getRootView();

        int halfwayWidth = root.getRight() / 2;
        int halfwayHeight = root.getBottom() / 2;
          //get the horizontal center
	int parentCenterX = ((gvr.right - gvr.left) / 2) + gvr.left;
	 //get the vertical center
	int parentCenterY = (gvr.bottom - gvr.top) / 2 + gvr.top;

	if (parentCenterY <= halfwayHeight) {
	   yOffset = -(halfwayHeight - parentCenterY);//this image is    above the center of gravity, i.e. the halfwayHeight
        } else {
	    yOffset = parentCenterY - halfwayHeight;
        }
	if (parentCenterX < halfwayWidth) { //this view is left of center             xOffset = -(halfwayWidth - parentCenterX);  	}  	if (parentCenterX >= halfwayWidth) {
	   //this view is right of center
	   xOffset = parentCenterX - halfwayWidth;
	}
     }
       Toast toast = Toast.makeText(activity, altText, Toast.LENGTH_SHORT);
       toast.setGravity(Gravity.CENTER, xOffset, yOffset);
       toast.show();
       }
});

Now knowing the center of the screen and center of the image, you can pass an appropriate x and y offset to the Toast. The sign of the offset will have to be negative for positions left and above the center.

Here’s the Toast showing over the image of the dog.

Two landscape images with Toast over the top image

Now looking at a report with three images in portrait orientation, we see that the Toast is properly positioned horizontally.

The Toast is properly positioned horizontally.

As always, I’d like to hear about smarter ways to do these things.

About these ads
Categories: Development Tags: , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: