diff --git a/OsmAnd-telegram/res/drawable-hdpi/ic_direction_arrow.png b/OsmAnd-telegram/res/drawable-hdpi/ic_direction_arrow.png new file mode 100644 index 0000000000..790efba776 Binary files /dev/null and b/OsmAnd-telegram/res/drawable-hdpi/ic_direction_arrow.png differ diff --git a/OsmAnd-telegram/res/drawable-mdpi/ic_direction_arrow.png b/OsmAnd-telegram/res/drawable-mdpi/ic_direction_arrow.png new file mode 100644 index 0000000000..0dd7c1772e Binary files /dev/null and b/OsmAnd-telegram/res/drawable-mdpi/ic_direction_arrow.png differ diff --git a/OsmAnd-telegram/res/drawable-xhdpi/ic_direction_arrow.png b/OsmAnd-telegram/res/drawable-xhdpi/ic_direction_arrow.png new file mode 100644 index 0000000000..fbab873b59 Binary files /dev/null and b/OsmAnd-telegram/res/drawable-xhdpi/ic_direction_arrow.png differ diff --git a/OsmAnd-telegram/res/drawable-xxhdpi/ic_direction_arrow.png b/OsmAnd-telegram/res/drawable-xxhdpi/ic_direction_arrow.png new file mode 100644 index 0000000000..bd17a41d7f Binary files /dev/null and b/OsmAnd-telegram/res/drawable-xxhdpi/ic_direction_arrow.png differ diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/views/DirectionDrawable.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/views/DirectionDrawable.kt new file mode 100644 index 0000000000..60e44aec52 --- /dev/null +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/views/DirectionDrawable.kt @@ -0,0 +1,63 @@ +package net.osmand.telegram.ui.views + +import android.graphics.Canvas +import android.graphics.ColorFilter +import android.graphics.PixelFormat +import android.graphics.Rect +import android.graphics.drawable.Drawable +import net.osmand.telegram.TelegramApplication + +class DirectionDrawable(private val app: TelegramApplication) : Drawable() { + + private var angle: Float = 0.toFloat() + private var arrowImage: Drawable? = null + + fun setImage(resourceId: Int, clrId: Int) { + arrowImage = app.uiUtils.getIcon(resourceId, clrId) + onBoundsChange(bounds) + } + + fun setAngle(angle: Float) { + this.angle = angle + } + + override fun getIntrinsicWidth() = arrowImage?.intrinsicWidth ?: super.getIntrinsicWidth() + + override fun getIntrinsicHeight() = arrowImage?.intrinsicHeight ?: super.getIntrinsicHeight() + + override fun onBoundsChange(bounds: Rect) { + super.onBoundsChange(bounds) + if (arrowImage != null) { + val w = arrowImage!!.intrinsicWidth + val h = arrowImage!!.intrinsicHeight + val dx = Math.max(0, bounds.width() - w) + val dy = Math.max(0, bounds.height() - h) + if (bounds.width() == 0 && bounds.height() == 0) { + arrowImage!!.setBounds(0, 0, w, h) + } else { + arrowImage!!.setBounds( + bounds.left + dx / 2, + bounds.top + dy / 2, + bounds.right - dx / 2, + bounds.bottom - dy / 2 + ) + } + } + } + + override fun draw(canvas: Canvas) { + canvas.save() + if (arrowImage != null) { + val r = bounds + canvas.rotate(angle, r.centerX().toFloat(), r.centerY().toFloat()) + arrowImage!!.draw(canvas) + } + canvas.restore() + } + + override fun getOpacity() = PixelFormat.UNKNOWN + + override fun setAlpha(alpha: Int) {} + + override fun setColorFilter(cf: ColorFilter?) {} +} diff --git a/OsmAnd-telegram/src/net/osmand/telegram/utils/UiUtils.kt b/OsmAnd-telegram/src/net/osmand/telegram/utils/UiUtils.kt index a45e53d8ba..b744ff09c7 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/utils/UiUtils.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/utils/UiUtils.kt @@ -1,15 +1,25 @@ package net.osmand.telegram.utils +import android.content.Context import android.graphics.* import android.graphics.drawable.Drawable import android.graphics.drawable.LayerDrawable +import android.hardware.Sensor +import android.hardware.SensorManager import android.support.annotation.ColorInt import android.support.annotation.ColorRes import android.support.annotation.DrawableRes import android.support.v4.content.ContextCompat import android.support.v4.graphics.drawable.DrawableCompat +import android.view.Surface +import android.view.WindowManager +import android.widget.ImageView +import android.widget.TextView +import net.osmand.Location +import net.osmand.data.LatLon import net.osmand.telegram.R import net.osmand.telegram.TelegramApplication +import net.osmand.telegram.ui.views.DirectionDrawable import java.util.* class UiUtils(private val app: TelegramApplication) { @@ -122,4 +132,84 @@ class UiUtils(private val app: TelegramApplication) { return bitmap } + + fun updateLocationView( + arrow: ImageView?, + text: TextView?, + lat: Double, + lon: Double, + cache: UpdateLocationViewCache + ) { + updateLocationView(arrow, text, LatLon(lat, lon), cache) + } + + fun updateLocationView( + arrow: ImageView?, + text: TextView?, + toLoc: LatLon, + cache: UpdateLocationViewCache + ) { + val fromLoc = app.locationProvider.lastKnownLocationLatLon + val heading = app.locationProvider.heading + val mes = FloatArray(2) + val locPassive = fromLoc == null || cache.outdatedLocation + val colorId = if (locPassive) R.color.icon_light else R.color.ctrl_active_light + + fromLoc?.also { l -> + Location.distanceBetween(toLoc.latitude, toLoc.longitude, l.latitude, l.longitude, mes) + } + + if (arrow != null) { + var newImage = false + val drawable = arrow.drawable + val dd = if (drawable is DirectionDrawable) { + drawable + } else { + newImage = true + DirectionDrawable(app) + } + dd.setImage(R.drawable.ic_direction_arrow, colorId) + if (fromLoc == null || heading == null) { + dd.setAngle(0f) + } else { + dd.setAngle(mes[1] - heading + 180 + cache.screenOrientation) + } + if (newImage) { + arrow.setImageDrawable(dd) + } + arrow.invalidate() + } + + if (text != null) { + text.setTextColor(ContextCompat.getColor(app, colorId)) + val meters = if (fromLoc == null) 0f else mes[1] + text.text = OsmandFormatter.getFormattedDistance(meters, app) + } + } + + fun getUpdateLocationViewCache() = + UpdateLocationViewCache().apply { screenOrientation = getScreenOrientation() } + + private fun getScreenOrientation(): Int { + // screenOrientation correction must not be applied for devices without compass + val sensorManager = app.getSystemService(Context.SENSOR_SERVICE) as SensorManager? + if (sensorManager?.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) == null) { + return 0 + } + + val windowManager = app.getSystemService(Context.WINDOW_SERVICE) as WindowManager? + val rotation = windowManager?.defaultDisplay?.rotation ?: return 0 + + return when (rotation) { + Surface.ROTATION_90 -> 90 + Surface.ROTATION_180 -> 180 + Surface.ROTATION_270 -> 270 + else -> 0 + } + } + + class UpdateLocationViewCache { + var screenOrientation: Int = 0 + var outdatedLocation: Boolean = false + } }