Skip to content

Commit

Permalink
Merge "Fix opening Map screen from session detail"
Browse files Browse the repository at this point in the history
  • Loading branch information
shailen authored and Gerrit Code Review committed Apr 30, 2018
2 parents 222a699 + 8665920 commit 09ff6de
Show file tree
Hide file tree
Showing 15 changed files with 286 additions and 54 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ map_default_camera_zoom = 16.4
map_default_camera_tilt = 0

# Zoom level to use when camera is programmatically centered on a marker
map_venue_camera_zoom = 17.2f
map_camera_focus_zoom = 18.7f

# Tile coordinates that map the floor plan SVG to World Coordinates (note: not lat-long coordinates)
# See http://stackoverflow.com/questions/21167584/google-io-2013-app-mystery-values
Expand Down
3 changes: 3 additions & 0 deletions mobile/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,15 @@ android {
"MAP_VIEWPORT_BOUND_SE",
"new com.google.android.gms.maps.model.LatLng(${map_viewport_bound_se})"

buildConfigField "float", "MAP_CAMERA_FOCUS_ZOOM", "${map_camera_focus_zoom}"

resValue "dimen", "map_camera_bearing", "${map_default_camera_bearing}"
resValue "dimen", "map_camera_target_lat", "${map_default_camera_target_lat}"
resValue "dimen", "map_camera_target_lng", "${map_default_camera_target_lng}"
resValue "dimen", "map_camera_tilt", "${map_default_camera_tilt}"
resValue "dimen", "map_camera_zoom", "${map_default_camera_zoom}"
resValue "dimen", "map_viewport_min_zoom", "${map_viewport_min_zoom}"

manifestPlaceholders = [crashlyticsEnabled: true]

}
Expand Down
4 changes: 4 additions & 0 deletions mobile/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
android:name=".ui.speaker.SpeakerActivity"
android:theme="@style/AppTheme.Speaker" />

<activity
android:name=".ui.map.MapActivity"
android:theme="@style/AppTheme.NoActionBar" />

<!-- This activity alias lets us change the main entry point without breaking launcher
shortcuts. DO NOT change its android:name attribute. -->
<activity-alias
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import com.google.samples.apps.iosched.ui.LaunchModule
import com.google.samples.apps.iosched.ui.LauncherActivity
import com.google.samples.apps.iosched.ui.MainActivity
import com.google.samples.apps.iosched.ui.info.InfoModule
import com.google.samples.apps.iosched.ui.map.MapActivity
import com.google.samples.apps.iosched.ui.map.MapModule
import com.google.samples.apps.iosched.ui.onboarding.OnboardingActivity
import com.google.samples.apps.iosched.ui.onboarding.OnboardingModule
Expand Down Expand Up @@ -89,4 +90,13 @@ abstract class ActivityBindingModule {
]
)
internal abstract fun speakerActivity(): SpeakerActivity

@ActivityScoped
@ContributesAndroidInjector(
modules = [
MapModule::class,
PreferenceModule::class
]
)
internal abstract fun mapActivity(): MapActivity
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright 2018 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.samples.apps.iosched.ui.map

import android.content.Context
import android.text.TextUtils
import com.google.android.gms.maps.GoogleMap
import com.google.maps.android.data.geojson.GeoJsonFeature
import com.google.maps.android.data.geojson.GeoJsonLayer
import com.google.samples.apps.iosched.shared.domain.UseCase
import javax.inject.Inject

/** Parameters for this use case. */
typealias LoadGeoJsonParams = Pair<GoogleMap, Int>

/** Data loaded by this use case. */
data class GeoJsonData(
val geoJsonLayer: GeoJsonLayer,
val featureMap: Map<String, GeoJsonFeature>
)

/** Use case that loads a GeoJsonLayer and its features. */
class LoadGeoJsonFeaturesUseCase @Inject constructor(
private val context: Context
): UseCase<LoadGeoJsonParams, GeoJsonData>() {

override fun execute(parameters: LoadGeoJsonParams): GeoJsonData {
val layer = GeoJsonLayer(parameters.first, parameters.second, context)
processGeoJsonLayer(layer, context)
layer.isLayerOnMap
return GeoJsonData(layer, buildFeatureMap(layer))
}

private fun buildFeatureMap(layer: GeoJsonLayer): Map<String, GeoJsonFeature> {
val featureMap: MutableMap<String, GeoJsonFeature> = mutableMapOf()
layer.features.forEach {
val id = it.getProperty("id")
if (!TextUtils.isEmpty(id)) {
featureMap[id] = it
}
}
return featureMap
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2018 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.samples.apps.iosched.ui.map

import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import com.google.samples.apps.iosched.R
import com.google.samples.apps.iosched.shared.util.inTransaction
import dagger.android.support.DaggerAppCompatActivity

/** Shell activity hosting a [MapFragment] */
class MapActivity : DaggerAppCompatActivity() {

companion object {
const val EXTRA_FEATURE_ID = "extra.FEATURE_ID"

fun starterIntent(context: Context, featureId: String): Intent {
return Intent(context, MapActivity::class.java).apply {
putExtra(EXTRA_FEATURE_ID, featureId)
}
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_map)

if (savedInstanceState == null) {
val featureId = intent.getStringExtra(EXTRA_FEATURE_ID)
val fragment = if (!TextUtils.isEmpty(featureId)) {
MapFragment.newInstance(featureId)
} else {
MapFragment()
}
supportFragmentManager.inTransaction {
add(R.id.fragment_container, fragment)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener
import com.google.android.gms.maps.MapView
import com.google.android.gms.maps.model.Marker
import com.google.samples.apps.iosched.databinding.FragmentMapBinding
import com.google.samples.apps.iosched.shared.util.viewModelProvider
import com.google.samples.apps.iosched.ui.MainNavigationFragment
import dagger.android.support.DaggerFragment
import javax.inject.Inject

class MapFragment : DaggerFragment(), MainNavigationFragment {
class MapFragment : DaggerFragment(), MainNavigationFragment, OnMarkerClickListener {

@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
private lateinit var viewModel: MapViewModel
Expand All @@ -37,9 +39,17 @@ class MapFragment : DaggerFragment(), MainNavigationFragment {

companion object {
val TAG: String = MapFragment::class.java.simpleName
fun newInstance() = MapFragment()
private const val MAPVIEW_BUNDLE_KEY = "MapViewBundleKey"

const val MAPVIEW_BUNDLE_KEY = "MapViewBundleKey"
private const val ARG_FEATURE_ID = "arg.FEATURE_ID"

fun newInstance(featureId: String): MapFragment {
return MapFragment().apply {
arguments = Bundle().apply {
putString(ARG_FEATURE_ID, featureId)
}
}
}
}

override fun onCreate(savedInstanceState: Bundle?) {
Expand All @@ -63,6 +73,12 @@ class MapFragment : DaggerFragment(), MainNavigationFragment {

initializeMap()

if (savedInstanceState == null) {
arguments?.getString(ARG_FEATURE_ID)?.let {
viewModel.requestHighlightFeature(it)
}
}

return binding.root
}

Expand Down Expand Up @@ -96,6 +112,7 @@ class MapFragment : DaggerFragment(), MainNavigationFragment {
override fun onDestroy() {
super.onDestroy()
mapView.onDestroy()
viewModel.onMapDestroyed()
}

override fun onLowMemory() {
Expand All @@ -104,23 +121,24 @@ class MapFragment : DaggerFragment(), MainNavigationFragment {
}

private fun initializeMap() {
// TODO: Move this completely to BindingAdapter.

mapView.getMapAsync {
// TODO: Initialize marker icon bitmaps (active and normal).
viewModel.onMapReady(it)

it?.apply {
// TODO set maps style.

setOnMarkerClickListener {
// TODO fwd to VM
false
}
setOnMarkerClickListener(this@MapFragment)
setOnMapClickListener {
// TODO fwd to VM
}
// TODO: if user has enabled location permission, enable that on map.
}
}
}

override fun onMarkerClick(marker: Marker): Boolean {
// This is a hack. We set the geojson feature ID as the snippet since there is no other way
// to add metadata and we need to look up the feature again by ID.
val id = marker.snippet ?: return false
viewModel.requestHighlightFeature(id)
return true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,17 @@ package com.google.samples.apps.iosched.ui.map
import android.content.Context
import android.graphics.Bitmap
import android.support.annotation.DrawableRes
import android.support.annotation.RawRes
import android.support.v7.content.res.AppCompatResources
import androidx.graphics.drawable.toBitmap
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.model.BitmapDescriptorFactory
import com.google.maps.android.data.geojson.GeoJsonLayer
import com.google.maps.android.data.geojson.GeoJsonPointStyle
import com.google.maps.android.ui.IconGenerator
import com.google.samples.apps.iosched.R
import java.util.Locale

/**
* Convert a raw resource to a GeoJsonLayer for display on a Map. The content of the resource must
* follow the [GeoJSON format][https://tools.ietf.org/html/rfc7946].
*/
fun applyGeoJsonLayer(
map: GoogleMap,
@RawRes resId: Int,
context: Context
): GeoJsonLayer {
val layer = GeoJsonLayer(map, resId, context)
/** Process a [GeoJsonLayer] for display on a Map. */
fun processGeoJsonLayer(layer: GeoJsonLayer, context: Context) {
val iconGenerator = getLabelIconGenerator(context)
layer.features.forEach { feature ->
val id = feature.getProperty("id")
Expand All @@ -53,8 +43,6 @@ fun applyGeoJsonLayer(
else -> GeoJsonPointStyle() // no styling
}
}

return layer
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ package com.google.samples.apps.iosched.ui.map
import android.databinding.BindingAdapter
import android.support.annotation.DimenRes
import android.support.annotation.RawRes
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.CameraUpdate
import com.google.android.gms.maps.MapView
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.LatLngBounds
import com.google.android.gms.maps.model.MapStyleOptions
import com.google.android.gms.maps.model.TileOverlayOptions
import com.google.android.gms.maps.model.TileProvider
import com.google.maps.android.data.geojson.GeoJsonLayer
import com.google.samples.apps.iosched.shared.result.Event
import com.google.samples.apps.iosched.util.getFloat

@BindingAdapter("mapStyle")
Expand All @@ -41,11 +42,8 @@ fun mapStyle(mapView: MapView, @RawRes resId: Int) {
* Adds list of markers to the GoogleMap.
*/
@BindingAdapter("mapMarkers")
fun mapMarkers(mapView: MapView, @RawRes markers: Int) {
mapView.getMapAsync {
val layer = applyGeoJsonLayer(it, markers, mapView.context)
layer.addLayerToMap()
}
fun mapMarkers(mapView: MapView, geoJsonLayer: GeoJsonLayer?) {
geoJsonLayer?.addLayerToMap()
}

/**
Expand All @@ -61,15 +59,13 @@ fun mapViewport(mapView: MapView, bounds: LatLngBounds?) {
}

/**
* Sets the center of the map's camera target. This will be called initially and then every time the
* user selects an event or a marker.
* Sets the center of the map's camera. Call this every time the user selects a marker.
*/
@BindingAdapter("mapCenter")
fun mapCenter(mapView: MapView, target: LatLng?) {
if (target != null) {
mapView.getMapAsync {
it.animateCamera(CameraUpdateFactory.newLatLng(target))
}
fun mapCenter(mapView: MapView, event: Event<CameraUpdate>?) {
val update = event?.getContentIfNotHandled() ?: return
mapView.getMapAsync {
it.animateCamera(update)
}
}

Expand Down
Loading

0 comments on commit 09ff6de

Please sign in to comment.