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))
}

--

--

--

developer

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

JavaScript’s .map()

How we improved our React Native cold start for Android

Getting Started React

Use Cases For TypeScript Discriminated Union Types and Generics

react-router-dom and Navigation

Beginners guide in React Native

什么是 Page Object

Webpack : an unexpected journey

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
Prima

Prima

developer

More from Medium

Missed Connections: The Difference in UI and UX of Android and iOS Notifications

The next beat — or the lessons we learned from evolving the “Heartbeat” project into “Evie by DHZB”.

Payswifter design revamp

Optimising Mobile App UX with Firebase