본문 바로가기
깡샘 코틀린

09-1 리소스의 종류와 특징

by 농농씨 2023. 6. 23.

안드로이드 프로그래밍은 리소스를 많이 이용한다는 특징이 있다. 9장에서는 리소스의 종류와 활용 조건을 어떻게 명시하는지, 기기의 크기와 호환하는 앱을 개발하려면 어떤 부분을 신경 써야 하는지에 초점을 맞춰 학습해야 한다. 

 

안드로이드 앱 개발에서 리소스(resource)란 정적인 자원이라고 할 수 있다. 변경되지 않는 정적인 콘텐츠는 코드에 작성하지 않고 리소스로 분리해서 외부 파일로 만들어 코드를 좀 더 간결하게 작성하고 프로그램의 유지,보수를 용이하게 할 수 있다.

앱에서 이용하는 리소스는 크게 앱 리소스플랫폼 리소스로 구분된다. 차례대로 알아보자.

 

 

앱 리소스 활용하기

앱 리소스란 개발자가 직접 추가한 리소스를 의미한다. 앱을 개발하기 위해 모듈을 만들면 자동으로 res라는 디렉터리가 생기고 그 아래에 drawable, layout, mipmap, values라는 디렉터리 4개가 생성된다. 개발자는 이 리소스 디렉터리에 리소스 파일을 각각 만든다.

 

모듈을 만들면 기본으로 디렉터리 4개가 만들어지미미나 리소스 파일의 종류는 더 많다. 즉, 기본 디렉터리뿐만 아니라 더 많은 디렉터리를 res 아래에 만들어 쓸 수 있다. 안드로이드 앱에서 이용되는 리소스의 종류는 animator(속성 애니메이션 XML), anim(트윈 애니메이션 XML) 등 11개가 있다. 

 

리소스 디렉터리와 파일 이름은 규칙이 있다. 1️⃣앞서 언급한 animator 등의 리소스 디렉터리명은 고정이며, 2️⃣res 디렉터리 아래에 개발자가 임의로 이름을 붙인 디렉터리를 만들 수 없고 하위 디렉터리 역시 추가할 수 없다. 3️⃣또한 리소스 파일명은 values에 추가하는 파일을 제외하고는 모두 자바의 이름 작성 규칙을 지켜야 하며 4️⃣알파벳 대문자를 사용할 수 없다. 이런 규칙이 있는 이유는 리소스 디렉터리와 파일을 코드에서 그대로 사용하지 않고 R 파일에 식별자로 등록해서 이용하기 때문이다.

 

여기서는 앱을 개발할 때 기본으로 이용하는 몇몇 리소스를 살펴볼 것이다.

 

레이아웃 리소스 - layout 디렉터리

앞장에서 살펴보았듯 화면을 구성하는 레이아웃 XML 파일을 저장하는 디렉터리이다.

 

이미지 리소스 - drawable 디렉터리

이미지 리소스를 저장하는 디렉터리이다. PNG, JPG, GIF, 9.PNG 파일의 이미지를 저장할 수 있다. 또한 XML 파일로 작성한 이미지도 이 디렉터리에 저장할 수 있다.

다음은 drawable 디렉터리에 gradient_box.xml이라는 이름으로 만든 이미지 파일이다.

// XML로 작성한 이미지
<shape xmlns:android="http://schemas.android.com/apk/res/android
	android:shape="rectangle" />
    <gradient
    	android:startColor="#FFFF0000"
        android:endColor="#80FF00FF"
        android:angle="45" />
    <corners android:radius="8dp" />
</shape>

이미지는 좌측 아래는 빨강, 오른쪽 위는 보라색이고 그라데이션 돼있다.

XML 파일로 작성했지만 이 파일도 이미지 리소스처럼 ImageView 등에서도 이용할 수 있다.

// XML 이미지를 사용하는 예
<ImageView
	android:layout_width="300dp"
    android:layout_height="300dp"
    android:src="@drawable/gradient_box" />

 

XMl 이미지를 만들 때는 다음 표와 같이 표현한다.

<XML 이미지 태그>

<shape> 도형을 의미하며 android:shape="rectangle"처럼 shape 속성을 이용해 도형의 타입을 지정. shape 값은 rectangle, oval, line, ring 중에서 선택한다.
<corners> 둥근 모서리를 그리는 데 사용. shape값이 rectangle 일 때만 적용
<gradient> 그라데이션 색상 지정
<size> 도형의 크기 지정
<solid> 도형의 색상 지정
<stroke> 도형의 윤곽선 지정

 

실행 아이콘 리소스

앱을 기기에 설치하면 나타나는 실행 아이콘의 이미지 리소스가 저장되는 디렉터리이다.

 

값 리소스 - values 디렉터리

값으로 이용되는 리소스를 저장하는 디렉터리이며 문자열, 색상, 크기, 스타일, 배열 등의 값을 XML로 저장할 수 있다. 그런데 values에 저장되는 리소스는 다른 디렉터리의 리소스와 이용 방법이 조금 다르다. 다른 디렉터리의 리소스는 파일명이 R인 파일에 식별자로 추가되므로 코드에서 이 식별자로 구분해서 사용한다.

res 파일에 layout 안에 activity_main.xml 파일이 있다. 이 리소스를 코드에서는 R.layout.activity_main으로 이용한다. 그런데 values 디렉터리에 있는 문자열 리소스 파일인 strings.xml은 R.values.string처럼 이용하지 않는다.

즉, values 디렉터리의 리소스 파일은 파일명이 R인 파일에 식별자로 등록되지 않고 리소스 파일에 값을 지정한 태그의 name 속성값이 등록된다.* 따라서 그림에서 values 디렉터리에 있는 colors.xml, string.xml 등의 파일명은 권장할 뿐 개발자가 자유롭게 정할 수 있으며 알파벳 대문자를 이용할 수 있다.

*왜 다른 리소스와 달리 values 디렉터리의 리소스만 파일이 아닌 '태그'를  R 파일에 등록할까?

values 리소스는 값을 의미하므로 파일을 R에 등록하려면 값 하나가 파일 하나로 등록되어야한다. 파일로 식별하면 문자열 하나당 파일이 하나씩 만들어져 앱 하나당 수백 수천개의 문자열 파일이 만들어지면 비효율적일 것이다.

// 문자열 리소스 등록
<resources>
	<string name="app_name">Test9</string>
    <string name="txt_data1">Hello</string>
    <string name="txt_data2">World</string>
</resources>

strings.xml 파일을 위처럼 작성했다면 태그의 name 속성에 지정한 값R 파일에 식별자로 기록된다. 따라서 레이아웃 XML과 코드에서 각각 다음처럼 이용한다. 

// XML에서 문자열 리소스 사용
<TextView
	android:"@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="string/txt_data1" /> // txt_data1을 name 속성으로 가지는 문자열 리소스를 사용
// 코드에서 문자열 리소스 사용
binding.textView.text = getString(R.string.txt_data2)
					// R 파일에 저장된 name 속성으로 호출함

 

values 디렉터리에 저장되는 리소스는 문자열 이외에도 색상, 크기, 스타일 등이 있다. 색상 리소스는 다음처럼 color 태그로 등록한다.

// 색상 리소스 등록
<resources>
	<color name="txt_color">#FFFF00</color>
    <color name="txt_bg_color">#FF0000</color>
</resources>

 

크기 리소스는 dimen 태그로 등록한다. 

// 크기 리소스 등록
<resources>
	<dimen name="txt_size">20dp</dimen>
</resources>

 

이렇게 등록한 색상과 크기 리소스를 레이아웃 XML과 코드에서 이용할 때는 각각 다음처럼 한다.

// XML에서 색상과 크기 리소스 사용
<TextView
	android:id="@+id/textView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/txt_data1" // 텍스트 리소스
    android:textColot="@color/txt_color" // 텍스트 색 리소스
    android:background="@dimen/txt_size" /> // 텍스트 사이즈 리소스
// 코드에서 색상과 크기 리소스 사용
binding.textView.text = getString(R.string.txt_data2)
// getString() 함수 사용하거나
binding.textView.setTextColor(REsourcesCompat.getColor(resources, R.color.txt_color, null))
// REsourcesCompat의 객체?로 호출하거나???
binding.textView.textSize = resources.getDimension(R.dimen.txt_size)
// resources.getDimension 함수?로 호출하거나?

 

스타일 리소스는 style 태그로 등록한다. 스타일 속성은 뷰에 설정되는 여러 속성을 스타일에 등록하여 한꺼번에 적용하거나 여러 뷰에 중복되는 속성을 스타일로 정의해 재사용하는 용도로 쓰인다.

// 스타일 등록
<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">#0000FF</item>
        <item name="android:background">@color/txt_bg_color</item>
    </style>
</resources>

스타일을 정의할 때는 다른 스타일을 상속받아 재정의할 수 있다. 

위의 예를 보면 상속받은 뒤에 textColor 속성을 재정의하고 background 속성을 추가했다. MyTextStyle을 뷰에 적용하면 속성 2개가 적용되고 그 아래꺼를 뷰에 적용하면 속성 3개가 적용된다.

// 스타일 리소스 사용
<TextView
	android:layout_width="match_parent"
    android:layout_height="wrap_content"
    style="@style/MyTextStyleSub"
    android:text="Hello World" />

 

색상 리소스 - color 디렉터리

color 디렉터리는 색상 리소스를 등록한다. 그런데 앞에서 살펴본 values 디렉터리에 만드는 리소스 파일에서도 <color>태그로 색상 리소스를 등록할 수 있다. 왜 color라는 리소스 디렉터리가 별도로 있을까?

values에 다 등록할수도 있지만 values 디렉터리에 <color> 태그로 등록한 리소스는 말 그대로 색상 하나를 리소스에 등록해 사용하겠다는 의미이다. 반면에 color 디렉터리의 리소스는 특정 뷰의 상태를 표현하고 그 상태에 적용되는 색상을 등록할 때 사용한다. 

예를 들어 어떤 버튼을 눌렀을 떄와 누르지 않았을 때의 색상을 리소스로 등록하고자 한다.

이를 values 디렉터리의 리소스 파일에 <color> 태그로 등록해 사용할 수도 있지만, 버튼의 상태에 따른 색상을 하나의 XML에 등록해 적용하면 더 편리하다. 이때 color 디렉터리를 이용한다. 

// 색상 리소스 등록
<?xml version="1.0" encoding="utf-8">
<selector xmlns:android="https://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>

색상 리소스 등록 예를 보면 <selector> 태그 아래에 <item> 태그를 이용해 이 리소스가 적용될 뷰의 상태와 그 상태일 때의 색상을 지정했다. android:state_pressed 는 뷰를 눌렀을 때의 상태이고 android:state_focused는 뷰에 포커스가 주어졌을 때를 의미한다. 그리고 android:color 속성으로 각 상태에 따른 색상을 지정했다. 

이렇게 color 리소스를 정의한 후 다음처럼 뷰에 등록해서 사용한다.

// 색상 리소스 사용
<Button
	android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Click Me!!"
    android:textColor="@color/button_text" />

 

글꼴 리소스 - font 디렉터리

font 디렉터리는 글꼴 리소스를 저장한다. 이곳에 TTF나 OTF파일을 저장한 후 글꼴을 적용할 뷰에서 이용하면 된다.

// 글꼴 리소스 사용
<TextView
	android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="HelloWorld"
    android:textSize="20dp"
    android:fontFamily="@font/pacifico" // 글꼴 리소스 사용함

 

 

플랫폼 리소스 사용하기

지금까지 살펴본 바와 같이 앱 개발자가 res 디렉터리에 추가하는 것은 앱 리소스이다. 그런데 개발자가 리소스를 따로 준비하지 않아도 이미 안드로이드 플랫폼이 제공하는 많은 리소스가 있어 이를 활용할 수 있다.

 

플랫폼 리소스는 안드로이드 스튜디오의 프로젝트 탐색 창에서 보기 옵션을 [Packages]로 설정한 후 [Libraries] 항목을 살펴보면 확인할 수 있다.

플랫폼의 라이브러리를 보면 anim, color, drawable 등 많은 리소스 디렉터리가 있다. 이곳에 있는 리소스가 플랫폼 리소스이다.

 

플랫폼 리소스도 R 파일에 등록된 식별자로 이용할 수 있다. 그런데 플랫폼 리소스는 앱에 있는 리소스가 아니므로 앱의 R 파일이 아니라 android.R 이라는 플랫폼 라이브러리의 R 파일에 등록되어있어 이를 이용해 플랫폼 리소스를 이용할 수 있다.

// 코드에서 플랫폼 리소스 사용
binding.imageView.setImageDrawable(ResourcesCompat.getDrawable(resources,
	android.R.drawable.alert_dark_frame, null))
    // alert_dark_frame 이라는 이름의 플랫폼리소스를 가져왔나보다~
binding.textView.text=getString(android.R.string.emptyPhoneNumber) 
// emptyPhoneNumber 이라는 이름의 플랫폼 리소스를 가져왔나보다~

 

XML에서 앱 리소스는 @기호로 R 파일의 리소스를 이용했다. XML에서 drawable의 save.png 파일을 이용한다면 @drawable/save처럼 작성한다. 그런데 플랫폼의 리소스를 XML에서 이용할 때는 @android:  패턴으로 한다. 예를 들어 플랫폼의 drawable 디렉터리에 save.png 파일이 있다면 @android:drawable/save로 이용한다.

// XML에서 플랫폼 리소스 사용
<ImageView
	android:id="@+id/imageView" // 아이디로 이미지뷰 불러옴
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@android:drawable/alert_dark_frame" // 플랫폼 리소스 불러옴

<TextView
	android::id="@+id/textView" // 아이디로 텍스트뷰 불러옴
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@android:string/emptyPhoneNumber" // 플랫폼 리소스 불러옴

 

 

 

 

이러한 리소스들을 다 외울 필요는 없고 개발할 때 필요한 리소스가 플랫폼 리소스에 있는지 먼저 찾아보는 것이 좋다.

 

 

09-1 공부후기

더보기

하... 코드 하나하나 치려니까 귀찮고 시간도 오래걸리고 그냥 복붙 하는 것 같아서 기분이 좀 별로다. 그냥 눈으로 보는 것보다는 이해될지도? 전에는 이해안되는 부분은 빼버리고 딱 배우는 파트만 쳤었는데.... 짧게짧게 있는거는 빼기도 애매하고 그냥 손이랑 눈에 익혀두는 것도 좋을 것 같아서 일단 그대로 다 쳐보고 있다. 

 

'깡샘 코틀린' 카테고리의 다른 글

09-3 폰 크기의 호환성  (0) 2023.06.23
09-2 리소스 조건 설정  (0) 2023.06.23
08-2 뷰 이벤트  (0) 2023.06.23
08-1 터치와 키 이벤트  (0) 2023.06.22
07-5 계층 구조로 배치 - ConstraintLayout  (0) 2023.06.20