1616 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1717 */
1818
19- package com.bobek .compass
19+ package com.earendel .compass
2020
2121import android.Manifest.permission.ACCESS_COARSE_LOCATION
2222import android.Manifest.permission.ACCESS_FINE_LOCATION
23+ import android.content.pm.ActivityInfo
2324import android.content.pm.PackageManager.PERMISSION_GRANTED
2425import android.content.res.ColorStateList
2526import android.hardware.Sensor
@@ -54,17 +55,17 @@ import androidx.fragment.app.Fragment
5455import androidx.fragment.app.viewModels
5556import androidx.lifecycle.Lifecycle
5657import androidx.navigation.fragment.findNavController
57- import com.bobek .compass.databinding.FragmentCompassBinding
58- import com.bobek .compass.databinding.SensorAlertDialogViewBinding
59- import com.bobek .compass.model.AppError
60- import com.bobek .compass.model.Azimuth
61- import com.bobek .compass.model.DisplayRotation
62- import com.bobek .compass.model.LocationStatus
63- import com.bobek .compass.model.RotationVector
64- import com.bobek .compass.model.SensorAccuracy
65- import com.bobek .compass.preference.PreferenceStore
66- import com.bobek .compass.util.MathUtils
67- import com.bobek .compass.view.CompassViewModel
58+ import com.earendel .compass.databinding.FragmentCompassBinding
59+ import com.earendel .compass.databinding.SensorAlertDialogViewBinding
60+ import com.earendel .compass.model.AppError
61+ import com.earendel .compass.model.Azimuth
62+ import com.earendel .compass.model.DisplayRotation
63+ import com.earendel .compass.model.LocationStatus
64+ import com.earendel .compass.model.RotationVector
65+ import com.earendel .compass.model.SensorAccuracy
66+ import com.earendel .compass.preference.PreferenceStore
67+ import com.earendel .compass.util.MathUtils
68+ import com.earendel .compass.view.CompassViewModel
6869import com.google.android.material.color.MaterialColors
6970import com.google.android.material.dialog.MaterialAlertDialogBuilder
7071import java.util.concurrent.Executor
@@ -112,6 +113,14 @@ class CompassFragment : Fragment() {
112113 preferenceStore.hapticFeedback.observe(viewLifecycleOwner) {
113114 compassViewModel.hapticFeedback.value = it
114115 }
116+ preferenceStore.isRotationEnabled.observe(viewLifecycleOwner) { isEnabled ->
117+ requireActivity().requestedOrientation = if (isEnabled) {
118+ ActivityInfo .SCREEN_ORIENTATION_UNSPECIFIED
119+ } else {
120+ ActivityInfo .SCREEN_ORIENTATION_PORTRAIT
121+ }
122+ compassViewModel.isRotationEnabled.value = isEnabled
123+ }
115124 }
116125 }
117126
@@ -336,31 +345,70 @@ class CompassFragment : Fragment() {
336345 override fun onCreateMenu (menu : Menu , menuInflater : MenuInflater ) {
337346 menuInflater.inflate(R .menu.menu_compass, menu)
338347 optionsMenu = menu
348+
349+ val sensorItem = menu.findItem(R .id.action_sensor_status)
350+ sensorItem.actionView?.setOnClickListener {
351+ onMenuItemSelected(sensorItem)
352+ }
353+
339354 compassViewModel.sensorAccuracy.observe(viewLifecycleOwner) { updateSensorStatusIcon(it) }
340- requirePreferenceStore().screenOrientationLocked.observe(viewLifecycleOwner) { updateScreenRotationIcon(it) }
341355 }
342356
343357 private fun updateSensorStatusIcon (sensorAccuracy : SensorAccuracy ) {
344- val menuItem = optionsMenu?.findItem(R .id.action_sensor_status)
345- menuItem?.setIcon(sensorAccuracy.iconResourceId)
358+ val menuItem = optionsMenu?.findItem(R .id.action_sensor_status) ? : return
359+
360+ // Update legacy icon just in case
361+ menuItem.setIcon(sensorAccuracy.iconResourceId)
362+
363+ // Update new ActionView (Vertical Pills)
364+ val actionView = menuItem.actionView
365+ if (actionView != null ) {
366+ val pill1 = actionView.findViewById<View >(R .id.sensor_pill_small)
367+ val pill2 = actionView.findViewById<View >(R .id.sensor_pill_medium)
368+ val pill3 = actionView.findViewById<View >(R .id.sensor_pill_large)
369+
370+ if (pill1 != null && pill2 != null && pill3 != null ) {
371+ val typedValue = android.util.TypedValue ()
372+ requireContext().theme.resolveAttribute(android.R .attr.isLightTheme, typedValue, true )
373+ val isLightTheme = typedValue.data != 0
374+
375+ val activeColor = ContextCompat .getColor(requireContext(), if (isLightTheme) R .color.pure_black else R .color.pure_white)
376+ val inactiveColor = ContextCompat .getColor(requireContext(), R .color.gray_medium)
377+ val errorColor = ContextCompat .getColor(requireContext(), android.R .color.holo_red_dark)
378+
379+ when (sensorAccuracy) {
380+ SensorAccuracy .HIGH -> {
381+ pill1.background?.setTint(activeColor); pill1.alpha = 1.0f
382+ pill2.background?.setTint(activeColor); pill2.alpha = 1.0f
383+ pill3.background?.setTint(activeColor); pill3.alpha = 1.0f
384+ }
385+ SensorAccuracy .MEDIUM -> {
386+ pill1.background?.setTint(activeColor); pill1.alpha = 1.0f
387+ pill2.background?.setTint(activeColor); pill2.alpha = 1.0f
388+ pill3.background?.setTint(inactiveColor); pill3.alpha = 0.2f
389+ }
390+ SensorAccuracy .LOW -> {
391+ pill1.background?.setTint(activeColor); pill1.alpha = 1.0f
392+ pill2.background?.setTint(inactiveColor); pill2.alpha = 0.2f
393+ pill3.background?.setTint(inactiveColor); pill3.alpha = 0.2f
394+ }
395+ SensorAccuracy .UNRELIABLE , SensorAccuracy .NO_CONTACT -> {
396+ pill1.background?.setTint(errorColor); pill1.alpha = 1.0f
397+ pill2.background?.setTint(inactiveColor); pill2.alpha = 0.2f
398+ pill3.background?.setTint(inactiveColor); pill3.alpha = 0.2f
399+ }
400+ }
401+ }
402+ }
346403
347404 if (VERSION .SDK_INT >= VERSION_CODES .O ) {
348405 sensorAccuracy.iconTintAttributeResourceId
349406 .let { MaterialColors .getColor(requireContext(), it, this ::class .simpleName) }
350407 .let { ColorStateList .valueOf(it) }
351- .also { menuItem? .iconTintList = it }
408+ .also { menuItem.iconTintList = it }
352409 }
353410 }
354411
355- private fun updateScreenRotationIcon (screenOrientationLocked : Boolean ) {
356- optionsMenu
357- ?.findItem(R .id.action_screen_rotation)
358- ?.setIcon(getScreenRotationIcon(screenOrientationLocked))
359- }
360-
361- @DrawableRes
362- private fun getScreenRotationIcon (screenOrientationLocked : Boolean ): Int =
363- if (screenOrientationLocked) R .drawable.ic_screen_rotation_lock else R .drawable.ic_screen_rotation
364412
365413 override fun onMenuItemSelected (menuItem : MenuItem ): Boolean {
366414 return when (menuItem.itemId) {
@@ -369,10 +417,6 @@ class CompassFragment : Fragment() {
369417 true
370418 }
371419
372- R .id.action_screen_rotation -> {
373- toggleRotationScreenLocked()
374- true
375- }
376420
377421 R .id.action_settings -> {
378422 showSettings()
@@ -398,12 +442,6 @@ class CompassFragment : Fragment() {
398442 .show()
399443 }
400444
401- private fun toggleRotationScreenLocked () {
402- val preferenceStore = requirePreferenceStore()
403- preferenceStore.screenOrientationLocked.value?.let { value ->
404- preferenceStore.screenOrientationLocked.value = value.not ()
405- }
406- }
407445
408446 private fun showSettings () {
409447 findNavController().navigate(R .id.action_CompassFragment_to_SettingsFragment)
0 commit comments