이 Codelab은 Android Kotlin 기초 교육 과정의 일부입니다. Codelab을 순서대로 진행한다면 이 과정을 통해 최대한의 가치를 얻을 수 있을 것입니다. 모든 과정 Codelab은 Android Kotlin 기초 Codelab 방문 페이지에 나열되어 있습니다.
소개
대부분의 사용자가 이용할 수 있도록 앱을 만들면 즐거움을 위해 개발하든 비즈니스 용도로 개발하든 관계없습니다. 이를 위한 여러 측정기준이 마련되어 있습니다.
- RTL 언어 지원 유럽과 기타 여러 언어를 왼쪽에서 오른쪽으로 읽으며 이러한 언어를 기반으로 하는 앱은 일반적으로 이러한 언어에 적합하도록 설계되었습니다. 아랍어와 같이 화자가 많은 오른쪽에서 왼쪽으로 읽는 언어도 많습니다. 앱의 오른쪽에서 왼쪽 (RTL) 언어로 작업하여 잠재고객을 늘리세요.
- 접근성을 검사합니다. 다른 사람이 앱을 어떻게 경험해 낼지 추측하는 것은 위험 가능성이 있습니다. 접근성 검사기 앱은 추측을 없애고 완성한 앱을 분석하여 접근성을 개선할 수 있는 위치를 파악합니다.
- 콘텐츠 설명이 있는 음성 안내 지원의 디자인을 제공합니다. 시각 장애는 생각보다 훨씬 흔하며, 시각장애인뿐 아니라 많은 사용자가 스크린 리더를 사용합니다. 콘텐츠 설명은 스크린 리더에서 사용자가 화면 요소와 상호작용할 때 말하는 구문입니다.
- 야간 모드 지원. 시각장애가 있는 많은 사용자는 화면 색상을 변경하면 대비가 높아지고 앱에서 시각적으로 잘 작동합니다. Android는 야간 모드를 간단하게 지원할 수 있으며 항상 야간 모드를 지원하여 사용자에게 기본 화면 색상의 대안을 제공해야 합니다.
이 Codelab에서는 이러한 각 옵션을 살펴보고 GDG Finder 앱에 대한 지원을 추가합니다.
Android 앱에서 칩을 사용하는 방법도 알아봅니다. 칩을 사용하면 앱의 접근성을 유지하면서 더욱 흥미로운 앱을 만들 수 있습니다.
기본 요건
다음을 잘 알고 있어야 합니다.
- 활동과 프래그먼트가 있는 앱을 만들고 데이터를 전달하는 프래그먼트 간에 이동하는 방법
- 뷰와 뷰 그룹을 사용하여 사용자 인터페이스, 특히 RecyclerView를 배치합니다.
ViewModel
를 포함한 아키텍처 구성요소를 권장 아키텍처와 함께 사용하여 잘 구조화되고 효율적인 앱을 만드는 방법- 데이터 결합, 코루틴, 마우스 클릭 처리 방법
- Room 데이터베이스를 사용하여 인터넷에 연결하고 데이터를 로컬에 캐시하는 방법
- 뷰 속성을 설정하는 방법과 XML 리소스 파일에서 리소스를 추출하고 리소스를 사용하는 방법을 알아야 합니다.
- 스타일 및 테마를 사용하여 앱 디자인을 맞춤설정하는 방법
- 머티리얼 구성요소, 측정기준 리소스, 맞춤 색상 지정 사용 방법
학습할 내용
- 최대한 많은 사용자가 앱을 사용할 수 있도록 하는 방법
- 앱이 RTL (오른쪽에서 왼쪽) 언어로 작동하도록 하는 방법
- 앱의 접근성을 평가하는 방법
- 콘텐츠 설명을 사용하여 스크린 리더에서 앱이 더 잘 작동하도록 만드는 방법
- 칩 사용 방법
- 앱이 어두운 모드에서 작동하도록 하는 방법
실습할 내용
- 특정 앱을 평가하고 확장하여 RTL 언어에서 작동하도록 만들어 접근성을 개선합니다.
- 앱을 스캔하여 접근성을 개선할 수 있는 위치를 파악합니다.
- 이미지에 콘텐츠 설명을 사용합니다.
- 드로어블 사용 방법을 알아봅니다.
- 앱에 야간 모드 사용 기능을 추가합니다.
GDG-finder 앱 시작 과정에서는 지금까지 학습한 모든 내용을 바탕으로 합니다.
앱이 ConstraintLayout
를 사용하여 화면 3개를 배치합니다. 두 화면은 Android에서 색상과 텍스트를 탐색하는 데 사용할 수 있는 레이아웃 파일입니다.
세 번째 화면은 GDG 파인더입니다. GDG(Google Developer 그룹스)는 Android를 비롯한 Google 기술에 중점을 둔 개발자 커뮤니티입니다. 전 세계 각지의 GDG에서 모임, 컨퍼런스, 스터디 그룹, 기타 이벤트를 개최합니다.
이 앱을 개발할 때 GDG의 실제 목록에서 작업합니다. 파인더 화면은 기기 위치를 사용하여 GDG를 거리별로 정렬합니다.
거주 지역에서 GDG가 있는 경우 웹사이트를 확인하고 이벤트에 참가할 수 있습니다. GDG 이벤트는 다른 Android 개발자를 만나고 이 과정에 적합하지 않은 업계 권장사항을 배울 수 있는 좋은 방법입니다.
아래 스크린샷은 이 Codelab의 시작부터 끝부분에 앱이 어떻게 변경되는지 보여줍니다.
왼쪽에서 오른쪽 (LTR)과 오른쪽에서 왼쪽 (RTL) 언어 간의 주요 차이점은 표시된 콘텐츠의 방향입니다. UI 방향이 LTR에서 RTL로 변경되거나 그 반대로 변경되는 경우 이를 미러링이라고 합니다. 미러링은 텍스트, 텍스트 필드 아이콘, 레이아웃, 방향이 있는 아이콘 (예: 화살표)을 비롯한 대부분의 화면에 영향을 줍니다. 숫자, 시계, 전화번호, 방향이 없는 아이콘(비행기 모드, Wi-Fi), 재생 컨트롤, 대부분의 차트 및 그래프와 같은 기타 항목은 미러링되지 않습니다.
RTL 텍스트 방향을 사용하는 언어는 전 세계 10억 명이 넘는 사용자가 사용합니다. 전 세계 Android 개발자는 전 세계의 GDG Finder 앱에서 RTL 언어를 지원해야 합니다.
1단계: RTL 지원 추가하기
이 단계에서는 GDG Finder 앱을 RTL 언어와 함께 사용합니다.
- 이 Codelab의 시작 앱인 GDGFinderMaterial 앱을 다운로드하여 실행하거나 이전 Codelab의 최종 코드에서 계속합니다.
- Android 매니페스트를 엽니다.
<application>
섹션에서 다음 코드를 추가하여 앱이 RTL을 지원하도록 지정합니다.
<application
...
android:supportsRtl="true">
- Design 탭에서 activity_main.xml을 엽니다.
- Locale for Preview 드롭다운 메뉴에서 Preview 오른쪽에서 왼쪽으로를 선택합니다. (이 메뉴를 찾을 수 없다면 창을 펼치거나 Attributes 창을 닫아 탐색하세요.)
- 미리보기에서 '& Findt&GDG' 헤더가 오른쪽으로 이동되었고 나머지 화면은 그대로 유지됩니다. 전반적으로 이 화면은 통과 가능합니다. 그러나 이제 텍스트 뷰의 정렬이 오른쪽이 아닌 왼쪽으로 정렬되기 때문에 잘못 정렬되었습니다.
- 기기에서 이 작업을 실행하려면 기기 또는 에뮬레이터 Settings의 Developer Options에서 Force RTL layout을 선택합니다. 개발자 옵션을 사용 설정해야 하는 경우 빌드 번호를 찾아 개발자임을 나타내는 토스트 메시지가 표시될 때까지 클릭합니다. 기기 및 Android 시스템의 버전에 따라 다릅니다.)
- 앱을 실행하고 기본 화면이 Preview와 같은지 기기에서 확인합니다. FAB가 왼쪽으로 전환되고 오른쪽에 햄버거 메뉴가 표시됩니다.
- 앱에서 탐색 창을 열고 검색 화면으로 이동합니다. 아래와 같이 아이콘이 여전히 왼쪽에 있으며 텍스트가 표시되지 않습니다. 텍스트가 아이콘 왼쪽에 있는 것으로 확인됩니다. 이는 코드가 뷰 속성 및 레이아웃 제약 조건에서 왼쪽/오른쪽 화면 참조를 사용하기 때문입니다.
2단계: 왼쪽과 오른쪽 대신 시작 및 끝 사용
(화면을 가리키면) 화면의 'QU&QUT;' 및 '오른쪽'은 변경되지 않습니다. 예를 들어 layout_constraintLeft_toLeftOf
는 항상 요소의 왼쪽을 화면 왼쪽으로 제한합니다. 앱의 스크린샷에는 RTL 언어에서 텍스트가 화면 밖에 있습니다.
이 문제를 해결하려면 "left" 및quot;오른쪽 대신 Start
및 End
용어를 사용하세요. 이 용어는 텍스트 및 시작의 끝을 현재 언어로 된 텍스트 방향에 맞게 설정하여 여백과 레이아웃이 화면의 올바른 영역에 위치하도록 합니다.
Open
list_item.xmlLeft
와Right
에 대한 참조를Start
및End
에 대한 참조로 바꿉니다.
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintStart_toEndOf="@+id/gdg_image"
app:layout_constraintEnd_toEndOf="parent"
ImageView
의layout_marginLeft
를layout_marginStart
로 바꿉니다. 이렇게 하면 여백이 올바른 위치로 이동되어 아이콘이 화면 가장자리에서 멀어집니다.
<ImageView
android:layout_marginStart="
?
fragment_gdg_list.xml
를 엽니다. 미리보기 창에서 GDG 목록을 확인합니다. 아이콘이 미러링되기 때문에 아이콘이 여전히 잘못된 방향을 가리키고 있습니다. 아이콘이 미러링되지 않으면 오른쪽에서 왼쪽 미리보기가 계속 표시되는지 확인하세요. 머티리얼 디자인 가이드라인에 따라 아이콘이 미러링되면 안 됩니다.- res/drawable/ic_gdg.xml을 엽니다.
- XML 코드의 첫 번째 줄에서
android:autoMirrored="true"
를 찾아 삭제하여 미러링을 사용 중지합니다. - 미리보기를 확인하거나 앱을 다시 실행하고 검색 GDG 화면을 엽니다. 이제 레이아웃이 수정되었습니다.
3단계: Android 스튜디오가 자동으로 작업하도록 하기
이전 연습에서는 RTL 언어를 지원하는 첫 번째 단계를 완료했습니다. 다행히 Android 스튜디오를 통해 앱을 검사하고 다양한 기본사항을 설정할 수 있습니다.
- list_item.xml의
TextView
에서 스캐너를 찾을 수 있도록layout_marginStart
를 다시layout_marginLeft
로 변경합니다.
<TextView
android:layout_marginLeft="@dimen/spacing_normal"
- Android 스튜디오에서 Refactor > Add RTL support when available을 선택하고 매니페스트 업데이트 체크박스를 선택하고 레이아웃 파일에서 시작 및 종료 속성을 사용합니다.
- Refactoring Preview 창에서 app 폴더를 찾아 모든 세부정보가 열릴 때까지 펼칩니다.
- 앱 폴더에서는 방금 변경한
layout_marginLeft
가 리팩터링할 코드로 나열됩니다.
- 미리보기에는 시스템 및 라이브러리 파일도 나열됩니다. layout 및 lout-watch-v20 및 app에 포함되지 않은 다른 폴더를 마우스 오른쪽 버튼으로 클릭하고 컨텍스트 메뉴에서 Exclude를 선택합니다.
- 지금 리팩터링하세요. 시스템 파일에 대한 팝업이 표시되는 경우 앱 코드에 포함되지 않은 모든 폴더를 제외했는지 확인하세요.
layout_marginLeft
가layout_marginStart
로 다시 변경되었습니다.
3단계: 언어 폴더 살펴보기
지금까지 앱에 사용된 기본 언어의 방향을 변경했습니다. 프로덕션 앱의 경우 번역사에게 strings.xml 파일을 전송하여 새 언어로 번역하도록 합니다. 이 Codelab에서는 앱이 스페인어로 strings.xml 파일을 제공합니다. Google 번역을 사용하여 번역을 생성했으므로 번역이 완벽하지 않습니다.
- Android 스튜디오에서 프로젝트 뷰를 Project Files로 전환합니다.
- res 폴더를 펼치고 res/values 및 res/values-es에 대한 폴더를 확인합니다. 폴더 이름에 '"는 스페인어의 언어 코드입니다. values-"language code" 폴더에는 지원되는 각 언어에 대한 값이 포함되어 있습니다. 확장자가 없는 values 폴더에는 달리 적용되는 기본 리소스가 포함되어 있습니다.
- values-es에서 strings.xml을 열고 모든 문자열이 스페인어로 표시됩니다.
- Android 스튜디오의 Design 탭에서
activity_main.xml
을 엽니다. - 현지화 대상 드롭다운에서 스페인어를 선택합니다. 이제 텍스트가 스페인어로 표시됩니다.
- [선택사항] RTL 언어에 능숙한 경우 해당 언어로 values 폴더와 strings.xml을 만든 후 기기에 어떻게 표시되는지 테스트합니다.
- [선택사항] 기기의 언어 설정을 변경하고 앱을 실행합니다. 실행취소하기가 어려울 수 있으므로 기기를 읽지 않은 언어로 변경하지 마세요.
이전 작업에서는 앱을 수동으로 변경한 후 Android 스튜디오를 사용하여 추가로 RTL을 개선했습니다.
접근성 검사기 앱은 앱의 접근성을 높이는 데 가장 적합합니다. 대상 기기에서 앱을 검사하여 터치 영역을 크게 만들고 대비를 늘리고 앱의 접근성을 높이기 위한 이미지 설명을 제공하는 등의 개선을 제안합니다. 접근성 검사기는 Google에서 제조했으며 Play 스토어에서 설치할 수 있습니다.
1단계: 접근성 검사기 설치 및 실행하기
- Play 스토어를 열고 필요한 경우 로그인합니다. 실제 기기나 에뮬레이터에서 진행할 수 있습니다. 이 Codelab에서는 에뮬레이터를 사용합니다.
- Play 스토어에서 Google LLC의 접근성 검사기를 검색합니다. 검사에 많은 권한이 필요하므로 올바른 앱을 Google에서 발급받았는지 확인하세요.
- 에뮬레이터에 스캐너를 설치합니다.
- 설치가 완료되면 열기를 클릭합니다.
- 시작하기를 클릭합니다.
- 설정에서 접근성 검사기 설정을 시작하려면 확인을 클릭합니다.
- 접근성 검사기를 클릭하여 기기의 접근성 설정으로 이동합니다.
- 서비스 사용을 클릭하여 사용 설정합니다.
- 화면에 표시된 안내에 따라 모든 권한을 부여합니다.
- 그런 다음 확인을 클릭하고 홈 화면으로 돌아갑니다. 화면의 어딘가에 체크표시가 있는 파란색 버튼이 표시될 수 있습니다. 이 버튼을 클릭하면 포그라운드에서 앱 테스트가 트리거됩니다. 드래그하여 버튼 위치를 변경할 수 있습니다. 이 버튼은 모든 앱 상단에 유지되므로 언제든지 테스트를 트리거할 수 있습니다.
- 앱을 열거나 실행합니다.
- 파란색 버튼을 클릭하고 추가 보안 경고 및 권한을 수락합니다.
접근성 검사기 아이콘을 처음 클릭하면 앱이 화면에 표시된 모든 항목을 표시하기 위한 권한을 요청합니다. 너무 무서운 권한이죠.
이렇게 권한을 부여하면 앱이 이메일을 읽거나 은행 계좌 정보를 가져올 수 있으므로 이런 권한을 부여할 필요가 거의 없습니다. 그러나 접근성 검사기가 작업을 하려면 사용자가 하는 것처럼 앱을 검사해야 하는데, 이 권한이 필요한 이유입니다.
- 파란색 버튼을 클릭하고 분석이 완료될 때까지 기다립니다. 제목과 FAB가 빨간색으로 박혀 있는 아래 스크린샷과 같이 표시됩니다. 이 화면의 접근성 개선을 위한 제안사항 두 가지를 나타냅니다.
- GDG 파인더 주변 상자를 클릭합니다. 그러면 이미지 대비 문제가 발생한 것을 나타내는 추가 정보가 포함된 창이 열립니다.
- 이미지 대비 정보를 펼치면 도구가 해결 방법을 제안합니다.
- 오른쪽 화살표를 클릭하여 다음 항목에 관한 정보를 확인합니다.
- 앱에서 신청하기 화면으로 이동한 다음 접근성 검사기 앱으로 스캔합니다. 그러면 왼쪽에 표시된 것처럼 몇 가지 제안을 확인할 수 있습니다. 12: 정확하게 말하면 공정성을 위해 이 중 일부는 유사한 항목의 중복 항목입니다.
- 오른쪽 스크린샷에서처럼 아래에 있는 툴바에서 '"stack"
아이콘을 클릭하여 모든 추천 단어 목록을 볼 수 있습니다. 이 Codelab에서는 이러한 문제를 모두 해결합니다.
Google에서 제공하는 앱 모음인 Android 접근성 도구 모음에는 앱의 접근성을 높이는 데 도움이 되는 도구가 포함되어 있습니다. 여기에는 음성 안내 지원과 같은 도구가 포함됩니다. 음성 안내 지원은 소리, 햅틱 및 음성 피드백을 제공하는 스크린 리더로, 사용자가 눈을 사용하지 않고 기기에서 콘텐츠를 탐색하고 사용할 수 있도록 합니다.
그 결과, 음성 안내 지원 기능은 시각장애인뿐 아니라 일종의 시각 장애가 있는 사용자들도 많이 사용하고 있습니다. 아니면 그냥 눈을 떼고 싶어 하는 사람들도 있습니다!
접근성은 누구나 사용할 수 있습니다. 이 작업에서는 음성 안내 지원을 사용해 보고 앱이 원활하게 작동하도록 업데이트합니다.
1단계: 접근성 도구 모음 설치 및 실행하기
음성 안내 지원은 많은 실제 기기에 사전 설치되어 있지만, 에뮬레이터에는 설치해야 합니다.
- Play 스토어를 엽니다.
- 접근성 도구 모음을 찾습니다. Google에서 제공하는 올바른 앱인지 확인하세요.
- 설치되어 있지 않으면 접근성 도구 모음을 설치합니다.
- 기기에서 음성 안내 지원을 사용 설정하려면 설정 및 접근성으로 이동하고 서비스 사용을 선택하여 음성 안내 지원을 사용 설정합니다. 접근성 스캐너와 마찬가지로 음성 안내 지원에서 화면의 콘텐츠를 읽으려면 권한이 필요합니다. 권한 요청을 수락하면 음성 안내 지원에서 음성 안내 지원 기능을 효과적으로 사용하는 방법을 알려주는 튜토리얼 목록을 제공합니다.
- 완료한 후 음성 안내 지원을 다시 끄는 방법을 알아보려면 다른 이유 없이 여기서 잠시 멈추고 가이드를 진행하세요.
- 튜토리얼을 종료하려면 뒤로 버튼을 클릭하여 선택한 다음 화면의 아무 곳이나 두 번 탭합니다.
- 음성 안내 지원과 함께 GDG 파인더 앱을 사용해 보세요. 음성 안내 지원에서 화면 또는 컨트롤에 관한 유용한 정보를 제공하지 않는 위치를 확인합니다. 이 문제는 다음 연습에서 해결합니다.
2단계: 콘텐츠 설명 추가
콘텐츠 설명어는 뷰의 의미를 설명하는 설명 라벨입니다. 대부분의 보기는 콘텐츠 설명을 포함해야 합니다.
- GDG Finder 앱이 실행되고 Talback이 사용 설정된 상태에서 GDG 실행 요청 화면으로 이동합니다.
- 기본 이미지를 탭해도 아무 일도 일어나지 않습니다.
- add_gdg_fragment.xml을 엽니다.
ImageView
에서 아래와 같이 콘텐츠 설명어 속성을 추가합니다.stage_image_description
문자열은 strings.xml에서 제공됩니다.
android:contentDescription="@string/stage_image_description"
- 앱을 실행합니다.
- Apply to run GDG(GDG 실행 요청)로 이동하여 이미지를 클릭합니다. 이제 이미지에 관한 간단한 설명을 들을 수 있습니다.
- [선택사항] 이 앱의 다른 이미지에 대한 콘텐츠 설명을 추가합니다. 프로덕션 앱에는 모든 이미지에 콘텐츠 설명이 있어야 합니다.
3단계: 수정 가능한 텍스트 필드에 힌트 추가
EditText
와 같은 수정 가능한 요소의 경우 XML에 android:hint
을 사용하면 사용자가 입력할 내용을 파악할 수 있습니다. 힌트는 입력란의 기본 텍스트이므로 항상 UI에 표시됩니다.
- add_gdg_fragment.xml에 계속 있습니다.
- 아래의 코드를 안내에 따라 콘텐츠 설명과 힌트를 추가하세요.
textViewIntro
에 추가:
android:contentDescription="@string/add_gdg"
편집 텍스트에 각각 추가합니다.
android:hint="@string/your_name_label"
android:hint="@string/email_label"
android:hint="@string/city_label"
android:hint="@string/country_label"
android:hint="@string/region_label"
labelTextWhy
에 콘텐츠 설명을 추가합니다.
android:contentDescription="@string/motivation"
EditTextWhy
에 힌트를 추가합니다. 편집 상자에 라벨을 지정하면 라벨에 콘텐츠 설명과 상자에 힌트를 추가할 수 있습니다.
android:hint="@string/enter_motivation"
- 제출 버튼의 콘텐츠 설명을 추가합니다. 모든 버튼에는 버튼을 누를 때 발생하는 상황에 관한 설명이 있어야 합니다.
android:contentDescription="@string/submit_button_description"
- Talback이 사용 설정된 상태에서 앱을 실행하고 GDG 실행을 위한 양식을 작성합니다.
4단계: 콘텐츠 그룹 만들기
음성 안내 지원을 그룹으로 취급해야 하는 UI 컨트롤의 경우 콘텐츠 그룹화를 사용할 수 있습니다. 함께 그룹화된 관련 콘텐츠는 함께 발표됩니다. 보조 기술 사용자는 화면의 모든 정보를 찾기 위해 자주 스와이프하거나 스캔하거나 기다릴 필요가 없습니다. 이는 화면에 컨트롤이 표시되는 방식에 영향을 미치지 않습니다.
UI 구성요소를 그룹화하려면 LinearLayout
와 같은 ViewGroup
에 래핑합니다. GDG Finder 앱에서 labelTextWhy
및 editTextWhy
요소는 의미상 서로 관련이 있기 때문에 그룹화하기에 적합합니다.
- add_gdg_fragment.xml을 엽니다.
LinearLayout
를LabelTextWhy
와EditTextWhy
로 래핑하여 콘텐츠 그룹을 만듭니다. 아래 코드를 복사하여 붙여넣으세요. 이LinearLayout
에는 이미 원하는 스타일 지정이 포함되어 있습니다.button
가LinearLayout
외부에 있는지 확인합니다.
<LinearLayout android:id="@+id/contentGroup" android:layout_width="match_parent"
android:layout_height="wrap_content" android:focusable="true"
app:layout_constraintTop_toBottomOf="@id/EditTextRegion"
android:orientation="vertical" app:layout_constraintStart_toStartOf="@+id/EditTextRegion"
app:layout_constraintEnd_toEndOf="@+id/EditTextRegion"
android:layout_marginTop="16dp" app:layout_constraintBottom_toTopOf="@+id/button"
android:layout_marginBottom="8dp">
<!-- label and edit text here –>
<LinearLayout/>
- Code > Reformat code를 선택하여 모든 코드를 적절하게 들여쓰기합니다.
labelTextWhy
및editTextWhy
에서 모든 레이아웃 여백을 삭제합니다.labelTextWhy
에서layout_constraintTop_toTopOf
제약 조건을contentGroup
로 변경합니다.
app:layout_constraintTop_toTopOf="@+id/contentGroup" />
editTextWhy
에서layout_constraintBottom_toBottomOf
제약 조건을contentGroup
로 변경합니다.
app:layout_constraintBottom_toBottomOf="@+id/contentGroup"
EditTextRegion
와Button
를contentGroup
에 제한하여 오류를 제거합니다.
app:layout_constraintBottom_toTopOf="@+id/contentGroup"
LinearLayout
에 여백을 추가합니다. 원하는 경우 이 여백을 측정기준으로 추출합니다.
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
도움이 필요하다면 솔루션 코드의 add_gdg_fragment.xml
와 코드를 대조합니다.
- 앱을 실행하고 음성 안내 지원을 사용하여 GDG 실행 적용 화면을 탐색합니다.
5단계: 서비스 중인 지역 추가
현재 제출 버튼의 라벨은 확인입니다. 양식이 제출되기 전에 버튼에 1개의 라벨과 설명이 있었고 사용자가 양식을 클릭하고 제출한 후에 다른 라벨 및 콘텐츠 설명으로 동적으로 변경되면 더 좋습니다. 서비스 중인 리전을 사용하여 이 작업을 수행할 수 있습니다.
실시간 지역은 접근성 서비스에 뷰가 변경될 때 사용자에게 알려야 하는지 여부를 나타냅니다. 예를 들어 잘못된 비밀번호나 네트워크 오류를 사용자에게 알리는 것이 앱의 접근성을 개선하는 좋은 방법입니다. 이 예에서는 간단하게 하기 위해 제출 버튼이 상태를 변경할 때 사용자에게 알립니다.
- add_gdg_fragment.xml을 엽니다.
- 제공된
submit
문자열 리소스를 사용하여 버튼의 텍스트 할당을 Submit으로 변경합니다.
android:text="@string/submit"
android:accessibilityLiveRegion
속성을 설정하여 버튼에 실시간 지역을 추가합니다. 입력할 때 값에 여러 옵션이 있습니다. 변경의 중요도에 따라 사용자의 방해 여부를 선택할 수 있습니다. 접근성 서비스에서는 "assertive" 값을 사용하여 진행 중인 음성을 중단하여 이 뷰의 변경사항을 즉시 알립니다. 값을 "none"로 설정하면 변경사항이 적용되지 않습니다. 접근성 서비스에서는 변경 사항을 알리지만 차례를 기다리면서<ph type="x-smartling-void-element"><wbr /></ph>확인합니다. 값을 "폴라이트"로 설정합니다.
android:accessibilityLiveRegion="polite"
- add 패키지에서 AddGdgFragment.kt를 엽니다.
showSnackBarEvent
Observer
내에서SnackBar
표시를 완료한 후 버튼의 새로운 콘텐츠 설명과 텍스트를 설정합니다.
binding.button.contentDescription=getString(R.string.submitted)
binding.button.text=getString(R.string.done)
- 앱을 실행하고 버튼을 클릭합니다. 버튼과 글꼴이 너무 작습니다.
6단계: 버튼 스타일 지정 수정
- add_gdg_fragment.xml에서 버튼과
width
및height
을wrap_content
로 변경하여 전체 라벨이 표시되고 적절한 버튼 크기를 설정합니다.
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- 앱에서 더 나은 테마 스타일 지정을 사용하도록 버튼에서
backgroundTint
,textColor
,textSize
속성을 삭제합니다. textViewIntro
에서textColor
속성을 삭제합니다. 테마 색상이 대비가 높아야 합니다.- 앱을 실행합니다. 훨씬 더 유용한 Submit 버튼이 표시됩니다. 제출을 클릭하여 완료로 변경되는 것을 확인합니다.
칩은 속성, 텍스트, 항목 또는 작업을 나타내는 작은 요소입니다. 사용자는 정보를 입력하거나, 선택사항을 선택하거나, 콘텐츠를 필터링하거나, 작업을 트리거할 수 있습니다.
Chip
위젯은 모든 레이아웃과 그리기 로직을 포함하는 ChipDrawable
주변의 얇은 뷰 래퍼입니다. 터치, 마우스, 키보드, 접근성 탐색을 지원하는 추가 로직이 있습니다. 기본 칩과 닫기 아이콘은 별도의 하위 뷰로 간주되며 자체 탐색 동작 및 상태를 포함합니다.
칩은 드로어블을 사용합니다. Android 드로어블을 사용하면 화면에 이미지, 도형, 애니메이션을 그릴 수 있으며 고정 크기나 동적으로 크기를 조절할 수 있습니다. GDG 앱의 이미지와 같이 이미지를 드로어블로 사용할 수 있습니다. 그리고 벡터 그림을 사용하여 상상할 수 있는 모든 것을 그릴 수 있습니다. 크기 조절이 가능한 드로어블인 9-패치 드로어블도 있으며 이 Codelab에서는 다루지 않습니다. drawable/ic_gdg.xml의 GDG 로고는 또 다른 드로어블입니다.
드로어블은 뷰가 아니므로 드로어블을 ConstraintLayout
내부에 직접 배치할 수 없습니다. 따라서 ImageView
에 드로어블을 배치해야 합니다. 또한 드로어블을 사용하여 텍스트 뷰 또는 버튼의 배경을 제공할 수 있으며, 배경은 텍스트 뒤에 그려집니다.
1단계: GDG 목록에 칩 추가하기
아래 선택된 칩은 세 개의 드로어블을 사용합니다. 배경과 체크표시는 각각 드로어블입니다. 칩을 터치하면 물결 효과가 생성됩니다. 이 효과는 상태 변경에 따른 물결 효과를 표시하는 특수한 RippleDrawable로 실행됩니다.
이 작업에서는 GDG 목록에 칩을 추가하고 GDG를 선택하면 상태가 변경되도록 합니다. 이 연습에서는 칩이라는 버튼을 검색 화면 상단에 추가합니다. 각 버튼은 사용자가 선택된 지역의 결과만 수신하도록 GDG 목록을 필터링합니다. 버튼을 선택하면 버튼의 배경이 바뀌고 체크표시가 표시됩니다.
- fragment_gdg_list.xml을 엽니다.
HorizontalScrollView.
내에서singleLine
속성을true
로 설정하여 모든 칩이 가로로 스크롤 가능한 한 줄에 정렬되도록 합니다. 한 번에 한 칩만 선택할 수 있도록singleSelection
속성을true
로 설정합니다. 코드는 다음과 같습니다.
<com.google.android.material.chip.ChipGroup
android:id="@+id/region_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:singleSelection="true"
android:padding="@dimen/spacing_normal"/>
- layout 폴더에서
Chip
의 레이아웃을 정의하는 region.xml이라는 새 레이아웃 리소스 파일을 만듭니다. - r.egion.xml에서 모든 코드를 아래와 같이
Chip
하나의 레이아웃으로 바꿉니다. 이Chip
은 머티리얼 구성요소입니다. 또한app:checkedIconVisible
속성을 설정하여 체크표시를 얻을 수 있습니다. 누락된selected_highlight
색상에 관한 오류가 표시됩니다.
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.chip.Chip
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.Chip.Choice"
app:chipBackgroundColor="@color/selected_highlight"
app:checkedIconVisible="true"
tools:checked="true"/>
- 누락된
selected_highlight
색상을 만들려면selected_highlight
에 커서를 놓고 의도 메뉴를 표시하고 선택한 강조표시의 색상 리소스를 만듭니다. 기본 옵션은 괜찮습니다. OK를 클릭하면 됩니다. 이 파일은 res/color 폴더에 생성됩니다. - res/color/selected_highlight.xml을 엽니다. 이 색상 상태 목록에서
<selector>
으로 인코딩된 다양한 상태에 다양한 색상을 제공할 수 있습니다. 각 상태와 관련 색상은<item>
로 인코딩됩니다. 이러한 색상에 관한 자세한 내용은 색상 테마 설정을 참고하세요.
<selector>
내부에서 기본 색상colorOnSurface
인 항목을 상태 목록에 추가합니다. 주 목록에는 항상 모든 상태를 포함하는 것이 중요합니다. 이를 위한 한 가지 방법은 기본 색상을 사용하는 것입니다.
<item android:alpha="0.18" android:color="?attr/colorOnSurface"/>
- 기본 색상 위에
colorPrimaryVariant
색상으로item
를 추가하고 선택한 상태가true
인 경우에만 사용을 제한합니다. 상태 목록은 케이스 명세서와 같이 위에서 아래로 처리됩니다. 일치하는 주가 없는 경우 기본 상태가 적용됩니다.
<item android:color="?attr/colorPrimaryVariant"
android:state_selected="true" />
2단계: 칩 행 표시하기
GDG 앱은 GDG가 포함된 지역을 표시하는 칩 목록을 생성합니다. 칩을 선택하면 앱이 해당 지역의 GDG 결과만 표시하도록 결과를 필터링합니다.
- search 패키지에서 GdgListFragment.kt를 엽니다.
onCreateView()
의return
문 바로 위에viewModel.regionList
에 관찰자를 추가하고onChanged()
를 재정의합니다. 뷰 모델에서 제공하는 리전 목록이 변경되면 칩을 다시 만들어야 합니다. 제공된data
이null
인 경우 즉시 반환할 문을 추가합니다.
viewModel.regionList.observe(viewLifecycleOwner, object: Observer<List<String>> {
override fun onChanged(data: List<String>?) {
data ?: return
}
})
onChanged()
의 null 테스트 아래에서binding.regionList
를chipGroup
라는 새 변수에 할당하여regionList
를 캐시합니다.
val chipGroup = binding.regionList
- 아래에서는
chipGroup.context
에서 칩을 확장하는 새layoutInflator
를 만듭니다.
val inflator = LayoutInflater.from(chipGroup.context)
- 데이터 결합 오류를 제거하려면 프로젝트를 지우고 다시 빌드합니다.
인플루언서 아래에서 이제 regionList
의 각 리전에 하나씩 실제 칩을 만들 수 있습니다.
- 모든 칩을 보유할 변수
children
를 만듭니다. 전달된data
에 매핑 함수를 할당하여 각 칩을 만들고 반환합니다.
val children = data.map {}
- 지도 람다 내에서 각
regionName
마다 칩을 만들고 확장합니다. 완성된 코드는 다음과 같습니다.
val children = data.map {
val children = data.map { regionName ->
val chip = inflator.inflate(R.layout.region, chipGroup, false) as Chip
chip.text = regionName
chip.tag = regionName
// TODO: Click listener goes here.
chip
}
}
chip
를 반환하기 직전에 람다 내에서 클릭 리스너를 추가합니다.chip
를 클릭하면 상태를checked
로 설정합니다.viewModel
에서onFilterChanged()
를 호출하면 이 필터의 결과를 가져오는 이벤트 시퀀스가 트리거됩니다.
chip.setOnCheckedChangeListener { button, isChecked ->
viewModel.onFilterChanged(button.tag as String, isChecked)
}
- 람바 끝에서
chipGroup
의 현재 뷰를 모두 삭제한 후children
의 모든 칩을chipGroup
에 추가합니다. 칩을 업데이트할 수 없으므로chipGroup
의 콘텐츠를 삭제하고 다시 만들어야 합니다.
chipGroup.removeAllViews()
for (chip in children) {
chipGroup.addView(chip)
}
완성된 관찰자는 다음과 같아야 합니다.
override fun onChanged(data: List<String>?) {
data ?: return
val chipGroup = binding.regionList
val inflator = LayoutInflater.from(chipGroup.context)
val children = data.map { regionName ->
val chip = inflator.inflate(R.layout.region, chipGroup, false) as Chip
chip.text = regionName
chip.tag = regionName
chip.setOnCheckedChangeListener { button, isChecked ->
viewModel.onFilterChanged(button.tag as String, isChecked)
}
chip
}
chipGroup.removeAllViews()
for (chip in children) {
chipGroup.addView(chip)
}
}
})
- 앱을 실행하고 GDGS를 검색하여 새로운 칩을 사용하는 검색 화면을 엽니다. 각 칩을 클릭하면 그 아래에 필터 그룹이 표시됩니다.
야간 모드를 사용하면 앱이 어두운 테마로 색상을 변경할 수 있습니다(예: 야간 모드를 사용 설정하기 위해 기기 설정이 설정된 경우). 야간 모드에서는 앱이 기본 밝은 배경을 어두운 색으로 변경하고 다른 모든 화면 요소도 그에 따라 변경합니다.
1단계: 야간 모드 사용 설정하기
앱에 어두운 테마를 제공하려면 테마를 Light
테마에서 DayNight
라는 테마로 변경합니다. DayNight
테마는 모드에 따라 밝게 또는 어둡게 표시됩니다.
styles.xml,
에서AppTheme
상위 테마를Light
에서DayNight
로 변경합니다.
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
MainActivity
의onCreate()
메서드에서AppCompatDelegate.setDefaultNightMode()
를 호출하여 프로그래매틱 방식으로 어두운 테마를 사용 설정합니다.
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
- 앱을 실행하고 어두운 테마로 전환되었는지 확인합니다.
2단계: 나만의 어두운 테마 색상 팔레트 생성
어두운 테마를 맞춤설정하려면 -night
테마로 어두운 테마를 사용할 폴더를 만듭니다. 예를 들어 values-night
라는 폴더를 만들어 야간 모드에 특정 색상을 지정할 수 있습니다.
- material.io 색상 선택 도구로 이동하여 야간 테마 색상 팔레트를 만듭니다. 예를 들어 어두운 파란색에 기반할 수 있습니다.
- colors.xml 파일을 생성하고 다운로드합니다.
- Project Files 뷰로 전환하여 프로젝트의 모든 폴더를 표시하세요.
- res 폴더를 찾아 펼칩니다.
- res/values-night 리소스 폴더를 만듭니다.
- 새 colors.xml 파일을 res/values-night 리소스 폴더에 추가합니다.
- 야간 모드를 사용 설정한 상태에서 앱을 실행하면 앱에서 res/values-night에 정의된 새 색상을 사용해야 합니다. 칩은 새 보조 색상을 사용합니다.
Android 스튜디오 프로젝트: GDGFinderFinal
RTL 언어 지원
- Android 매니페스트에서
android:supportsRtl="true"
를 설정합니다. - 에뮬레이터에서 RTL을 미리 볼 수 있으며 자체 언어를 사용하여 화면 레이아웃을 확인할 수 있습니다. 기기 또는 에뮬레이터에서 Settings(설정)를 열고 Developer Options(개발자 옵션)에서 Force RTL layout을 선택합니다.
Left
및Right
에 대한 참조를Start
및End
에 대한 참조로 대체합니다.android:autoMirrored="true"
를 삭제하여 드로어블의 미러링을 사용 중지합니다.- Refactor > Add RTL support if needed를 선택하여 Android 스튜디오가 자동으로 작동하도록 합니다.
- values-"language code" 폴더를 사용하여 언어별 리소스를 저장하세요.
접근성 검색
- Play 스토어에서 Google LLC의 접근성 검사기를 다운로드하여 실행하여 화면 요소를 스캔하고 개선합니다.
콘텐츠 설명이 있는 음성 안내 지원 디자인
- 음성 안내 지원이 포함된 Google의 Android 접근성 도구 모음을 설치합니다.
- 모든 UI 요소에 콘텐츠 설명을 추가합니다. 예를 들면 다음과 같습니다.
android:contentDescription="@string/stage_image_description"
EditText
와 같은 수정 가능한 요소의 경우 XML에android:hint
속성을 사용하여 사용자에게 무엇을 입력할지 힌트를 제공합니다.- 관련 요소를 뷰 그룹으로 래핑하여 콘텐츠 그룹을 만듭니다.
android:accessibilityLiveRegion
로 사용자에게 추가 의견을 제공할 수 있는 실시간 지역을 만드세요.
칩을 사용하여 필터 구현
- Chip은 속성, 텍스트, 항목 또는 동작을 나타내는 작은 요소입니다.
- 칩 그룹을 만들려면
com.google.android.material.chip.ChipGroup
를 사용합니다. com.google.android.material.chip.Chip
하나의 레이아웃을 정의합니다.- 칩에서 색상을 변경하려면 색상 상태 목록을 스테이트풀(Stateful) 색상이 있는
<selector>
로 제공하세요.<item android:color="?attr/colorPrimaryVariant"
android:state_selected="true" /> - 뷰 모델의 데이터에 관찰자를 추가하여 칩을 실시간 데이터에 결합합니다.
- 칩을 표시하려면 칩 그룹용 팽창기를 만듭니다.
LayoutInflater.from(chipGroup.context)
- 칩을 만들고, 원하는 작업을 트리거하는 클릭 리스너를 추가한 다음 칩 그룹에 칩을 추가합니다.
어두운 모드 지원
- 어두운 모드를 지원하려면
DayNight
AppTheme
를 사용합니다. - 프로그래매틱 방식으로 어두운 모드를 설정할 수 있습니다.
AppCompatDelegate.setDefaultNightMode()
- res/values-night 리소스 폴더를 만들어 어두운 모드의 맞춤 색상과 값을 제공합니다.
Android 개발자 문서:
LayoutDirection
(RTL)- 양방향성
- 접근성 검사기 시작하기
- 음성 안내 지원
- 음성 안내 지원 동작
- 드로어블 개요 문서
- 콘텐츠 설명어
- 콘텐츠 분류
- 서비스 중인 지역
- NinePatch 드로어블
- 그리기 9 패치 도구
- 칩
ChipGroup
- 어두운 테마
- 색상 테마
- 색상 도구
- 드로어블 그래픽 애니메이션화
기타 리소스:
- Kotlin을 사용하여 Android 앱 개발(Udacity 과정)
- 프로그래머를 위한 Kotlin 부트캠프 (Udacity 과정)
- 프로그래머를 위한 Kotlin 부트캠프 Codelab
이 섹션에는 강사가 진행하는 과정의 일부로 이 Codelab을 통해 작업하는 학생들의 숙제 과제가 나와 있습니다. 강사는 다음을 처리합니다.
- 필요한 경우 과제를 할당합니다.
- 학생에게 과제 과제를 제출하는 방법을 알려주세요.
- 과제 과제를 채점합니다.
강사는 이러한 추천을 원하는 만큼 사용할 수 있으며 다른 적절한 숙제를 할당해도 좋습니다.
이 Codelab을 직접 학습하고 있다면 언제든지 숙제를 통해 지식을 확인해 보세요.
질문 1
다음 중 RTL 언어를 지원하는 데 반드시 필요한 것은 무엇인가요?
▢ 속성에서 Left
및 Right
를 Start
및 End
(으)로 대체
▢ RTL 언어로 전환
▢ 모든 아이콘에서 android:autoMirrored="true"
사용
▢ 콘텐츠 설명 제공
질문 2
다음 중 대부분의 Android 기기에 내장된 접근성 도구는 무엇인가요?
▢ 음성 안내 지원
▢ 접근성 검사기
▢ Android 스튜디오에서 Refactor > RTL 지원(가능한 경우)
▢ 린트
질문 3
다음 중 칩에 관한 설명으로 올바르지 않은 것은 무엇인가요?
▢ 칩을 ChipGroup
의 일부로 표시합니다.
▢ ChipGroup
의 색상 상태 목록을 제공할 수 있습니다.
▢ 칩은 입력, 속성 또는 액션을 나타내는 간단한 요소입니다.
▢ 앱에서 칩을 사용하는 경우 항상 DarkTheme
를 사용 설정해야 합니다.
질문 4
어두운 테마와 밝은 모드 스타일을 지정하는 테마는 무엇인가요?
▢ DayNight
▢ DarkTheme
▢ DarkAndLightTheme
▢ Light
질문 5
라이브 영역이란 무엇인가요?
▢ 사용자에게 중요한 정보를 포함하는 노드
▢ 머티리얼 가이드라인에 따라 모양이 변하는 화면 영역
▢ 동영상을 스트리밍할 수 있는 뷰
▢ 애니메이션 드로어블