Some ui changes and fixes

This commit is contained in:
Henry Hiles 2023-12-25 14:07:15 -05:00
parent e75c7f770d
commit 3b456682f6
9 changed files with 65 additions and 87 deletions

View file

@ -3,7 +3,6 @@ package com.henryhiles.qweather.presentation
import android.os.Bundle import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
@ -22,7 +21,6 @@ class QWeatherActivity : ComponentActivity() {
private val prefs: AppearancePreferenceManager by inject() private val prefs: AppearancePreferenceManager by inject()
private val location: LocationPreferenceManager by inject() private val location: LocationPreferenceManager by inject()
@OptIn(ExperimentalAnimationApi::class)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContent { setContent {
@ -36,9 +34,6 @@ class QWeatherActivity : ComponentActivity() {
Surface(modifier = Modifier.fillMaxSize()) { Surface(modifier = Modifier.fillMaxSize()) {
Navigator( Navigator(
screen = if (location.locations.isEmpty()) LocationPickerScreen() else MainScreen(), screen = if (location.locations.isEmpty()) LocationPickerScreen() else MainScreen(),
onBackPressed = {
it !is MainScreen
}
) { ) {
SlideTransition(it) SlideTransition(it)
} }

View file

@ -4,10 +4,10 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Thermostat
import androidx.compose.material.icons.outlined.WaterDrop import androidx.compose.material.icons.outlined.WaterDrop
import androidx.compose.material.icons.outlined.WindPower import androidx.compose.material.icons.outlined.WindPower
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@ -40,7 +40,8 @@ fun WeatherCard(hour: HourlyWeatherData?, modifier: Modifier = Modifier) {
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
Text( Text(
text = "Today $formattedTime", text = formattedTime,
style = MaterialTheme.typography.headlineSmall,
) )
} }
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
@ -53,18 +54,12 @@ fun WeatherCard(hour: HourlyWeatherData?, modifier: Modifier = Modifier) {
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
Text(text = "${it.temperature}°C", fontSize = 50.sp) Text(text = "${it.temperature}°C", fontSize = 50.sp)
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
Text(text = it.weatherType.weatherDesc, fontSize = 20.sp) Text(text = "${it.weatherType.weatherDesc} - Feels like ${it.apparentTemperature}°C", fontSize = 20.sp)
Spacer(modifier = Modifier.height(32.dp)) Spacer(modifier = Modifier.height(32.dp))
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceAround horizontalArrangement = Arrangement.SpaceEvenly
) { ) {
WeatherDataDisplay(
value = it.apparentTemperature,
unit = "°C",
icon = Icons.Outlined.Thermostat,
description = "Feels like",
)
WeatherDataDisplay( WeatherDataDisplay(
value = it.precipitationProbability, value = it.precipitationProbability,
unit = "%", unit = "%",

View file

@ -67,7 +67,7 @@ fun WeatherDay(dailyWeatherData: DailyWeatherData) {
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp), .padding(start = 16.dp, end = 16.dp, bottom = 16.dp),
horizontalArrangement = Arrangement.Center horizontalArrangement = Arrangement.SpaceEvenly
) { ) {
WeatherDataDisplay( WeatherDataDisplay(
value = dailyWeatherData.precipitationProbabilityMax, value = dailyWeatherData.precipitationProbabilityMax,

View file

@ -2,7 +2,7 @@ package com.henryhiles.qweather.presentation.components.weather
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.items
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -16,14 +16,13 @@ fun WeatherForecast(
onChangeSelected: (Int) -> Unit onChangeSelected: (Int) -> Unit
) { ) {
state.hourlyWeatherInfo?.weatherData?.let { state.hourlyWeatherInfo?.weatherData?.let {
val hour = LocalDateTime.now().hour
LazyRow(modifier = modifier) { LazyRow(modifier = modifier) {
itemsIndexed(it.subList(hour, it.size)) { index, data -> items(it.subList(LocalDateTime.now().hour, it.size)) {
WeatherHour( WeatherHour(
data = data, data = it,
modifier = Modifier modifier = Modifier
.padding(horizontal = 8.dp) .padding(horizontal = 8.dp)
) { onChangeSelected(index) } ) { onChangeSelected(it.time.hour) }
} }
} }
} }

View file

@ -1,25 +1,44 @@
package com.henryhiles.qweather.presentation.components.weather package com.henryhiles.qweather.presentation.components.weather
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.henryhiles.qweather.R import com.henryhiles.qweather.R
import com.henryhiles.qweather.presentation.components.VerticalDivider import com.henryhiles.qweather.presentation.components.VerticalDivider
import com.henryhiles.qweather.presentation.screenmodel.HourlyWeatherState import com.henryhiles.qweather.presentation.screenmodel.HourlyWeatherState
import com.henryhiles.qweather.presentation.screenmodel.LocationPreferenceManager
import org.koin.compose.koinInject
@Composable @Composable
fun WeatherToday(state: HourlyWeatherState) { fun WeatherToday(state: HourlyWeatherState) {
val locationPreferenceManager: LocationPreferenceManager = koinInject()
state.hourlyWeatherInfo?.let { state.hourlyWeatherInfo?.let {
Card(
shape = RoundedCornerShape(8.dp),
) {
Column(modifier = Modifier.padding(8.dp), horizontalAlignment = Alignment.CenterHorizontally) {
Text(
text = stringResource(id = R.string.today_in, with(locationPreferenceManager) {
locations.getOrNull(selectedIndex)?.location?.split(",")?.first()
?: stringResource(id = R.string.unknown)
}),
style = MaterialTheme.typography.headlineSmall
)
Spacer(modifier = Modifier.height(8.dp))
Row( Row(
modifier = Modifier modifier = Modifier
.height(24.dp) .height(24.dp)
.fillMaxWidth(), .fillMaxWidth(),
horizontalArrangement = Arrangement.Center horizontalArrangement = Arrangement.Center
) { ) {
Text( Text(
text = stringResource(R.string.weather_high, it.highTemperature), text = stringResource(R.string.weather_high, it.highTemperature),
) )
@ -34,10 +53,10 @@ fun WeatherToday(state: HourlyWeatherState) {
id = R.string.weather_precipitation, id = R.string.weather_precipitation,
it it
) )
} ?: stringResource( } ?: stringResource(id = R.string.unknown)
id = R.string.unknown
)
) )
} }
} }
} }
}
}

View file

@ -8,7 +8,6 @@ import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material.icons.outlined.Search import androidx.compose.material.icons.outlined.Search
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
@ -31,7 +30,6 @@ class LocationPickerScreen : Screen {
override fun Content() { override fun Content() {
val screenModel: LocationPickerScreenModel = getScreenModel() val screenModel: LocationPickerScreenModel = getScreenModel()
var locationSearch by remember { mutableStateOf("") } var locationSearch by remember { mutableStateOf("") }
var isAboutOpen by remember { mutableStateOf(false) }
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
Scaffold( Scaffold(
@ -41,15 +39,7 @@ class LocationPickerScreen : Screen {
SmallToolbar( SmallToolbar(
title = { Text(text = stringResource(id = R.string.location_choose)) }, title = { Text(text = stringResource(id = R.string.location_choose)) },
backButton = screenModel.prefs.locations.isNotEmpty(), backButton = screenModel.prefs.locations.isNotEmpty(),
actions = {
IconButton(
onClick = { isAboutOpen = true }) {
Icon(
imageVector = Icons.Outlined.Info,
contentDescription = stringResource(id = R.string.help_screen)
) )
}
})
screenModel.state.error?.let { screenModel.state.error?.let {
AlertDialog( AlertDialog(
onDismissRequest = { navigator.pop() }, onDismissRequest = { navigator.pop() },
@ -69,19 +59,6 @@ class LocationPickerScreen : Screen {
) )
} ?: kotlin.run { } ?: kotlin.run {
Column(modifier = Modifier.padding(16.dp)) { Column(modifier = Modifier.padding(16.dp)) {
if (isAboutOpen)
AlertDialog(
title = { Text(text = stringResource(id = R.string.location_choose)) },
text = { Text(text = stringResource(id = R.string.help_location_picker)) },
onDismissRequest = { isAboutOpen = false },
confirmButton = {
TextButton(
onClick = { isAboutOpen = false }) {
Text(text = stringResource(id = R.string.action_confirm))
}
}
)
OutlinedTextField( OutlinedTextField(
label = { Text(text = stringResource(id = R.string.location)) }, label = { Text(text = stringResource(id = R.string.location)) },
keyboardOptions = KeyboardOptions( keyboardOptions = KeyboardOptions(

View file

@ -19,16 +19,13 @@ import com.henryhiles.qweather.domain.util.NavigationTab
import com.henryhiles.qweather.presentation.components.location.LocationsDrawer import com.henryhiles.qweather.presentation.components.location.LocationsDrawer
import com.henryhiles.qweather.presentation.components.navigation.BottomBar import com.henryhiles.qweather.presentation.components.navigation.BottomBar
import com.henryhiles.qweather.presentation.components.navigation.SmallToolbar import com.henryhiles.qweather.presentation.components.navigation.SmallToolbar
import com.henryhiles.qweather.presentation.screenmodel.LocationPreferenceManager
import com.henryhiles.qweather.presentation.tabs.TodayTab import com.henryhiles.qweather.presentation.tabs.TodayTab
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koin.compose.koinInject
class MainScreen : Screen { class MainScreen : Screen {
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
override fun Content() { override fun Content() {
val locationPreferenceManager: LocationPreferenceManager = koinInject()
val drawerState = val drawerState =
rememberDrawerState(initialValue = DrawerValue.Closed) rememberDrawerState(initialValue = DrawerValue.Closed)
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
@ -42,14 +39,11 @@ class MainScreen : Screen {
topBar = { topBar = {
SmallToolbar( SmallToolbar(
title = { title = {
with(locationPreferenceManager) {
Text( Text(
text = locations.getOrNull(selectedIndex)?.location text = it.current.options.title,
?: stringResource(id = R.string.unknown),
maxLines = 1, maxLines = 1,
modifier = Modifier.basicMarquee() modifier = Modifier.basicMarquee()
) )
}
}, },
actions = { actions = {
(it.current as? NavigationTab)?.Actions() (it.current as? NavigationTab)?.Actions()

View file

@ -81,12 +81,12 @@ object TodayTab : NavigationTab {
.padding(16.dp), .padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp) verticalArrangement = Arrangement.spacedBy(16.dp)
) { ) {
WeatherToday(state = weatherViewModel.state)
WeatherCard( WeatherCard(
hour = weatherViewModel.state.selected?.let { hour = weatherViewModel.state.selected?.let {
weatherViewModel.state.hourlyWeatherInfo?.weatherData?.get(it) weatherViewModel.state.hourlyWeatherInfo?.weatherData?.get(it)
} ?: weatherViewModel.state.hourlyWeatherInfo?.currentWeatherData, } ?: weatherViewModel.state.hourlyWeatherInfo?.currentWeatherData,
) )
WeatherToday(state = weatherViewModel.state)
WeatherForecast( WeatherForecast(
state = weatherViewModel.state state = weatherViewModel.state
) { weatherViewModel.setSelected(it) } ) { weatherViewModel.setSelected(it) }

View file

@ -15,9 +15,6 @@
<string name="selected">Selected</string> <string name="selected">Selected</string>
<string name="help_screen">How do I use this screen?</string>
<string name="help_location_picker">Please search a location, then tap a result. Then tap the apply button in the bottom left corner.</string>
<string name="appearance_theme">Theme</string> <string name="appearance_theme">Theme</string>
<string name="appearance_monet">Dynamic Theme</string> <string name="appearance_monet">Dynamic Theme</string>
<string name="appearance_monet_description">Available on Android 12+</string> <string name="appearance_monet_description">Available on Android 12+</string>
@ -41,6 +38,8 @@
<string name="weather_low">Low: %1$d°C</string> <string name="weather_low">Low: %1$d°C</string>
<string name="weather_precipitation">Precipitation: %1$d&#65130;</string> <string name="weather_precipitation">Precipitation: %1$d&#65130;</string>
<string name="today_in">Today in %1$s</string>
<string name="unknown">Unknown</string> <string name="unknown">Unknown</string>
<string name="error">An error occurred</string> <string name="error">An error occurred</string>