이번 포스팅은 레이아웃 관련 포스팅 입니다.
먼저 간단하게 텍스트 두개를 화면에 보이도록 작성해 보겠습니다.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
}
}
}
data class UserInform(val name : String, val ege : Int)
@Composable
fun HelloWorld(userInform : UserInform){
Text(userInform.name)
Text(userInform.ege.toString())
}
@Preview
@Composable
fun PreviewHelloWorld(){
HelloWorld(userInform = UserInform("Shino72", 17))
}
다음과 같이 작성을 하면, 계층적 구조에 따라 이름 아래에 나이 또는 이름 옆에 나이가 나오는 화면이 보일 것 같지만,
실제 결과는 아래와 같이 겹쳐서 나타나게 됩니다.
이유는 "정렬 정보가 정의되지 않았기 때문" 입니다.
1. 정렬 함수
Column 함수를 이용하여, 요소를 수직으로 정의해보겠습니다.
코드는 다음과 같습니다.
@Preview
@Composable
fun PreviewHelloWorld(){
Column {
HelloWorld(userInform = UserInform("Shino72", 17))
}
}
Column 함수를 사용하여, 수직으로 텍스트가 잘 정렬 되었음을 확인할 수 있습니다.
Row를 활용하여 다음과 같이 표현할 수 있습니다.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Row{
Image(painter = painterResource(id = R.drawable.bom_mouse), contentDescription = "android")
Column {
HelloWorld(userInform = UserInform("Shino72", 17))
}
}
}
}
}
이미지의 경우 Image 함수를 사용합니다. 함수 인자로는, Image id 값과, 이미지 요약을 인자로 받습니다.
2. Modifier
레이아웃의 마진, 패딩, width, height와 같은 요소들의 적용은 modifier를 통해 가능하다.
마진과 패딩의 경우에는
modifier = Modifier.padding(all = 8.dp)
다음과 같이 사용이 가능한데, 인자로 하나만 값을 넣게 되면, all이다. 만약 상하좌우각각 넣고 싶다면 각각 top,bottom,start,end 순으로 값을 넣어주면 된다.
또한 이미지를 동그랗게 만들고 싶다면, 다음과 같이 하면된다
추가적으로,다른 요소도 같이 넣고 싶다면 아래와 같이 작성해 주면된다. 각각 width, height,패딩, 도형 모양, 외각선을 정의가 가능하다.
modifier = Modifier
.width(50.dp)
.height(50.dp)
.padding(top = 5.dp, start = 5.dp, end = 5.dp, bottom = 5.dp)
.clip(CircleShape)
.border(1.5.dp, Color.Red, CircleShape)
여백을 넣고 싶다면,
Spacer를 사용한다.
Spacer(modifier = Modifier.width(8.dp))
3. 인스타 댓글 모양으로 만들어보기
위에서 modifier를 통해 여러 요소를 넣어주었다, 이제는 인스타나 유튜브 댓글창을 만들어보고자 한다.
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.compose.ui.theme.ComposeTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Row(modifier = Modifier.padding(all = 8.dp)){
Image(
painter = painterResource(id = R.drawable.bom_mouse),
contentDescription = null,
modifier = Modifier
.width(50.dp)
.height(50.dp)
.padding(top = 5.dp, start = 5.dp, end = 5.dp, bottom = 5.dp)
.clip(CircleShape)
.border(1.5.dp, Color.Red, CircleShape)
)
Spacer(modifier = Modifier.width(8.dp))
Column {
Text(
text = "봄",
color = Color.Black,
style = MaterialTheme.typography.titleMedium
)
Spacer(modifier = Modifier.height(4.dp))
Surface(shape = MaterialTheme.shapes.medium) {
Text(text = "고양이", modifier = Modifier.padding(4.dp))
}
}
}
}
}
}
완성~
4. 댓글 여러개 달기
생각을 해보면, 댓글이 여러개 달릴수도 있다. 이러한 경우에는 어떻게 해야할까.
LazyColumn이나 LazyRow를 사용한다.
화면에 보이는 컴포넌트만 랜더링하므로 댓글과 같이 긴 목록에는 상당히 효율적이라고 한다.
그러면 각각 적용해서 만들어보겠다.
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.compose.ui.theme.ComposeTheme
import org.w3c.dom.Comment
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val commentsList = mutableListOf<Comment>(
Comment("1","hi"),
Comment("2","my"),
Comment("3","name"),
Comment("4","shino72"),
Comment("1","hi"),
Comment("2","my"),
Comment("3","name"),
Comment("4","shino72"),
Comment("1","hi"),
Comment("2","my"),
Comment("3","name"),
Comment("4","shino72"),
Comment("1","hi"),
Comment("2","my"),
Comment("3","name"),
Comment("4","shino72"),
)
setContent {
LazyColumn{
items(commentsList) { comment ->
CommentView(comment = comment)
}
}
}
}
data class Comment(val name : String, val contents : String)
@Composable
fun CommentView(comment : Comment){
Row(modifier = Modifier.padding(all = 8.dp)){
Image(
painter = painterResource(id = R.drawable.bom_mouse),
contentDescription = null,
modifier = Modifier
.width(50.dp)
.height(50.dp)
.padding(top = 5.dp, start = 5.dp, end = 5.dp, bottom = 5.dp)
.clip(CircleShape)
.border(1.5.dp, Color.Red, CircleShape)
)
Spacer(modifier = Modifier.width(8.dp))
Column {
Text(
text = comment.name,
color = Color.Black,
style = MaterialTheme.typography.titleMedium
)
Spacer(modifier = Modifier.height(4.dp))
Surface(shape = MaterialTheme.shapes.medium) {
Text(text = comment.contents, modifier = Modifier.padding(4.dp))
}
}
}
}
}
스크롤도 잘된다.
+ 추가적으로 댓글 클릭시 자세히 보기를 구현해본다.
5. 상태 감지
remember과 mutableStateOf를 사용해서 구현한다.
remember의 경우네는 메모리에 로컬 상태를 저장하고,
mutableStateOf에 전달된 값에 변경사항이 발생하면 체크가 가능하다.
이번에는 댓글을 클릭하게 되면, isClicked의 값이 바뀌고 이를 감지하여 텍스트의 maxLines를 1에서 MAX 값으로 바꾸어 댓글이 자세히 보이도록 하였다.
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.compose.ui.theme.ComposeTheme
import org.w3c.dom.Comment
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val commentsList = mutableListOf<Comment>(
Comment("1","hifsdafdsafgfdsggfdsgdsgdsfgdfsgdsgdffdgdfgfdgsdfgdffgds"),
Comment("2","my"),
Comment("3","name"),
Comment("4","shino72"),
Comment("1","hi"),
Comment("2","my"),
Comment("3","name"),
Comment("4","shino72"),
Comment("1","hi"),
Comment("2","my"),
Comment("3","name"),
Comment("4","shino72"),
Comment("1","hi"),
Comment("2","my"),
Comment("3","name"),
Comment("4","shino72"),
)
setContent {
LazyColumn{
items(commentsList) { comment ->
CommentView(comment = comment)
}
}
}
}
data class Comment(val name : String, val contents : String)
@Composable
fun CommentView(comment : Comment){
Row(modifier = Modifier.padding(all = 8.dp)){
Image(
painter = painterResource(id = R.drawable.bom_mouse),
contentDescription = null,
modifier = Modifier
.width(50.dp)
.height(50.dp)
.padding(top = 5.dp, start = 5.dp, end = 5.dp, bottom = 5.dp)
.clip(CircleShape)
.border(1.5.dp, Color.Red, CircleShape)
)
Spacer(modifier = Modifier.width(8.dp))
var isClicked by remember { mutableStateOf(false) }
Column (modifier = Modifier.clickable { isClicked = !isClicked }){
Text(
text = comment.name,
color = Color.Black,
style = MaterialTheme.typography.titleMedium
)
Spacer(modifier = Modifier.height(4.dp))
Surface(shape = MaterialTheme.shapes.medium) {
Text(text = comment.contents, modifier = Modifier.padding(4.dp), maxLines = if(isClicked) Int.MAX_VALUE else 1)
}
}
}
}
}
'안드로이드 > Compose' 카테고리의 다른 글
[Compose UI] 텍스트/이미지 반짝임 로딩화면 만들기 (1) | 2023.11.29 |
---|---|
[Compose UI] Cutstom Pager를 이용하여 swipe transition 구현하기 (0) | 2023.11.28 |
Modifier 적용시 padding이 적용이 안될 때 (0) | 2023.10.24 |
JetPack Compose - FlowLayout + Chip (0) | 2023.10.20 |
[Jetpack Compose] 1. Compose 튜토리얼 (0) | 2023.05.22 |