-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Step1: 장바구니 목록 구성 #48
base: ironelder
Are you sure you want to change the base?
Changes from all commits
414963f
8d25e0d
3fbf6e3
f306441
d087bbd
ca4aaca
85e4cc0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,26 +3,87 @@ package nextstep.shoppingcart | |
import android.os.Bundle | ||
import androidx.activity.ComponentActivity | ||
import androidx.activity.compose.setContent | ||
import androidx.compose.foundation.background | ||
import androidx.compose.foundation.layout.Arrangement | ||
import androidx.compose.foundation.layout.fillMaxSize | ||
import androidx.compose.foundation.layout.fillMaxWidth | ||
import androidx.compose.foundation.layout.padding | ||
import androidx.compose.foundation.lazy.grid.GridCells | ||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid | ||
import androidx.compose.foundation.lazy.grid.items | ||
import androidx.compose.material.icons.Icons | ||
import androidx.compose.material.icons.filled.ShoppingCart | ||
import androidx.compose.material3.ExperimentalMaterial3Api | ||
import androidx.compose.material3.Icon | ||
import androidx.compose.material3.MaterialTheme | ||
import androidx.compose.material3.Scaffold | ||
import androidx.compose.material3.Surface | ||
import androidx.compose.material3.Text | ||
import androidx.compose.material3.TopAppBar | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.graphics.Color | ||
import androidx.compose.ui.res.stringResource | ||
import androidx.compose.ui.text.style.TextAlign | ||
import androidx.compose.ui.tooling.preview.Preview | ||
import androidx.compose.ui.unit.dp | ||
import nextstep.shoppingcart.data.model.Product | ||
import nextstep.shoppingcart.ui.component.ShoppingItemView | ||
import nextstep.shoppingcart.ui.theme.ShoppingCartTheme | ||
|
||
class MainActivity : ComponentActivity() { | ||
@OptIn(ExperimentalMaterial3Api::class) | ||
override fun onCreate(savedInstanceState: Bundle?) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. onCreate가 너무 비대해졌네요! |
||
super.onCreate(savedInstanceState) | ||
val listOfItems = listOf( | ||
Product(name = "name", price = 10000, description = "description"), | ||
Product(name = "name2", price = 15000, description = "description"), | ||
Product(name = "name3", price = 12000, description = "description"), | ||
Product(name = "name4", price = 9000, description = "description"), | ||
Product(name = "name5", price = 5500, description = "description"), | ||
Product(name = "name6", price = 125000, description = "description"), | ||
Product(name = "name7", price = 9900, description = "description"), | ||
Product(name = "name8", price = 52000, description = "description") | ||
) | ||
setContent { | ||
ShoppingCartTheme { | ||
// A surface container using the 'background' color from the theme | ||
Surface( | ||
modifier = Modifier.fillMaxSize(), | ||
color = MaterialTheme.colorScheme.background | ||
modifier = Modifier | ||
.fillMaxSize() | ||
.background(Color.White), | ||
color = MaterialTheme.colorScheme.background, | ||
) { | ||
Greeting("Android") | ||
Scaffold( | ||
topBar = { | ||
TopAppBar( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 컴포넌트를 나누는 본인만의 규칙을 고민해보는건 어떨까요? |
||
title = { | ||
Text( | ||
text = stringResource(id = R.string.product_list), | ||
modifier = Modifier.fillMaxWidth(), | ||
textAlign = TextAlign.Center | ||
) | ||
}, | ||
actions = { | ||
Icon(Icons.Filled.ShoppingCart, contentDescription = stringResource(id = R.string.app_name)) | ||
} | ||
) | ||
}, | ||
content = { padding -> | ||
LazyVerticalGrid( | ||
modifier = Modifier | ||
.fillMaxSize() | ||
.padding(padding), | ||
columns = GridCells.Fixed(2), | ||
verticalArrangement = Arrangement.spacedBy(10.dp), | ||
horizontalArrangement = Arrangement.Center | ||
) { | ||
items(listOfItems) { item -> | ||
ShoppingItemView(item) | ||
} | ||
} | ||
} | ||
) | ||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package nextstep.shoppingcart.data.model | ||
|
||
data class Product( | ||
val imageUrl: String = "https://picsum.photos/500", | ||
val name: String, | ||
val price: Int, | ||
val description: String | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
package nextstep.shoppingcart.ui.component | ||
|
||
import android.util.Log | ||
import androidx.compose.foundation.background | ||
import androidx.compose.foundation.isSystemInDarkTheme | ||
import androidx.compose.foundation.layout.Column | ||
import androidx.compose.foundation.layout.fillMaxWidth | ||
import androidx.compose.foundation.layout.height | ||
import androidx.compose.foundation.layout.padding | ||
import androidx.compose.foundation.layout.wrapContentHeight | ||
import androidx.compose.material3.Surface | ||
import androidx.compose.material3.Text | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.ui.Alignment | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.graphics.Color | ||
import androidx.compose.ui.layout.ContentScale | ||
import androidx.compose.ui.platform.LocalContext | ||
import androidx.compose.ui.res.stringResource | ||
import androidx.compose.ui.text.font.FontWeight | ||
import androidx.compose.ui.text.style.TextOverflow | ||
import androidx.compose.ui.tooling.preview.Preview | ||
import androidx.compose.ui.unit.dp | ||
import coil.ImageLoader | ||
import coil.compose.AsyncImage | ||
import coil.compose.AsyncImagePainter | ||
import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi | ||
import nextstep.shoppingcart.R | ||
import nextstep.shoppingcart.data.model.Product | ||
import nextstep.shoppingcart.ui.theme.getColorScheme | ||
import okhttp3.OkHttpClient | ||
import java.security.SecureRandom | ||
import java.security.cert.X509Certificate | ||
import javax.net.ssl.SSLContext | ||
import javax.net.ssl.TrustManager | ||
import javax.net.ssl.X509TrustManager | ||
|
||
@OptIn(ExperimentalGlideComposeApi::class) | ||
@Composable | ||
fun ShoppingItemView(product: Product) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 기존 XML 기반에 View 와는 구분하기위해, 컴포즈에선 보통 ~View라고 네이밍 짓지 않고 있어요 |
||
val colorScheme = getColorScheme() | ||
|
||
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager { | ||
override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {} | ||
override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {} | ||
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf() | ||
}) | ||
|
||
val sslContext = SSLContext.getInstance("SSL").apply { | ||
init(null, trustAllCerts, SecureRandom()) | ||
} | ||
|
||
val okHttpClient = OkHttpClient.Builder() | ||
.sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager) | ||
.hostnameVerifier { _, _ -> true } | ||
.build() | ||
Comment on lines
+43
to
+56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ssl 관련 설정을 하신 이유가 있나요? |
||
|
||
val imageLoader = ImageLoader.Builder(LocalContext.current) | ||
.okHttpClient { okHttpClient } | ||
.build() | ||
|
||
Column( | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.wrapContentHeight() | ||
.padding(5.dp) | ||
.background(colorScheme.background), | ||
Comment on lines
+63
to
+67
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ShoppingItemView에 Modifier를 파라미터로 넘겨주는것과 |
||
horizontalAlignment = Alignment.CenterHorizontally | ||
) { | ||
AsyncImage( | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.height(158.dp), | ||
contentScale = ContentScale.Crop, | ||
model = product.imageUrl, | ||
contentDescription = null, | ||
imageLoader = imageLoader, | ||
onState = { state -> | ||
when (state) { | ||
Comment on lines
+78
to
+79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. onState를 사용하신 이유가 있을까요? |
||
is AsyncImagePainter.State.Loading -> { | ||
|
||
} | ||
|
||
is AsyncImagePainter.State.Success -> { | ||
|
||
} | ||
|
||
is AsyncImagePainter.State.Error -> { | ||
Log.d("irondler", "Error = ${state.result.throwable.message}") | ||
} | ||
|
||
else -> { | ||
|
||
} | ||
} | ||
} | ||
) | ||
Text( | ||
text = product.name, | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.padding(horizontal = 2.dp), | ||
maxLines = 1, | ||
softWrap = true, | ||
fontWeight = FontWeight.Bold, | ||
overflow = TextOverflow.Ellipsis, | ||
color = if(isSystemInDarkTheme()) Color.White else Color.Black | ||
) | ||
Text( | ||
text = stringResource(id = R.string.product_price, product.price), | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.padding(horizontal = 2.dp), | ||
maxLines = 1, | ||
softWrap = true, | ||
overflow = TextOverflow.Ellipsis, | ||
color = if(isSystemInDarkTheme()) Color.White else Color.Black | ||
) | ||
} | ||
} | ||
|
||
@Preview | ||
@Composable | ||
fun ShoppingItemViewPreview() { | ||
Surface { | ||
ShoppingItemView(Product(name = "name", price = 9999, description = "description")) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
<resources> | ||
<string name="app_name">Shopping Cart</string> | ||
</resources> | ||
<string name="product_list">상품 목록</string> | ||
<string name="product_price">%1d원</string> | ||
</resources> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
glide compose는 아직 beta이군요, 평소에도 glide compose를 활용하시는 편이신가요?
그러나, 이번 과제에서는 glide를 사용하지 않는거 같아요 :)
지워주셔도 좋을거같네요!