View Pop-ups on Web Map (Android SDK)

2345
7
08-20-2019 08:06 AM
MICHAILVOUTSIDIS
New Contributor

Hi guys!! I will need your help because i am a bit confused!

I create a web map (https://voutsos.maps.arcgis.com/home/item.html?id=66e13c949c074b0ba726837684b664a7 ) which compines a basemap and a feature layer. I create a mobile app using the existing arcgis tutorials and the tutorial for adding a web map (Display a web map | ArcGIS for Developers ). Till here everything is ok! My only problem is that when i click to an item, it's pop-up (with all the info's about the item) from the web map, doesn't show up .

I'm trying for 5 days to figure it out but i cant! What code should i add to make this work? Please help!

private void setupMap() {      if (mMapView != null) {          String itemId = "41281c51f9de45edaf1c8ed44bb10e30";          Portal portal = new Portal("https://www.arcgis.com", false);          PortalItem portalItem = new PortalItem(portal, itemId);          ArcGISMap map = new ArcGISMap(portalItem);          mMapView.setMap(map);      }  }

This is the code to display the web map ...

Tags (1)
0 Kudos
7 Replies
XuemingWu
Esri Contributor

We are still working on a toolkit and a sample for this but you should be able to do something like this now with our Runtime for Android SDK providing your own UI. The general workflow is:

1. Use identify to get to the popup when clicking on the map. This sample shows how to work with identify.

2. Create your own UI.

3. Use PopupManager class to get popup components and display these components on your UI.

The following are some code snippets show how to construct a PopupManager and work with it:

mPopupManager = new PopupManager(context, popup);

/**

* Initializes title view including symbol image, popup title and

* edit summary if there is one.

*

* @param popupView

*/

private void initTitleView(View popupView) {

  // Symbol image

  ImageView imageView = (ImageView) popupView.findViewById(R.id.popup_titleview_symbolimage);

  try {

    Symbol symbol = mPopupManager.getSymbol();

    if (symbol == null) {

      Log.i(TAG, "Null symbol is returned! ");

    } else {

      Bitmap image = symbol.createSwatchAsync(popupView.getContext(), Color.TRANSPARENT).get();

      imageView.setImageBitmap(image);

    }

  } catch (Exception e) {

    e.printStackTrace();

  }

  // Popup title

  TextView titleView = (TextView) popupView.findViewById(R.id.popup_titleview_title);

  titleView.setText(mPopupManager.getTitle());

  // Edit summary

  TextView editInfoView = (TextView) popupView.findViewById(R.id.popup_titleview_editinfo);

  editInfoView.setText(mPopupManager.getEditSummary());

}

0 Kudos
MICHAILVOUTSIDIS
New Contributor

Thanks for the quick reply and for the info! Because I am not so good at programming I want to ask. I should do all the three steps to make the pop-ups display? The UI is only for the pop-up? And if yes how can I create one? I thing those procedures are extremely difficult for a beginner Please help!

Also i found a perfect sample but in older version ( GitHub - Esri/ArcGIS-runtime-samples-android at v10.2.9 ) and more specific (ArcGIS-runtime-samples-android/PopupInWebMapForViewing at v10.2.9 · Esri/arcgis-runtime-samples-andr... ). I saw - run it in the samples and its EXACTLY what I want! But how can I adapt that code to my app? That's the problem.

Please consider for your answer that i haven't enough experience with java!

Thanks in advance 

0 Kudos
XuemingWu
Esri Contributor

You have to do all the 3 steps if you want to display popups for your features. And you have to create your UI to show the content of a popup. You can create a layout and add a few views such as text view, recycle view and image view. More info on working with UI on Android can be found here

The samples you talked about were for our 10.2.9 SDK. We reworked our SDK since 100.0.0. The current version is 100.5.0. The 100.0.0+ SDK is quite different from the 10.2.9 except that we try to keep the same functionalities. With regard to popup APIs, 10.2.9 SDK provides built-in UI for popups while 100.0.0+ doesn't provide UI for popups instead we will provide popup UI through toolkit. 

If you just want to show some simple info about an item, there is a simpler solution. You can use Callout class. Here is sample Feature Layer Show Attributes.

MICHAILVOUTSIDIS
New Contributor

So.. I have already made a table (ArcGIS for Developers ) with all the necessery details of every item. I want that info with the structure I gave them (not as callout) 

I have already had a UI in my app for the user which is connected to my web map ( https://voutsos.maps.arcgis.com/home/item.html?id=66e13c949c074b0ba726837684b664a7 ) and also displays the position of the user. The only thing missing is the pop-up display when the user taps to the item. This is a screenshot from the app:

I can clearly see the items and their names on the map! The final step is how to show the pop up now and I m done!

Do we know when a sample will be ready??

Because its extremely important for me to finish that app inside the next two weeks can you briefly tell me (write) a simple code to add to my code to make that work?? I will attach the code I use in my class. Your help will be salvation for me  

0 Kudos
XuemingWu
Esri Contributor

Hi Michail,

The followings are some example code snippets to work with our API to display a simple popup in an Android app. The simple popup will only show title and attributes. If your popup configuration includes media and attachment, you need to add more logics into your app to display these elements in your popup. I also include some links to a few classes of our Android SDK that you may want to check out. You may also want to take a look at a .Net open source app called Data Collection for .Net which displays popups in some workflows. Though it is a .Net app the API patterns and workflows supported by our Runtime Android SDK and .Net SDK are very similar. Hopeful these can get you started. 

Links:

https://developers.arcgis.com/android/latest/api-reference/reference/com/esri/arcgisruntime/mapping/...

https://developers.arcgis.com/android/latest/api-reference/reference/com/esri/arcgisruntime/mapping/...

https://developers.arcgis.com/android/latest/api-reference/reference/com/esri/arcgisruntime/mapping/...

https://developers.arcgis.com/android/latest/api-reference/reference/com/esri/arcgisruntime/mapping/...

Code snippets:

1. Use identify to obtain popups from your web map

// Set a custom OnTouchListener on MapView
mMapView.setOnTouchListener(new MyTouchListener(this, mMapView));‍‍

/**
   * A custom OnTouchListener on MapView to identify geo-elements when users single tap
   * on a map view.
   */
  private class MyTouchListener extends DefaultMapViewOnTouchListener {

    private MapView mapView;
    private Context context;

    /**
     * Constructs a DefaultMapViewOnTouchListener with the given Context and MapView.
     *
     * @param context the context from which this is being created
     * @param mapView the MapView with which to interact
     * @since 100.0.0
     */
    public MyTouchListener(Context context, MapView mapView) {
      super(context, mapView);

      this.context = context;
      this.mapView = mapView;
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
      // Validation
      if (mapView == null ) {
        return super.onSingleTapConfirmed(e);
      }

      // Obtain GeoElements, and create popup
      android.graphics.Point screenPoint = new android.graphics.Point((int) e.getX(), (int) e.getY());
      doIdentify(mapView, screenPoint);

      return true;
    }

    /**
     * Creates popup for the first GeoElement obtained from identify.
     *
     * @param mapView
     * @param screenPoint
     * @return
     */
    private void doIdentify(final MapView mapView, final android.graphics.Point screenPoint) {
      // Identify all layers in the map view
      final ListenableFuture<List<IdentifyLayerResult>> future = mapView.identifyLayersAsync(
          screenPoint, 10.0, false, 3);
      future.addDoneListener(new Runnable() {
        @Override public void run() {
          try {
            // Obtain identify results
            List<IdentifyLayerResult> results = future.get();
            if ((results == null) || (results.isEmpty())) {
              Log.i(TAG, "Null or empty result from identify. ");
              return;
            }

            // Get the first popup
            IdentifyLayerResult result = results.get(0);
            List<Popup> popups = result.getPopups();
            if ((popups == null) || (popups.isEmpty())) {
              Log.i(TAG, "Null or empty popup from identify. ");
            }

            Popup popup = popups.get(0);
            // Create a popup view for the first popup
            createPopupView(popup);
          } catch (Exception ex) {
            Log.i(TAG, "exception in identify: " + ex.getMessage());
          }
        }
      });
    }
  }

  /**
   * Creates a popup view for a given popup.
   * @param popup
   */
  private void createPopupView(Popup popup) {
    // Create a popup view
    SimplePopupFragment fragment = SimplePopupFragment.newInstance();
    fragment.setPopupManager(SimplePopupActivity.this, popup);
    getSupportFragmentManager().beginTransaction().
        replace(android.R.id.content, fragment, "popup fragment")
        .addToBackStack("popup fragment")
        .commit();
  }
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

2. Show popup elements in a fragment

/**
 * Fragment to provide a popup view that contains a title view, a scrollable
 * attribute/description view.
 */
public class SimplePopupFragment extends Fragment {

  private PopupManager mPopupManager;

  private static final String TAG = SimplePopupFragment.class.getSimpleName();

  public static SimplePopupFragment newInstance() {
    SimplePopupFragment fragment = new SimplePopupFragment();
    return fragment;
  }

  @Nullable
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    if (!checkPopupManager()) {
      return null;
    }
    View view = inflater.inflate(R.layout.simple_popup_view, container, false);
    initPopupView(view);

    return view;
  }


  /**
   * Sets PopupManager which is a must have property of SimplePopupFragment.
   *
   * @param popup
   */
  public void setPopupManager(Context context, Popup popup) {
    mPopupManager = new PopupManager(context, popup);
  }

  /**
   * Checks if PopupManager has been set. Logs a message if it hasn't.
   *
   * @return
   */
  private boolean checkPopupManager() {
    if (mPopupManager == null) {
      Log.w(TAG, "Need to set PopupManager before showing the popup view!");
      return false;
    }
    return true;
  }

  /**
   * Initializes the popup view.
   *
   * @param popupView
   */
  private void initPopupView(View popupView) {
    if (mPopupManager == null) {
      return;
    }

    // Initializes each individual component view
    initTitleView(popupView);
    initAttributeView(popupView);
  }


  /**
   * Initializes title view including symbol image, popup title and
   * edit summary if there is one.
   *
   * @param popupView
   */
  private void initTitleView(View popupView) {
    // Popup title
    TextView titleView = (TextView) popupView.findViewById(R.id.simple_titleview_title);
    titleView.setText(mPopupManager.getTitle());
    // Edit summary
    TextView editInfoView = (TextView) popupView.findViewById(R.id.simple_titleview_editinfo);
    editInfoView.setText(mPopupManager.getEditSummary());
  }

  /**
   * Constructs SimpleAttributeAdapter and initializes attribute view.
   *
   * @param popupView
   */
  private void initAttributeView(View popupView) {
    RecyclerView attrView = (RecyclerView) popupView.findViewById(R.id.simple_attribute_view);
    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
    linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    attrView.setLayoutManager(linearLayoutManager);

    if ((mPopupManager.getCustomHtmlDescription() == null) || (mPopupManager.getCustomHtmlDescription().length()== 0)) {
      // Showing attributes
      WebView webView = (WebView) popupView.findViewById(R.id.simple_description_view);
      webView.setVisibility(View.GONE);
      attrView.setVisibility(View.VISIBLE);

      attrView.setHasFixedSize(true);
      SimpleAttributeAdapter adapter = new SimpleAttributeAdapter(mPopupManager);
      attrView.setAdapter(adapter);
    } else {
      // Showing custom description
      attrView.setVisibility(View.GONE);
      WebView webView = (WebView) popupView.findViewById(R.id.simple_description_view);
      webView.loadData(mPopupManager.getCustomHtmlDescription(), "text/html; charset=utf-8", null);
      webView.setVisibility(View.VISIBLE);
    }
  }

}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

3. Adapter of attributes

/**
 * Custom adapter for attributes displayed in a popup view.
 */
public class SimpleAttributeAdapter extends RecyclerView.Adapter<SimpleAttributeAdapter.ViewHolder> {

  private static PopupManager mPopupManager;

  public SimpleAttributeAdapter(PopupManager popupManager) {
    mPopupManager = popupManager;
  }

  @Override
  public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext())
        .inflate(R.layout.simple_attribute_row, parent, false);

    return new ViewHolder(view);
  }

  @Override
  public void onBindViewHolder(ViewHolder holder, int position) {
    // Validate
    if (mPopupManager == null) {
      return;
    }

    // Current popup field
    PopupField field = mPopupManager.getDisplayedFields().get(position);
    // Show formatted value
    holder.getValueView().setText(mPopupManager.getFormattedValue(field));

    // Field label
    if ((mPopupManager.getFieldLabel(field) == null)
        || (mPopupManager.getFieldLabel(field).length() == 0)) {
      holder.getLableView().setText(field.getFieldName());
    } else {
      holder.getLableView().setText(mPopupManager.getFieldLabel(field));
    }
  }

  @Override
  public int getItemCount() {
    int count = 0;

    if (mPopupManager != null) {
      count = mPopupManager.getDisplayedFields().size();
    }

    return count;
  }

  @Override public int getItemViewType(int position) {
    return position;
  }


  public static class ViewHolder extends RecyclerView.ViewHolder {

    private TextView mLabelView;
    private TextView mValueView;

    public ViewHolder(View itemView) {
      super(itemView);

      // Field label
      mLabelView = (TextView) itemView.findViewById(R.id.popup_attributeview_fieldlabel);
      // Field value
      mValueView = (TextView) itemView.findViewById(R.id.popup_attributeview_fieldvalue);
    }

    public TextView getLableView() {
      return mLabelView;
    }

    public TextView getValueView() {
      return mValueView;
    }

  }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

4. Layout of popup fragment

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

    <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/white"
            android:fillViewport="true"
            android:orientation="vertical"
            android:padding="10dp">

        <LinearLayout android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">

            <!-- title view-->
            <LinearLayout android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical">
                <TextView
                        android:id="@+id/simple_titleview_title"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:textColor="@android:color/black"
                        android:textSize="13dp"/>
                <TextView
                        android:id="@+id/simple_titleview_editinfo"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginBottom="5dp"
                        android:textColor="@android:color/darker_gray"
                        android:textSize="11dp"/>
                <View
                        android:layout_width="match_parent"
                        android:layout_height="2dp"
                        android:background="@android:color/black"/>
            </LinearLayout>

            <!-- attribute view -->
            <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="300dp"
                    android:layout_marginTop="10dp"
                    android:orientation="vertical">
                <androidx.recyclerview.widget.RecyclerView
                        android:id="@+id/simple_attribute_view"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content">
                </androidx.recyclerview.widget.RecyclerView>
                <WebView
                        android:id="@+id/simple_description_view"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:visibility="invisible">
                </WebView>
            </LinearLayout>

        </LinearLayout>
    </ScrollView>
</LinearLayout> ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

5. Layout of an attribute row

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    <TextView
            android:id="@+id/popup_attributeview_fieldlabel"
            android:textSize="15dp"
            android:textColor="@android:color/darker_gray"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    <TextView
            android:id="@+id/popup_attributeview_fieldvalue"
            android:textSize="15dp"
            android:textStyle="bold"
            android:textColor="@android:color/black"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

</LinearLayout>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
g3oapp
by
New Contributor II

Hi @XuemingWu,

we have seen some Android SDK releases since 100.5... any changes in the way to show the popup configured in the web map? I am wondering if we still have to deal with the UI.

Having something like the "PopupViewController" class from the iOS SDK, which is able to manage the popups even with images, would be great!

0 Kudos
XuemingWu
Esri Contributor

Hi @g3oapp

Similar to iOS SDK, our Android SDK also provides a "PopupView" and "PopupViewModel" through ToolKit to help simplify your popup workflows. The ToolKit for Android including documents and examples can be found in github. The links are listed below.

 

ToolKit: https://developers.arcgis.com/android/toolkit/

Popup toolkit: https://github.com/Esri/arcgis-runtime-toolkit-android/tree/master/arcgis-android-toolkit/src/main/j...

Doc of Popup toolkit: https://github.com/Esri/arcgis-runtime-toolkit-android/tree/master/Documentation/Popup

Example: https://github.com/Esri/arcgis-runtime-toolkit-android/tree/master/toolkit-test-app/src/main/java/co...