/* 본 게시물은 ' 취준생을 위한 안드로이드 앱만들기 콤포즈UI 기본개념 Jetpack Compose '
의 내용을 토대로 작성되었습니다. */
참고 자료
[취준생을 위한 안드로이드 앱만들기 콤포즈UI 기본개념 Jetpack Compose] : https://www.youtube.com/watch?v=1apENzDbtCQ&t=190s
#Jetpack Compose 사용해보기
build.gradle
Jetpack Compose 는 kotlin 1.5.10 이상 버전에서 실행 가능하다.
MainActivity
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import com.example.composeuibasic.ui.theme.ComposeUIBasicTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeUIBasicTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
Greeting(name = "IdeaLim")
}
}
}
}
}
// @Composable : compose view를 반환 / view
@Composable
fun Greeting(name: String) {
//Scaffold : 기본 메터리얼 디자인 Drawer, FloatingActionButton, TopApp Bar 등 다양한 컴포저블을 제공
Scaffold(
//TopBar
topBar = {
TopAppBar(title = {Text("Compose AppBar")},
backgroundColor = Color(0xffE5FBB8)) },
//FloatingActionButton
floatingActionButtonPosition = FabPosition.End,
floatingActionButton = {
FloatingActionButton(onClick = {}) {
Text("클릭")
} },
)
// TextBlock
{
Text(text = "Hello $name!") // ctrl + B 로 Modifier 확인 가능
}
}
//미리보기
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
ComposeUIBasicTheme {
Greeting("Android")
}
}
- @Composable : View를 만드는 애노테이션이다.
- @Preview : 미리보기
- Scaffold : 기본 메터리얼 디자인 제공.
실행 결과
Layout : Column, Row
@Composable
fun MyComposableView() {
Log.d("Tag", "MyComposableView:")
Column(Modifier.background(Color(0xffC0FEFC))){
// Row: horizontal linear layout
Row(
Modifier.padding(10.dp).background(Color(0xff628395)),
//gravity
verticalAlignment = Alignment.CenterVertically
) {
Text(text = "안녕하세요",
modifier = Modifier.background(Color(0xffF9F9F9)).padding(10.dp),
color = Color(0xffD83A56))
Spacer(modifier = Modifier.size(10.dp))
Text(text = "Hello")
}
Row(
Modifier.padding(10.dp).background(Color(0xff628395)),
//gravity
verticalAlignment = Alignment.CenterVertically
) {
Text(text = "안녕하세요",
modifier = Modifier.background(Color(0xffF9F9F9)).padding(10.dp),
color = Color(0xffD83A56))
Spacer(modifier = Modifier.size(10.dp))
Text(text = "Hello")
}
Row(
Modifier.padding(10.dp).background(Color(0xff628395)),
//gravity
verticalAlignment = Alignment.CenterVertically
) {
Text(text = "안녕하세요",
modifier = Modifier.background(Color(0xffF9F9F9)).padding(10.dp),
color = Color(0xffD83A56))
Spacer(modifier = Modifier.size(10.dp))
Text(text = "Hello")
}
}
}
Row 부분을 함수로 만들어서 깔끔하게 나타내보자.
@Composable
fun MyRow(){
Row(
Modifier
.padding(10.dp)
.background(Color(0xff628395)),
//gravity
verticalAlignment = Alignment.CenterVertically
) {
Text(text = "안녕하세요",
modifier = Modifier
.background(Color(0xffF9F9F9))
.padding(10.dp),
color = Color(0xffD83A56))
Spacer(modifier = Modifier.size(10.dp))
Text(text = "Hello",
modifier = Modifier.padding(10.dp))
}
}
//스택 Column, Row, Box(겹치기)
@Composable
fun MyComposableView() {
Log.d("Tag", "MyComposableView:")
Column(
Modifier
.background(Color(0xffC0FEFC))
.verticalScroll(rememberScrollState()) // 스크롤 가능하게..
){
// MyRow() 20개 생성
for (i in 1..20){
MyRow()
}
}
}
실행결과
이번에는 LazyColumn을 이용해서 메모리 관리를 하는 List를 만들어보자.
LazyColumnActivity
class LazyColumnActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeUIBasicTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
ContextLayout()
}
}
}
}
}
// TopAppBar 생성 / RandomUserListView 생성
@Composable
fun ContextLayout() {
Surface(color = MaterialTheme.colors.background) {
Scaffold(
topBar = {
AppBar()
}
) {
RandomUserListView(randomUsers = DummyDataProvider.userList)
}
}
}
// AppBar Setting
@Composable
fun AppBar(){
TopAppBar(
title = { Text("Lazy Column", fontSize = 20.sp) },
backgroundColor = TopBarColor,
elevation = 10.dp,
modifier = Modifier.height(58.dp)
)
}
// RandomUserListView: LazyColumn을 randomUsers
@Composable
fun RandomUserListView(randomUsers: List<RandomUser>){
//메모리 관리하는 LazyColumn (RecyclerView 와 비슷)
LazyColumn(){
// items() : randomUsers 의 리스트 데이터 하나 씩 가져옴
items(randomUsers){ randomUser ->
RandomUserView(randomUser) // RandomUserView(it) 으로 간략히 쓸 수 있음.
}
}
}
@Composable
fun RandomUserView(randomUser: RandomUser){
//cardView
Card(modifier = Modifier
.fillMaxWidth() // match_parent
.padding(10.dp),
elevation = 10.dp,
shape = RoundedCornerShape(12.dp)
) {
RandomUserCardView(randomUser = randomUser)
}
}
@Composable
fun RandomUserCardView(randomUser: RandomUser){
Row(modifier = Modifier.padding(10.dp),
verticalAlignment = Alignment.CenterVertically // 세로로 Card 안에 있는 View 를 가운데 정렬
){
// Box(modifier = Modifier
// .size(width = 50.dp, height = 50.dp)
// .clip(CircleShape)
// .background(TopBarColor)
// )
RandomUserProfileImage(imgUrl = randomUser.profileImage)
RandomUserNameAndDescription(randomUser = randomUser)
}
}
@Composable
fun RandomUserNameAndDescription(randomUser: RandomUser){
Column(
modifier = Modifier.padding(10.dp)
) {
// custom style 은 Theme > typography > subtitle1
Text(text = randomUser.name, style = MaterialTheme.typography.subtitle1)
Text(text = randomUser.description, style = MaterialTheme.typography.body1)
}
}
@Composable
fun RandomUserProfileImage(imgUrl: String, modifier: Modifier = Modifier) {
// 이미지 비트맵 가져오기
val bitmap : MutableState<Bitmap?> = remember { mutableStateOf(null) }
Glide.with(LocalContext.current)
.asBitmap()
.load(imgUrl)
.into(object : CustomTarget<Bitmap>(){
override fun onLoadCleared(placeholder: Drawable?) {
}
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
bitmap.value = resource // resource 는 다운 받은 이미지.
}
})
bitmap.value?.asImageBitmap()?.let {
Image(bitmap = it,
contentScale = ContentScale.Fit,
contentDescription = null,
modifier = modifier
.size(50.dp)
.clip(CircleShape)
)
} ?: Image(painter = painterResource(id = R.drawable.ic_profile_null),
contentScale = ContentScale.Fit,
contentDescription = null,
modifier = modifier
.size(50.dp)
.clip(RoundedCornerShape(10.dp))
)
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview2() {
ComposeUIBasicTheme {
ContextLayout()
}
}
<중요 Point>
1. LazyColumn을 RecyclerView 처럼 사용.
2. Glide를 사용해 Url에서 image를 bitmap으로 가져오기
3. MaterialTheme.typography.subtitle1 처럼 MaterialTheme 를 커스터마이징 가능.
DummyDataProvider
data class RandomUser(
val name: String = "이름",
val description: String = "설명",
val profileImage: String = "https://randomuser.me/api/portraits/women/76.jpg"
)
object DummyDataProvider {
val userList = List<RandomUser>(200) { RandomUser() }
}
실행결과