Android 앱에 이미지 추가

1. 시작하기 전에

이 Codelab에서는 Image 컴포저블을 사용하여 앱에 이미지를 추가하는 방법을 알아봅니다.

기본 요건

  • Android 스튜디오에서 앱을 만들고 실행하는 방법에 관한 기본 지식
  • 텍스트 컴포저블과 같은 UI 요소를 추가하는 방법에 관한 기본 지식

학습할 내용

  • Android 앱에 이미지나 사진을 추가하는 방법
  • Image 컴포저블을 사용하여 앱에 이미지를 표시하는 방법
  • String 리소스 사용 권장사항

빌드할 항목

  • 이미지를 포함하도록 Happy Birthday 앱을 개선합니다.

필요한 항목

2. 앱 설정

Android 스튜디오에서 이전 Codelab의 Happy Birthday 프로젝트를 엽니다.

앱을 실행하면 다음 스크린샷과 같이 표시됩니다.

fdf3fc55ab1d348a.png

프로젝트에 이미지 추가

이 작업에서는 인터넷에서 이미지를 다운로드하여 Happy Birthday 앱에 추가합니다.

  1. 링크에서 생일 카드 앱의 이미지를 엽니다.
  2. 다운로드를 클릭합니다.

1d731e32164fca8a.png

  1. 이미지를 마우스 오른쪽 버튼으로 클릭한 다음 파일을 컴퓨터에 androidparty.png로 저장합니다.
  2. 이미지를 저장한 위치를 기록합니다.

예를 들어 다운로드 폴더에 파일을 저장했을 수 있습니다.

  1. Android 스튜디오에서 View > Tool Windows > Resource Manager(보기 > 도구창 > Resource Manager)를 클릭하거나 Project(프로젝트) 창 옆에 있는 Resource Manager 탭을 클릭합니다.

3cda2692405276d.png

3b6c04c505468229.png

  1. +(모듈에 리소스 추가) > Import Drawables(드로어블 가져오기)를 클릭합니다.

a85b707150fcff9a.png

  1. 파일 브라우저에서 다운로드한 이미지 파일을 선택한 다음 Open(열기)을 클릭합니다.

이렇게 하면 Import drawables(드로어블 가져오기) 대화상자가 열립니다.

d64abadd7b79ecf0.png

  1. Android 스튜디오에 이미지의 미리보기가 표시됩니다. QUALIFIER TYPE(한정자 유형) 드롭다운 목록에서 Density(밀도)를 선택합니다. 이렇게 하는 이유는 이후 섹션에서 알아보겠습니다.

한정자 유형을 밀도로 설정하는 화면

  1. VALUE(값) 목록에서 No Density(밀도 없음)를 선택합니다.

 값 드롭다운에서 선택된 dpi 없음

Android 기기는 다양한 화면 크기(예: 휴대전화, 태블릿, TV)로 제공되며 이러한 화면은 픽셀 크기도 다릅니다. 즉, 한 기기에서는 제곱인치당 160픽셀을 사용하지만 다른 기기에서는 같은 공간에 480픽셀을 사용합니다. 이러한 픽셀 밀도의 차이를 고려하지 않으면 시스템이 이미지를 확대하여 흐릿한 이미지, 메모리를 과도하게 사용하는 큰 이미지 또는 부적절한 크기의 이미지를 얻을 수 있습니다.

Android 시스템에서 처리할 수 있는 것보다 큰 이미지의 크기를 조절하면 메모리 부족 오류가 발생합니다. 사진 및 배경 이미지(예: 현재 이미지 androidparty.png)의 경우 drawable-nodpi 폴더에 배치해야 크기 조절 동작이 중지됩니다.

픽셀 밀도에 관한 자세한 내용은 다양한 픽셀 밀도 지원을 참고하세요.

  1. Next(다음)를 클릭합니다.
  2. Android 스튜디오에서는 이미지가 배치될 폴더 구조를 보여줍니다. drawable-nodpi 폴더를 확인합니다.
  3. Import(C)(가져오기(C))를 클릭합니다.

74d23f98b8018f93.png

Android 스튜디오는 drawable-nodpi 폴더를 만들고 그 안에 이미지를 배치합니다. Android 스튜디오 프로젝트 뷰에는 리소스 이름이 androidparty.png (nodpi)로 표시됩니다. 컴퓨터 파일 시스템에서는 Android 스튜디오가 drawable-nodpi라는 폴더를 만듭니다.

5e5ca441e391929e.png

drawable 폴더(dpi 없음) 아래에 배치됩니다.

이미지를 성공적으로 가져오면 Android 스튜디오는 Drawable(드로어블) 탭 아래의 목록에 이미지를 추가합니다. 이 목록에는 앱의 이미지와 아이콘이 모두 포함됩니다. 이제 앱에서 이 이미지를 사용할 수 있습니다.

새로 추가된 이미지 표시

  1. 다시 프로젝트 뷰로 전환합니다. View > Tool Windows > Project(보기 > 도구 창 > 프로젝트)를 클릭하거나 맨 왼쪽의 Project(프로젝트) 탭을 클릭합니다.
  2. app > res > drawable을 클릭하여 이미지가 drawable 폴더에 있는지 확인합니다.

f95964d9f0ee2dba.png

3. 이미지 컴포저블 추가

앱에서 이미지를 표시하려면 표시할 위치가 필요합니다. 구성 가능한 함수 Text를 사용하여 텍스트를 표시하는 것처럼 구성 가능한 함수 Image를 사용하여 이미지를 표시할 수 있습니다.

이 작업에서는 앱에 구성 가능한 함수 Image를 추가하고 다운로드한 이미지로 이미지를 설정하고 위치를 지정한 후 화면이 채워지도록 크기를 조정합니다.

구성 가능한 함수를 추가하여 이미지 추가

  1. MainActivity.kt 파일에서 GreetingText() 함수 뒤에 구성 가능한 함수 GreetingImage()를 추가합니다.
  2. GreetingImage() 함수에 String 매개변수 두 개를 전달합니다. 하나는 생일 축하용 message이고 다른 하나는 서명용 from입니다.
@Composable
fun GreetingImage(message: String, from: String) {
}
  1. 모든 구성 가능한 함수는 선택적 Modifier 매개변수를 허용해야 합니다. 수정자는 상위 요소 레이아웃 내에서 UI 요소가 배치되고 표시되고 동작하는 방식을 UI 요소에 알려줍니다. GreetingImage() 컴포저블에 다른 매개변수를 추가합니다.
@Composable
fun GreetingImage(message: String, from: String, modifier: Modifier = Modifier) {
}

Jetpack Compose의 리소스

리소스는 코드에서 사용하는 추가 파일과 정적인 콘텐츠입니다. 예를 들어 비트맵, 사용자 인터페이스 문자열, 애니메이션 지침 등이 있습니다. Android의 리소스에 관한 자세한 내용은 앱 리소스 개요를 참고하세요.

이미지와 문자열 등 애플리케이션 리소스는 독립적인 유지관리가 가능하도록 항상 코드로부터 분리해야 합니다. Android는 런타임에 현재 구성을 근거로 적절한 리소스를 사용합니다. 예를 들어 화면 크기에 따라 다른 UI 레이아웃을 제공하거나 언어 설정에 따라 다른 문자열을 제공할 수 있습니다.

리소스 그룹화

항상 프로젝트의 res/ 디렉터리에 있는 특정 하위 디렉터리에 각 유형의 리소스를 배치해야 합니다. 간단한 프로젝트에서 볼 수 있는 파일 계층 구조의 예는 다음과 같습니다.

MyProject/
    src/
        MyActivity.kt
    res/
        drawable/
            graphic.png
        mipmap/
            icon.png
        values/
            strings.xml

이 예시에서 볼 수 있듯이 res/ 디렉터리에는 이미지 리소스용 drawable/ 디렉터리, 런처 아이콘용 mipmap/ 디렉터리, 문자열 리소스용 values/ 디렉터리가 포함된 하위 디렉터리의 모든 리소스가 포함되어 있습니다. 앱 리소스의 사용, 형식, 문법에 관한 자세한 내용은 리소스 유형 개요를 참고하세요.

리소스 액세스

Jetpack Compose는 Android 프로젝트에 정의된 리소스에 액세스할 수 있습니다. 프로젝트의 R 클래스에서 생성된 리소스 ID로 리소스에 액세스할 수 있습니다.

R 클래스는 Android에서 자동으로 생성되는 클래스로, 프로젝트에 있는 모든 리소스의 ID를 포함합니다. 대부분의 경우 리소스 ID는 파일 이름과 동일합니다. 예를 들어 이전 파일 계층 구조의 이미지는 다음 코드로 액세스할 수 있습니다.

R.drawable.graphic

R은 자동 생성된 클래스이고 drawable은 res 폴더의 하위 디렉터리이며 graphic은 리소스 ID입니다.

다음 작업에서는 이전 작업에서 추가한 이미지 androidparty.png 파일을 사용합니다.

  1. GreetingImage() 함수에서 val 속성을 선언하고 이름을 image로 지정합니다.
  2. androidparty 리소스를 전달하여 painterResource() 함수를 호출합니다. 반환된 값을 image 변수에 할당합니다.
val image = painterResource(R.drawable.androidparty)

Android 스튜디오에서는painterResource 코드가 강조 표시됩니다. 앱을 컴파일하려면 함수를 가져와야 하기 때문입니다.

82323978341a0bdc.png

  1. Android 스튜디오에서 강조 표시된 .painterResource를 클릭합니다.
  2. 팝업에서 Import(가져오기)를 클릭하여 androidx.compose.ui.res.painterResource 가져오기를 추가합니다.

painterResource() 함수는 드로어블 이미지 리소스를 로드하고 리소스 ID(이 경우 R.drawable.androidparty)를 인수로 사용합니다.

  1. painterResource() 함수를 호출한 후 Image 컴포저블을 추가하고 image를 이름이 지정된 painter 인수로 전달합니다.
Image(
    painter = image
)

앱을 컴파일하려면 함수를 가져와야 하므로 Android 스튜디오는 Image 코드를 강조 표시합니다.

e2bead11643e0577.png

이 경고를 해결하려면 MainActivity.kt 파일 상단에 다음 가져오기를 추가하세요.

import androidx.compose.foundation.Image

이제 초기 경고는 해결되었지만 Image라는 단어 위로 마우스를 가져가면 Android 스튜디오에 '입력한 인수로 다음 함수를 호출할 수 없습니다'라는 새로운 경고가 표시됩니다. 이는 제공된 인수가 Image 함수 서명과 일치하지 않기 때문입니다.

ad35f0a40f8fc849.png

이 경고는 다음 섹션에서 해결될 예정입니다.

앱 접근성 확인

접근성을 위한 코딩 사례를 따르면 장애가 있는 사용자를 비롯한 모든 사용자가 앱을 더 쉽게 탐색하고 상호작용할 수 있습니다.

Android 스튜디오에서 제공하는 힌트와 경고를 통해 앱의 접근성을 개선할 수 있습니다. 콘텐츠 설명은 UI 요소의 목적을 정의하고 이를 통해 앱이 TalkBack으로 더 유용해집니다.

그러나 이 앱의 이미지는 장식 목적으로만 포함됩니다. 이 경우 이미지의 콘텐츠 설명을 추가하면 TalkBack과 함께 사용하기가 더 어려워집니다. 사용자에게 표시되는 콘텐츠 설명을 설정하는 대신 이미지의 contentDescription 인수를 null로 설정하여 TalkBack이 Image 컴포저블을 건너뛰도록 할 수 있습니다.

  • Image 컴포저블에서 contentDescription이라는 이름이 지정된 또 다른 인수를 추가하고 그 값을 null로 설정합니다.
Image(
    painter = image,
    contentDescription = null
)

Image 컴포저블 미리보기

이 작업에서는 이미지 컴포저블을 미리 보고 에뮬레이터나 기기에서 앱을 실행합니다.

  1. BirthdayCardPreview() 함수에서 GreetingText() 함수 호출을 GreetingImage() 함수 호출로 바꿉니다.

함수는 다음 코드 스니펫과 같이 표시됩니다.

@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
    HappyBirthdayTheme {
        GreetingImage(
            message = "Happy Birthday Sam!",
            from = "From Emma"
        )
    }
}
  1. Design 창이 자동으로 업데이트됩니다. 창이 업데이트되지 않으면 609ccb451d05cf6b.png 아이콘을 클릭하여 빌드합니다.

새 함수에는 구성 가능한 함수 Image만 있고 구성 가능한 함수 Text는 없으므로 텍스트가 더 이상 표시되지 않습니다.

acd47e25eb2a8d55.png

4. Box 레이아웃 추가

Compose의 세 가지 기본 표준 레이아웃 요소는 Column, Row, Box 컴포저블입니다. 이전 Codelab에서 Column, Row 컴포저블을 알아봤으므로 이제 Box 컴포저블에 관해 자세히 살펴보겠습니다.

Box 레이아웃은 Compose의 표준 레이아웃 요소 중 하나입니다. Box 레이아웃을 사용하여 요소를 서로 위에 쌓습니다. Box 레이아웃을 사용하면 포함된 요소의 특정 정렬도 구성할 수 있습니다.

4d191637aaecf374.png

  1. GreetingImage() 함수에서 다음과 같이 구성 가능한 함수 Image 주위에 구성 가능한 함수 Box를 추가합니다.
@Composable
fun GreetingImage(message: String, from: String, modifier: Modifier = Modifier) {
    val image = painterResource(R.drawable.androidparty)
    Box {
        Image(
            painter = image,
            contentDescription = null
        )
    }
}
  1. Android 스튜디오에서 메시지가 표시되면 androidx.compose.foundation.layout.Box 함수를 가져옵니다.
  2. modifier 매개변수를 Box 컴포저블에 전달하는 코드를 추가합니다.
@Composable
fun GreetingImage(message: String, from: String, modifier: Modifier = Modifier) {
    val image = painterResource(R.drawable.androidparty)
    Box(modifier) {
        Image(
            painter = image,
            contentDescription = null
        )
    }
}
  1. 구성 가능한 함수 Box의 끝에서 GreetingText() 함수를 호출하고 아래와 같이 생일 메시지와 서명, 수정자를 전달합니다.
@Composable
fun GreetingImage(message: String, from: String, modifier: Modifier = Modifier) {
    val image = painterResource(R.drawable.androidparty)
    Box(modifier) {
        Image(
            painter = image,
            contentDescription = null
        )
        GreetingText(
            message = message,
            from = from,
            modifier = Modifier
                .fillMaxSize()
                .padding(8.dp)
        )
    }
}
  1. Design(디자인) 창에서 업데이트된 미리보기를 확인합니다.

텍스트와 이미지가 표시됩니다.

배경 이미지가 상단에 고정됨

  1. 에뮬레이터나 기기에 위의 변경사항이 반영되도록 하려면 onCreate() 함수에서 GreetingText() 함수 호출을 GreetingImage() 함수 호출로 바꿉니다.

setContent 블록은 다음 코드 스니펫과 같습니다.

setContent {
    HappyBirthdayTheme {
        // A surface container using the 'background' color from the theme
        Surface(
            modifier = Modifier.fillMaxSize(),
            color = MaterialTheme.colorScheme.background
        ) {
            GreetingImage(
                message = "Happy Birthday Sam!",
                from = "From Emma"
            )
        }
    }
}

이미지의 너비가 화면 너비와 같지만 이미지는 화면 상단에 고정되어 있습니다. 화면 하단에 공백이 있어 별로 보기 좋지 않습니다. 다음 작업에서는 화면의 너비와 높이를 채우고 이미지의 크기를 조정하여 화면 전체를 채웁니다.

5. 불투명도 변경 및 이미지 크기 조정

이 작업에서는 이미지를 전체 화면 크기로 조정하여 앱을 아름답게 꾸밉니다. 이를 위해 ContentScale 매개변수를 사용합니다.

콘텐츠 조정

앱에 이미지를 추가하고 위치를 지정했습니다. 이제 이미지 크기를 조절하는 방법을 나타내는 이미지의 배율 유형을 조정하여 전체 화면이 되도록 해야 합니다.

여러 ContentScale 유형을 사용할 수 있습니다. ContentScale.Crop 매개변수 배율을 사용합니다. 그러면 이미지의 너비와 높이가 상응하는 화면의 크기와 같거나 더 커지도록 이미지의 크기를 조정하여 가로세로 비율이 균일하게 유지됩니다.

  1. 이미지에 ContentScale이라는 인수를 추가합니다.
Image(
    painter = image,
    contentDescription = null,
    contentScale = ContentScale.Crop
)
  1. Android 스튜디오에서 메시지가 표시되면 androidx.compose.ui.layout.ContentScale 인터페이스를 가져옵니다.
  2. Design 창을 확인합니다.

이제 다음 스크린샷에서 보는 것과 같이 이미지가 전체 미리보기 화면을 채웁니다.

ae1a5ec6b294f466.png

불투명도 변경

앱의 대비를 개선하려면 배경 이미지의 불투명도를 변경하세요.

Image 컴포저블에 alpha 매개변수를 추가하고 0.5F로 설정합니다.

Image(
    painter = image,
    contentDescription = null,
    contentScale = ContentScale.Crop,
    alpha = 0.5F
)

이미지 불투명도의 변화를 확인합니다.

코드가 많습니다. 이제 그동안 했던 작업을 미리 확인해 보겠습니다.

앱 실행

기기나 에뮬레이터에서 앱을 실행합니다.

9d1416521733e8c.png

전체 화면 이미지 및 문자 메시지가 잘 처리되었습니다. 이미지의 불투명도도 변경했습니다.

레이아웃 수정자

수정자는 Jetpack Compose UI 요소를 장식하거나 이 요소에 동작을 추가하는 데 사용됩니다. 예를 들어 행이나 텍스트, 버튼에 배경이나 패딩, 동작을 추가할 수 있습니다. 이를 설정하려면 컴포저블이나 레이아웃에서 수정자를 매개변수로 허용해야 합니다.

이전 Codelab에서는 수정자에 관해 알아보고 패딩 수정자(Modifier.padding)를 사용하여 Text 컴포저블 주위에 공간을 추가했습니다. 수정자는 많은 작업을 할 수 있으며 이 개발자 과정과 다음 개발자 과정에서 확인할 수 있습니다.

예를 들어 이 Text 컴포저블에는 배경 색상을 녹색으로 변경하는 Modifier 인수가 있습니다.

// Example
Text(
    text = "Hello, World!",
    // Solid element background color
    modifier = Modifier.background(color = Color.Green)
)

위의 예와 마찬가지로 레이아웃에 수정자를 추가하여 arrangement 및 alignment 속성을 통해 하위 요소를 배치할 수 있습니다.

Row 내에서 하위 요소의 위치를 설정하려면 horizontalArrangementverticalAlignment 인수를 설정하세요. Column의 경우 verticalArrangementhorizontalAlignment 인수를 설정합니다.

arrangement 속성은 레이아웃 크기가 그 하위 요소의 합보다 큰 경우 하위 요소를 정렬하는 데 사용됩니다.

예를 들어 Column의 크기가 그 하위 요소 크기의 합보다 큰 경우 verticalArrangement를 지정하여 Column 내 하위 요소의 배치를 정의할 수 있습니다. 다음은 다양한 세로 정렬을 보여주는 예입니다.

동일한 높이, 사이 간격, 주위 간격, 균등 간격, 상단, 가운데, 하단

마찬가지로 Row의 크기가 그 하위 요소 크기의 합보다 큰 경우 horizontalArrangement를 지정하여 Row 내 하위 요소의 배치를 정의할 수 있습니다. 다음은 다양한 가로 정렬을 보여주는 예입니다.

동일한 가중치, 사이 간격, 주위 간격, 균등 간격, 끝, 가운데, 시작

alignment 속성은 레이아웃의 시작, 가운데 또는 끝에 하위 요소를 정렬하는 데 사용됩니다.

6. 텍스트 정렬

이 작업에서는 이전 Codelab에서 앱의 텍스트를 정렬하기 위해 추가한 코드를 확인합니다.

  1. MainActivity.kt 파일에서 GreetingText() 함수로 스크롤합니다. 열의 verticalArrangement 속성이 Arrangement.Center로 설정되어 있습니다. 따라서 텍스트 콘텐츠가 화면 중앙에 배치됩니다.
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Column(
        verticalArrangement = Arrangement.Center,
        modifier = modifier
    ) {
        Text(
            text = message,
            fontSize = 100.sp,
            lineHeight = 116.sp,
            textAlign = TextAlign.Center
        )
        Text(
            text = from,
            fontSize = 36.sp,
            modifier = Modifier
                .padding(16.dp)
                .align(alignment = Alignment.End)
        )
    }
}

패딩

UI 요소는 콘텐츠 주위로 래핑됩니다. 너무 비좁게 래핑되지 않도록 각 면의 패딩 값을 지정할 수 있습니다.

패딩이 없는 텍스트 컴포저블

패딩이 있는 텍스트 컴포저블

패딩은 수정자로 사용되므로 모든 컴포저블에 적용할 수 있습니다. 컴포저블의 각 면의 경우 padding 수정자는 패딩 값을 정의하는 선택적 인수를 사용합니다.

상단, 시작 부분, 하단, 끝 부분 패딩을 보여주는 다이어그램

// This is an example.
Modifier.padding(
    start = 16.dp,
    top = 16.dp,
    end = 16.dp,
    bottom = 16.dp
)
  1. 이제 직접 해볼 차례입니다. MainActivity.kt 파일에서 GreetingText() 함수가 호출되는 위치로 스크롤한 다음 패딩 속성을 확인합니다.
modifier = Modifier
    .fillMaxSize()
    .padding(8.dp)
  1. 마찬가지로 GreetingText() 함수 내에서 서명 Text 컴포저블의 패딩을 확인합니다.
modifier = Modifier
    .padding(16.dp)
    .align(alignment = Alignment.End)

7. 적절한 코드 사례 채택

번역

앱을 작성할 때는 특정 시점에 다른 언어로 번역될 수 있음을 기억해야 합니다. 이전 Codelab에서 알아본 것처럼 String 데이터 유형은 "Happy Birthday Sam!"과 같은 일련의 문자입니다.

하드코딩 문자열은 앱 코드에 직접 작성된 문자열입니다. 하드코딩 문자열로 인해 앱을 다른 언어로 번역하기가 더 어렵고 앱의 다른 위치에서 문자열을 재사용하기가 더 힘듭니다. 문자열을 리소스 파일로 추출하여 이러한 문제를 해결할 수 있습니다. 코드에서 문자열을 하드코딩하는 대신 문자열을 파일에 넣고 문자열 리소스의 이름을 지정한 후 문자열을 사용할 때마다 이름을 사용합니다. 이름은 문자열을 변경하거나 다른 언어로 번역하더라도 동일하게 유지됩니다.

  1. MainActivity.kt 파일에서 onCreate() 함수로 스크롤합니다. 생일 축하 메시지, Happy Birthday Sam! 문자열(따옴표 제외)을 선택합니다.
  2. 화면 왼쪽에 있는 전구를 클릭합니다.
  3. Extract string resource(문자열 리소스 추출)를 선택합니다.

eed032464b68ee5.png

Android 스튜디오에서 Extract Resource(리소스 추출) 대화상자가 열립니다. 이 대화상자에서 문자열 리소스 이름과 이를 저장하는 방법에 관한 세부사항을 맞춤설정할 수 있습니다. Resource name 필드에는 호출될 문자열을 입력합니다. Resource value 필드에는 실제 문자열 자체를 입력합니다.

  1. Extract Resource 대화상자에서 Resource namehappy_birthday_text로 변경합니다.

문자열 리소스에는 소문자 이름이 있어야 하고 여러 단어는 밑줄로 구분되어야 합니다. 다른 설정은 기본값으로 둡니다.

d6cb11f087b79f1e.png

  1. OK(확인)을 클릭합니다.
  2. 코드의 변경사항을 확인합니다.

이제 하드코딩 문자열이 getString() 함수 호출로 대체됩니다.

GreetingImage(
    message = getString(R.string.happy_birthday_text),
    from = "From Emma",
    modifier = Modifier.padding(8.dp)
)
  1. Project 창에서 app > res > values > strings.xml 경로의 strings.xml을 열고 Android 스튜디오에 happy_birthday_text라는 문자열 리소스가 생성된 것을 확인합니다.
<resources>
    <string name="app_name">Happy Birthday</string>
    <string name="happy_birthday_text">Happy Birthday Sam!</string>
</resources>

strings.xml 파일에는 사용자가 앱에서 보는 문자열 목록이 있습니다. 앱 이름도 문자열 리소스입니다. 문자열을 모두 한곳에 배치하면 앱의 모든 텍스트를 더 쉽게 번역하고 앱의 다양한 부분에서 문자열을 더 쉽게 재사용할 수 있습니다.

  1. 동일한 단계를 따라 서명 Text 컴포저블의 텍스트를 추출합니다. 이번에는 Resource name 필드에 signature_text를 입력합니다.

완성된 파일은 다음 코드 스니펫과 같이 표시됩니다.

<resources>
    <string name="app_name">Happy Birthday</string>
    <string name="happy_birthday_text">Happy Birthday Sam!</string>
    <string name="signature_text">From Emma</string>
</resources>
  1. stringResource() 및 추출된 문자열을 사용하도록 BirthdayCardPreview()를 업데이트합니다.
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
    HappyBirthdayTheme {
        GreetingImage(
            message = stringResource(R.string.happy_birthday_text),
            from = stringResource(R.string.signature_text)
        )
    }
}
  1. 앱을 다시 실행하여 여전히 작동하는지 확인합니다.

8. 도전과제 해 보기

이미지를 앱에 추가했습니다. 다음은 도전과제입니다.

  1. 화면 중앙에 정렬되도록 서명 텍스트의 구성 가능한 함수를 정렬합니다.

앱이 다음과 같이 표시됩니다.

b681900fe13e5598.png

다음은 참조용으로 제공된 GreetingText() 함수의 솔루션 코드입니다.

@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Column(
        verticalArrangement = Arrangement.Center,
        modifier = modifier
    ) {
        Text(
            text = message,
            fontSize = 100.sp,
            lineHeight = 116.sp,
            textAlign = TextAlign.Center
        )
        Text(
            text = from,
            fontSize = 36.sp,
            modifier = Modifier
                .padding(16.dp)
                .align(alignment = Alignment.CenterHorizontally)
        )
    }
}

9. 솔루션 코드 가져오기

Happy Birthday 앱의 솔루션 코드는 GitHub에 있습니다.

GitHub는 개발자가 소프트웨어 프로젝트의 코드를 관리할 수 있는 서비스로, 버전 제어 시스템인 Git을 사용하여 각 코드 버전의 변경사항을 추적합니다. Google Docs에서 문서의 버전 기록을 본 적이 있다면 수정 내용과 수정 시간을 확인할 수 있습니다. 이와 마찬가지로 프로젝트에서 코드의 버전 기록을 추적할 수 있습니다. 이는 개인적으로 또는 팀과 함께 프로젝트를 진행할 때 유용합니다.

GitHub에는 프로젝트를 보고 관리할 수 있는 웹사이트도 있습니다. 이 GitHub 링크를 통해 Happy Birthday 프로젝트 파일을 온라인으로 탐색하거나 컴퓨터에 다운로드할 수 있습니다.

완료된 Codelab의 코드를 다운로드하려면 다음 git 명령어를 사용하면 됩니다.

$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-birthday-card-app.git

또는 ZIP 파일로 저장소를 다운로드한 다음 압축을 풀고 Android 스튜디오에서 열어도 됩니다.

솔루션 코드를 보려면 GitHub에서 확인하세요.

GitHub의 브랜치

분기가 무엇인지 알아보기 전에 먼저 저장소가 무엇인지 알아보세요. 저장소는 컴퓨터에 클론(복사)하는 전체 프로젝트(디렉터리 및 파일)입니다. 브랜치는 저장소의 버전, 즉 독립적인 개발 라인입니다. 예를 들어 이 과정에서 starter 분기는 Codelab을 진행하는 데 기초로 사용한 프로젝트의 버전이 될 수 있습니다. main 또는 solution 분기는 Codelab을 마칠 때 있는 프로젝트의 버전으로, 전체 솔루션 코드가 포함되어 있습니다.

저장소에는 여러 브랜치가 포함될 수 있습니다. 즉, 저장소에는 여러 버전의 코드가 있습니다.

10. 결론

Happy Birthday 앱에 이미지를 추가하고 수정자를 사용하여 텍스트를 정렬하고 접근성 가이드라인을 준수하며 앱을 더 쉽게 다른 언어로 번역할 수 있도록 했습니다. 이렇게 Happy Birthday 앱을 만들었다는 사실이 무엇보다 중요합니다. 작업을 소셜 미디어에 공유하고 해시태그 #AndroidBasics를 사용하면 모두가 볼 수 있습니다.

요약

  • Android 스튜디오의 Resource Manager 탭을 사용하면 이미지와 기타 리소스를 추가하고 구성할 수 있습니다.
  • Image 컴포저블은 앱에 이미지를 표시하는 UI 요소입니다.
  • Image 컴포저블에는 콘텐츠 설명이 있어야 앱의 접근성이 높아집니다.
  • 생일 축하 메시지와 같이 사용자에게 표시되는 텍스트는 문자열 리소스로 추출해야 앱을 다른 언어로 쉽게 번역할 수 있습니다.

자세히 알아보기