diff --git a/Habitica/res/layout/activity_main_content.xml b/Habitica/res/layout/activity_main_content.xml index 2fa5f8769..20aa1445b 100644 --- a/Habitica/res/layout/activity_main_content.xml +++ b/Habitica/res/layout/activity_main_content.xml @@ -140,8 +140,7 @@ android:id="@+id/snackbar_container" android:layout_width="match_parent" android:layout_height="400dp" - android:layout_alignParentBottom="true" - android:paddingBottom="50dp" /> + android:layout_alignParentBottom="true" /> + android:background="?attr/colorContentBackground" + android:clipToPadding="false"/> diff --git a/Habitica/res/layout/snackbar_view.xml b/Habitica/res/layout/snackbar_view.xml index 9dd48cc9c..9346c9983 100644 --- a/Habitica/res/layout/snackbar_view.xml +++ b/Habitica/res/layout/snackbar_view.xml @@ -9,8 +9,7 @@ android:paddingEnd="0dp" android:gravity="center" tools:background="@drawable/snackbar_background_green" - android:layout_marginBottom="32dp" - android:layout_gravity="center_horizontal" + android:layout_gravity="center_horizontal|bottom" android:elevation="24dp" android:clipToPadding="false"> + val bars = insets.getInsets( + WindowInsetsCompat.Type.systemBars() + or WindowInsetsCompat.Type.displayCutout() + ) + v.updatePadding( + top = bars.top, + bottom = bars.bottom, + left = bars.left, + right = bars.right + ) + consumeWindowInsetsAbove30(insets) + } + } + override fun onOptionsItemSelected(item: MenuItem): Boolean { return if (item.itemId == android.R.id.home) { NavUtils.navigateUpFromSameTask(this) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.kt index 11e4f322e..8d923d2e4 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.kt @@ -15,7 +15,6 @@ import android.view.LayoutInflater import android.view.Menu import android.view.MenuItem import android.view.View -import android.view.ViewGroup.MarginLayoutParams import androidx.activity.SystemBarStyle import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity @@ -24,16 +23,11 @@ import androidx.appcompat.widget.Toolbar import androidx.core.content.ContextCompat import androidx.core.net.toUri import androidx.core.view.ViewCompat -import androidx.core.view.ViewGroupCompat import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat -import androidx.core.view.updateLayoutParams import androidx.core.view.updatePadding -import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.repeatOnLifecycle import androidx.preference.PreferenceManager -import com.google.android.material.appbar.AppBarLayout import com.habitrpg.android.habitica.HabiticaApplication import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.data.UserRepository @@ -52,7 +46,6 @@ import com.habitrpg.common.habitica.extensions.isUsingNightModeResources import com.habitrpg.common.habitica.helpers.ExceptionHandler import com.habitrpg.common.habitica.helpers.LanguageHelper import com.habitrpg.common.habitica.helpers.launchCatching -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import java.io.File import java.io.FileNotFoundException @@ -147,8 +140,13 @@ abstract class BaseActivity : AppCompatActivity() { findViewById(R.id.appbar)?.let { appbar -> val paddingTop = appbar.paddingTop ViewCompat.setOnApplyWindowInsetsListener(appbar) { v, windowInsets -> - val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.updatePadding(top = insets.top + paddingTop) + val insets = windowInsets.getInsets( + WindowInsetsCompat.Type.systemBars() + + WindowInsetsCompat.Type.displayCutout() + ) + v.updatePadding(top = insets.top + paddingTop, + left = insets.left, + right = insets.right) consumeWindowInsetsAbove30(windowInsets) } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.kt index 34beee6c3..12331d82d 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.kt @@ -31,10 +31,13 @@ import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateMapOf import androidx.compose.runtime.toMutableStateList import androidx.core.content.ContextCompat +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat import androidx.core.view.children import androidx.core.view.forEachIndexed import androidx.core.view.isVisible import androidx.core.view.iterator +import androidx.core.view.updatePadding import androidx.core.widget.NestedScrollView import androidx.lifecycle.lifecycleScope import com.habitrpg.android.habitica.R @@ -45,6 +48,7 @@ import com.habitrpg.android.habitica.data.TaskRepository import com.habitrpg.android.habitica.databinding.ActivityTaskFormBinding import com.habitrpg.android.habitica.extensions.OnChangeTextWatcher import com.habitrpg.android.habitica.extensions.addCancelButton +import com.habitrpg.android.habitica.extensions.consumeWindowInsetsAbove30 import com.habitrpg.android.habitica.helpers.AppConfigManager import com.habitrpg.android.habitica.helpers.TaskAlarmManager import com.habitrpg.android.habitica.helpers.notifications.PushNotificationManager @@ -221,8 +225,8 @@ class TaskFormActivity : BaseActivity() { ContextCompat.getColor(this, R.color.white), upperTintColor ) - binding.appbar.setBackgroundColor(upperTintColor) } + binding.appbar.setBackgroundColor(upperTintColor) supportActionBar?.setBackgroundDrawable(ColorDrawable(upperTintColor)) binding.upperTextWrapper.setBackgroundColor(upperTintColor) @@ -427,21 +431,20 @@ class TaskFormActivity : BaseActivity() { configureForm() } + override fun onAttachedToWindow() { + super.onAttachedToWindow() + ViewCompat.setOnApplyWindowInsetsListener(binding.mainFormContent) { v, windowInsets -> + val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) + v.updatePadding(bottom = insets.bottom) + consumeWindowInsetsAbove30(windowInsets) + } + } + override fun onResume() { checkIfShowNotifLayout() super.onResume() } - override fun loadTheme( - sharedPreferences: SharedPreferences, - forced: Boolean - ) { - super.loadTheme(sharedPreferences, forced) - val upperTintColor = - if (forcedTheme == "taskform") getThemeColor(R.attr.taskFormTint) else getThemeColor(R.attr.colorAccent) - window.statusBarColor = upperTintColor - } - override fun onStart() { super.onStart() if (isCreating) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/BaseMainFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/BaseMainFragment.kt index 6c62ff2af..20497ac61 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/BaseMainFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/BaseMainFragment.kt @@ -9,7 +9,6 @@ import android.view.MenuItem import android.view.View import android.view.ViewGroup import androidx.core.os.bundleOf -import androidx.core.view.ViewCompat import androidx.core.view.WindowCompat import androidx.viewbinding.ViewBinding import com.google.android.material.appbar.AppBarLayout @@ -21,6 +20,7 @@ import com.habitrpg.android.habitica.helpers.SoundManager import com.habitrpg.android.habitica.ui.activities.MainActivity import com.habitrpg.android.habitica.ui.helpers.ToolbarColorHelper import com.habitrpg.common.habitica.extensions.getThemeColor +import com.habitrpg.common.habitica.extensions.isUsingNightModeResources import javax.inject.Inject abstract class BaseMainFragment : BaseFragment() { @@ -58,7 +58,7 @@ abstract class BaseMainFragment : BaseFragment() { windowInsetsController.isAppearanceLightNavigationBars = false } else { bottomNavigation?.visibility = View.GONE - windowInsetsController.isAppearanceLightNavigationBars = true + windowInsetsController.isAppearanceLightNavigationBars = requireActivity().isUsingNightModeResources() } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/GemsPurchaseFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/GemsPurchaseFragment.kt index 492d9978a..8d486b62a 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/GemsPurchaseFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/GemsPurchaseFragment.kt @@ -10,9 +10,11 @@ import androidx.compose.foundation.layout.padding import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat import androidx.core.view.isVisible +import androidx.core.view.updatePadding import androidx.fragment.app.Fragment -import androidx.fragment.app.replace import androidx.lifecycle.lifecycleScope import com.android.billingclient.api.ProductDetails import com.habitrpg.android.habitica.R @@ -20,6 +22,7 @@ import com.habitrpg.android.habitica.data.UserRepository import com.habitrpg.android.habitica.databinding.FragmentGemPurchaseBinding import com.habitrpg.android.habitica.extensions.addCancelButton import com.habitrpg.android.habitica.extensions.addCloseButton +import com.habitrpg.android.habitica.extensions.consumeWindowInsetsAbove30 import com.habitrpg.android.habitica.helpers.Analytics import com.habitrpg.android.habitica.helpers.AppConfigManager import com.habitrpg.android.habitica.helpers.PurchaseHandler @@ -124,6 +127,20 @@ class GemsPurchaseFragment : BaseFragment() { } loadInventory() + binding?.supportTextView?.let { + val paddingBottom = it.paddingBottom + ViewCompat.setOnApplyWindowInsetsListener(it) { v, insets -> + val bars = insets.getInsets( + WindowInsetsCompat.Type.systemBars() + or WindowInsetsCompat.Type.displayCutout() + ) + v.updatePadding( + bottom = bars.bottom + paddingBottom, + ) + consumeWindowInsetsAbove30(insets) + } + } + Analytics.sendNavigationEvent("gem screen") } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt index 9d2284e2a..87a349215 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt @@ -18,16 +18,20 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.requiredSize import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.systemBarsIgnoringVisibility import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -119,6 +123,7 @@ fun getTranslatedClassNamePlural( } } +@OptIn(ExperimentalLayoutApi::class) @Composable fun AppHeaderView( user: Avatar?, @@ -132,7 +137,8 @@ fun AppHeaderView( configManager: AppConfigManager? = null ) { val isPlayerOptedOutOfClass = user?.preferences?.disableClasses ?: false - Column(modifier) { + Column(modifier + .windowInsetsPadding(WindowInsets.systemBarsIgnoringVisibility)) { Row { ComposableAvatarView( user, diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/BottomSheetUtils.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/BottomSheetUtils.kt index 9390ec2a1..afa92811e 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/BottomSheetUtils.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/BottomSheetUtils.kt @@ -53,7 +53,6 @@ fun Fragment.showAsBottomSheet(content: @Composable (() -> Unit) -> Unit) { } // Helper method -@OptIn(ExperimentalLayoutApi::class) private fun addContentToView( viewGroup: ViewGroup, content: @Composable (() -> Unit) -> Unit diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaSnackbar.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaSnackbar.kt index b6bf6aa59..30af6a95b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaSnackbar.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaSnackbar.kt @@ -8,7 +8,6 @@ import android.view.ViewGroup import android.view.animation.AccelerateInterpolator import androidx.annotation.ColorInt import androidx.core.content.ContextCompat -import androidx.core.view.ViewCompat import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.snackbar.Snackbar import com.habitrpg.android.habitica.R @@ -100,11 +99,11 @@ private constructor(parent: ViewGroup, content: View, callback: ContentViewCallb ) { content.scaleY = 0f content.scaleX = 0f - ViewCompat.animate(content).scaleY(1f).setDuration(duration.toLong()).startDelay = + content.animate().scaleY(1f).setDuration(duration.toLong()).startDelay = delay.toLong() - ViewCompat.animate(content).scaleX(1f).setDuration(duration.toLong()).startDelay = + content.animate().scaleX(1f).setDuration(duration.toLong()).startDelay = delay.toLong() - ViewCompat.animate(content).alpha(1f).setDuration(duration.toLong()).startDelay = + content.animate().alpha(1f).setDuration(duration.toLong()).startDelay = delay.toLong() } @@ -114,11 +113,11 @@ private constructor(parent: ViewGroup, content: View, callback: ContentViewCallb ) { content.scaleY = 1f content.scaleX = 1f - ViewCompat.animate(content).scaleY(0f).setDuration(duration.toLong()).startDelay = + content.animate().scaleY(0f).setDuration(duration.toLong()).startDelay = delay.toLong() - ViewCompat.animate(content).scaleX(0f).setDuration(duration.toLong()).startDelay = + content.animate().scaleX(0f).setDuration(duration.toLong()).startDelay = delay.toLong() - ViewCompat.animate(content).alpha(0f).setDuration(duration.toLong()).startDelay = + content.animate().alpha(0f).setDuration(duration.toLong()).startDelay = delay.toLong() } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/LabeledBar.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/LabeledBar.kt index 49fb80963..9fc7db742 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/LabeledBar.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/LabeledBar.kt @@ -113,6 +113,8 @@ fun LabeledBar( .clip(CircleShape) .height(barHeight), trackColor = barColor, + drawStopIndicator = {}, + gapSize = -barHeight, color = color ) AnimatedVisibility(visible = !displayCompact) { @@ -179,6 +181,14 @@ private fun Preview() { maxValue = 50.0, displayCompact = compact ) + LabeledBar( + icon = HabiticaIconsHelper.imageOfExperience(), + label = stringResource(id = R.string.XP_default), + color = colorResource(R.color.xpColor), + value = 100.0, + maxValue = 300.0, + displayCompact = compact + ) LabeledBar( icon = HabiticaIconsHelper.imageOfExperience(), label = stringResource(id = R.string.XP_default), diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/HabiticaBottomSheetDialog.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/HabiticaBottomSheetDialog.kt index b51710129..118d1abaa 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/HabiticaBottomSheetDialog.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/HabiticaBottomSheetDialog.kt @@ -2,12 +2,13 @@ package com.habitrpg.android.habitica.ui.views.dialogs import android.content.Context import android.view.View -import androidx.core.view.WindowCompat -import androidx.core.view.updateLayoutParams +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.updatePadding import com.google.android.material.bottomsheet.BottomSheetDialog -import com.google.android.material.internal.ViewUtils.doOnApplyWindowInsets import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.databinding.BottomSheetWrapperBinding +import com.habitrpg.android.habitica.extensions.consumeWindowInsetsAbove30 open class HabiticaBottomSheetDialog(context: Context) : BottomSheetDialog(context, R.style.SheetDialog) { @@ -15,6 +16,14 @@ open class HabiticaBottomSheetDialog(context: Context) : init { behavior.peekHeight = context.resources.displayMetrics.heightPixels / 2 + ViewCompat.setOnApplyWindowInsetsListener(wrapperBinding.container) { v, windowInsets -> + val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) + v.updatePadding( + left = insets.left, + right = insets.right, + bottom = insets.bottom) + consumeWindowInsetsAbove30(windowInsets) + } } var grabberVisibility: Int