1. 시작하기 전에
이전 Codelab에서는 RecyclerView
에 텍스트 목록을 표시하는 Affirmations 앱을 만들었습니다.
계속해서 이번 Codelab에서는 앱에 나오는 각각의 긍정적 문구에 감동적인 이미지를 추가합니다. Android 라이브러리 Material Component의 MaterialCardView
위젯을 사용하여 카드 내에서 긍정적 텍스트 및 이미지를 각각 표시합니다. 그런 다음, UI에 세련미를 입히고 더 일관되고 아름다운 사용자 환경을 만들어 앱을 완성합니다. 다음은 완성된 앱의 스크린샷입니다.
기본 요건
- 앱에 이미지 리소스를 추가할 수 있음
- XML 레이아웃을 쉽게 수정할 수 있음
RecyclerView
에 텍스트 목록을 표시하는 앱을 만들 수 있음RecyclerView
의 어댑터를 만들 수 있음
학습할 내용
RecyclerView
에 표시되는 긍정적 문구 목록에 이미지를 추가하는 방법RecyclerView
항목 레이아웃에서MaterialCardView
를 사용하는 방법- 앱이 더 세련되게 보이도록 UI에서 시각적인 변화를 주는 방법
빌드할 프로그램
RecyclerView
를 사용하여 카드 목록을 표시하는 개선된 Affirmations 앱입니다. 각 카드에는 이미지 및 긍정적인 텍스트가 포함됩니다.
필요한 항목
- Android 스튜디오 버전 4.1 이상이 설치된 컴퓨터
- 이미지 파일을 다운로드하기 위해 인터넷 연결에 액세스 가능
- 이전 Affirmations 앱 만들기 Codelab의 Affirmations 앱 (시작 코드가 제공되지 않습니다. 앱 생성은 기본 요건입니다.)
2. 목록 항목에 이미지 추가
지금까지 RecyclerView
에 긍정적인 문구의 문자열을 표시하는 어댑터인 ItemAdapter
를 만들었습니다. 이 어댑터는 기능적으로는 훌륭하게 작동하지만 시각적으로 그다지 매력적이지 않습니다. 이 작업에서는 목록 항목 레이아웃 및 어댑터 코드를 수정하여 긍정적 문구와 함께 이미지를 표시합니다.
이미지 다운로드
- 시작하려면 Android 스튜디오에서 이전 Codelab의 Affirmations 앱 프로젝트를 엽니다. 이 프로젝트가 없다면 이전 Codelab의 단계를 진행하여 프로젝트를 만듭니다. 그런 다음, 다시 여기로 돌아옵니다.
- 다음으로, 컴퓨터에 이미지 파일을 다운로드합니다. 앱의 각 긍정적 문구마다 하나씩 10개의 이미지가 있어야 합니다. 파일 이름을
image1.jpg
~image10.jpg
로 지정해야 합니다. - 컴퓨터의 이미지를 Android 스튜디오 내 프로젝트의 res > drawable 폴더(
app/src/main/res/drawable
)로 복사합니다. 이러한 리소스를 앱에 추가하면R.drawable.image1
과 같은 리소스 ID를 사용하여 코드에서 이러한 이미지에 액세스할 수 있습니다. (이미지를 찾으려면 Android 스튜디오의 코드를 다시 빌드해야 할 수도 있습니다.)
이제 앱에서 이미지를 사용할 준비가 되었습니다.
Affirmation 클래스에서 이미지 지원 추가
이 단계에서는 Affirmation
데이터 클래스에서 이미지 리소스 ID의 값을 보유하는 속성을 추가합니다. 이렇게 하면 단일 Affirmation
객체 인스턴스에 긍정적인 문구 텍스트의 리소스 ID 및 긍정적인 이미지의 리소스 ID가 포함됩니다.
model
패키지 내의Affirmation.kt
파일을 엽니다.imageResourceId
라는 또 다른Int
매개변수를 추가하여Affirmation
클래스의 생성자를 수정합니다.
리소스 주석 사용
stringResourceId
와 imageResourceId
는 모두 정숫값입니다. 문제가 없어 보이지만, 호출자가 실수로 잘못된 순서로 인수를 전달할 수 있습니다(stringResourceId
대신 imageResourceId
먼저).
이를 방지하기 위해 리소스 주석을 사용할 수 있습니다. 주석은 클래스, 메서드 또는 매개변수에 부가적인 정보를 추가하므로 유용합니다. 주석은 항상 @ 기호로 선언됩니다. 이 경우에는 @StringRes
주석을 문자열 리소스 ID 속성에 추가하고 @DrawableRes
주석을 드로어블 리소스 ID 속성에 추가합니다. 그러면 잘못된 유형의 리소스 ID를 제공하는 경우 경고가 표시됩니다.
@StringRes
주석을stringResourceId
에 추가합니다.@DrawableRes
주석을imageResourceId
에 추가합니다.- 패키지 선언 뒤 파일의 상단에
androidx.annotation.DrawableRes
및androidx.annotation.StringRes
가져오기를 추가했는지 확인합니다.
Affirmation.kt
package com.example.affirmations.model
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
data class Affirmation(
@StringRes val stringResourceId: Int,
@DrawableRes val imageResourceId: Int
)
이미지로 긍정적 문구 목록 초기화
Affirmation
클래스의 생성자를 변경했으므로 이제 Datasource
클래스를 업데이트해야 합니다. 초기화되는 각 Affirmation
객체에 이미지 리소스 ID를 전달합니다.
Datasource.kt
를 엽니다.Affirmation
을 각각 인스턴스화하는 것에 관한 오류가 표시됩니다.- 각
Affirmation
마다 이미지의 리소스 ID를 인수로 추가합니다(예:R.drawable.image1
).
Datasource.kt
package com.example.affirmations.data
import com.example.affirmations.R
import com.example.affirmations.model.Affirmation
class Datasource() {
fun loadAffirmations(): List<Affirmation> {
return listOf<Affirmation>(
Affirmation(R.string.affirmation1, R.drawable.image1),
Affirmation(R.string.affirmation2, R.drawable.image2),
Affirmation(R.string.affirmation3, R.drawable.image3),
Affirmation(R.string.affirmation4, R.drawable.image4),
Affirmation(R.string.affirmation5, R.drawable.image5),
Affirmation(R.string.affirmation6, R.drawable.image6),
Affirmation(R.string.affirmation7, R.drawable.image7),
Affirmation(R.string.affirmation8, R.drawable.image8),
Affirmation(R.string.affirmation9, R.drawable.image9),
Affirmation(R.string.affirmation10, R.drawable.image10)
)
}
}
목록 항목 레이아웃에 ImageView 추가
목록에서 각 긍정적 문구의 이미지를 표시하려면 항목 레이아웃에 ImageView
를 추가해야 합니다. 이제 2개의 뷰(TextView
및 ImageView
)가 있으므로 이러한 뷰를 ViewGroup
내의 하위 뷰로 배치해야 합니다. 뷰를 세로 열로 정렬하려면 LinearLayout
을 사용하면 됩니다. LinearLayout
은 모든 하위 뷰를 세로 또는 가로의 단일 방향으로 정렬합니다.
- res > layout > list_item.xml을 엽니다. 기존
TextView
주위에LinearLayout
을 추가하고orientation
속성을vertical
로 설정합니다. xmlns schema
선언 줄을TextView
요소에서LinearLayout
요소로 이동하여 오류를 제거합니다.
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
LinearLayout,
내에서TextView,
앞에 리소스 ID가item_image
인ImageView
를 추가합니다.ImageView
의 너비를match_parent
로 높이를194dp
로 설정합니다. 화면 크기에 따라 이 값은 언제든지 화면에 몇 개의 카드를 표시합니다.scaleType
을centerCrop.
으로 설정합니다.- 이미지가 장식용으로 사용되므로
importantForAccessibility
속성을no
로 설정합니다.
<ImageView
android:layout_width="match_parent"
android:layout_height="194dp"
android:id="@+id/item_image"
android:importantForAccessibility="no"
android:scaleType="centerCrop" />
ItemAdapter를 업데이트하여 이미지 설정
adapter/ItemAdapter.kt
를 엽니다(app > java > adapter > ItemAdapter).ItemViewHolder
클래스로 이동합니다.ItemViewHolder
인스턴스는 목록 항목 레이아웃에서TextView
에 대한 참조 및ImageView
에 대한 참조를 보유해야 합니다. 다음과 같이 변경합니다.
textView
속성의 초기화 아래에 imageView
라는 val
을 추가합니다. findViewById()
를 사용하여 ID가 item_image
인 ImageView
에 대한 참조를 찾아 이를 imageView
속성에 할당합니다.
ItemAdapter.kt
class ItemViewHolder(private val view: View): RecyclerView.ViewHolder(view) {
val textView: TextView = view.findViewById(R.id.item_title)
val imageView: ImageView = view.findViewById(R.id.item_image)
}
ItemAdapter
에서onBindViewHolder()
함수를 찾습니다.- 이전에는 긍정적 문구의
stringResourceId
를ItemViewHolder
의textView
로 설정했습니다. 이제 긍정적 문구 항목의imageResourceId
를 목록 항목 뷰의ImageView
로 설정합니다.
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val item = dataset[position]
holder.textView.text = context.resources.getString(item.stringResourceId)
holder.imageView.setImageResource(item.imageResourceId)
}
- 앱을 실행하고 긍정적 문구 목록을 스크롤합니다.
앱이 이미지로 인해 훨씬 더 매력적으로 보입니다! 그렇지만 여전히 앱 UI 개선의 여지는 있습니다. 다음 섹션에서는 앱을 약간 조정하여 UI를 개선합니다.
3. UI 개선
지금까지 긍정적인 문구 문자열 및 이미지 목록으로 구성된 기능적인 앱을 빌드했습니다. 이 섹션에서는 코드 및 XML의 사소한 변경으로 앱이 더욱 세련되게 보이게 하는 방법을 알아보겠습니다.
패딩 추가
먼저, 목록의 항목 사이에 공백을 추가합니다.
item_list.xml
을 엽니다(app > res > layout > item_list.xml). 그리고16dp
패딩을 기존LinearLayout
에 추가합니다.
list_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
16dp
패딩을item_title
TextView
에 추가합니다.TextView
에서textAppearance
속성을?attr/textAppearanceHeadline6
으로 설정합니다.textAppearance
는 텍스트별 스타일을 정의할 수 있는 속성입니다. 그 외에 미리 정의된 텍스트 모양 값의 경우 이 일반적인 테마 속성에 관한 블로그 게시물의 TextAppearances 섹션을 참고하세요.
<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:textAppearance="?attr/textAppearanceHeadline6" />
- 앱을 실행합니다. 이 목록이 더 좋아 보이나요?
카드 사용
이미지가 위 또는 아래에 있는 긍정적 텍스트 중 어디에 속하는지 구별하기가 여전히 어렵습니다. Card 뷰를 사용하여 이 문제를 해결할 수 있습니다. Card 뷰를 사용하면 컨테이너의 스타일을 일관되게 유지하면서 간편하게 뷰 그룹을 포함할 수 있습니다. 카드 사용에 관한 자세한 Material Design 안내는 카드에 관한 이 가이드를 참고하세요.
- 기존
LinearLayout
주위에MaterialCardView
를 추가합니다. - 다시 한번 스키마 선언을
LinearLayout
에서MaterialCardView
로 이동합니다. MaterialCardView
의layout_width
를match_parent
로,layout_height
를wrap_content
로 설정합니다.8dp
의layout_margin
을 추가합니다.- 공백이 너무 많지 않도록
LinearLayout
에서 패딩을 삭제합니다. - 이제 앱을 다시 실행합니다.
MaterialCardView
를 사용하여 각 긍정적 문구를 더 명확하게 구별할 수 있나요?
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/item_image"
android:layout_width="match_parent"
android:layout_height="194dp"
android:importantForAccessibility="no"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:textAppearance="?attr/textAppearanceHeadline6" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
앱 테마 색상 변경
기본 앱 테마 색상은 선택 가능한 다른 몇 가지 옵션만큼 차분한 느낌을 주지 않을 수 있습니다. 이 작업에서는 앱 테마 색상을 파란색으로 변경합니다. 그런 다음, 자신의 아이디어를 활용하여 다시 변경할 수 있습니다!
이 링크의 Material Design 색상 팔레트에서 미리 정의된 파란색 셰이드를 찾을 수 있습니다.
이 Codelab에서는 다음과 같은 Material Design 팔레트의 색상을 사용합니다.
- blue_200:
#FF90CAF9
- blue_500:
#FF2196F3
- blue_700:
#FF1976D2
색상 리소스 추가
앱 내에서 사용되는 색상을 중앙 위치인 colors.xml
파일에 정의합니다.
colors.xml
을 엽니다(res > values > colors.xml).- 정의된 파란색 색상에 관한 파일에 아래와 같이 새 색상 리소스를 추가합니다.
<color name="blue_200">#FF90CAF9</color>
<color name="blue_500">#FF2196F3</color>
<color name="blue_700">#FF1976D2</color>
테마 색상 변경
이제 새 색상 리소스가 있으므로 테마에서 사용할 수 있습니다.
themes.xml
을 엽니다(res > values > themes > themes.xml).<!-- Primary brand color. -->
섹션을 찾습니다.colorPrimary
를 추가하거나 변경하여@color/blue_500
을 사용합니다.colorPrimaryVariant
를 추가하거나 변경하여@color/blue_700
을 사용합니다.
<item name="colorPrimary">@color/blue_500</item>
<item name="colorPrimaryVariant">@color/blue_700</item>
- 앱을 실행합니다. 앱 바 색상이 파란색으로 변경된 것을 확인할 수 있습니다.
어두운 테마 색상 업데이트
앱의 어두운 테마에는 채도가 더 낮은 색상을 선택하는 것이 좋습니다.
- 어두운 테마
themes.xml
파일을 엽니다(themes > themes.xml (night)). - 다음과 같이
colorPrimary
및colorPrimaryVariant
테마 속성을 추가하거나 변경합니다.
<item name="colorPrimary">@color/blue_200</item>
<item name="colorPrimaryVariant">@color/blue_500</item>
- 앱을 실행합니다.
- 기기의 설정에서 어두운 테마를 사용 설정합니다.
- 앱이 어두운 테마로 전환됩니다. 아래 스크린샷과 같이 표시됩니다.
- 이 시점에서
colors.xml
파일에서 사용되지 않는 색상(예: 기본 앱 테마에서 사용된 자주색 색상 리소스)을 삭제할 수도 있습니다.
앱 아이콘 변경
마지막 단계로, 앱 아이콘을 업데이트합니다.
- 앱 아이콘 파일
ic_launcher_foreground.xml
및ic_launcher_background.xml
을 다운로드합니다. 브라우저에서 파일을 다운로드하지 않고 표시하는 경우 파일 > 페이지를 다른 이름으로 저장을 선택하여 파일을 컴퓨터에 저장합니다. - Android 스튜디오에서
drawable/ic_launcher_background.xml
및drawable-v24/ic_launcher_foreground.xml
파일을 삭제합니다. 이 두 파일은 이전의 앱 아이콘 파일이기 때문입니다. Safe delete (with usage search) 체크박스를 선택 해제할 수 있습니다. - 그런 다음, res > drawable 폴더를 마우스 오른쪽 버튼으로 클릭하고 New > Image Asset을 선택합니다.
- Configure Image Asset 창에서 Foreground layer가 선택되어 있는지 확인합니다.
- 아래쪽에서 Path 라벨을 찾습니다.
- Path 텍스트 상자 내의 폴더 아이콘을 클릭합니다.
- 컴퓨터에 다운로드한
ic_launcher_foreground.xml
파일을 찾아서 엽니다.
- Background Layer 탭으로 전환합니다.
- Path 텍스트 상자 내의 Browse 아이콘을 클릭합니다.
- 컴퓨터의
ic_launcher_background.xml
파일을 찾아서 엽니다. 다른 변경은 필요하지 않습니다. - Next를 클릭합니다.
- Confirm Icon Path 대화상자에서 Finish를 클릭합니다. 기존 아이콘을 덮어써도 괜찮습니다.
- 권장사항에 따라 새 벡터 드로어블
ic_launcher_foreground.xml
과ic_launcher_background.xml
을drawable-anydpi-v26
이라는 새 리소스 디렉터리로 이동할 수 있습니다. 적응형 아이콘은 API 26에서 도입되었으므로 이러한 리소스는 API 26 이상을 실행하는 기기에서만 사용됩니다(어떤 dpi든 관계없음). drawable-v24
디렉터리에 아무것도 남아 있지 않다면 이 디렉터리를 삭제합니다.- 앱을 실행하고 앱 검색 창에서 새로운 멋진 앱 아이콘을 확인합니다.
- 마지막 단계로, 코드가 더 깔끔하게 유지되고 스타일 가이드라인을 준수하도록 프로젝트에서 Kotlin 및 XML 파일의 형식을 다시 지정합니다.
축하합니다. 감동적인 Affirmations 앱을 만들었습니다.
Android 앱에서 데이터 목록을 표시하는 방법에 관한 이 지식을 사용하여 다음에 무엇을 빌드할 수 있을까요?
4. 솔루션 코드
Affirmations 앱의 솔루션 코드는 아래의 GitHub 저장소에 있습니다.
- 프로젝트에 제공된 GitHub 저장소 페이지로 이동합니다.
- 브랜치 이름이 Codelab에 지정된 브랜치 이름과 일치하는지 확인합니다. 예를 들어 다음 스크린샷에서 브랜치 이름은 main입니다.
- 프로젝트의 GitHub 페이지에서 Code 버튼을 클릭하여 팝업을 엽니다.
- 팝업에서 Download ZIP 버튼을 클릭하여 컴퓨터에 프로젝트를 저장합니다. 다운로드가 완료될 때까지 기다립니다.
- 컴퓨터에서 파일을 찾습니다(예: Downloads 폴더).
- ZIP 파일을 더블클릭하여 압축을 해제합니다. 프로젝트 파일이 포함된 새 폴더가 만들어집니다.
Android 스튜디오에서 프로젝트 열기
- Android 스튜디오를 시작합니다.
- Welcome to Android Studio 창에서 Open을 클릭합니다.
참고: Android 스튜디오가 이미 열려 있는 경우 File > Open 메뉴 옵션을 대신 선택합니다.
- 파일 브라우저에서 압축 해제된 프로젝트 폴더가 있는 위치로 이동합니다(예: Downloads 폴더).
- 프로젝트 폴더를 더블클릭합니다.
- Android 스튜디오가 프로젝트를 열 때까지 기다립니다.
- Run 버튼 을 클릭하여 앱을 빌드하고 실행합니다. 예상대로 작동하는지 확인합니다.
5. 요약
RecyclerView
에 추가 콘텐츠를 표시하려면 기본 데이터 모델 클래스와 데이터 소스를 수정합니다. 그런 다음, 목록 항목 레이아웃 및 어댑터를 업데이트하여 데이터를 뷰에 설정합니다.- 리소스 주석을 사용하여 올바른 유형의 리소스 ID가 클래스 생성자에 전달되도록 합니다.
- Android 라이브러리의 Material 구성요소를 사용하여 더 간편하게 앱이 권장 Material Design 가이드라인을 준수하도록 합니다.
MaterialCardView
를 사용하여 Material 카드에 콘텐츠를 표시합니다.- 색상 및 간격의 측면에서 앱을 시각적으로 조금만 수정하면 앱이 더욱 세련되고 일관되게 보이도록 할 수 있습니다.
6. 자세히 알아보기
RecyclerView
로 목록 만들기RecyclerView
클래스RecyclerView
어댑터RecyclerView
ViewHolder- Material Design의 목록
- Material Design의 카드
MaterialCardView
- Android의 Material 구성요소 시작하기
- Android 스타일 지정: 테마와 스타일 비교
- 적응형 아이콘
7. 작업에 도전해보기
이 Codelab 시리즈에서는 RecyclerView
와 함께 LinearLayoutManager
를 사용하는 방법을 알아보았습니다. RecyclerView
는 다양한 LayoutManager를 사용하여 데이터를 서로 다르게 배치할 수 있습니다.
RecyclerView
의layoutManager
속성을GridLayoutManager
로 변경합니다.- 열 개수를 3으로 변경합니다.
- 어댑터 레이아웃을 변경하여 데이터를 그리드로 시각화합니다.