[Do it! 깡샘의 안드로이드 앱 프로그래밍 with 코틀린] 리소스 활용하기

안드로이드 앱 개발에서 리소스를 효과적으로 활용하는 방법을 정리했다. 리소스는 앱 리소스와 플랫폼 리소스로 나뉘며, 레이아웃, 이미지, 실행 아이콘, 값, 색상, 글꼴 리소스 등 다양한 종류가 있다. 리소스 조건 설정을 통해 특정 환경에서만 적용되도록 설정할 수 있으며, 화면 회전과 국제 언어 지원에도 대응할 수 있다. 또한, 안드로이드 폰의 다양한 크기에 호환성을 고려하여 논리적인 단위로 크기를 지정하고, 기기의 크기 정보를 가져와 직접 조정할 수 있다.
DriedPollack's avatar
Jul 26, 2024
[Do it! 깡샘의 안드로이드 앱 프로그래밍 with 코틀린] 리소스 활용하기

🌼리소스의 종류와 특징

  • 리소스는 앱 리소스와 플랫폼 리소스로 나뉜다.

💡앱 리소스 사용하기

  • 리소스란 정적인 자원이다. 정적인 콘텐츠는 코드에 작성하지 않고 분리해서 외부 파일로 만들어 이용할 수 있다.
  • 앱 리소스란 개발자가 직접 추가한 리소스다.
    • 모듈을 만들면 기본으로 디렉터리 4개가 만들어지지만 리소스 파일의 종류는 더 많다.
      • 디렉터리명
        리소스 종류
        animotor
        속성 애니메이션 XML
        anim
        트윈 애니메이션 XML
        color
        색상 상태 목록 정의 XML
        drawable
        이미지 리소스
        mipmap
        앱 실행 아이콘 리소스
        layout
        레이아웃 XML
        menu
        메뉴 구성 XML
        raw
        워닛 형태로 이용되는 리소스 파일
        values
        단순 값으로 이용되는 리소스
        xml
        특정 디렉터리가 정의되지 않은 나머지 XML 파일
        font
        글꼴 리소스
  • res 디렉터리 아래에 개발자가 임의로 이름을 붙인 디렉터리를 만들 수 없고 하위 디렉터리를 추가할 수 없다. 또한 리소스 파일명은 values레 추가하는 파일을 제외하고는 모두 자바의 이름 작성 규칙을 지켜야 하며 알파벳 대문자를 사용할 수 없다.
  • 레이아웃 리소스layout 디렉터리에 저장한다.
    • 화면을 구성하는 레이아웃 XMl 파일이다.
  • 이미지 리소스drawable 디렉터리에 저장한다.
    • 이미지는 PNG, JPG, GIF, WEBP, XML로 작성된 이미지다.
    • XML 이미지를 만들 때는 다음 태그로 표현한다.
      • 태그
        설명
        <shape>
        도형을 의미하며 android:shape=”rectangle”처럼 shape 속성을이용해 도형의 타입을 지정. shape 값은 rectangle, oval, line, ring 중에서 선택.
        <corners>
        둥근 모서리를 그리는 데 사용. shape 값이 rectangle일 때만 적용
        <gradient>
        그라데이션 색상 지정
        <size>
        도형의 크기 지정
        <solid>
        도형의 색상 지정
        <stroke>
        도형의 윤곽선 지정
  • 실행 아이콘 리소스mipmap 디렉터리에 저장한다.
    • 앱을 기기에 설치하면 나타나는 실행 아이콘의 이미지 리소스다.
  • 값 리소스values 디렉터리에 저장된다.
    • 문자열, 색상, 크기, 스타일, 배열 등의 값을 XMl로 저장할 수 있다.
    • values 디렉터리의 리소스 파일은 파일명이 R인 파일에 식별자로 등록되지 않고 리소스 파일에 값을 지정한 태그의 name 속성값이 등록된다.
    • 따라서 파일명은 개발자가 자유롭게 정할 수 있고 대문자를 사용할 수도 있다.
      • // 문자열 리소스 등록 <resources> <string name="app_name">Test9</string> <string name="txt_data1">Hello</string> <string name="txt_data2">World</string> </resources> // XML에서 문자열 리소스 사용 <TextView (...생략...) android:text="@string/txt/data1"/> // 코드에서 문자열 리소스 사용 binding.textView.text = getString(R.string.txt_data2) // 색상 리소스 등록 <resources> <color name="txt_color">#FFFF00</color> <color name="txt_bg_color">#FF0000</color> </resources> // 크기 리소스 등록 <resources> <dimen name="txt_size">20sp</dimen> </resources> // XML에서 색상과 크기 리소스 사용 <TextView (...생략...) android:textColor="@color/txt_color" android:background="@color/txt_bg_color" android:textSize="@dimen/txt_size"/> // 코드에서 색상과 크기 리소스 사용 binding.textView.text = getString(R.string.txt_data2) binding.textView.setTextColor(ResourcesCompat.getColor(resources, R.color.txt_color, null)) binding.textView.textSize = resources.getDimension(R.dimen.txt_size) // 스타일 등록 <resources> <style name="MyTextStyle"> <item name="android:textSize">@dimen/txt_size</item> <item name="android:textColor">@color/txt_color</item> </style> <style name="MyTextStyleSub" parent="MyTextStyle"> <item name="android:textColor">#00FF00</item> <item name="android:background">@color/txt_bg_color</item> </style> </resources> // 스타일 리소스 사용 <TextView (...생략...) style="@style/MyTextStyleSub" (...생략...)/>
  • 색상 리소스color 디렉터리에 저장한다.
    • values 디렉터리에 만드는 리소스 파일에서 <color> 태그로 등록할 수도 있지만, 해당 리소스는 색상 하나를 리소스에 등록하겠다는 의미다. 반면에 color 디렉터리의 리소스는 특정 뷰의 상태를 표현하고 그 상태에 적용되는 색상을 등록할 때 사용한다.
      • // 색상 리소스 등록 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:color="#ffff0000"/> <item android:state_focused="true" android:color="#ff0000ff"/> <item android:color="#ff000000"/> </selector> //색상 리소스 사용 <Button (...생략...) android:textColor="@color/button_text" />
  • 글꼴 리소스font 디렉터리를 사용한다.
    • TTF나 OTF 파일을 저장한 후 글꼴을 적용할 뷰에서 이용하면 된다.

💡플랫폼 리소스 사용하기

  • 안드로이드 플랫폼이 제공하는 리소스를 활용할 수 있다.
  • 안드로이드 스튜디오의 프로제그 탐색 창에서 보기 옵션을 [Packages]로 설정한 후 [Libraries]항목을 살펴보면 확인할 수 있다.
  • 플랫폼 리소스도 R파일에 등록된 식별자로 이용할 수 있다.
    • // 코드에서 플랫폼 리소스 사용 binding.imageView.setImageDrawable(ResourcesCompat.getDrawable(resources, android.R.drawable.alert_dark_frame, null)) binding.textView.text=getString(android.R.string.emptyPhoneNumber) // XML에서 플랫폼 리소스 사용 <ImageView (...생략...) android:src="@android:drawable/alert_dark_frame"/> <TextView (...생략...) android:src="@android:string/emptyPhoneNumber"/>
      💡
      기초 리소스 같은 경우 플랫폼에서 미리 준비해 놓을 수 있으므로 개발할 때 필요한 리소스가 플랫폼 리소스에 있는지 먼저 찾아보는 것이 좋다.ㄴ
 

🌼리소스 조건 설정

💡리소스 조건 설정이란

  • 리소스 조건 설정이란 어떤 리소스를 특정 환경에서만 적용되도록 설정하는 것이다.
    • 예를 들어 개발자가 실행 아이콘에 사용할 이미지를 하나만 준비했는데, 기기마다 화면 크기가 달라지면 선명하게 나오지 않는 문제가 발생한다.
      • 화면 밀도
        크기
        XXXHDPI
        192 x 192
        XXHDPI
        144 x 144
        XHDPI
        96 x 96
        HDPI
        72 x 72
        MDPI
        48 x 48
    • 따라서 보통 앱을 개발할 때는 각 크기별로 이미지를 5개씩 준비한다.
    • 리소스 조건을 이용하려면 아이콘의 파일명을 똑같이 지정해야 한다.
    • 그 후 mipmap-mdpi/ic_launcher.png와 같이 조건을 명시해서 사용한다.
    • 리소스 디렉터리명에 지정할 수 있는 조건은 다음과 같다.
      • 조건
        예시
        MCC 및 MNC
        mcc310 mcc310-mnc004
        언어 및 지역
        en ko-kr
        레이아웃 방향
        Idrtl Idltr
        더 작은 쪽
        sw320dp
        이용 가능한 너비
        w720dp
        이용 가능한 높이
        h720dp
        화면 크기
        small, normal, large, xlarge
        화면 비율
        long, notlong
        원형 화면
        round, notround
        화면 방향
        port, land
        UI 모드
        car, desk, television, application, watch, vrheadset
        야간 모드
        night, notnight
        화면 픽셀 밀도
        ldpi, mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi, nodpi, tvdpi, anydpi, nnndpi
        터치 스크린 유형
        notouch, finger
        키보드 가용성
        keysexposed, keyshidden, keyssoft
        기본 텍스트 입력방법
        nokeys, qwerty, 12key
        탐색 키 가용성
        navexposed, navhidden
        기본 비터치 탐색방법
        nanav, dpad, trackball, wheel
        플랫폼 버전
        v21
    • 조건을 디렉터리에 명시할 때 하나의 디렉터리에 여러 조건을 지정해도 되지만, 조건의 순서는 위와 같은 순서를 지켜야 한다.

💡화면 회전에 대응하기

  • 리소스 조건을 이용해 화면 회전에 대응하는 UI를 만들 수 있다. 화면 회전에 대응하려면 가로와 세로 방향일 때 출력할 레이아웃 XML 파일을 각각 준비해야 한다.
    • 이 경우 어떤 방향에서 어떤 XML 파일을 출력할지를 리소스 조건으로 설정하여 처리한다.
    • 파일명은 모두 같아야 한다.
💡
화면이 회전하면 서비스에 문제가 생기는 게임 앱의 경우 AndroidManifest.xml 파일에 설정하는 것으로 화면을 고정할 수 있다. 하지만 데이터 위주로 서비스하는 앱이라면 가로 방향과 세로 방향을 사용자가 선택할 수 있게 해야 한다.

💡국제 언어 제공하기

  • 글로벌 서비스를 제공하는 앱이라면 리소스 문자열을 각국 언어로 제공해야 한다.
    • 문자열 리소스는 values 디렉터리의 리소스이므로 식별자는 파일명이 아니라 <string> 태그의 name값이 된다.
 

🌼폰 크기의 호환성

  • 안드로이드 폰은 다양한 크기로 출시된다. 따라서 폰 크기의 호환성을 안드로이드 시스템에서, 또는 개발자가 고려해야 하는 부분이 존재한다.

💡논리적인 단위 알아보기

  • 안드로이드 시스템은 다음과 같이 기기의 크기를 구분하여 콘텐츠의 크기를 늘리거나 줄여서 출력한다.
    • 크기
      설명
      배율
      ldpi
      ~120dpi
      0.75
      mdpi
      ~160dpi
      1.0
      hdpi
      ~240dpi
      1.5
      xhdpi
      ~320dpi
      2.0
      xxhdpi
      ~480dpi
      3.0
      xxxhdpi
      ~640dpi
      4.0
  • 안드로이드에서 앱을 개발할 때 크기 지정에 사용할 수 있는 단위는 다음과 같다.
    • dp : 스크린의 물리적 밀도에 기반을 둔 단위
    • sp : dp와 유사하며 글꼴 크기에 적용
    • tp : 스크린 크기의 1/72을 1pt로 함
    • px : 픽셀
    • mm : 밀리미터
    • in : 인치
  • 위 표에 따르면 xxxhdpi의 폰은 개발자가 지정한 크기보다 3배 정도 크게 출력된다. 따라서 콘텐츠의 크기는 될 수 있으면 논리적인 단위로 지정하여 시스템의 도움을 받는 편이 좋다.

💡화면 정보 가져오기

  • 개발자가 직접 코드에서 크기 호환성을 조정할 수도 있다. 이 경우 기기의 크기 정보를 가져와야 한다.
  • API 레벨 30버전부터는 DisplayMetrics가 아닌 WindowMetrics를 이용해야 한다.
    • // 기기의 가로, 세로 크기 가져오기 // Build.VERSION.SDK_INT: 앱이 실행되는 기기의 버전 // Build.VERSION_CODES.R: 안드로이드 11버전(API 레벨 30) if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R{ val windowMetrics: WindowMetrics = windowManager.currentWindowMetrics binding.textView.text = "width : ${windowMetrics.bounds.width()}, height : ${windowMetrics.bounds.height()}" }else{ val display = windowManager.defaultDisplay val displayMetrics = DisplayMetrics() display?.getRealMetrics(displayMetrics) binding.textView.text = "width : ${displayMetrics.widthPixels}, height : ${displayMetrics.heightPixels}" }
 

🏁결론

안드로이드 앱 개발에서 리소스를 효과적으로 활용하는 방법을 정리했다. 리소스는 앱 리소스와 플랫폼 리소스로 나뉘며, 레이아웃, 이미지, 실행 아이콘, 값, 색상, 글꼴 리소스 등 다양한 종류가 있다. 리소스 조건 설정을 통해 특정 환경에서만 적용되도록 설정할 수 있으며, 화면 회전과 국제 언어 지원에도 대응할 수 있다. 또한, 안드로이드 폰의 다양한 크기에 호환성을 고려하여 논리적인 단위로 크기를 지정하고, 기기의 크기 정보를 가져와 직접 조정할 수 있다.
Share article

More articles

See more posts

👨🏻‍💻DriedPollack's Blog