mirror of
https://github.com/openlibrecommunity/olcng.git
synced 2026-07-03 14:05:17 +02:00
feat(ui): enable edge-to-edge layout and fix status bar color
This commit is contained in:
@@ -32,8 +32,9 @@ class AngApplication : Application() {
|
||||
*/
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
// Apply Material You dynamic colors (Android 12+)
|
||||
DynamicColors.applyToActivitiesIfAvailable(this)
|
||||
// DynamicColors отключён — на Android 12-15 он красит статус-бар в акцент ОС
|
||||
// и это нельзя переопределить через statusBarColor
|
||||
// DynamicColors.applyToActivitiesIfAvailable(this)
|
||||
|
||||
val mmkvDir = java.io.File(filesDir, "mmkv")
|
||||
if (!java.io.File(mmkvDir, "MAIN").exists()) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package xyz.zarazaex.olc.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
@@ -16,7 +15,6 @@ import androidx.core.view.WindowCompat
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
import xyz.zarazaex.olc.R
|
||||
import xyz.zarazaex.olc.handler.SettingsManager
|
||||
@@ -187,13 +185,10 @@ abstract class BaseActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun syncStatusBarWithToolbar(toolbar: Toolbar) {
|
||||
val toolbarColor = (toolbar.background as? ColorDrawable)?.color
|
||||
?: toolbar.backgroundTintList?.defaultColor
|
||||
?: MaterialColors.getColor(toolbar, com.google.android.material.R.attr.colorSurface)
|
||||
|
||||
window.statusBarColor = toolbarColor
|
||||
// Статус-бар прозрачный (задан в теме). Управляем только цветом иконок.
|
||||
val bgColor = ContextCompat.getColor(this, R.color.md_theme_surface)
|
||||
WindowCompat.getInsetsController(window, window.decorView)?.isAppearanceLightStatusBars =
|
||||
ColorUtils.calculateLuminance(toolbarColor) > 0.5
|
||||
ColorUtils.calculateLuminance(bgColor) > 0.5
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,7 @@ import androidx.appcompat.widget.SearchView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.GravityCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
@@ -76,6 +77,19 @@ class MainActivity : HelperBaseActivity(), NavigationView.OnNavigationItemSelect
|
||||
setContentView(binding.root)
|
||||
setupToolbar(binding.toolbar, false, getString(R.string.app_name))
|
||||
|
||||
// edge-to-edge: контент идёт под статус-бар, AppBarLayout тянется под него же
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.appBarLayout) { v, insets ->
|
||||
v.setPadding(0, insets.getInsets(WindowInsetsCompat.Type.statusBars()).top, 0, 0)
|
||||
insets
|
||||
}
|
||||
// Нижние кнопки поднимаются над навигационной панелью
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.bottomContainer) { v, insets ->
|
||||
val navBarHeight = insets.getInsets(WindowInsetsCompat.Type.navigationBars()).bottom
|
||||
v.setPadding(0, 0, 0, navBarHeight)
|
||||
insets
|
||||
}
|
||||
|
||||
groupPagerAdapter = GroupPagerAdapter(this, emptyList())
|
||||
binding.viewPager.adapter = groupPagerAdapter
|
||||
binding.viewPager.isUserInputEnabled = true
|
||||
@@ -171,15 +185,15 @@ class MainActivity : HelperBaseActivity(), NavigationView.OnNavigationItemSelect
|
||||
mainViewModel.isTesting.observe(this) { testing ->
|
||||
setButtonsEnabled(!testing)
|
||||
if (testing) {
|
||||
// Allow stopping the test
|
||||
binding.btnSummaryLite.isEnabled = true
|
||||
binding.btnSummaryLite.alpha = 1.0f
|
||||
binding.btnSummaryLite.setImageResource(R.drawable.ic_stop_24dp)
|
||||
binding.btnSummaryLite.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.color_fab_active))
|
||||
} else {
|
||||
binding.btnSummaryLite.setImageResource(R.drawable.bolt_24)
|
||||
// Re-apply running state to set correct enabled state
|
||||
val isRunning = mainViewModel.isRunning.value == true
|
||||
binding.btnSummaryLite.isEnabled = !isRunning
|
||||
binding.btnSummaryLite.alpha = if (isRunning) 0.5f else 1.0f
|
||||
binding.btnSummaryLite.isEnabled = true
|
||||
binding.btnSummaryLite.alpha = 1.0f
|
||||
binding.btnSummaryLite.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.color_fab_inactive))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,6 +428,16 @@ class MainActivity : HelperBaseActivity(), NavigationView.OnNavigationItemSelect
|
||||
|
||||
private fun showStatus(resId: Int) = showStatus(getString(resId))
|
||||
|
||||
private fun accentColor(): ColorStateList {
|
||||
val typedValue = android.util.TypedValue()
|
||||
theme.resolveAttribute(androidx.appcompat.R.attr.colorPrimary, typedValue, true)
|
||||
val color = if (typedValue.resourceId != 0)
|
||||
ContextCompat.getColor(this, typedValue.resourceId)
|
||||
else
|
||||
typedValue.data
|
||||
return ColorStateList.valueOf(color)
|
||||
}
|
||||
|
||||
private fun applyRunningState(isLoading: Boolean, isRunning: Boolean) {
|
||||
if (isLoading) {
|
||||
binding.fab.isEnabled = false
|
||||
@@ -424,27 +448,22 @@ class MainActivity : HelperBaseActivity(), NavigationView.OnNavigationItemSelect
|
||||
if (isRunning) {
|
||||
binding.fab.isEnabled = true
|
||||
binding.fab.alpha = 1.0f
|
||||
binding.fab.setImageResource(R.drawable.security_24)
|
||||
binding.fab.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.color_fab_active))
|
||||
binding.btnSummaryLite.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.color_fab_active))
|
||||
binding.fab.backgroundTintList = accentColor()
|
||||
binding.btnSummaryLite.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.color_fab_inactive))
|
||||
binding.fab.contentDescription = getString(R.string.action_stop_service)
|
||||
setTestState(getString(R.string.connection_connected))
|
||||
binding.layoutTest.isFocusable = true
|
||||
// Block lightning while VPN is connected (unless test is running)
|
||||
if (mainViewModel.isTesting.value != true) {
|
||||
binding.btnSummaryLite.isEnabled = false
|
||||
binding.btnSummaryLite.alpha = 0.5f
|
||||
}
|
||||
// Молния всегда активна — пользователь может запустить тест даже при работающем VPN
|
||||
binding.btnSummaryLite.isEnabled = true
|
||||
binding.btnSummaryLite.alpha = 1.0f
|
||||
} else {
|
||||
binding.fab.isEnabled = true
|
||||
binding.fab.alpha = 1.0f
|
||||
binding.fab.setImageResource(R.drawable.shield_24)
|
||||
binding.fab.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.color_fab_inactive))
|
||||
binding.btnSummaryLite.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.color_fab_inactive))
|
||||
binding.fab.contentDescription = getString(R.string.tasker_start_service)
|
||||
setTestState(getString(R.string.connection_not_connected))
|
||||
binding.layoutTest.isFocusable = false
|
||||
// Enable lightning when VPN is disconnected
|
||||
binding.btnSummaryLite.isEnabled = true
|
||||
binding.btnSummaryLite.alpha = 1.0f
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorOnSurface"
|
||||
android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/>
|
||||
</vector>
|
||||
@@ -4,17 +4,19 @@
|
||||
android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true">
|
||||
android:background="@color/md_theme_surface">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/app_bar_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/md_theme_surface"
|
||||
app:elevation="0dp">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
@@ -67,6 +69,7 @@
|
||||
android:layout_weight="1" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottom_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
@@ -13,15 +13,15 @@
|
||||
android:title="Проверить задержку профилей"
|
||||
app:showAsAction="always" />
|
||||
|
||||
<item
|
||||
android:id="@+id/sub_update"
|
||||
android:icon="@drawable/update_24"
|
||||
android:title="@string/title_sub_update"
|
||||
app:showAsAction="always" />
|
||||
|
||||
<item
|
||||
android:id="@+id/filter_by_country"
|
||||
android:icon="@drawable/public_24"
|
||||
android:title="Фильтр по странам"
|
||||
app:showAsAction="always" />
|
||||
|
||||
<item
|
||||
android:id="@+id/sub_update"
|
||||
android:icon="@drawable/ic_check_update_24dp"
|
||||
android:title="@string/title_sub_update"
|
||||
app:showAsAction="always" />
|
||||
</menu>
|
||||
@@ -49,7 +49,7 @@
|
||||
<item name="colorPrimaryInverse">@color/md_theme_inversePrimary</item>
|
||||
|
||||
<!-- Status bar and navigation bar - system bars -->
|
||||
<item name="android:statusBarColor">@color/md_theme_surface</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="android:navigationBarColor">@color/md_theme_surface</item>
|
||||
|
||||
<!-- Typography: use Roboto (Google's Material font) everywhere -->
|
||||
|
||||
Reference in New Issue
Block a user