diff --git a/demo/src/main/java/com/peterlaurence/mapview/demo/fragments/RotatingMapFragment.kt b/demo/src/main/java/com/peterlaurence/mapview/demo/fragments/RotatingMapFragment.kt index b0c7f79..207c622 100644 --- a/demo/src/main/java/com/peterlaurence/mapview/demo/fragments/RotatingMapFragment.kt +++ b/demo/src/main/java/com/peterlaurence/mapview/demo/fragments/RotatingMapFragment.kt @@ -10,6 +10,7 @@ import com.peterlaurence.mapview.MapView import com.peterlaurence.mapview.MapViewConfiguration import com.peterlaurence.mapview.api.addCallout import com.peterlaurence.mapview.api.addMarker +import com.peterlaurence.mapview.api.rotateMarker import com.peterlaurence.mapview.api.setMarkerTapListener import com.peterlaurence.mapview.core.TileStreamProvider import com.peterlaurence.mapview.demo.R @@ -70,17 +71,23 @@ class RotatingMapFragment : Fragment() { mapView.addNewMarker(0.5, 0.5, "marker #1") mapView.addNewMarker(0.4, 0.3, "marker #2") mapView.addNewMarker(0.6, 0.4, "marker #3") - + mapView.addCurrentPositionMarker(0.7, 0.7, 0f) /* When a marker is tapped, we want to show a callout view */ mapView.setMarkerTapListener(object : MarkerTapListener { override fun onMarkerTap(view: View, x: Int, y: Int) { if (view is MapMarker) { - val callout = MarkerCallout(context) - callout.setTitle(view.name) - callout.setSubTitle("position: ${view.x} , ${view.y}") - mapView.addCallout(callout, view.x, view.y, -0.5f, -1.2f, 0f, 0f) - callout.transitionIn() + if (view.name == POSITION_MARKER) { + val randomAngle = (0..360).random().toFloat() + mapView.rotateMarker(view, randomAngle) + } + else { + val callout = MarkerCallout(context) + callout.setTitle(view.name) + callout.setSubTitle("position: ${view.x} , ${view.y}") + mapView.addCallout(callout, view.x, view.y, -0.5f, -1.2f, 0f, 0f) + callout.transitionIn() + } } } }) @@ -128,4 +135,14 @@ class RotatingMapFragment : Fragment() { addMarker(marker, x, y) } -} \ No newline at end of file + + private fun MapView.addCurrentPositionMarker(x: Double, y: Double, fixedAngle: Float) { + val marker = MapMarker(context, x, y, POSITION_MARKER).apply { + setImageResource(R.drawable.position_marker) + } + + addMarker(marker, x, y, -0.5f, -0.5f, fixedAngle = fixedAngle) + } +} + +const val POSITION_MARKER = "position marker" diff --git a/demo/src/main/res/drawable/position_marker.xml b/demo/src/main/res/drawable/position_marker.xml new file mode 100644 index 0000000..0e183b5 --- /dev/null +++ b/demo/src/main/res/drawable/position_marker.xml @@ -0,0 +1,5 @@ + + + diff --git a/mapview/src/main/java/com/peterlaurence/mapview/api/MarkerApi.kt b/mapview/src/main/java/com/peterlaurence/mapview/api/MarkerApi.kt index 33dd680..b59d3f2 100644 --- a/mapview/src/main/java/com/peterlaurence/mapview/api/MarkerApi.kt +++ b/mapview/src/main/java/com/peterlaurence/mapview/api/MarkerApi.kt @@ -16,16 +16,19 @@ import com.peterlaurence.mapview.markers.MarkerTapListener * @param relativeAnchorTop The y-axis position of a marker will be offset by a number equal to the height of the marker multiplied by this value. * @param absoluteAnchorLeft The x-axis position of a marker will be offset by this value. * @param absoluteAnchorTop The y-axis position of a marker will be offset by this value. + * @param fixedAngle Angle which the marker should face (depends on map angle). + * If the angle is null the marker will not rotate. */ fun MapView.addMarker(view: View, x: Double, y: Double, relativeAnchorLeft: Float = -0.5f, relativeAnchorTop: Float = -1f, absoluteAnchorLeft: Float = 0f, - absoluteAnchorTop: Float = 0f) { + absoluteAnchorTop: Float = 0f, fixedAngle: Float? = null) { markerLayout.addMarker(view, coordinateTranslater.translateX(x), coordinateTranslater.translateY(y), relativeAnchorLeft, relativeAnchorTop, - absoluteAnchorLeft, absoluteAnchorTop + absoluteAnchorLeft, absoluteAnchorTop, + fixedAngle ) } @@ -42,14 +45,27 @@ fun MapView.setMarkerTapListener(markerTapListener: MarkerTapListener) { /** * Moves an existing marker to another position. * - * @param view The marker View to be repositioned. - * @param x Relative x position the View instance should be positioned at. - * @param y Relative y position the View instance should be positioned at. + * @param view The marker View to be repositioned. + * @param x Relative x position the View instance should be positioned at. + * @param y Relative y position the View instance should be positioned at. + * @param angle Angle by which the marker should be rotated (depends on map angle). + * If the angle is null the marker will not rotate. */ -fun MapView.moveMarker(view: View, x: Double, y: Double) { +fun MapView.moveMarker(view: View, x: Double, y: Double, angle: Float? = null) { markerLayout.moveMarker(view, coordinateTranslater.translateX(x), - coordinateTranslater.translateY(y)) + coordinateTranslater.translateY(y), + angle) +} + +/** + * Rotates an existing marker. + * + * @param view The marker View to be repositioned. + * @param angle Angle by which the marker should be rotated (depends on map angle). + */ +fun MapView.rotateMarker(view: View, angle: Float) { + markerLayout.rotateMarker(view, angle) } /** diff --git a/mapview/src/main/java/com/peterlaurence/mapview/markers/MarkerLayout.kt b/mapview/src/main/java/com/peterlaurence/mapview/markers/MarkerLayout.kt index 59b8966..62e2ce9 100644 --- a/mapview/src/main/java/com/peterlaurence/mapview/markers/MarkerLayout.kt +++ b/mapview/src/main/java/com/peterlaurence/mapview/markers/MarkerLayout.kt @@ -73,12 +73,19 @@ open class MarkerLayout(context: Context) : ViewGroup(context), ReferentialOwner layoutParams.top = (rotateCenteredY(scaledX, scaledY, centerX, centerY, angleRad) + heightOffset).toInt() layoutParams.right = layoutParams.left + actualWidth layoutParams.bottom = layoutParams.top + actualHeight + + if (layoutParams.fixedAngle != null) { + // rotates marker with map or keeps fixed angle + child.rotation = layoutParams.fixedAngle!!.plus(referentialData.angle) + } } else { // save computed values layoutParams.left = (scaledX + widthOffset).toInt() layoutParams.top = (scaledY + heightOffset).toInt() layoutParams.right = layoutParams.left + actualWidth layoutParams.bottom = layoutParams.top + actualHeight + + child.rotation = layoutParams.fixedAngle ?: 0f } } return layoutParams @@ -99,13 +106,13 @@ open class MarkerLayout(context: Context) : ViewGroup(context), ReferentialOwner fun addMarker(view: View, left: Int, top: Int, relativeAnchorLeft: Float = -0.5f, relativeAnchorTop: Float = -1f, absoluteAnchorLeft: Float = 0f, - absoluteAnchorTop: Float = 0f) { + absoluteAnchorTop: Float = 0f, fixedAngle: Float? = null) { val layoutParams = MarkerLayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, left, top, relativeAnchorLeft, relativeAnchorTop, - absoluteAnchorLeft, absoluteAnchorTop) + absoluteAnchorLeft, absoluteAnchorTop, fixedAngle) addView(view, layoutParams) } @@ -136,10 +143,18 @@ open class MarkerLayout(context: Context) : ViewGroup(context), ReferentialOwner invalidate() } - fun moveMarker(view: View, x: Int, y: Int) { + fun moveMarker(view: View, x: Int, y: Int, angle: Float?) { val lp = view.layoutParams as? MarkerLayoutParams ?: return lp.x = x lp.y = y + lp.fixedAngle = angle + view.layoutParams = lp + requestLayout() + } + + fun rotateMarker(view: View, angle: Float) { + val lp = view.layoutParams as? MarkerLayoutParams ?: return + lp.fixedAngle = angle view.layoutParams = lp requestLayout() } @@ -172,7 +187,9 @@ open class MarkerLayout(context: Context) : ViewGroup(context), ReferentialOwner internal class MarkerLayoutParams(width: Int, height: Int, var x: Int, var y: Int, var relativeAnchorX: Float, var relativeAnchorY: Float, - var absoluteAnchorX: Float, var absoluteAnchorY: Float) : ViewGroup.LayoutParams(width, height) { + var absoluteAnchorX: Float, var absoluteAnchorY: Float, + var fixedAngle: Float? = null) + : ViewGroup.LayoutParams(width, height) { var top: Int = 0 var left: Int = 0