Jetpack Compose UI (2)

HEETAE HEO·2022년 8월 6일
0
post-thumbnail

저번 시간에 이어 계속해서 Compose에 대해 작성하겠습니다.

Material Design

Compose의 경우 Material Design 원칙을 지원하도록 빌드되었습니다.

Material Design이란? :
Material Design은 플랫폼 및 기기 전반의 시각적 요소, 모션 및 상호작용 디자인을 위한 포괄적인 가이드 입니다. 대표적으로 애플리케이션 내에서 다크 모드를 지원하는 부분과 버튼 클릭의 애니메이션 동작과 같은 것들이 Material Design이라고 할 수 있습니다.

Jetpack Compose는 머티리얼 디자인 및 UI 요소를 즉시 사용가능하도록 구현합니다. Material Design 스타일 지정을 사용하여 MessageCard의 디자인을 개선해보는 코드를 작성해보겠습니다.

Base Code

// ...

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeTutorialTheme {
                Surface(modifier = Modifier.fillMaxSize()) {
                    MessageCard(Message("Android", "Jetpack Compose"))
                }
            }
        }
    }
}

@Preview
@Composable
fun PreviewMessageCard() {
    ComposeTutorialTheme {
        Surface {
            MessageCard(
                msg = Message("Colleague", "Take a look at Jetpack Compose, it's great!")
            )
        }
    }
}

색상 추가

MaterialTheme.colors를 사용하여 래핑된 테마의 색상으로 스타일을 지정할 수 있습니다.

여기에서는 제목 스타일을 지정하고 이미지에 테두리를 추가합니다.

@Composable
fun MessageCard(msg: Message) {
   Row(modifier = Modifier.padding(all = 8.dp)) {
       Image(
           painter = painterResource(R.drawable.profile_picture),
           contentDescription = null,
           modifier = Modifier
               .size(40.dp)
               .clip(CircleShape)
               .border(1.5.dp, MaterialTheme.colors.secondary, CircleShape)
       )

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

       Column {
           Text(
               text = msg.author,
               color = MaterialTheme.colors.secondaryVariant
           )

           Spacer(modifier = Modifier.height(4.dp))
           Text(text = msg.body)
       }
   }
}

서체 추가

Material 서체 스타일은 MaterialTheme에서 사용할 수 있으며, Text 컴포저블에 추가하기만 하면 됩니다.

// ...

@Composable
fun MessageCard(msg: Message) {
   Row(modifier = Modifier.padding(all = 8.dp)) {
       Image(
           painter = painterResource(R.drawable.profile_picture),
           contentDescription = null,
           modifier = Modifier
               .size(40.dp)
               .clip(CircleShape)
               .border(1.5.dp, MaterialTheme.colors.secondary, CircleShape)
       )
       Spacer(modifier = Modifier.width(8.dp))

       Column {
           Text(
               text = msg.author,
               color = MaterialTheme.colors.secondaryVariant,
               style = MaterialTheme.typography.subtitle2
           )

           Spacer(modifier = Modifier.height(4.dp))

           Text(
               text = msg.body,
               style = MaterialTheme.typography.body2
           )
       }
   }
}

도형 추가

Shape을 사용하여 최종 터치를 추가할 수 있습니다. 먼저 Surface 컴포저블을 중심으로 메시지 본문 테스트를 래핑합니다. 이렇게 하면 메시지 본문의 도형과 높이를 맞춤설정할 수 있습니다. 추가적으로 메시지에 패딩도 추가할 수 있습니다.

// ...
import androidx.compose.material.Surface

@Composable
fun MessageCard(msg: Message) {
   Row(modifier = Modifier.padding(all = 8.dp)) {
       Image(
           painter = painterResource(R.drawable.profile_picture),
           contentDescription = null,
           modifier = Modifier
               .size(40.dp)
               .clip(CircleShape)
               .border(1.5.dp, MaterialTheme.colors.secondary, CircleShape)
       )
       Spacer(modifier = Modifier.width(8.dp))

       Column {
           Text(
               text = msg.author,
               color = MaterialTheme.colors.secondaryVariant,
               style = MaterialTheme.typography.subtitle2
           )

           Spacer(modifier = Modifier.height(4.dp))

           Surface(shape = MaterialTheme.shapes.medium, elevation = 1.dp) {
               Text(
                   text = msg.body,
                   modifier = Modifier.padding(all = 4.dp),
                   style = MaterialTheme.typography.body2
               )
           }
       }
   }
}

어두운 테마 사용

어두운 테마의 경우 기기 배터리 절약 및 OLED 디스플레이 번인 현상, 어두운 환경에서의 사용들을 위해 자주 사용합니다. Jetpack Compose는 기본적으로 어두운 테마를 처리할 수 있습니다. 머티리얼 디자인 색상, 텍스트, 배경을 사용하면 어두운 배경에 맞춰 자동으로 조정됩니다.

// ...
import android.content.res.Configuration

@Preview(name = "Light Mode")
@Preview(
    uiMode = Configuration.UI_MODE_NIGHT_YES,
    showBackground = true,
    name = "Dark Mode"
)
@Composable
fun PreviewMessageCard() {
   ComposeTutorialTheme {
    Surface {
      MessageCard(
        msg = Message("Colleague", "Hey, take a look at Jetpack Compose, it's great!")
      )
    }
   }
}

목록 및 애니메이션

메시지 목록 만들기

메시지를 주고 받다 보면 여러 메서지 전송 기록들을 볼 수 있습니다. LazyColumn과 LazyRow를 사용합니다. 이러한 컴포저블은 화면에 표시되는 요소만 렌더링하므로 긴 목록에 매우 효율적으로 설계되었습니다.

LazyColumn에 items 하위 요소가 있음을 할 수 있고 List를 매개변수로 가져오고 람다는 Message의 인스턴스인 message라는 매개변수를 수신합니다.

// ...
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items

@Composable
fun Conversation(messages: List<Message>) {
    LazyColumn {
        items(messages) { message ->
            MessageCard(message)
        }
    }
}

@Preview
@Composable
fun PreviewConversation() {
    ComposeTutorialTheme {
        Conversation(SampleData.conversationSample)
    }
}

축약 메시지 펼처보기

메시지 종류중에서 일정 글 이상이 작성되어 있다면 가려지며 해당 내용을 보고 싶다면 터치를 통해 해당 메시지 칸을 확장하여 보게됩니다. Compose에서 그러한 기능을 수행할 수 있습니다.

// ...
import androidx.compose.foundation.clickable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue

class MainActivity : ComponentActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContent {
           ComposeTutorialTheme {
               Conversation(SampleData.conversationSample)
           }
       }
   }
}

@Composable
fun MessageCard(msg: Message) {
    Row(modifier = Modifier.padding(all = 8.dp)) {
        Image(
            painter = painterResource(R.drawable.profile_picture),
            contentDescription = null,
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
                .border(1.5.dp, MaterialTheme.colors.secondaryVariant, CircleShape)
        )
        Spacer(modifier = Modifier.width(8.dp))

        // We keep track if the message is expanded or not in this
        // variable
        var isExpanded by remember { mutableStateOf(false) }

        // We toggle the isExpanded variable when we click on this Column
        Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {
            Text(
                text = msg.author,
                color = MaterialTheme.colors.secondaryVariant,
                style = MaterialTheme.typography.subtitle2
            )

            Spacer(modifier = Modifier.height(4.dp))

            Surface(
                shape = MaterialTheme.shapes.medium,
                elevation = 1.dp,
            ) {
                Text(
                    text = msg.body,
                    modifier = Modifier.padding(all = 4.dp),
                    // If the message is expanded, we display all its content
                    // otherwise we only display the first line
                    maxLines = if (isExpanded) Int.MAX_VALUE else 1,
                    style = MaterialTheme.typography.body2
                )
            }
        }
    }
}

references

https://developer.android.com/jetpack/compose/tutorial?hl=ko

profile
Android 개발 잘하고 싶어요!!!

0개의 댓글