Skip to content

Commit 64b4d98

Browse files
authoredDec 3, 2020
[Jetchat] Update to be edge-to-edge and add animated IME support (android#306)
* Add Accompanist-Insets dependency * Set system bars to transparent and draw behind them * Update Scaffold content to be edge-to-edge * Update Conversation to go edge-to-edge * Update Profile to go edge-to-edge * Enable animated insets support * Fix tests * Add more comments to Insets modifier usage * Update README * One more comment
1 parent f658d03 commit 64b4d98

File tree

19 files changed

+204
-99
lines changed

19 files changed

+204
-99
lines changed
 

‎Jetchat/README.md

+10
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ When the Emoji panel is shown the keyboard must be hidden and vice versa. This i
4444
### Multiple types of animations and transitions
4545
This sample uses animations ranging from simple `AnimatedVisibility` in [FunctionalityNotAvailablePanel](app/src/main/java/com/example/compose/jetchat/conversation/UserInput.kt) to choreographed transitions found in the [FloatingActionButton](https://material.io/develop/android/components/floating-action-button) of the Profile screen and implemented in [AnimatingFabContent](app/src/main/java/com/example/compose/jetchat/conversation/UserInput.kt)
4646

47+
### Edge-to-edge UI with synchronized IME transitions
48+
This sample is laid out [edge-to-edge](https://medium.com/androiddevelopers/gesture-navigation-going-edge-to-edge-812f62e4e83e), drawing its content behind the system bars for a more immersive look.
49+
50+
The sample also supports synchronized IME transitions when running on API 30+ devices. See the use of `Modifier.navigationBarsWithImePadding()` in [ConversationContent](app/src/main/java/com/example/compose/jetchat/conversation/UserInput.kt).
51+
52+
<img src="screenshots/ime-transition.gif" />
53+
54+
The sample uses the
55+
[Accompanist Insets library](https://chrisbanes.github.io/accompanist/insets/) for WindowInsets support.
56+
4757
### Saved state across configuration changes
4858
Some composable state survives activity or process recreation, like `currentInputSelector` in [UserInput](app/src/main/java/com/example/compose/jetchat/conversation/UserInput.kt).
4959

‎Jetchat/app/build.gradle

+2
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ dependencies {
109109
implementation Libs.AndroidX.Compose.runtimeLivedata
110110
implementation Libs.AndroidX.Compose.viewBinding
111111

112+
implementation Libs.Accompanist.insets
113+
112114
androidTestImplementation Libs.junit
113115
androidTestImplementation Libs.AndroidX.Test.core
114116
androidTestImplementation Libs.AndroidX.Test.espressoCore

‎Jetchat/app/src/androidTest/java/com/example/compose/jetchat/ConversationTest.kt

+9-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ import com.example.compose.jetchat.conversation.ConversationContent
3535
import com.example.compose.jetchat.conversation.ConversationTestTag
3636
import com.example.compose.jetchat.data.exampleUiState
3737
import com.example.compose.jetchat.theme.JetchatTheme
38+
import dev.chrisbanes.accompanist.insets.AmbientWindowInsets
39+
import dev.chrisbanes.accompanist.insets.WindowInsets
3840
import kotlinx.coroutines.flow.MutableStateFlow
3941
import org.junit.Before
4042
import org.junit.Rule
@@ -58,9 +60,15 @@ class ConversationTest {
5860
fun setUp() {
5961
composeTestRule.activityRule.scenario.onActivity { newActivity ->
6062
activity = newActivity
63+
// Provide empty insets. We can modify this value as necessary
64+
val windowInsets = WindowInsets()
65+
6166
// Launch the conversation screen
6267
composeTestRule.setContent {
63-
Providers(AmbientBackPressedDispatcher provides newActivity) {
68+
Providers(
69+
AmbientBackPressedDispatcher provides newActivity,
70+
AmbientWindowInsets provides windowInsets
71+
) {
6472
JetchatTheme(isDarkTheme = themeIsDark.collectAsState(false).value) {
6573
ConversationContent(
6674
uiState = exampleUiState,

‎Jetchat/app/src/androidTest/java/com/example/compose/jetchat/NavigationTest.kt

+9-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import com.example.compose.jetchat.conversation.AmbientBackPressedDispatcher
2929
import com.example.compose.jetchat.conversation.ConversationContent
3030
import com.example.compose.jetchat.data.exampleUiState
3131
import com.example.compose.jetchat.theme.JetchatTheme
32+
import dev.chrisbanes.accompanist.insets.AmbientWindowInsets
33+
import dev.chrisbanes.accompanist.insets.WindowInsets
3234
import org.junit.Assert.assertEquals
3335
import org.junit.Before
3436
import org.junit.Rule
@@ -57,9 +59,15 @@ class NavigationTest {
5759
navController = Navigation.findNavController(navHostFragment)
5860
}
5961

62+
// Provide empty insets. We can modify this value as necessary
63+
val windowInsets = WindowInsets()
64+
6065
// Start the app
6166
composeTestRule.setContent {
62-
Providers(AmbientBackPressedDispatcher provides activity) {
67+
Providers(
68+
AmbientBackPressedDispatcher provides activity,
69+
AmbientWindowInsets provides windowInsets,
70+
) {
6371
JetchatTheme {
6472
ConversationContent(
6573
uiState = exampleUiState,

‎Jetchat/app/src/androidTest/java/com/example/compose/jetchat/UserInputTest.kt

+9-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ import com.example.compose.jetchat.conversation.ConversationContent
3737
import com.example.compose.jetchat.conversation.KeyboardShownKey
3838
import com.example.compose.jetchat.data.exampleUiState
3939
import com.example.compose.jetchat.theme.JetchatTheme
40+
import dev.chrisbanes.accompanist.insets.AmbientWindowInsets
41+
import dev.chrisbanes.accompanist.insets.WindowInsets
4042
import org.junit.Before
4143
import org.junit.Rule
4244
import org.junit.Test
@@ -57,9 +59,15 @@ class UserInputTest {
5759
fun setUp() {
5860
composeTestRule.activityRule.scenario.onActivity { newActivity ->
5961
activity = newActivity
62+
// Provide empty insets. We can modify this value as necessary
63+
val windowInsets = WindowInsets()
64+
6065
// Launch the conversation screen
6166
composeTestRule.setContent {
62-
Providers(AmbientBackPressedDispatcher provides activity) {
67+
Providers(
68+
AmbientBackPressedDispatcher provides activity,
69+
AmbientWindowInsets provides windowInsets,
70+
) {
6371
JetchatTheme {
6472
ConversationContent(
6573
uiState = exampleUiState,

‎Jetchat/app/src/main/java/com/example/compose/jetchat/NavActivity.kt

+42-31
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@ import androidx.compose.runtime.livedata.observeAsState
2525
import androidx.compose.ui.platform.setContent
2626
import androidx.compose.ui.viewinterop.AndroidViewBinding
2727
import androidx.core.os.bundleOf
28+
import androidx.core.view.WindowCompat
2829
import androidx.navigation.findNavController
2930
import com.example.compose.jetchat.components.JetchatScaffold
3031
import com.example.compose.jetchat.conversation.AmbientBackPressedDispatcher
3132
import com.example.compose.jetchat.conversation.backPressHandler
3233
import com.example.compose.jetchat.databinding.ContentMainBinding
34+
import dev.chrisbanes.accompanist.insets.ProvideWindowInsets
3335

3436
/**
3537
* Main activity for the app.
@@ -39,43 +41,52 @@ class NavActivity : AppCompatActivity() {
3941

4042
override fun onCreate(savedInstanceState: Bundle?) {
4143
super.onCreate(savedInstanceState)
44+
45+
// Turn off the decor fitting system windows, which allows us to handle insets,
46+
// including IME animations
47+
WindowCompat.setDecorFitsSystemWindows(window, false)
48+
4249
setContent {
43-
Providers(AmbientBackPressedDispatcher provides this) {
44-
val scaffoldState = rememberScaffoldState()
50+
// Provide WindowInsets to our content. We don't want to consume them, so that
51+
// they keep being pass down the view hierarchy (since we're using fragments).
52+
ProvideWindowInsets(consumeWindowInsets = false) {
53+
Providers(AmbientBackPressedDispatcher provides this) {
54+
val scaffoldState = rememberScaffoldState()
4555

46-
val openDrawerEvent = viewModel.drawerShouldBeOpened.observeAsState()
47-
if (openDrawerEvent.value == true) {
48-
// Open drawer and reset state in VM.
49-
scaffoldState.drawerState.open {
50-
viewModel.resetOpenDrawerAction()
56+
val openDrawerEvent = viewModel.drawerShouldBeOpened.observeAsState()
57+
if (openDrawerEvent.value == true) {
58+
// Open drawer and reset state in VM.
59+
scaffoldState.drawerState.open {
60+
viewModel.resetOpenDrawerAction()
61+
}
5162
}
52-
}
5363

54-
// Intercepts back navigation when the drawer is open
55-
backPressHandler(
56-
enabled = scaffoldState.drawerState.isOpen,
57-
onBackPressed = { scaffoldState.drawerState.close() },
58-
highPriority = true
59-
)
64+
// Intercepts back navigation when the drawer is open
65+
backPressHandler(
66+
enabled = scaffoldState.drawerState.isOpen,
67+
onBackPressed = { scaffoldState.drawerState.close() },
68+
highPriority = true
69+
)
6070

61-
JetchatScaffold(
62-
scaffoldState,
63-
onChatClicked = {
64-
findNavController(R.id.nav_host_fragment)
65-
.popBackStack(R.id.nav_home, true)
66-
scaffoldState.drawerState.close()
67-
},
68-
onProfileClicked = {
69-
val bundle = bundleOf("userId" to it)
70-
findNavController(R.id.nav_host_fragment).navigate(
71-
R.id.nav_profile,
72-
bundle
73-
)
74-
scaffoldState.drawerState.close()
71+
JetchatScaffold(
72+
scaffoldState,
73+
onChatClicked = {
74+
findNavController(R.id.nav_host_fragment)
75+
.popBackStack(R.id.nav_home, true)
76+
scaffoldState.drawerState.close()
77+
},
78+
onProfileClicked = {
79+
val bundle = bundleOf("userId" to it)
80+
findNavController(R.id.nav_host_fragment).navigate(
81+
R.id.nav_profile,
82+
bundle
83+
)
84+
scaffoldState.drawerState.close()
85+
}
86+
) {
87+
// Inflate the XML layout using View Binding:
88+
AndroidViewBinding(ContentMainBinding::inflate)
7589
}
76-
) {
77-
// Inflate the XML layout using View Binding:
78-
AndroidViewBinding(ContentMainBinding::inflate)
7990
}
8091
}
8192
}

‎Jetchat/app/src/main/java/com/example/compose/jetchat/components/JetchatAppBar.kt

+13-6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.example.compose.jetchat.components
1818

1919
import androidx.compose.foundation.Image
20+
import androidx.compose.foundation.background
2021
import androidx.compose.foundation.clickable
2122
import androidx.compose.foundation.layout.Column
2223
import androidx.compose.foundation.layout.Row
@@ -28,6 +29,7 @@ import androidx.compose.material.Text
2829
import androidx.compose.material.TopAppBar
2930
import androidx.compose.runtime.Composable
3031
import androidx.compose.ui.Modifier
32+
import androidx.compose.ui.graphics.Color
3133
import androidx.compose.ui.res.vectorResource
3234
import androidx.compose.ui.tooling.preview.Preview
3335
import androidx.compose.ui.unit.dp
@@ -42,14 +44,19 @@ fun JetchatAppBar(
4244
title: @Composable RowScope.() -> Unit,
4345
actions: @Composable RowScope.() -> Unit = {}
4446
) {
45-
Column {
46-
// This bar needs to be translucent but, if the backgroundColor in TopAppBar is not
47-
// opaque, the elevation is ignored. We need to manually calculate the elevated surface
48-
// color for dark mode:
49-
val backgroundColor = MaterialTheme.colors.elevatedSurface(3.dp)
47+
// This bar is translucent but elevation overlays are not applied to translucent colors.
48+
// Instead we manually calculate the elevated surface color from the opaque color,
49+
// then apply our alpha.
50+
//
51+
// We set the background on the Column rather than the TopAppBar,
52+
// so that the background is drawn behind any padding set on the app bar (i.e. status bar).
53+
val backgroundColor = MaterialTheme.colors.elevatedSurface(3.dp)
54+
Column(
55+
Modifier.background(backgroundColor.copy(alpha = 0.95f))
56+
) {
5057
TopAppBar(
5158
modifier = modifier,
52-
backgroundColor = backgroundColor.copy(alpha = 0.95f),
59+
backgroundColor = Color.Transparent,
5360
elevation = 0.dp, // No shadow needed
5461
contentColor = MaterialTheme.colors.onSurface,
5562
actions = actions,

‎Jetchat/app/src/main/java/com/example/compose/jetchat/components/JetchatDrawer.kt

+4
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,13 @@ import com.example.compose.jetchat.R
5252
import com.example.compose.jetchat.data.colleagueProfile
5353
import com.example.compose.jetchat.data.meProfile
5454
import com.example.compose.jetchat.theme.JetchatTheme
55+
import dev.chrisbanes.accompanist.insets.statusBarsHeight
5556

5657
@Composable
5758
fun ColumnScope.JetchatDrawer(onProfileClicked: (String) -> Unit, onChatClicked: (String) -> Unit) {
59+
// Use statusBarsHeight() to add a spacer which pushes the drawer content
60+
// below the status bar (y-axis)
61+
Spacer(Modifier.statusBarsHeight())
5862
DrawerHeader()
5963
Divider()
6064
DrawerItemHeader("Chats")

‎Jetchat/app/src/main/java/com/example/compose/jetchat/conversation/Conversation.kt

+9-2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ import com.example.compose.jetchat.components.JetchatAppBar
7070
import com.example.compose.jetchat.data.exampleUiState
7171
import com.example.compose.jetchat.theme.JetchatTheme
7272
import com.example.compose.jetchat.theme.elevatedSurface
73+
import dev.chrisbanes.accompanist.insets.navigationBarsWithImePadding
74+
import dev.chrisbanes.accompanist.insets.statusBarsPadding
7375

7476
/**
7577
* Entry point for a conversation screen.
@@ -105,14 +107,19 @@ fun ConversationContent(
105107
Message(authorMe, content, timeNow)
106108
)
107109
},
108-
scrollState
110+
scrollState = scrollState,
111+
// Use navigationBarsWithImePadding(), to move the input panel above both the
112+
// navigation bar, and on-screen keyboard (IME)
113+
modifier = Modifier.navigationBarsWithImePadding(),
109114
)
110115
}
111116
// Channel name bar floats above the messages
112117
ChannelNameBar(
113118
channelName = uiState.channelName,
114119
channelMembers = uiState.channelMembers,
115-
onNavIconPressed = onNavIconPressed
120+
onNavIconPressed = onNavIconPressed,
121+
// Use statusBarsPadding() to move the app bar content below the status bar
122+
modifier = Modifier.statusBarsPadding(),
116123
)
117124
}
118125
}

‎Jetchat/app/src/main/java/com/example/compose/jetchat/conversation/ConversationFragment.kt

+38-20
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import android.os.Bundle
2020
import android.view.LayoutInflater
2121
import android.view.View
2222
import android.view.ViewGroup
23+
import android.view.ViewGroup.LayoutParams
24+
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
2325
import androidx.compose.runtime.Providers
2426
import androidx.compose.ui.platform.ComposeView
2527
import androidx.core.os.bundleOf
@@ -30,35 +32,51 @@ import com.example.compose.jetchat.MainViewModel
3032
import com.example.compose.jetchat.R
3133
import com.example.compose.jetchat.data.exampleUiState
3234
import com.example.compose.jetchat.theme.JetchatTheme
35+
import dev.chrisbanes.accompanist.insets.AmbientWindowInsets
36+
import dev.chrisbanes.accompanist.insets.ExperimentalAnimatedInsets
37+
import dev.chrisbanes.accompanist.insets.ViewWindowInsetObserver
3338

3439
class ConversationFragment : Fragment() {
3540

3641
private val activityViewModel: MainViewModel by activityViewModels()
3742

43+
@OptIn(ExperimentalAnimatedInsets::class) // Opt-in to experiment animated insets support
3844
override fun onCreateView(
3945
inflater: LayoutInflater,
4046
container: ViewGroup?,
4147
savedInstanceState: Bundle?
42-
): View {
43-
return ComposeView(context = requireContext()).apply {
44-
setContent {
45-
Providers(AmbientBackPressedDispatcher provides requireActivity()) {
46-
JetchatTheme {
47-
ConversationContent(
48-
uiState = exampleUiState,
49-
navigateToProfile = { user ->
50-
// Click callback
51-
val bundle = bundleOf("userId" to user)
52-
findNavController().navigate(
53-
R.id.nav_profile,
54-
bundle
55-
)
56-
},
57-
onNavIconPressed = {
58-
activityViewModel.openDrawer()
59-
}
60-
)
61-
}
48+
): View = ComposeView(inflater.context).apply {
49+
layoutParams = LayoutParams(MATCH_PARENT, MATCH_PARENT)
50+
51+
// Create a ViewWindowInsetObserver using this view, and call start() to
52+
// start listening now. The WindowInsets instance is returned, allowing us to
53+
// provide it to AmbientWindowInsets in our content below.
54+
val windowInsets = ViewWindowInsetObserver(this)
55+
// We use the `windowInsetsAnimationsEnabled` parameter to enable animated
56+
// insets support. This allows our `ConversationContent` to animate with the
57+
// on-screen keyboard (IME) as it enters/exits the screen.
58+
.start(windowInsetsAnimationsEnabled = true)
59+
60+
setContent {
61+
Providers(
62+
AmbientBackPressedDispatcher provides requireActivity(),
63+
AmbientWindowInsets provides windowInsets,
64+
) {
65+
JetchatTheme {
66+
ConversationContent(
67+
uiState = exampleUiState,
68+
navigateToProfile = { user ->
69+
// Click callback
70+
val bundle = bundleOf("userId" to user)
71+
findNavController().navigate(
72+
R.id.nav_profile,
73+
bundle
74+
)
75+
},
76+
onNavIconPressed = {
77+
activityViewModel.openDrawer()
78+
}
79+
)
6280
}
6381
}
6482
}

‎Jetchat/app/src/main/java/com/example/compose/jetchat/conversation/UserInput.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ fun UserInputPreview() {
121121
@Composable
122122
fun UserInput(
123123
onMessageSent: (String) -> Unit,
124-
scrollState: ScrollState
124+
scrollState: ScrollState,
125+
modifier: Modifier = Modifier,
125126
) {
126127
var currentInputSelector by savedInstanceState { InputSelector.NONE }
127128
val dismissKeyboard = { currentInputSelector = InputSelector.NONE }
@@ -135,7 +136,7 @@ fun UserInput(
135136
// Used to decide if the keyboard should be shown
136137
var textFieldFocusState by remember { mutableStateOf(false) }
137138

138-
Column {
139+
Column(modifier) {
139140
Divider()
140141
UserInputText(
141142
textFieldValue = textState,

‎Jetchat/app/src/main/java/com/example/compose/jetchat/profile/Profile.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import com.example.compose.jetchat.components.JetchatAppBar
6262
import com.example.compose.jetchat.components.baselineHeight
6363
import com.example.compose.jetchat.data.meProfile
6464
import com.example.compose.jetchat.theme.JetchatTheme
65+
import dev.chrisbanes.accompanist.insets.statusBarsPadding
6566

6667
@Composable
6768
fun ProfileScreen(userData: ProfileScreenState, onNavIconPressed: () -> Unit = { }) {
@@ -70,7 +71,8 @@ fun ProfileScreen(userData: ProfileScreenState, onNavIconPressed: () -> Unit = {
7071

7172
Column(modifier = Modifier.fillMaxSize()) {
7273
JetchatAppBar(
73-
modifier = Modifier.fillMaxWidth(),
74+
// Use statusBarsPadding() to move the app bar content below the status bar
75+
modifier = Modifier.fillMaxWidth().statusBarsPadding(),
7476
onNavIconPressed = onNavIconPressed,
7577
title = { },
7678
actions = {

‎Jetchat/app/src/main/java/com/example/compose/jetchat/profile/ProfileFragment.kt

+28-15
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,17 @@ import android.os.Bundle
2121
import android.view.LayoutInflater
2222
import android.view.View
2323
import android.view.ViewGroup
24+
import androidx.compose.runtime.Providers
25+
import androidx.compose.runtime.getValue
2426
import androidx.compose.runtime.livedata.observeAsState
2527
import androidx.compose.ui.platform.ComposeView
2628
import androidx.fragment.app.Fragment
2729
import androidx.fragment.app.activityViewModels
2830
import androidx.fragment.app.viewModels
2931
import com.example.compose.jetchat.MainViewModel
3032
import com.example.compose.jetchat.theme.JetchatTheme
33+
import dev.chrisbanes.accompanist.insets.AmbientWindowInsets
34+
import dev.chrisbanes.accompanist.insets.ViewWindowInsetObserver
3135

3236
class ProfileFragment : Fragment() {
3337

@@ -45,22 +49,31 @@ class ProfileFragment : Fragment() {
4549
inflater: LayoutInflater,
4650
container: ViewGroup?,
4751
savedInstanceState: Bundle?
48-
): View {
52+
): View = ComposeView(inflater.context).apply {
53+
layoutParams = ViewGroup.LayoutParams(
54+
ViewGroup.LayoutParams.MATCH_PARENT,
55+
ViewGroup.LayoutParams.MATCH_PARENT
56+
)
4957

50-
return ComposeView(context = requireContext()).apply {
51-
setContent {
52-
viewModel.userData.observeAsState().value.let { userData ->
53-
JetchatTheme {
54-
if (userData == null) {
55-
ProfileError()
56-
} else {
57-
ProfileScreen(
58-
userData = userData,
59-
onNavIconPressed = {
60-
activityViewModel.openDrawer()
61-
}
62-
)
63-
}
58+
// Create a ViewWindowInsetObserver using this view, and call start() to
59+
// start listening now. The WindowInsets instance is returned, allowing us to
60+
// provide it to AmbientWindowInsets in our content below.
61+
val windowInsets = ViewWindowInsetObserver(this).start()
62+
63+
setContent {
64+
val userData by viewModel.userData.observeAsState()
65+
66+
Providers(AmbientWindowInsets provides windowInsets) {
67+
JetchatTheme {
68+
if (userData == null) {
69+
ProfileError()
70+
} else {
71+
ProfileScreen(
72+
userData = userData!!,
73+
onNavIconPressed = {
74+
activityViewModel.openDrawer()
75+
}
76+
)
6477
}
6578
}
6679
}

‎Jetchat/app/src/main/res/values-night/themes.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616

1717
<resources>
1818

19-
<style name="Theme.Jetchat" parent="Theme.MaterialComponents.DayNight.DarkActionBar" >
19+
<!-- Our dark theme -->
20+
<style name="Theme.Jetchat" parent="Platform.Theme.Jetchat" >
2021
<item name="colorPrimary">@color/blue300</item>
2122
<item name="colorPrimaryDark">@color/blue400</item>
2223
<item name="colorAccent">@color/yellow400</item>
23-
<item name="android:statusBarColor">@color/black30</item>
2424
</style>
2525

2626
</resources>

‎Jetchat/app/src/main/res/values-v23/themes.xml

+4-10
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,11 @@
1414
~ limitations under the License.
1515
-->
1616

17-
<resources xmlns:tools="http://schemas.android.com/tools">
17+
<resources>
1818

19-
<style name="Theme.Jetchat" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
20-
<item name="colorPrimary">@color/blue500</item>
21-
<item name="colorPrimaryDark">@color/blue800</item>
22-
<item name="colorAccent">@color/yellow700</item>
23-
<item name="android:statusBarColor">?attr/colorSurface</item>
19+
<style name="Platform.Theme.Jetchat" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
20+
<item name="android:statusBarColor">@android:color/transparent</item>
2421
<item name="android:windowLightStatusBar">?attr/isLightTheme</item>
25-
<!-- TODO: Fix navigation bar color in API <26 -->
26-
<item name="android:windowLightNavigationBar" tools:targetApi="o_mr1">?attr/isLightTheme</item>
27-
<item name="android:navigationBarColor">?attr/colorSurface</item>
28-
<item name="android:navigationMode">?attr/colorSurface</item>
2922
</style>
23+
3024
</resources>

‎Jetchat/app/src/main/res/values-night-v23/themes.xml renamed to ‎Jetchat/app/src/main/res/values-v27/themes.xml

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616

1717
<resources>
1818

19-
<style name="Theme.Jetchat" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
20-
<item name="colorPrimary">@color/blue300</item>
21-
<item name="colorPrimaryDark">@color/blue400</item>
22-
<item name="colorAccent">@color/yellow400</item>
23-
<item name="android:statusBarColor">?attr/colorSurface</item>
19+
<style name="Platform.Theme.Jetchat" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
20+
<item name="android:statusBarColor">@android:color/transparent</item>
2421
<item name="android:windowLightStatusBar">?attr/isLightTheme</item>
22+
<item name="android:navigationBarColor">@android:color/transparent</item>
23+
<item name="android:windowLightNavigationBar">?attr/isLightTheme</item>
2524
</style>
25+
2626
</resources>

‎Jetchat/app/src/main/res/values/themes.xml

+9-2
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,18 @@
1616

1717
<resources>
1818

19-
<style name="Theme.Jetchat" parent="Theme.MaterialComponents.DayNight.DarkActionBar" >
19+
<!-- Allows us to override platform level specific attributes in their
20+
respective values-vXX folder. -->
21+
<style name="Platform.Theme.Jetchat" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
22+
<item name="android:statusBarColor">@color/black30</item>
23+
</style>
24+
25+
<!-- The actual theme we use. This varies for light theme (here),
26+
and values-night for dark theme. -->
27+
<style name="Theme.Jetchat" parent="Platform.Theme.Jetchat">
2028
<item name="colorPrimary">@color/blue500</item>
2129
<item name="colorPrimaryDark">@color/blue800</item>
2230
<item name="colorAccent">@color/yellow700</item>
23-
<item name="android:statusBarColor">@color/black30</item>
2431
</style>
2532

2633
<style name="Theme.Jetchat.NoActionBar">

‎Jetchat/buildSrc/src/main/java/com/example/compose/jetchat/buildsrc/dependencies.kt

+5
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ object Libs {
4242
const val test = "org.jetbrains.kotlinx:kotlinx-coroutines-test:$version"
4343
}
4444

45+
object Accompanist {
46+
private const val version = "0.4.0"
47+
const val insets = "dev.chrisbanes.accompanist:accompanist-insets:$version"
48+
}
49+
4550
object AndroidX {
4651
const val appcompat = "androidx.appcompat:appcompat:1.2.0-rc01"
4752
const val coreKtx = "androidx.core:core-ktx:1.5.0-alpha04"
2.54 MB
Loading

0 commit comments

Comments
 (0)
Please sign in to comment.