Android Open Source - arcgis-runtime-samples-android Attribute List Adapter






From Project

Back to project page arcgis-runtime-samples-android.

License

The source code is released under:

Apache License

If you think the Android project arcgis-runtime-samples-android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/* Copyright 2014 ESRI
 *//from  ww w  . ja  va2s. c om
 * All rights reserved under the copyright laws of the United States
 * and applicable international laws, treaties, and conventions.
 *
 * You may freely redistribute and use this sample code, with or
 * without modification, provided you include the original copyright
 * notice and use restrictions.
 *
 * See the sample code usage restrictions document for further information.
 *
 */

package com.esri.arcgis.android.samples.attributeeditor;

import java.text.DateFormat;
import java.text.ParseException;
import java.util.Calendar;
import java.util.HashMap;

import com.esri.arcgis.android.samples.attributeeditor.FeatureLayerUtils.FieldType;
import com.esri.core.map.FeatureSet;
import com.esri.core.map.FeatureType;
import com.esri.core.map.Field;

import android.app.DatePickerDialog;
import android.app.DatePickerDialog.OnDateSetListener;
import android.content.Context;
import android.database.DataSetObserver;
import android.text.InputFilter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.TextView.BufferType;

/**
 * Adapter class which contains the logic of how to use and process the
 * FeatureLayers Fields and Attributes into an List Layout
 */
public class AttributeListAdapter extends BaseAdapter {

  FeatureSet featureSet;

  Field[] fields;

  FeatureType[] types;

  String typeIdFieldName;

  Context context;

  LayoutInflater lInflator;

  int[] editableFieldIndexes;

  String[] typeNames;

  HashMap<String, FeatureType> typeMap;

  AttributeItem[] items;

  DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.SHORT,
      DateFormat.SHORT);

  /**
   * Constructor
   */
  public AttributeListAdapter(Context context, Field[] fields,
      FeatureType[] types, String typeIdFieldName) {

    this.context = context;
    this.lInflator = LayoutInflater.from(context);
    this.fields = fields;
    this.types = types;
    this.typeIdFieldName = typeIdFieldName;

    // this.fieldsTemplateMap = createInitialFieldTemplateMap(this.fields);
    // parseTypes();

    // Setup processed variables
    this.editableFieldIndexes = FeatureLayerUtils
        .createArrayOfFieldIndexes(this.fields);
    this.typeNames = FeatureLayerUtils.createTypeNameArray(this.types);
    this.typeMap = FeatureLayerUtils.createTypeMapByValue(this.types);

    // register dataset observer to track when the underlying data is
    // changed
    this.registerDataSetObserver(new DataSetObserver() {

      public void onChanged() {

        // clear the array of attribute items
        AttributeListAdapter.this.items = new AttributeItem[AttributeListAdapter.this.editableFieldIndexes.length];

      }
    });
  }

  /**
   * Implemented method from BaseAdapter class
   */
  public int getCount() {

    return this.editableFieldIndexes.length;

  }

  /**
   * Implemented method from BaseAdapter class. This method returns the actual
   * data associated with a row in the list. In this case we return the field
   * along with the field value as a custom object. We subsequently add the
   * View which displays the value to this object so we can retrieve it when
   * applying edits.
   */
  public Object getItem(int position) {

    // get field associated with the position from the editableFieldIndexes
    // array created at startup
    int fieldIndex = this.editableFieldIndexes[position];

    AttributeItem row = null;

    // check to see if we have already created an attribute item if not
    // create
    // one
    if (items[position] == null) {

      // create new Attribute item for persisting the data for subsequent
      // events
      row = new AttributeItem();
      row.setField(this.fields[fieldIndex]);
      Object value = this.featureSet.getGraphics()[0]
          .getAttributeValue(fields[fieldIndex].getName());
      row.setValue(value);
      items[position] = row;

    } else {

      // reuse existing item to ensure View instance is kept.
      row = items[position];

    }

    return row;

  }

  /**
   * Implemented method from BaseAdapter class
   */
  public long getItemId(int position) {

    return position;

  }

  /**
   * Implemented method from BaseAdapter class. This is the main method for
   * returning a View which corresponds to a row in the list. This calls the
   * getItem() method to get the data. It is called multiple times by the
   * ListView and may be improved on by saving the previous result.
   */
  public View getView(int position, View convertView, ViewGroup parent) {

    View container = null;

    AttributeItem item = (AttributeItem) getItem(position);

    // check field type
    // TODO if you want to support domains, add checks here and use the
    // createSpinnerViewFromArray to create spinners
    if (item.getField().getName().equals(this.typeIdFieldName)) {
      // This is the featurelayers type field

      container = lInflator.inflate(R.layout.item_spinner, null);
      // get the types name for this feature from the available values
      String typeStringValue = this.typeMap.get(
          item.getValue().toString()).getName();
      Spinner spinner = createSpinnerViewFromArray(container,
          item.getField(), typeStringValue, this.typeNames);
      item.setView(spinner);

      // TODO set listener to change types associated domain fields if
      // required

    } else if (FieldType.determineFieldType(item.getField()) == FieldType.DATE) {
      // create date picker for date fields

      container = lInflator.inflate(R.layout.item_date, null);
      long date = Long.parseLong(item.getValue().toString());

      Button dateButton = createDateButtonFromLongValue(container,
          item.getField(), date);
      item.setView(dateButton);

    } else {
      // create number and text fields
      // View object for saving in the AttrbuteItem once it has been set
      // up, for
      // accessing later when we apply edits.
      View valueView = null;

      if (FieldType.determineFieldType(item.getField()) == FieldType.STRING) {

        // get the string specific layout
        container = lInflator.inflate(R.layout.item_text, null);
        valueView = createAttributeRow(container, item.getField(),
            item.getValue());

      } else if (FieldType.determineFieldType(item.getField()) == FieldType.NUMBER) {

        // get the number specific layout
        container = lInflator.inflate(R.layout.item_number, null);
        valueView = createAttributeRow(container, item.getField(),
            item.getValue());

      } else if (FieldType.determineFieldType(item.getField()) == FieldType.DECIMAL) {

        // get the decimal specific layout
        container = lInflator.inflate(R.layout.item_decimal, null);
        valueView = createAttributeRow(container, item.getField(),
            item.getValue());

      }

      // set the rows view onto the item so it can be received when
      // applying
      // edits
      item.setView(valueView);

    }

    return container;

  }

  /**
   * Sets the FeatureSet, called by the activity when a new queryResult is
   * returned
   * 
   * @param featureSet
   */
  public void setFeatureSet(FeatureSet featureSet) {

    this.featureSet = featureSet;

  }

  /**
   * Helper method to create a spinner for a field and insert it into the View
   * container. This uses, the String[] to create the list, and selects the
   * value that is passed in from the list (the features value). Can be used
   * for domains as well as types.
   */
  Spinner createSpinnerViewFromArray(View container, Field field,
      Object value, String[] values) {

    TextView fieldAlias = (TextView) container
        .findViewById(R.id.field_alias_txt);
    Spinner spinner = (Spinner) container
        .findViewById(R.id.field_value_spinner);
    fieldAlias.setText(field.getAlias());
    spinner.setPrompt(field.getAlias());

    ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(
        this.context, android.R.layout.simple_spinner_item, values);
    spinnerAdapter
        .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(spinnerAdapter);
    // set current selection based on the value passed in
    spinner.setSelection(spinnerAdapter.getPosition(value.toString()));

    return spinner;
  }

  /**
   * Helper method to create a date button, with appropriate onClick and
   * onDateSet listeners to handle dates as a long (milliseconds since 1970),
   * it uses the locale and presents a button with the date and time in short
   * format.
   */
  Button createDateButtonFromLongValue(View container, Field field, long date) {

    TextView fieldAlias = (TextView) container
        .findViewById(R.id.field_alias_txt);
    Button dateButton = (Button) container
        .findViewById(R.id.field_date_btn);
    fieldAlias.setText(field.getAlias());

    Calendar c = Calendar.getInstance();
    c.setTimeInMillis(date);
    dateButton.setText(formatter.format(c.getTime()));

    addListenersToDatebutton(dateButton);

    return dateButton;
  }

  /**
   * Helper method to add the field alias and the fields value into columns of
   * a view using standard id names. If the field has a length set, then this
   * is used to constrain the EditText's allowable characters. No validation
   * is applied here, it is assumed that the container has this set already
   * (in XML).
   */
  View createAttributeRow(View container, Field field, Object value) {

    TextView fieldAlias = (TextView) container
        .findViewById(R.id.field_alias_txt);
    EditText fieldValue = (EditText) container
        .findViewById(R.id.field_value_txt);
    fieldAlias.setText(field.getAlias());

    // set the length of the text field and its value
    if (field.getLength() > 0) {
      InputFilter.LengthFilter filter = new InputFilter.LengthFilter(
          field.getLength());
      fieldValue.setFilters(new InputFilter[] { filter });
    }

    Log.d(AttributeEditorActivity.TAG, "value is null? =" + (value == null));
    Log.d(AttributeEditorActivity.TAG, "value=" + value);

    if (value != null) {
      fieldValue.setText(value.toString(), BufferType.EDITABLE);
    } else {
      fieldValue.setText("", BufferType.EDITABLE);
    }

    return fieldValue;
  }

  /**
   * Helper method to create the date button and its associated events
   */
  void addListenersToDatebutton(Button dateButton) {

    // create new onDateSetLisetener with the button associated with it
    final ListOnDateSetListener listener = new ListOnDateSetListener(
        dateButton);

    // add a click listener to the button
    dateButton.setOnClickListener(new View.OnClickListener() {

      public void onClick(View v) {

        // if its a date, get the milliseconds value
        Calendar c = Calendar.getInstance();
        formatter.setCalendar(c);

        try {

          // parse to a double
          Button button = (Button) v;
          c.setTime(formatter.parse(button.getText().toString()));

        } catch (ParseException e) {
          // do nothing as should parse
        }

        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH);
        int day = c.get(Calendar.DAY_OF_MONTH);

        // show date picker with date set to the items value (hence
        // built
        // outside of onCreateDialog)
        // TODO implement time picker if required, this picker only
        // supports
        // date and therefore showing the dialog will cause a change in
        // the time
        // value for the field
        DatePickerDialog dialog = new DatePickerDialog(context,
            listener, year, month, day);
        dialog.show();
      }
    });
  }

  /**
   * Inner class for handling date change events from the date picker dialog
   */
  class ListOnDateSetListener implements OnDateSetListener {

    Button button;

    public ListOnDateSetListener(Button button) {

      this.button = button;
    }

    public void onDateSet(DatePicker view, int year, int month, int day) {

      Calendar c = Calendar.getInstance();
      c.set(year, month, day);

      // Update the button to show the chosen date
      button.setText(formatter.format(c.getTime()));

    }
  }
}




Java Source Code List

com.arcgis.android.samples.ExportTileCacheTask.ExportTileCacheTaskSampleActivity.java
com.arcgis.android.samples.cloudportal.featureservicetablequery.MainActivity.java
com.arcgis.android.samples.cloudportal.querycloudfeatureservice.MainActivity.java
com.arcgis.android.samples.dynamiclayer.DynamicLayerRendererActivity.java
com.arcgis.android.samples.geometrysample.BufferFragment.java
com.arcgis.android.samples.geometrysample.GeometrySampleActivity.java
com.arcgis.android.samples.geometrysample.GeometryUtil.java
com.arcgis.android.samples.geometrysample.SampleListFragment.java
com.arcgis.android.samples.geometrysample.SpatialRelationshipsFragment.java
com.arcgis.android.samples.geometrysample.UnionDifferenceFragment.java
com.arcgis.android.samples.localdata.localrasterdata.EditTextUtils.java
com.arcgis.android.samples.localdata.localrasterdata.FileBrowserFragment.java
com.arcgis.android.samples.localdata.localrasterdata.HillshadeRendererParametersFragment.java
com.arcgis.android.samples.localdata.localrasterdata.MainActivity.java
com.arcgis.android.samples.localdata.localrasterdata.OnDialogDismissListener.java
com.arcgis.android.samples.localdata.localrasterdata.RendererType.java
com.arcgis.android.samples.localdata.localrasterdata.StretchParametersFragment.java
com.arcgis.android.samples.maps.basemaps.MainActivity.java
com.arcgis.android.samples.maps.fragmentmanagement.BasemapListFragment.java
com.arcgis.android.samples.maps.fragmentmanagement.MainActivity.java
com.arcgis.android.samples.maps.fragmentmanagement.MapFragment.java
com.arcgis.android.samples.maps.helloworld.MainActivity.java
com.arcgis.android.samples.maps.maplegend.LegendDialogFragment.java
com.arcgis.android.samples.maps.maplegend.MainActivity.java
com.arcgis.android.samples.maps.maprotation.Compass.java
com.arcgis.android.samples.maps.maprotation.MainActivity.java
com.arcgis.android.samples.maps.switchmaps.MainActivity.java
com.arcgis.android.samples.maps.switchmaps.MapFragment.java
com.arcgis.android.samples.milsym2525c.MainActivity.java
com.arcgis.android.samples.milsym2525c.Mil2525cMessageParser.java
com.arcgis.android.samples.oauth2sample.MapFragment.java
com.arcgis.android.samples.oauth2sample.OAuth2Sample.java
com.arcgis.android.samples.oauth2sample.UserContentActivity.java
com.arcgis.android.samples.oauth2sample.UserContentArrayAdapter.java
com.arcgis.android.samples.oauth2sample.UserContentFragment.java
com.arcgis.android.samples.oauth2sample.UserWebmaps.java
com.arcgis.android.samples.search.placesearch.MainActivity.java
com.esri.android.sample.closestfacilities.MainActivity.java
com.esri.android.samples.mbtiles.LocalMBTiles.java
com.esri.android.samples.mbtiles.MBTilesLayer.java
com.esri.android.samples.mgrsgrid.LocateMGRSActivity.java
com.esri.arcgis.android.sample.runtimegeodb.CreateRuntimeGeodatabaseActivity.java
com.esri.arcgis.android.sample.simplemap.SimpleMapActivity.java
com.esri.arcgis.android.sample.simplemap.SimpleMapFragment.java
com.esri.arcgis.android.sample.simplemap.SingleFragmentActivity.java
com.esri.arcgis.android.samples.GeoJSONEarthquakeMap.GeoJSONEarthquakeMapActivity.java
com.esri.arcgis.android.samples.PopupUICustomization.LayerQueryTask.java
com.esri.arcgis.android.samples.PopupUICustomization.MyAttachmentsView.java
com.esri.arcgis.android.samples.PopupUICustomization.MyEditAttributesAdapter.java
com.esri.arcgis.android.samples.PopupUICustomization.MyMediaAdapter.java
com.esri.arcgis.android.samples.PopupUICustomization.MyMediaView.java
com.esri.arcgis.android.samples.PopupUICustomization.MyReadOnlyAttributesAdapter.java
com.esri.arcgis.android.samples.PopupUICustomization.MyTitleView.java
com.esri.arcgis.android.samples.PopupUICustomization.PopupFragment.java
com.esri.arcgis.android.samples.PopupUICustomization.PopupUICustomizationActivity.java
com.esri.arcgis.android.samples.addcsv2graphic.AddCSVActivity.java
com.esri.arcgis.android.samples.attributeeditor.AttributeEditorActivity.java
com.esri.arcgis.android.samples.attributeeditor.AttributeItem.java
com.esri.arcgis.android.samples.attributeeditor.AttributeListAdapter.java
com.esri.arcgis.android.samples.attributeeditor.FeatureLayerUtils.java
com.esri.arcgis.android.samples.basiclicense.MainActivity.java
com.esri.arcgis.android.samples.basiclicense.MessageDialogFragment.java
com.esri.arcgis.android.samples.classbreaksrenderer.ClassBreaksRendererActivity.java
com.esri.arcgis.android.samples.featuredusergroup.FeaturedGroupsActivity.java
com.esri.arcgis.android.samples.featuredusergroup.GroupsFragment.java
com.esri.arcgis.android.samples.featuredusergroup.ItemsFragment.java
com.esri.arcgis.android.samples.featuredusergroup.MapActivity.java
com.esri.arcgis.android.samples.geometryeditor.ConfirmDiscardDialogFragment.java
com.esri.arcgis.android.samples.geometryeditor.EditFailedDialogFragment.java
com.esri.arcgis.android.samples.geometryeditor.FeatureTypeData.java
com.esri.arcgis.android.samples.geometryeditor.FeatureTypeDialogFragment.java
com.esri.arcgis.android.samples.geometryeditor.GeometryEditorActivity.java
com.esri.arcgis.android.samples.identifytask.Identify.java
com.esri.arcgis.android.samples.measure.MainActivity.java
com.esri.arcgis.android.samples.nearby.Nearby.java
com.esri.arcgis.android.samples.offlineeditor.GDBUtil.java
com.esri.arcgis.android.samples.offlineeditor.OfflineActions.java
com.esri.arcgis.android.samples.offlineeditor.OfflineEditorActivity.java
com.esri.arcgis.android.samples.offlineeditor.TemplatePicker.java
com.esri.arcgis.android.samples.offlineroutingandgeocoding.RoutingAndGeocoding.java
com.esri.arcgis.android.samples.popupinwebmapforediting.PopupInWebmapForEditing.java
com.esri.arcgis.android.samples.popupinwebmapforviewing.PopupInWebmapForViewing.java
com.esri.arcgis.android.samples.querytask.MainActivity.java
com.esri.arcgis.android.samples.routing.MyAdapter.java
com.esri.arcgis.android.samples.routing.RoutingDialogFragment.java
com.esri.arcgis.android.samples.routing.RoutingListFragment.java
com.esri.arcgis.android.samples.routing.RoutingSample.java
com.esri.arcgis.android.samples.servicearea.EditFragment.java
com.esri.arcgis.android.samples.servicearea.ServiceAreaSample.java
com.esri.arcgis.android.samples.standardlicense.MainActivity.java
com.esri.arcgis.android.samples.standardlicense.MessageDialogFragment.java
com.esri.arcgis.android.samples.standardlicenseoffline.MainActivity.java
com.esri.arcgis.android.samples.standardlicenseoffline.MessageDialogFragment.java
com.esri.arcgis.android.samples.uniquevaluerenderer.UniqueValueRendererSampleActivity.java
com.esri.arcgis.android.samples.viewshed.Viewshed.java
com.esri.arcgis.android.samples.wmslayer.MainActivity.java
com.esri.arcgis.samples.offlineanalysis.MainActivity.java