Displaying Web Map Popups

Complexity: Beginner Data Requirement: ArcGIS Tutorial Data for Desktop

A map is more than a picture. It conveys information about our surroundings and helps make decisions. But a picture does not tell the whole story. There is a wealth of information hidden behind the image. Popups are a great way to reveal information about features on a map, such as a business, a location, a natural phenomena, or a geopolitical entity.

Learn more about popups

You can configure popups when authoring web maps at ArcGIS Online. A popup is associated with a specific layer in a web map and describes how information about features in that layer should be presented. When configuring popups, the author of a web map can choose which fields to display, give them aliases, specify formatting for numbers and dates, configure charts, so on and so forth.

Learn more about authoring web maps with popups

Displaying information using popups

PopupContainer is the main class developers need to use to display popups in their applications. It provides the basic user interface (UI) and behavior for displaying and editing information about graphics in a popup. It holds and manages one or more PopupView objects to provide UI for attribute editing, media displaying, attachment managing, and etc. It also manages the transitions between PopupViews.

Steps:
  1. Instantiate a PopupContainer.
  2. Add PopupViews to the PopupContainer.
  3. Display the PopupContainer.

1. Instantiating PopupContainer

To instantiate PopupContainer, you need to have a reference to the context within which the PopupContainer is displayed.

MapView map = …;
PopupContainer popupContainer = new PopupContainer(map.getContext());

2. Adding PopupViews to the PopupContainer

PopupView is the class that represents a popup which associates a graphic with popup definition for the purpose of displaying in a PopupContainer. It manages a number of views behind the scenes, each of which is designed for a specific purpose, such as editing an attribute, displaying media, managing attachments, etc.

Each PopupView contains a graphic whose information you want to display on the popup and the popup definition for that graphic. The graphic could be chosen by a user in a variety of ways - by tapping on the map, or by tapping on the accessory button in the callout for a specific graphic. A popup definition is represented by a PopupInfo object. You can retrieve it from a layer of a web map.

Retrieving popup definitions from a web map

You can retrieve popup definitions from a web map provided you know which layer or service the popup is associated with.

Layer layer = …;  // a layer of the web map
int subLayerId = …; // sub-layer in the layer containing the popup definition
PopupInfo popupInfo = layer.getPopupInfo(subLayerId);

For Feature service, the sub-layer id will be 0. There is an alternative way to retrieve popup definition for feature service. If you have a reference to a graphic belonging to a feature layer, you can retrieve the popup definition for that graphic as so

ArcGISFeatureLayer featureLayer = …;
PopupInfo popupInfo = featureLayer.getPopupInfo();

Adding PopupViews to the PopupContainer

You can add a PopupView to the PopupContainer by passing the reference to a graphic and the popup definition for that graphic.

PopupInfo popupInfo = …;
Graphic graphic = …;
PopupContainer popupContainer = …;

popupContainer.addPopupView(popupInfo, graphic);

If you want to add more than one PopupView to the PopupContainer at the same time, you can do as so

MapView map = …;
PopupContainer popupContainer = …;
ArcGISFeatureLayer featureLayer = …;
int tolerance = …;
float x = …, y = …;

int[] ids = featureLayer.getGraphicIDs(x, y, tolerance);
ArrayList<PopupView> popupViews = new ArrayList<PopupView>();
PopupInfo popupInfo = featureLayer.getPopupInfo();
if (popupInfo != null) {
  for (int i = 0; i < ids.length; i++) {
    Graphic g = featureLayer.getGraphic(ids[i]);
    if (g == null)
      continue;
          
    PopupView popupView = new PopupView(map.getContext(), popupInfo, g);
    popupViews.add(popupView);
  }
}

if (popupViews.size() > 0) {
  popupContainer.addPopupViews(popupViews.toArray(new PopupView[0]));
}

3. Displaying PopupContainer

PopupContainer is a subclass of LinearLayout. Like any Android LinearLayout, it can be displayed in a variety of ways. The following is example of displaying a PopupContainer.

MapView map = …;
PopupContainer popupContainer = …;

if (popupContainer != null && popupContainer.getPopupCount() > 0) {
  FullScreenDialog popups = new FullScreenDialog(map.getContext(),popupContainer);
  popups.show();
}

...

private class FullScreenDialog extends Dialog {
  private View popupContainer;
	  
  public FullScreenDialog(Context context, PopupContainer popupContainer) {
    super(context, android.R.style.Theme);
    this.popupContainer = popupContainer;
	 }
	  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(popupContainer, new LayoutParams(LayoutParams.FILL_PARENT, 
      LayoutParams.FILL_PARENT));		  
  }

}

Handling user interaction

PopupContainer also handles most of user interaction with the UI, such as bringing up an appropriate keyboard when the user starts editing a numeric attribute, allowing the user to take a picture or browse the photo gallery for attachments, etc.

In many cases, PopupContainer does not implement any default behavior, but instead, provides hooks for developers to handle user interaction on their own. For example, when a user taps the Edit Geometry or Save button, the PopupContainer calls its listener so that it can appropriately dismiss the popup. To respond to such user interaction, you must set the PopupEditingListener for the PopupContainer.

PopupContainer popupContainer = …;
PopupEditingListener editingListener = …;

popupContainer.setPopupEditingListener(editingListener);

PopupEditingListener is an interface. You should implement one or more methods defined in the protocol which pertain to the user interaction you want to handle. Refer to next section for some examples of PopupEditingListener.

Editing information using popups

The PopupContainer provides a UI that makes it very easy to collect information about a graphic from the user. The PopupContainer calls its PopupEditingListener as the user attempts to edit a graphic.

Editing Attributes

The UI for attribute editing automatically applies rules governing the legal values permitted for a graphic's attribute. Such rules include enforcement of coded value domains, range domains, length, data type, whether the attribute is read-only, etc. Information regarding the validation that needs to be applied to each attribute is gathered from the feature layer which the graphic belongs to.

Editing Attachments

Popups make it very easy to edit media attachments for a graphic. Users can attach photos and videos to graphics either by choosing an existing item from the device's photo gallery or by using the device's camera, if one is available. You do not need to write any code to implement this functionality, it is provided by the PopupContainer.

Editing Geometry

PopupContainer does not provide any default UI for capturing or editing a graphic's geometry. Instead, it informs its PopupEditingListener.onGeometryEditing method when a user initiates the geometry editing workflow. The geometry that needs to be edited is passed into the method.

It is your responsibility to implement this method and present an appropriate view which will allow the user to edit an existing graphic's geometry, or create a new geometry from scratch.

PopupContainer popupContainer = …;
Dialog popupDialog = …;

popupContainer.setPopupEditingListener(new PopupEditingListener() {
  @override 
  public void onAddAttachment() {
    ...
  }

...

  @Override
  public void onGeometryEditing(Geometry geometry) {
    popupDialog.hide();
    startCollecting(geometry); //edit geometry
  }

  @override 
  public boolean onDelete() {
    ...
  }

  ...
});

...
private void startCollecting(Geometry geometry) {
  ...
}

Persisting Edits

All edits made to a graphic via the popup UI exist only locally on the device. If the user quits your application, or if the device powers down, the edits will be lost. PopupContainer notifies its PopupEditingListener whenever a user edits or deletes a feature. For example, the PopupEditingListener.onSave method is invoked when a user wants to save the edits made to a graphic's geometry and attributes, and the PopupEditingListener.onDelete method is invoked when the user deletes a feature. It is your responsibility to implement such methods and appropriately commit edits to the server or persist them some other way.

You would typically use an ArcGISFeatureLayer to commit the edits to an ArcGIS Feature Service. You can use methods on the feature layer to commit edits made to a feature's geometry and attributes. You could also use the feature layer to commit edits made to a feature's attachments.

PopupContainer popupContainer = …;
ArcGISFeatureLayer featureLayer = …;

popupContainer.setPopupEditingListener(new PopupEditingListener() {
  @Override
  public void onSave(Map<String, Object> attributes) { 
    // get the current editing feature
    Graphic g = popupContainer.getSelectedPopup().getGraphic();  
    // create a new graphic using the updated attributes  
    Graphic graphic = new Graphic(g.getGeometry(), g.getSymbol(),
      attributes, g.getInfoTemplate()); 
				
    // post the edits to the server    
    featureLayer.applyEdits(null, null, new Graphic[] {graphic}, 
      new CallbackListener<FeatureEditResult[][]>() {   
                 
      public void onError(Throwable e) {
        // fail to save edits to the server
        runOnUiThread(new Runnable() {                      
          public void run() {
            Toast.makeText(PopupDialog.this, "save graphic failed.", 
              Toast.LENGTH_SHORT).show();
            }
          });
        }

        public void onCallback(FeatureEditResult[][] objs) {
          runOnUiThread(new Runnable() {
            // changes have been save to the server successfully
            public void run() {
              Toast.makeText(PopupDialog.this, "save graphic successed.", 
                Toast.LENGTH_SHORT).show();
            }
          });
        }  
    });
  }
    
...
});

Customizing the UI

Color

You can change the color of popup background, text and selector by modifying some property on PopupContainer.

PopupContainer popupContainer = …;

popupContainer.setPopupBackgroundColor(Color.WHITE); // popup background color
popupContainer.setPopupTextColor(Color.BLACK); // text color
popupContainer.setPopupSelectorColors(Color.BLUE, Color.RED, 
  Color.CYAN, Color.MAGENTA); // selector colors

Custom Action

You can replace default toolbar of the popup view by setting the PopupToolbar property on PopupContainer. You can perform any action when the buttons in the custom toolbar are clicked, such as zooming into the feature being displayed in the popup, or displaying a custom action sheet with further options.

Localizing the UI

The text displayed in the popup views has been externalized into a xml file called arcgis_ui_strings.xml to make localization easy. This file is included in the res/values folder for each local. Translations for the following languages are included by default-

When displaying the UI, the PopupContainer will automatically pick up the appropriate translations from resources folder depending upon the language setting of the device.

5/31/2012