JetpackCompose — Weather App — random design — code snippet

Design 1

/***
[LocationScreen] is a screen who displays weather info for a single location
@param[locationName] location for which to display weather info for
*/
@Composable
fun LocationScreen(navController: NavController, locationName: String = "Seoul"){
val sunnyColor = Color(0xFFFFF2B2)
val sunnyColorEnd = Color(0xFFECDA82)
val sunnyGradient = Brush.verticalGradient(
listOf(sunnyColor, sunnyColorEnd)
)

Surface(){
Scaffold(
modifier = Modifier.background(sunnyColor),
backgroundColor = Color.Transparent,
topBar = {
TopAppBar(
backgroundColor = Color.Transparent,
title = { Text("") },
modifier = Modifier.padding(0.dp),
elevation = 0.dp,
actions = {
IconButton(onClick = { /*TODO*/ }) {
Icon(Icons.Default.Search, null, tint = Color.Black)
}
}
)
}
) {
Column(modifier = Modifier.background(Color.White).fillMaxSize()) {
Column(
modifier = Modifier
.fillMaxWidth()
.background(sunnyGradient),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Seoul", fontWeight = FontWeight.Bold, fontSize = 28.sp)
Text("Sunday, 13. Junij", fontSize = 14.sp)
Spacer(Modifier.height(16.dp))


Text("20°", fontSize = 64.sp, fontWeight = FontWeight.Light)
Text("27° / 9°")
Text("Sunny", fontWeight = FontWeight.Bold)


val imgUrl =
"https://vreme.arso.gov.si/app/common/images/svg/weather/partCloudy_day.svg"
val imageLoader = ImageLoader.Builder(LocalContext.current)
.componentRegistry {
add(SvgDecoder(LocalContext.current))
}
.build()

CompositionLocalProvider(LocalImageLoader provides imageLoader) {
// This will automatically use the value of LocalImageLoader
Image(
painter = rememberCoilPainter(imgUrl),
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.height(150.dp)
)
}

Row(){
CurrentForecastDetailItem(
detailText = "šibek",
detailValue = "9km/h",
icon = Icons.Default.Air,
iconBackgroundColor = Color(0xFFe4f4e5),
iconColor = Color(0xFF98d2a5))

CurrentForecastDetailItem(
detailText = "srednja",
detailValue = "50%",
icon = Icons.Default.Bloodtype,
iconBackgroundColor = Color(0xFFe0eff6),
iconColor = Color(0xFF7dc1e5)
)
}

Canvas(modifier = Modifier
.fillMaxWidth()
.height(50.dp), onDraw = {

val path3 = Path().apply {
moveTo(size.width * 0.5f, size.height)
quadraticBezierTo(
size.width * 0.5f,
0f,
size.width * 0.8f,
size.height * 0.1f
)
lineTo(size.width, size.height)
close()
}
drawPath(path3, sunnyColor.copy(alpha = 0.5f))

val path2 = Path().apply {
moveTo(0f, size.height)
quadraticBezierTo(
size.width * 0.1f,
0f,
size.width * 0.3f,
size.height * 0.1f
)
lineTo(size.width, size.height)
close()
}
drawPath(path2, sunnyColor.copy(alpha = 0.5f))
// drawPath(path2, Color.Red)

val path = Path().apply {
moveTo(0f, size.height)
quadraticBezierTo(size.width * 0.3f, 0f, size.width, size.height)
close()
}
drawPath(path, Color.White)
})


}

Row(modifier = Modifier
.padding(16.dp)
.horizontalScroll(rememberScrollState())
) {
Forecast1hCard()
Forecast1hCard()
Forecast1hCard()
Forecast1hCard()
Forecast1hCard()
}
}
}
}
}

@Composable
fun Forecast1hCard(){
Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier
.padding(8.dp)
.border(1.dp, Color.LightGray)
.padding(8.dp)){
Text("12:00", fontSize = 14.sp)
Text("\uF00D", fontFamily = weatherFontFamily, fontSize = 24.sp)
Text("27° / 9°", fontSize = 14.sp)
}
}

@Composable
private fun CurrentForecastDetailItem(detailText: String, detailValue: String, icon: ImageVector, iconBackgroundColor: Color, iconColor: Color) {
Row(modifier = Modifier.padding(8.dp)){
Box(modifier = Modifier
.clip(RoundedCornerShape(10.dp))
.size(40.dp)
.background(color = iconBackgroundColor),
contentAlignment = Alignment.Center
) {
Icon(icon, contentDescription = null, tint = iconColor)
}

Spacer(modifier = Modifier.width(8.dp))

Column() {
Text(detailText, fontSize = 14.sp)
Text(detailValue, fontSize = 12.sp)
}
}
}

Design 2

/***
[LocationScreen] is a screen who displays weather info for a single location
@param[locationName] location for which to display weather info for
*/
@Composable
fun LocationScreen(navController: NavController, locationName: String = "Seoul"){
val sunnyColor = Color(0xFFffeb95)

Surface(){
Scaffold(
modifier = Modifier,
backgroundColor = sunnyColor,
topBar = {
TopAppBar(
title = { Text("") },
modifier = Modifier.padding(16.dp),
elevation = 0.dp,
actions = {
IconButton(onClick = { /*TODO*/ }) {
Icon(Icons.Default.Search, null)
}
}
)
}
) {
Column(modifier = Modifier.fillMaxSize().background(Color.White)) {

Box(modifier = Modifier.fillMaxWidth().height(300.dp)){
Canvas(modifier = Modifier.fillMaxSize(), onDraw = {
val path = Path().apply{
moveTo(x = 0f, y = 0f)
lineTo(x = 0f, y = size.height)
lineTo(x = size.width, y = size.height - 150f)
lineTo(x = size.width, y = 0f)
close()
}

drawPath(path = path, color = sunnyColor)
})
Column(modifier = Modifier.padding(16.dp)) {
Column() {
Text("Seoul", fontSize = 42.sp)
Text("Sunny", fontSize = 20.sp)
}
Spacer(Modifier.height(32.dp))

Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
Text("\uF00D", fontFamily = weatherFontFamily, fontSize = 82.sp)

Column(horizontalAlignment = Alignment.Start) {
Text(buildAnnotatedString {
append("20")
withStyle(SpanStyle(baselineShift = BaselineShift.Superscript, fontSize = 16.sp)){
append("C")
}
}
, fontSize = 48.sp)

Row(){

Text("9C")
Icon(Icons.Default.KeyboardArrowDown, null, modifier = Modifier.size(14.dp))
Spacer(Modifier.width(8.dp))
Text("28C")
Icon(Icons.Default.KeyboardArrowUp, null, modifier = Modifier.size(14.dp))
}
}
}
}
}


Spacer(Modifier.height(16.dp))

Row(modifier = Modifier.padding(16.dp).horizontalScroll(rememberScrollState())) {
Forecast1hCard(true)
Forecast1hCard()
Forecast1hCard()
Forecast1hCard()
Forecast1hCard()
Forecast1hCard()
Forecast1hCard()
Forecast1hCard()
Forecast1hCard()
}
}
}
}
}

@Composable
fun Forecast1hCard(active: Boolean = false){
val roundShape = RoundedCornerShape(10)
val hourFormatter = DateTimeFormatter.ofPattern("HH:mm")

var modifier = Modifier
.clip(roundShape)
.border(BorderStroke(1.dp, Color(0xFFe8e9ec)), roundShape)

if(active){
modifier = modifier.background(
brush = Brush.verticalGradient(
colors = listOf(
Color(0xffa5c6fd),
Color(0xff5a95fb)
)
)
)
}

val textColor = Color.Black

Column(
modifier = modifier.padding(8.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "12:00",
color = textColor,
fontSize = 14.sp,
fontWeight = FontWeight.Normal
)

Text("\uF00D", fontFamily = weatherFontFamily, fontSize = 24.sp)

Text(buildAnnotatedString {
append("20")
withStyle(SpanStyle(baselineShift = BaselineShift.Superscript, fontSize = 10.sp, fontWeight = FontWeight.Normal)){
append("c")
}
}
, fontWeight = FontWeight.Bold, color = textColor)

Text("9km/h", fontSize = 12.sp, color = textColor)
Text("40%", fontSize = 12.sp, color = textColor)
}
Spacer(modifier = Modifier.width(16.dp))
}

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store