Back to project page clusterkraf.
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.
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); } }