diff --git a/buildSrc/components.json b/buildSrc/components.json
index dd37cd970..b4a04ac9e 100755
--- a/buildSrc/components.json
+++ b/buildSrc/components.json
@@ -2105,5 +2105,34 @@
"samples": [],
"has_mirror": false,
"mirror_repo": ""
+ },
+ {
+ "id": "common-tools",
+ "version": "0.5.0",
+ "unstable_version": 0,
+ "stable": false,
+ "dir": "common-tools",
+ "libs": [
+ {
+ "name": "status-bar-switcher",
+ "dir": "lib-status-bar-switcher",
+ "artifact_name": "status-bar-switcher",
+ "third_party_dependencies": [
+ {
+ "name": "androidx.palette:palette-ktx",
+ "type": "implementation"
+ }
+ ],
+ "android_standard_dependencies": []
+ }
+ ],
+ "samples": [
+ {
+ "name": "common-tools-sample",
+ "dir": "sample"
+ }
+ ],
+ "has_mirror": false,
+ "mirror_repo": ""
}
]
\ No newline at end of file
diff --git a/buildSrc/config.gradle b/buildSrc/config.gradle
index ecc1a60d8..0b85cc53a 100755
--- a/buildSrc/config.gradle
+++ b/buildSrc/config.gradle
@@ -43,6 +43,7 @@ ext {
"androidx.core:core" : "1.2.0", //https://bit.ly/2yYY82h
"androidx.core:core-ktx" : "1.2.0", //http://bit.ly/2qY7ffW
"androidx.constraintlayout:constraintlayout" : "2.0.0-beta4", //http://bit.ly/2S1WoNg
+ "androidx.palette:palette-ktx" : "1.0.0", //https://bit.ly/30afhnJ
"androidx.appcompat:appcompat" : "1.1.0", //http://bit.ly/2zjueqh
"androidx.lifecycle:lifecycle-runtime-ktx" : "2.2.0", //https://bit.ly/3anEaR2
"androidx.multidex:multidex" : "2.0.1", //http://bit.ly/2r6uX9G
diff --git a/common-tools/README.md b/common-tools/README.md
new file mode 100755
index 000000000..cbe995bde
--- /dev/null
+++ b/common-tools/README.md
@@ -0,0 +1,6 @@
+# Common tools
+
+## Модули
+
+- [Status bar switcher](lib-status-bar-switcher)
+- [Пример](sample)
\ No newline at end of file
diff --git a/common-tools/RELEASE_NOTES.md b/common-tools/RELEASE_NOTES.md
new file mode 100644
index 000000000..519b7b019
--- /dev/null
+++ b/common-tools/RELEASE_NOTES.md
@@ -0,0 +1,7 @@
+# Common tools Release Notes
+
+- [0.5.0-alpha](#050-alpha)
+
+## 0.5.0-alpha
+##### Common tools
+* TODO
\ No newline at end of file
diff --git a/common-tools/lib-status-bar-switcher/.gitignore b/common-tools/lib-status-bar-switcher/.gitignore
new file mode 100755
index 000000000..796b96d1c
--- /dev/null
+++ b/common-tools/lib-status-bar-switcher/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/common-tools/lib-status-bar-switcher/README.md b/common-tools/lib-status-bar-switcher/README.md
new file mode 100644
index 000000000..acc498183
--- /dev/null
+++ b/common-tools/lib-status-bar-switcher/README.md
@@ -0,0 +1,23 @@
+# Status bar switcher
+
+Сущность для автоматического переключения цвета статус-бара в зависимости от цвета контента, находящегося под ним.
+
+# Использование
+[Пример использования для определенного экрана](../sample)
+
+Для того, чтобы цвет статус-бара переключался автоматически для каждого экрана, нужно воспользоваться ActivityLifecycleCallbacks:
+
+```kotlin
+object : Application.ActivityLifecycleCallbacks() {
+
+ //...
+
+ override fun onActivityResumed(activity: Activity) {
+ statusBarSwitcher.attach(activity)
+ }
+
+ override fun onActivityStopped(activity: Activity) {
+ statusBarSwitcher.detach()
+ }
+}
+```
\ No newline at end of file
diff --git a/common-tools/lib-status-bar-switcher/build.gradle b/common-tools/lib-status-bar-switcher/build.gradle
new file mode 100644
index 000000000..aec5f43ed
--- /dev/null
+++ b/common-tools/lib-status-bar-switcher/build.gradle
@@ -0,0 +1 @@
+apply from: "$rootDir/buildSrc/baseBuild.gradle"
\ No newline at end of file
diff --git a/common-tools/lib-status-bar-switcher/src/main/AndroidManifest.xml b/common-tools/lib-status-bar-switcher/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..64426bba8
--- /dev/null
+++ b/common-tools/lib-status-bar-switcher/src/main/AndroidManifest.xml
@@ -0,0 +1 @@
+
diff --git a/common-tools/lib-status-bar-switcher/src/main/java/ru/surfstudio/android/common/tools/statusbarswitcher/StatusBarSwitcher.kt b/common-tools/lib-status-bar-switcher/src/main/java/ru/surfstudio/android/common/tools/statusbarswitcher/StatusBarSwitcher.kt
new file mode 100644
index 000000000..1a7a20576
--- /dev/null
+++ b/common-tools/lib-status-bar-switcher/src/main/java/ru/surfstudio/android/common/tools/statusbarswitcher/StatusBarSwitcher.kt
@@ -0,0 +1,160 @@
+/*
+ Copyright (c) 2020-present, SurfStudio LLC.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+package ru.surfstudio.android.common.tools.statusbarswitcher
+
+import android.app.Activity
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Rect
+import android.os.AsyncTask
+import android.os.Build
+import android.util.DisplayMetrics
+import android.view.View
+import android.view.ViewTreeObserver
+import androidx.annotation.ColorInt
+import androidx.core.view.OnApplyWindowInsetsListener
+import androidx.core.view.ViewCompat
+import androidx.palette.graphics.Palette
+import kotlin.math.sqrt
+
+/**
+ * Helper class for switching status bar color automatically.
+ *
+ * Status bar color calculation based on the underlying content brightness.
+ */
+class StatusBarSwitcher(private val displayMetrics: DisplayMetrics) {
+
+ private val colorFilter = Palette.Filter { _, _ -> true }
+
+ private val width: Int
+ get() = displayMetrics.widthPixels
+
+ private var attachedActivity: Activity? = null
+
+ private val decorView: View?
+ get() = attachedActivity?.window?.decorView
+
+ private var statusBarHeight: Int = 0
+
+ private val statusBarHeightListener = OnApplyWindowInsetsListener { _, insets ->
+ statusBarHeight = insets.stableInsetTop
+ insets
+ }
+
+ private var hasStatusBarListenerAttached: Boolean = false
+
+ private val onPreDrawListener = ViewTreeObserver.OnPreDrawListener {
+ if (statusBarHeight != 0) {
+ val bitmap = Bitmap.createBitmap(width, statusBarHeight, Bitmap.Config.RGB_565)
+ val canvas = Canvas(bitmap)
+ val statusBarRect = Rect(0, 0, width, statusBarHeight)
+ canvas.clipRect(statusBarRect)
+ decorView?.draw(canvas)
+
+ Palette.from(bitmap)
+ .clearFilters()
+ .addFilter(colorFilter)
+ .tryGenerate { palette ->
+ val dominantColor = palette.getDominantColor(Color.WHITE)
+ val isLightStatusBar = isBrightColor(dominantColor)
+ attachedActivity?.let { setLightStatusBar(it, isLightStatusBar) }
+ }
+ }
+ true
+ }
+
+ /**
+ * Sets status bar height manually.
+ */
+ fun setStatusBarHeight(statusBarHeight: Int) {
+ this.statusBarHeight = statusBarHeight
+ }
+
+ /**
+ * Attaches [StatusBarSwitcher] to the [activity].
+ *
+ * @param shouldDetectStatusBarHeight defines whether status bar height should be calculated
+ * automatically.
+ */
+ fun attach(
+ activity: Activity,
+ shouldDetectStatusBarHeight: Boolean = true
+ ) {
+ val decorView = activity.window.decorView
+ decorView.viewTreeObserver.addOnPreDrawListener(onPreDrawListener)
+ if (shouldDetectStatusBarHeight) {
+ ViewCompat.setOnApplyWindowInsetsListener(decorView, statusBarHeightListener)
+ hasStatusBarListenerAttached = true
+ }
+ attachedActivity = activity
+ }
+
+ /**
+ * Detaches [StatusBarSwitcher] from the latest activity.
+ */
+ fun detach() {
+ val activity = attachedActivity ?: return
+ attachedActivity = null
+
+ val decorView = activity.window.decorView ?: return
+ if (hasStatusBarListenerAttached) {
+ ViewCompat.setOnApplyWindowInsetsListener(decorView, null)
+ hasStatusBarListenerAttached = false
+ }
+ decorView.viewTreeObserver.removeOnPreDrawListener(onPreDrawListener)
+ }
+
+ /**
+ * Defines brightness of color.
+ *
+ * @return true, if color is bright; false otherwise.
+ */
+ private fun isBrightColor(@ColorInt color: Int): Boolean {
+ val rgb = intArrayOf(Color.red(color), Color.green(color), Color.blue(color))
+ val brightness = sqrt(
+ rgb[0] * rgb[0] * .241 +
+ rgb[1] * rgb[1] * .691 +
+ rgb[2] * rgb[2] * .068
+ )
+ return brightness >= 200
+ }
+
+ private fun Palette.Builder.tryGenerate(onGeneratedAction: (Palette) -> Unit): AsyncTask {
+ return this.generate { palette: Palette? ->
+ palette ?: return@generate
+ onGeneratedAction(palette)
+ }
+ }
+
+ companion object {
+
+ /**
+ * Toggles status bar color for the defined [activity].
+ */
+ fun setLightStatusBar(activity: Activity, isLightStatusBar: Boolean) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ val window = activity.window
+ val decorView = window?.decorView ?: return
+ val systemUiVisibilityFlags = decorView.systemUiVisibility
+ decorView.systemUiVisibility = when {
+ isLightStatusBar -> systemUiVisibilityFlags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
+ else -> systemUiVisibilityFlags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/common-tools/sample/.gitignore b/common-tools/sample/.gitignore
new file mode 100755
index 000000000..796b96d1c
--- /dev/null
+++ b/common-tools/sample/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/common-tools/sample/build.gradle b/common-tools/sample/build.gradle
new file mode 100755
index 000000000..5cb584729
--- /dev/null
+++ b/common-tools/sample/build.gradle
@@ -0,0 +1,18 @@
+import ru.surfstudio.android.build.DependencyConfigurator
+
+apply from: "$rootDir/buildSrc/androidSample.gradle"
+
+android {
+ defaultConfig {
+ applicationId "ru.surfstudio.android.common.tools.sample"
+ }
+}
+
+dependencies {
+ DependencyConfigurator.projectImplementation(project, "status-bar-switcher")
+ DependencyConfigurator.projectImplementation(project, "sample-common")
+ DependencyConfigurator.projectImplementation(project, "imageloader")
+ DependencyConfigurator.projectImplementation(project, "easyadapter")
+
+ DependencyConfigurator.kapt(project, "com.google.dagger:dagger-compiler")
+}
\ No newline at end of file
diff --git a/common-tools/sample/src/main/AndroidManifest.xml b/common-tools/sample/src/main/AndroidManifest.xml
new file mode 100755
index 000000000..af6a8b4af
--- /dev/null
+++ b/common-tools/sample/src/main/AndroidManifest.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/main/MainActivity.kt b/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/main/MainActivity.kt
new file mode 100644
index 000000000..6665e9abf
--- /dev/null
+++ b/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/main/MainActivity.kt
@@ -0,0 +1,24 @@
+package ru.surfstudio.android.common.tools.sample.screen.main
+
+import android.content.Intent
+import android.os.Bundle
+import android.widget.Button
+import androidx.appcompat.app.AppCompatActivity
+import kotlinx.android.synthetic.main.activity_main.*
+import ru.surfstudio.android.common.tools.sample.R
+import ru.surfstudio.android.common.tools.sample.screen.status_bar_switcher.StatusBarSwitcherActivityView
+
+class MainActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+ setOnClickListener(open_status_bar_switcher_btn, StatusBarSwitcherActivityView::class.java)
+ }
+
+ private fun setOnClickListener(btn: Button, activityClass: Class<*>) {
+ btn.setOnClickListener {
+ startActivity(Intent(this, activityClass))
+ }
+ }
+}
diff --git a/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/StatusBarSwitcherActivityRoute.kt b/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/StatusBarSwitcherActivityRoute.kt
new file mode 100644
index 000000000..d62dd98b4
--- /dev/null
+++ b/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/StatusBarSwitcherActivityRoute.kt
@@ -0,0 +1,11 @@
+package ru.surfstudio.android.common.tools.sample.screen.status_bar_switcher
+
+import android.content.Context
+import android.content.Intent
+import ru.surfstudio.android.core.ui.navigation.activity.route.ActivityRoute
+
+class StatusBarSwitcherActivityRoute : ActivityRoute() {
+
+ override fun prepareIntent(context: Context) =
+ Intent(context, StatusBarSwitcherActivityView::class.java)
+}
\ No newline at end of file
diff --git a/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/StatusBarSwitcherActivityView.kt b/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/StatusBarSwitcherActivityView.kt
new file mode 100644
index 000000000..13da325cd
--- /dev/null
+++ b/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/StatusBarSwitcherActivityView.kt
@@ -0,0 +1,79 @@
+package ru.surfstudio.android.common.tools.sample.screen.status_bar_switcher
+
+import android.os.Bundle
+import android.os.PersistableBundle
+import android.view.View
+import androidx.core.view.ViewCompat
+import androidx.core.view.marginTop
+import kotlinx.android.synthetic.main.activity_status_bar_switcher.*
+import ru.surfstudio.android.common.tools.sample.R
+import ru.surfstudio.android.common.tools.sample.screen.status_bar_switcher.controller.ImageItemController
+import ru.surfstudio.android.common.tools.statusbarswitcher.StatusBarSwitcher
+import ru.surfstudio.android.core.mvp.activity.BaseRenderableActivityView
+import ru.surfstudio.android.core.mvp.configurator.BaseActivityViewConfigurator
+import ru.surfstudio.android.easyadapter.EasyAdapter
+import ru.surfstudio.android.easyadapter.ItemList
+import ru.surfstudio.android.utilktx.ktx.ui.view.setTopMargin
+import javax.inject.Inject
+
+internal class StatusBarSwitcherActivityView : BaseRenderableActivityView() {
+
+ @Inject
+ lateinit var presenter: StatusBarSwitcherPresenter
+
+ private val easyAdapter = EasyAdapter()
+ private val itemController = ImageItemController()
+
+ override fun createConfigurator(): BaseActivityViewConfigurator<*, *, *> =
+ StatusBarSwitcherScreenConfigurator(intent)
+
+ override fun getScreenName() = "StatusBarSwitcherActivityView"
+
+ override fun getContentView() = R.layout.activity_status_bar_switcher
+
+ override fun getPresenters() = arrayOf(presenter)
+
+ override fun onCreate(
+ savedInstanceState: Bundle?,
+ persistentState: PersistableBundle?,
+ viewRecreated: Boolean
+ ) {
+ ViewCompat.setOnApplyWindowInsetsListener(window.decorView) { _, insets ->
+ status_bar_switcher_back_btn.setTopMargin(status_bar_switcher_back_btn.marginTop + insets.stableInsetTop)
+ presenter.setStatusBarHeight(insets.stableInsetTop)
+ insets
+ }
+ setFullscreenMode()
+ initViews()
+ }
+
+ fun attachStatusBarSwitcher(statusBarSwitcher: StatusBarSwitcher) {
+ statusBarSwitcher.attach(this)
+ }
+
+ private fun initViews() {
+ status_bar_switcher_rv.adapter = easyAdapter
+
+ status_bar_switcher_back_btn.setOnClickListener { presenter.closeScreen() }
+ status_bar_switcher_mode_btn.setOnClickListener { presenter.toggleStatusBarSwitchingMode() }
+ }
+
+ override fun renderInternal(sm: StatusBarSwitcherScreenModel) {
+ val switchModeTextRes = when {
+ sm.isAutoSwitchingEnabled -> R.string.status_bar_auto_switch_mode_btn_enabled_text
+ else -> R.string.status_bar_auto_switch_mode_btn_disabled_text
+ }
+ status_bar_switcher_mode_btn.text = getString(switchModeTextRes)
+
+ val itemList = ItemList().addAll(sm.sampleList, itemController)
+ easyAdapter.setItems(itemList)
+ }
+
+ private fun setFullscreenMode() {
+ val decorView = window?.decorView ?: return
+ val systemUiVisibilityFlags = decorView.systemUiVisibility
+ decorView.systemUiVisibility = systemUiVisibilityFlags or
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ }
+}
diff --git a/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/StatusBarSwitcherPresenter.kt b/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/StatusBarSwitcherPresenter.kt
new file mode 100644
index 000000000..2398ac99f
--- /dev/null
+++ b/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/StatusBarSwitcherPresenter.kt
@@ -0,0 +1,62 @@
+package ru.surfstudio.android.common.tools.sample.screen.status_bar_switcher
+
+import ru.surfstudio.android.common.tools.statusbarswitcher.StatusBarSwitcher
+import ru.surfstudio.android.core.mvp.presenter.BasePresenter
+import ru.surfstudio.android.core.mvp.presenter.BasePresenterDependency
+import ru.surfstudio.android.dagger.scope.PerScreen
+import javax.inject.Inject
+
+@PerScreen
+internal class StatusBarSwitcherPresenter @Inject constructor(
+ basePresenterDependency: BasePresenterDependency,
+ private val statusBarSwitcher: StatusBarSwitcher
+) : BasePresenter(basePresenterDependency) {
+
+ private val screenModel = StatusBarSwitcherScreenModel()
+
+ override fun onFirstLoad() {
+ view.render(screenModel)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ if (screenModel.statusBarHeight != 0 && screenModel.isAutoSwitchingEnabled) {
+ attachStatusBarSwitcher()
+ }
+ }
+
+ override fun onPause() {
+ super.onPause()
+ statusBarSwitcher.detach()
+ }
+
+ fun setStatusBarHeight(statusBarHeight: Int) {
+ val shouldEnableStatusBarSwitcher = screenModel.statusBarHeight == 0 && screenModel.isAutoSwitchingEnabled
+ screenModel.statusBarHeight = statusBarHeight
+ if (shouldEnableStatusBarSwitcher) {
+ attachStatusBarSwitcher()
+ }
+ }
+
+ fun toggleStatusBarSwitchingMode() {
+ val newIsAutoSwitchingEnabled = !screenModel.isAutoSwitchingEnabled
+ screenModel.isAutoSwitchingEnabled = newIsAutoSwitchingEnabled
+
+ if (newIsAutoSwitchingEnabled) {
+ attachStatusBarSwitcher()
+ } else {
+ statusBarSwitcher.detach()
+ }
+
+ view.render(screenModel)
+ }
+
+ fun closeScreen() {
+ finish()
+ }
+
+ private fun attachStatusBarSwitcher() {
+ statusBarSwitcher.setStatusBarHeight(screenModel.statusBarHeight)
+ view.attachStatusBarSwitcher(statusBarSwitcher)
+ }
+}
\ No newline at end of file
diff --git a/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/StatusBarSwitcherScreenConfigurator.kt b/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/StatusBarSwitcherScreenConfigurator.kt
new file mode 100755
index 000000000..1800b6471
--- /dev/null
+++ b/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/StatusBarSwitcherScreenConfigurator.kt
@@ -0,0 +1,49 @@
+package ru.surfstudio.android.common.tools.sample.screen.status_bar_switcher
+
+import android.content.Context
+import android.content.Intent
+import dagger.Component
+import dagger.Module
+import dagger.Provides
+import ru.surfstudio.android.common.tools.statusbarswitcher.StatusBarSwitcher
+import ru.surfstudio.android.core.mvp.configurator.ScreenComponent
+import ru.surfstudio.android.dagger.scope.PerScreen
+import ru.surfstudio.android.sample.dagger.ui.base.configurator.DefaultActivityScreenConfigurator
+import ru.surfstudio.android.sample.dagger.ui.base.dagger.activity.DefaultActivityComponent
+import ru.surfstudio.android.sample.dagger.ui.base.dagger.screen.DefaultActivityScreenModule
+import ru.surfstudio.android.sample.dagger.ui.base.dagger.screen.DefaultCustomScreenModule
+import ru.surfstudio.android.utilktx.ktx.ui.context.getDisplayMetrics
+
+internal class StatusBarSwitcherScreenConfigurator(intent: Intent) : DefaultActivityScreenConfigurator(intent) {
+
+ @PerScreen
+ @Component(
+ dependencies = [DefaultActivityComponent::class],
+ modules = [DefaultActivityScreenModule::class, StatusBarSwitcherScreenModule::class]
+ )
+ internal interface StatusBarSwitcherScreenComponent : ScreenComponent
+
+ @Module
+ internal class StatusBarSwitcherScreenModule(
+ route: StatusBarSwitcherActivityRoute
+ ) : DefaultCustomScreenModule(route) {
+
+ @Provides
+ @PerScreen
+ internal fun provideStatusBarSwitcher(context: Context): StatusBarSwitcher {
+ return StatusBarSwitcher(context.getDisplayMetrics())
+ }
+ }
+
+ override fun createScreenComponent(
+ defaultActivityComponent: DefaultActivityComponent,
+ defaultActivityScreenModule: DefaultActivityScreenModule,
+ intent: Intent
+ ): ScreenComponent<*> {
+ return DaggerStatusBarSwitcherScreenConfigurator_StatusBarSwitcherScreenComponent.builder()
+ .defaultActivityComponent(defaultActivityComponent)
+ .defaultActivityScreenModule(defaultActivityScreenModule)
+ .statusBarSwitcherScreenModule(StatusBarSwitcherScreenModule(StatusBarSwitcherActivityRoute()))
+ .build()
+ }
+}
diff --git a/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/StatusBarSwitcherScreenModel.kt b/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/StatusBarSwitcherScreenModel.kt
new file mode 100644
index 000000000..2dda6906c
--- /dev/null
+++ b/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/StatusBarSwitcherScreenModel.kt
@@ -0,0 +1,22 @@
+package ru.surfstudio.android.common.tools.sample.screen.status_bar_switcher
+
+import ru.surfstudio.android.common.tools.sample.R
+import ru.surfstudio.android.common.tools.sample.screen.status_bar_switcher.data.Item
+import ru.surfstudio.android.core.mvp.model.ScreenModel
+
+internal data class StatusBarSwitcherScreenModel(
+ var isAutoSwitchingEnabled: Boolean = true,
+ var statusBarHeight: Int = 0,
+ val sampleList: List- = listOf(
+ Item.Image("https://placekitten.com/408/287"),
+ Item.Image("https://placekitten.com/200/287"),
+ Item.Image("https://placekitten.com/200/286"),
+ Item.Image("https://placekitten.com/96/140"),
+ Item.Color(R.color.statusBarSwitcherSampleColor1),
+ Item.Space(),
+ Item.Color(R.color.statusBarSwitcherSampleColor2),
+ Item.Space(),
+ Item.Color(R.color.statusBarSwitcherSampleColor3),
+ Item.Space()
+ )
+) : ScreenModel()
\ No newline at end of file
diff --git a/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/controller/ImageItemController.kt b/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/controller/ImageItemController.kt
new file mode 100644
index 000000000..5a247af62
--- /dev/null
+++ b/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/controller/ImageItemController.kt
@@ -0,0 +1,58 @@
+package ru.surfstudio.android.common.tools.sample.screen.status_bar_switcher.controller
+
+import android.view.ViewGroup
+import android.widget.ImageView
+import androidx.core.content.ContextCompat
+import androidx.core.view.updateLayoutParams
+import ru.surfstudio.android.common.tools.sample.R
+import ru.surfstudio.android.common.tools.sample.screen.status_bar_switcher.data.Item
+import ru.surfstudio.android.easyadapter.controller.BindableItemController
+import ru.surfstudio.android.easyadapter.holder.BindableViewHolder
+import ru.surfstudio.android.imageloader.ImageLoader
+
+internal class ImageItemController : BindableItemController
- () {
+
+ override fun createViewHolder(parent: ViewGroup) = Holder(parent)
+
+ override fun getItemId(item: Item) = "ImageItemController$item"
+
+ class Holder(parent: ViewGroup) : BindableViewHolder
- (parent, R.layout.item_image) {
+
+ private val imageView = itemView as ImageView
+
+ private val context get() = itemView.context.applicationContext
+
+ override fun bind(item: Item) {
+ imageView.background = null
+ imageView.setImageDrawable(null)
+ when (item) {
+ is Item.Image -> renderImage(item)
+ is Item.Color -> renderColor(item)
+ is Item.Space -> renderSpace()
+ }
+ }
+
+ private fun renderImage(item: Item.Image) {
+ updateImageViewHeight(context.resources.getDimensionPixelOffset(R.dimen.imageItemHeight))
+ ImageLoader.with(context)
+ .url(item.url)
+ .centerCrop()
+ .into(imageView)
+ }
+
+ private fun renderColor(item: Item.Color) {
+ updateImageViewHeight(context.resources.getDimensionPixelOffset(R.dimen.colorItemHeight))
+ imageView.setBackgroundColor(ContextCompat.getColor(context, item.color))
+ }
+
+ private fun renderSpace() {
+ updateImageViewHeight(context.resources.getDimensionPixelOffset(R.dimen.spaceItemHeight))
+ }
+
+ private fun updateImageViewHeight(newHeight: Int) {
+ imageView.updateLayoutParams {
+ height = newHeight
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/data/Item.kt b/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/data/Item.kt
new file mode 100644
index 000000000..aa903c02d
--- /dev/null
+++ b/common-tools/sample/src/main/java/ru/surfstudio/android/common/tools/sample/screen/status_bar_switcher/data/Item.kt
@@ -0,0 +1,10 @@
+package ru.surfstudio.android.common.tools.sample.screen.status_bar_switcher.data
+
+import androidx.annotation.ColorRes
+
+internal sealed class Item {
+
+ data class Color(@ColorRes val color: Int) : Item()
+ data class Image(val url: String) : Item()
+ class Space : Item()
+}
\ No newline at end of file
diff --git a/common-tools/sample/src/main/res/drawable-v21/bg_round_button.xml b/common-tools/sample/src/main/res/drawable-v21/bg_round_button.xml
new file mode 100644
index 000000000..1b3a1ff92
--- /dev/null
+++ b/common-tools/sample/src/main/res/drawable-v21/bg_round_button.xml
@@ -0,0 +1,11 @@
+
+
+
+
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/common-tools/sample/src/main/res/drawable/bg_round_button.xml b/common-tools/sample/src/main/res/drawable/bg_round_button.xml
new file mode 100644
index 000000000..0d1f0e034
--- /dev/null
+++ b/common-tools/sample/src/main/res/drawable/bg_round_button.xml
@@ -0,0 +1,13 @@
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/common-tools/sample/src/main/res/drawable/ic_baseline_arrow_back_24.xml b/common-tools/sample/src/main/res/drawable/ic_baseline_arrow_back_24.xml
new file mode 100644
index 000000000..1fe523c43
--- /dev/null
+++ b/common-tools/sample/src/main/res/drawable/ic_baseline_arrow_back_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/common-tools/sample/src/main/res/layout/activity_main.xml b/common-tools/sample/src/main/res/layout/activity_main.xml
new file mode 100644
index 000000000..2b846f385
--- /dev/null
+++ b/common-tools/sample/src/main/res/layout/activity_main.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/common-tools/sample/src/main/res/layout/activity_status_bar_switcher.xml b/common-tools/sample/src/main/res/layout/activity_status_bar_switcher.xml
new file mode 100644
index 000000000..d294d593d
--- /dev/null
+++ b/common-tools/sample/src/main/res/layout/activity_status_bar_switcher.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/common-tools/sample/src/main/res/layout/item_image.xml b/common-tools/sample/src/main/res/layout/item_image.xml
new file mode 100644
index 000000000..b1659ab3b
--- /dev/null
+++ b/common-tools/sample/src/main/res/layout/item_image.xml
@@ -0,0 +1,4 @@
+
+
diff --git a/common-tools/sample/src/main/res/values/colors.xml b/common-tools/sample/src/main/res/values/colors.xml
new file mode 100644
index 000000000..a9ee8335e
--- /dev/null
+++ b/common-tools/sample/src/main/res/values/colors.xml
@@ -0,0 +1,12 @@
+
+
+
+ @color/colorAccent
+ @color/colorPrimary
+ @color/colorPrimaryDark
+
+ #FFF
+ #BCBCBC
+ #818181
+
+
\ No newline at end of file
diff --git a/common-tools/sample/src/main/res/values/dimens.xml b/common-tools/sample/src/main/res/values/dimens.xml
new file mode 100644
index 000000000..77ad74771
--- /dev/null
+++ b/common-tools/sample/src/main/res/values/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 200dp
+ 56dp
+ 50dp
+
\ No newline at end of file
diff --git a/common-tools/sample/src/main/res/values/strings.xml b/common-tools/sample/src/main/res/values/strings.xml
new file mode 100644
index 000000000..acafc348a
--- /dev/null
+++ b/common-tools/sample/src/main/res/values/strings.xml
@@ -0,0 +1,7 @@
+
+
+ Common tools sample
+ Open status bar switcher screen
+ Auto switch enabled
+ Auto switch disabled
+
\ No newline at end of file
diff --git a/common-tools/sample/src/main/res/values/styles.xml b/common-tools/sample/src/main/res/values/styles.xml
new file mode 100644
index 000000000..b6b4c1e68
--- /dev/null
+++ b/common-tools/sample/src/main/res/values/styles.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file