Android Open Source - clusterkraf Sample Activity






From Project

Back to project page clusterkraf.

License

The source code is released under:

Apache License

If you think the Android project clusterkraf 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

package com.twotoasters.clusterkraf.sample;
//ww w  .j  a va2  s.  c o m
import java.io.Serializable;
import java.util.ArrayList;

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.FragmentActivity;
import android.util.DisplayMetrics;
import android.view.MenuItem;
import android.view.Window;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnCameraChangeListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.UiSettings;
import com.google.android.gms.maps.model.CameraPosition;
import com.twotoasters.clusterkraf.Clusterkraf;
import com.twotoasters.clusterkraf.Clusterkraf.ProcessingListener;
import com.twotoasters.clusterkraf.InputPoint;
import com.twotoasters.clusterkraf.Options.ClusterClickBehavior;
import com.twotoasters.clusterkraf.Options.ClusterInfoWindowClickBehavior;
import com.twotoasters.clusterkraf.Options.SinglePointClickBehavior;
import com.twotoasters.clusterkraf.sample.RandomPointsProvider.GenerateCallback;
import com.twotoasters.clusterkraf.sample.RandomPointsProvider.GeographicDistribution;

public class SampleActivity extends FragmentActivity implements GenerateCallback, ProcessingListener {

  public static final String EXTRA_OPTIONS = "options";

  private static final String KEY_CAMERA_POSITION = "camera position";

  private static final long DELAY_CLUSTERING_SPINNER_MILLIS = 200l;

  private final Handler handler = new Handler();

  private Options options;

  private GoogleMap map;
  private CameraPosition restoreCameraPosition;
  private Clusterkraf clusterkraf;
  private ArrayList<InputPoint> inputPoints;
  private DelayedIndeterminateProgressBarRunnable delayedIndeterminateProgressBarRunnable;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    setProgressBarIndeterminate(true);

    setContentView(R.layout.activity_sample);

    int titleFormatArg = 0;
    Intent i = getIntent();
    if (i != null) {
      Object options = i.getSerializableExtra(EXTRA_OPTIONS);
      if (options instanceof Options) {
        this.options = (Options)options;
        titleFormatArg = R.string.mode_advanced_label;
      }
    }
    if (this.options == null) {
      this.options = new Options();
      titleFormatArg = R.string.mode_normal_label;
    }
    setTitle(getString(R.string.sample_activity, getString(titleFormatArg)));

    RandomPointsProvider rpp = RandomPointsProvider.getInstance();

    if (savedInstanceState != null && rpp.hasPoints()) {
      this.restoreCameraPosition = savedInstanceState.getParcelable(KEY_CAMERA_POSITION);
      this.inputPoints = rpp.getPoints();
    } else {
      setProgressBarIndeterminateVisibility(true);

      rpp.generate(this, options.geographicDistribution, options.pointCount);
    }

    initMap();
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    switch(item.getItemId()) {
      case android.R.id.home:
        finish();
        return true;
    }
    return super.onOptionsItemSelected(item);
  }

  @Override
  protected void onPause() {
    super.onPause();
    /**
     * When pausing, we clear all of the clusterkraf's markers in order to
     * conserve memory. When (if) we resume, we can rebuild from where we
     * left off.
     */
    if (clusterkraf != null) {
      clusterkraf.clear();
      clusterkraf = null;
      if (map != null) {
        restoreCameraPosition = map.getCameraPosition();
      }
    }
  }

  @Override
  protected void onResume() {
    super.onResume();
    initMap();
  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    if (map != null) {
      CameraPosition cameraPosition = map.getCameraPosition();
      if (cameraPosition != null) {
        outState.putParcelable(KEY_CAMERA_POSITION, cameraPosition);
      }
    }
  }

  private void initMap() {
    if (map == null) {
      SupportMapFragment mapFragment = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
      if (mapFragment != null) {
        map = mapFragment.getMap();
        if (map != null) {
          UiSettings uiSettings = map.getUiSettings();
          uiSettings.setAllGesturesEnabled(false);
          uiSettings.setScrollGesturesEnabled(true);
          uiSettings.setZoomGesturesEnabled(true);
          map.setOnCameraChangeListener(new OnCameraChangeListener() {
            @Override
            public void onCameraChange(CameraPosition arg0) {
              moveMapCameraToBoundsAndInitClusterkraf();
            }
          });
        }
      }
    } else {
      moveMapCameraToBoundsAndInitClusterkraf();
    }
  }

  private void moveMapCameraToBoundsAndInitClusterkraf() {
    if (map != null && options != null && inputPoints != null) {
      try {
        if (restoreCameraPosition != null) {
          /**
           * if a restoreCameraPosition is available, move the camera
           * there
           */
          map.moveCamera(CameraUpdateFactory.newCameraPosition(restoreCameraPosition));
          restoreCameraPosition = null;
        } else {
          /**
           * otherwise, move the camera over the Two Toasters office
           * at an appropriate zoom based on the user's choice of
           * geographic distribution
           */
          float zoom = options.geographicDistribution == GeographicDistribution.NearTwoToasters ? 11 : 4;
          map.moveCamera(CameraUpdateFactory.newLatLngZoom(MarkerData.TwoToasters.getLatLng(), zoom));
        }
        initClusterkraf();
      } catch (IllegalStateException ise) {
        // no-op
      }
    }
  }

  private void initClusterkraf() {
    if (map != null && inputPoints != null && inputPoints.size() > 0) {
      com.twotoasters.clusterkraf.Options options = new com.twotoasters.clusterkraf.Options();
      applyDemoOptionsToClusterkrafOptions(options);
      clusterkraf = new Clusterkraf(map, options, inputPoints);
    }
  }

  /**
   * Applies the sample.SampleActivity.Options chosen in Normal or Advanced
   * mode menus to the clusterkraf.Options which will be used to construct our
   * Clusterkraf instance
   * 
   * @param options
   */
  private void applyDemoOptionsToClusterkrafOptions(com.twotoasters.clusterkraf.Options options) {
    options.setTransitionDuration(this.options.transitionDuration);

    /**
     * this is probably not how you would set an interpolator in your own
     * app. You would probably have just one that you wanted to hard code in
     * your app (show me the mobile app user who actually wants to fiddle
     * with the interpolator used in their animations), so you would do
     * something more like `options.setInterpolator(new
     * DecelerateInterpolator());` rather than mess around with reflection.
     */
    Interpolator interpolator = null;
    try {
      interpolator = (Interpolator)Class.forName(this.options.transitionInterpolator).newInstance();
    } catch (InstantiationException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
    options.setTransitionInterpolator(interpolator);

    /**
     * Clusterkraf calculates whether InputPoint objects should join a
     * cluster based on their pixel proximity. If you want to offer your app
     * on devices with different screen densities, you should identify a
     * Device Independent Pixel measurement and convert it to pixels based
     * on the device's screen density at runtime.
     */
    options.setPixelDistanceToJoinCluster(getPixelDistanceToJoinCluster());

    options.setZoomToBoundsAnimationDuration(this.options.zoomToBoundsAnimationDuration);
    options.setShowInfoWindowAnimationDuration(this.options.showInfoWindowAnimationDuration);
    options.setExpandBoundsFactor(this.options.expandBoundsFactor);
    options.setSinglePointClickBehavior(this.options.singlePointClickBehavior);
    options.setClusterClickBehavior(this.options.clusterClickBehavior);
    options.setClusterInfoWindowClickBehavior(this.options.clusterInfoWindowClickBehavior);

    /**
     * Device Independent Pixel measurement should be converted to pixels
     * here too. In this case, we cheat a little by using a Drawable's
     * height. It's only cheating because we don't offer a variant for that
     * Drawable for every density (xxhdpi, tvdpi, others?).
     */
    options.setZoomToBoundsPadding(getResources().getDrawable(R.drawable.ic_map_pin_cluster).getIntrinsicHeight());

    options.setMarkerOptionsChooser(new ToastedMarkerOptionsChooser(this, inputPoints.get(0)));
    options.setOnMarkerClickDownstreamListener(new ToastedOnMarkerClickDownstreamListener(this));
    options.setProcessingListener(this);
  }

  private int getPixelDistanceToJoinCluster() {
    return convertDeviceIndependentPixelsToPixels(this.options.dipDistanceToJoinCluster);
  }

  private int convertDeviceIndependentPixelsToPixels(int dip) {
    DisplayMetrics displayMetrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
    return Math.round(displayMetrics.density * dip);
  }

  @Override
  public void onRandomMarkersGenerated(ArrayList<InputPoint> inputPoints) {
    this.inputPoints = inputPoints;
    initMap();
  }

  static class Options implements Serializable {

    private static final long serialVersionUID = 7492713360265465944L;

    // sample app-specific options
    int pointCount = 100;
    GeographicDistribution geographicDistribution = GeographicDistribution.NearTwoToasters;

    // clusterkraf library options
    int transitionDuration = 500;
    String transitionInterpolator = LinearInterpolator.class.getCanonicalName();
    int dipDistanceToJoinCluster = 100;
    int zoomToBoundsAnimationDuration = 500;
    int showInfoWindowAnimationDuration = 500;
    double expandBoundsFactor = 0.5d;
    SinglePointClickBehavior singlePointClickBehavior = SinglePointClickBehavior.SHOW_INFO_WINDOW;
    ClusterClickBehavior clusterClickBehavior = ClusterClickBehavior.ZOOM_TO_BOUNDS;
    ClusterInfoWindowClickBehavior clusterInfoWindowClickBehavior = ClusterInfoWindowClickBehavior.ZOOM_TO_BOUNDS;
  }

  @Override
  public void onClusteringStarted() {
    if (delayedIndeterminateProgressBarRunnable == null) {
      delayedIndeterminateProgressBarRunnable = new DelayedIndeterminateProgressBarRunnable(this);
      handler.postDelayed(delayedIndeterminateProgressBarRunnable, DELAY_CLUSTERING_SPINNER_MILLIS);
    }
  }

  @Override
  public void onClusteringFinished() {
    if (delayedIndeterminateProgressBarRunnable != null) {
      handler.removeCallbacks(delayedIndeterminateProgressBarRunnable);
      delayedIndeterminateProgressBarRunnable = null;
    }
    setProgressBarIndeterminateVisibility(false);
  }

}




Java Source Code List

android.UnusedStub.java
com.twotoasters.clusterkraf.AnimatedTransition.java
com.twotoasters.clusterkraf.BasePoint.java
com.twotoasters.clusterkraf.ClusterPoint.java
com.twotoasters.clusterkraf.ClusterTransitionsAnimation.java
com.twotoasters.clusterkraf.ClusterTransitionsBuildingTask.java
com.twotoasters.clusterkraf.ClusterTransitions.java
com.twotoasters.clusterkraf.ClusteringOnCameraChangeListener.java
com.twotoasters.clusterkraf.ClusteringTask.java
com.twotoasters.clusterkraf.Clusterkraf.java
com.twotoasters.clusterkraf.ClustersBuilder.java
com.twotoasters.clusterkraf.InfoWindowDownstreamAdapter.java
com.twotoasters.clusterkraf.InputPoint.java
com.twotoasters.clusterkraf.MarkerOptionsChooser.java
com.twotoasters.clusterkraf.OnInfoWindowClickDownstreamListener.java
com.twotoasters.clusterkraf.OnMarkerClickDownstreamListener.java
com.twotoasters.clusterkraf.Options.java
com.twotoasters.clusterkraf.sample.AdvancedModeFragment.java
com.twotoasters.clusterkraf.sample.DelayedIndeterminateProgressBarRunnable.java
com.twotoasters.clusterkraf.sample.MainActivity.java
com.twotoasters.clusterkraf.sample.MarkerData.java
com.twotoasters.clusterkraf.sample.NormalModeFragment.java
com.twotoasters.clusterkraf.sample.RandomPointsProvider.java
com.twotoasters.clusterkraf.sample.SampleActivity.java
com.twotoasters.clusterkraf.sample.SingleChoiceDialogFragment.java
com.twotoasters.clusterkraf.sample.ToastedMarkerOptionsChooser.java
com.twotoasters.clusterkraf.sample.ToastedOnMarkerClickDownstreamListener.java
com.twotoasters.clusterkraf.sample.TwoToastersActivity.java
com.twotoasters.clusterkraf.util.Distance.java