Skip to content

Commit

Permalink
Add sighting compass to bearing input
Browse files Browse the repository at this point in the history
Closes #1186
  • Loading branch information
kylecorry31 committed Sep 24, 2023
1 parent 2126320 commit b944c65
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package com.kylecorry.trail_sense.shared.camera

import android.annotation.SuppressLint
import android.content.DialogInterface
import android.net.Uri
import android.os.Bundle
import android.util.Size
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.camera.core.ExperimentalZeroShutterLag
import androidx.camera.core.ImageCapture
import androidx.camera.view.PreviewView
import androidx.core.net.toUri
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import com.kylecorry.andromeda.camera.ImageCaptureSettings
import com.kylecorry.andromeda.fragments.BoundFullscreenDialogFragment
import com.kylecorry.trail_sense.databinding.FragmentPhotoImportSheetBinding
import com.kylecorry.andromeda.fragments.inBackground
import com.kylecorry.sol.units.Bearing
import com.kylecorry.trail_sense.databinding.FragmentSightingCompassSheetBinding
import com.kylecorry.trail_sense.shared.FormatService
import com.kylecorry.trail_sense.shared.extensions.onIO
import com.kylecorry.trail_sense.shared.extensions.onMain
import com.kylecorry.trail_sense.shared.io.FileSubsystem

class SightingCompassBottomSheetFragment(
private val onSelect: (bearing: Bearing?) -> Unit
) : BoundFullscreenDialogFragment<FragmentSightingCompassSheetBinding>() {

private val formatter by lazy { FormatService.getInstance(requireContext()) }

var bearing: Float? = null
set(value) {
field = value
if (isBound) {
updateUI()
}
}

@SuppressLint("UnsafeOptInUsageError")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

val volumeKeys = listOf(KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_UP)
dialog?.setOnKeyListener { _, keyCode, event ->
if (!volumeKeys.contains(keyCode) || event.action != KeyEvent.ACTION_DOWN) {
return@setOnKeyListener false
}
confirmBearing()
true
}

dialog?.setOnCancelListener { onSelect(null) }

binding.camera.setScaleType(PreviewView.ScaleType.FIT_CENTER)
binding.camera.clipToOutline = true
binding.camera.start(
lifecycleOwner = this,
readFrames = false
)

binding.toolTitle.rightButton.setOnClickListener {
onSelect(null)
dismiss()
}

binding.captureButton.setOnClickListener {
confirmBearing()
}

updateUI()
}

private fun updateUI() {
binding.toolTitle.title.text = bearing?.let { formatter.formatDegrees(it) } ?: ""
binding.linearCompass.azimuth = Bearing(bearing ?: 0f)
}

private fun confirmBearing() {
onSelect(bearing?.let { Bearing(it) })
dismiss()
}

override fun onDestroyView() {
if (isBound) {
binding.camera.stop()
}
super.onDestroyView()
}

override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
binding.camera.stop()
}

override fun generateBinding(
layoutInflater: LayoutInflater,
container: ViewGroup?
): FragmentSightingCompassSheetBinding {
return FragmentSightingCompassSheetBinding.inflate(layoutInflater, container, false)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@ import android.widget.TextView
import androidx.appcompat.widget.SwitchCompat
import androidx.core.view.isVisible
import androidx.core.widget.addTextChangedListener
import com.kylecorry.andromeda.fragments.AndromedaActivity
import com.kylecorry.andromeda.fragments.AndromedaFragment
import com.kylecorry.andromeda.fragments.show
import com.kylecorry.sol.units.Bearing
import com.kylecorry.trail_sense.R
import com.kylecorry.trail_sense.shared.FormatService
import com.kylecorry.trail_sense.shared.camera.SightingCompassBottomSheetFragment
import com.kylecorry.trail_sense.shared.extensions.floatValue
import com.kylecorry.trail_sense.shared.permissions.alertNoCameraPermission
import com.kylecorry.trail_sense.shared.permissions.requestCamera
import com.kylecorry.trail_sense.shared.sensors.SensorService
import kotlin.math.roundToInt

Expand Down Expand Up @@ -50,15 +56,19 @@ class BearingInputView(context: Context, attrs: AttributeSet? = null) :

private val bearingEdit: EditText
private val compassBtn: ImageButton
private val cameraBtn: ImageButton
private val compassText: TextView
private val trueNorthSwitch: SwitchCompat

private var cameraSheet: SightingCompassBottomSheetFragment? = null


init {
inflate(context, R.layout.view_bearing_input, this)

bearingEdit = findViewById(R.id.bearing)
compassBtn = findViewById(R.id.compass_btn)
cameraBtn = findViewById(R.id.camera_btn)
compassText = findViewById(R.id.compass_bearing)
trueNorthSwitch = findViewById(R.id.true_north)

Expand All @@ -73,21 +83,45 @@ class BearingInputView(context: Context, attrs: AttributeSet? = null) :
trueNorth = false
}

cameraBtn.setOnClickListener {
val activity = context as? AndromedaActivity ?: return@setOnClickListener
val fragment = activity.getFragment() as? AndromedaFragment ?: return@setOnClickListener

fragment.requestCamera { hasPermission ->
if (hasPermission) {
if (cameraSheet == null) {
cameraSheet = SightingCompassBottomSheetFragment {
bearing = it
trueNorth = false
}
}

cameraSheet?.show(fragment)
} else {
fragment.alertNoCameraPermission()
}
}
}

if (!hasCompass) {
findViewById<View>(R.id.compass_autofill_holder).isVisible = false
cameraBtn.isVisible = false
}
}

fun start() {
stop()
compass.start {
compassText.text = formatter.formatDegrees(compass.bearing.value, replace360 = true)
val bearing = compass.rawBearing
compassText.text = formatter.formatDegrees(bearing, replace360 = true)
cameraSheet?.bearing = bearing
true
}
}

fun stop() {
compass.stop(null)
cameraSheet?.dismiss()
}

private fun onChange() {
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/layout/fragment_photo_import_sheet.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
app:layout_constraintTop_toTopOf="parent"
app:rightButtonIcon="@drawable/ic_cancel"
app:showSubtitle="false"
app:title="Take photo" />
app:title="@string/take_photo" />

<com.kylecorry.trail_sense.shared.views.CameraView
android:id="@+id/camera"
Expand Down
62 changes: 62 additions & 0 deletions app/src/main/res/layout/fragment_sighting_compass_sheet.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/AppTheme">

<com.kylecorry.ceres.toolbar.CeresToolbar
android:id="@+id/tool_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:flattenButtons="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:rightButtonIcon="@drawable/ic_cancel"
app:showSubtitle="false" />

<com.kylecorry.trail_sense.shared.views.CameraView
android:id="@+id/camera"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:background="@drawable/rounded_rectangle"
app:layout_constraintBottom_toTopOf="@id/capture_button"
app:layout_constraintDimensionRatio="H,1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tool_title" />

<View
android:id="@+id/view_camera_line"
android:layout_width="1dp"
android:layout_height="0dp"
android:background="@color/orange_40"
app:layout_constraintBottom_toBottomOf="@id/camera"
app:layout_constraintEnd_toEndOf="@id/camera"
app:layout_constraintStart_toStartOf="@id/camera"
app:layout_constraintTop_toTopOf="@id/camera" />

<com.kylecorry.trail_sense.navigation.ui.LinearCompassView
android:id="@+id/linear_compass"
android:layout_width="0dp"
android:layout_height="100dp"
app:layout_constraintBottom_toBottomOf="@id/camera"
app:layout_constraintEnd_toEndOf="@id/camera"
app:layout_constraintStart_toStartOf="@id/camera"
app:layout_constraintTop_toTopOf="@id/camera" />

<com.kylecorry.trail_sense.shared.camera.ShutterButton
android:id="@+id/capture_button"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginBottom="16dp"
android:text="@string/camera_capture"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
13 changes: 12 additions & 1 deletion app/src/main/res/layout/view_bearing_input.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
android:layout_gravity="center"
android:background="@drawable/rounded_rectangle"
android:backgroundTint="@color/orange_40"
android:elevation="4dp"
android:padding="8dp"
app:srcCompat="@drawable/ic_compass_icon"
app:tint="@color/black" />
Expand All @@ -40,6 +39,18 @@

</LinearLayout>

<ImageButton
android:id="@+id/camera_btn"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
android:layout_marginEnd="8dp"
android:background="@drawable/rounded_rectangle"
android:backgroundTint="@color/orange_40"
android:padding="8dp"
app:srcCompat="@drawable/ic_camera"
app:tint="@color/black" />

<com.google.android.material.textfield.TextInputLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
Expand Down

0 comments on commit b944c65

Please sign in to comment.