안드로이드 R클래스를 사용하여 리소스(Resources) 폴더의 xml 파일 등 리소스에 접근시, 변수 Resource ID를 문자열로 획득 및 프로그래밍방식으로 접근하는 방법
안드로이드는 리소스 폴더에서 이미지, 문자열, 레이아웃 등등 많은 리소스들을 관리합니다. 그런다음 프로그래밍 코드상에서 R클래스를 호출하여 접근할 수 있도록 구현되어 있습니다. 이러한 리소스에 접근시 레이아웃에서 속성 태그를 사용하여 지정할 수 있어요. 아래 레이아웃을 살펴볼까요? 테스트 코드를 구현하기 위해 5개의 TextView를 만들었습니다. TextView가 5개가 아닌 더 많은 텍스트뷰나 버튼 뷰가 있다면 더더욱 효과적인 코딩이 될거에요.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/sample_text_view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Hello World!"
app:drawableStartCompat="@drawable/icon_key_1"/>
<TextView
android:id="@+id/sample_text_view2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Second, Hello World!" />
<TextView
android:id="@+id/sample_text_view3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Third, Hello World!"/>
<TextView
android:id="@+id/sample_text_view4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="forth, Hello World!"/>
<TextView
android:id="@+id/sample_text_view5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="fifth, Hello World!"/>
<Button
android:id="@+id/button_1"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="Android"
android:drawableLeft="@drawable/ic_launcher_foreground"
android:onClick="listener">
</Button>
</LinearLayout>
기본적인 접근방법은 findViewById()메소드를 사용하여 R.id.리소스Id를 찾아서 초기화를 해준 후 값을 변경하는 등의 핸들링을 하게 됩니다. 접근해야할 뷰가 몇 개 안되면 문제 되지 않아요. 그러나 접근해야할 텍스트뷰가 20개 30개 100개면 어떻게 처리할까요? 아래와 같은 방법은 노가대성 작업이 됩니다. 이럴때 리소스Id값을 for문을 사용하여 접근하면 간단해집니다.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.sample_text_view1);
TextView textView2 = findViewById(R.id.sample_text_view2);
TextView textView3 = findViewById(R.id.sample_text_view3);
TextView textView4 = findViewById(R.id.sample_text_view4);
TextView textView5 = findViewById(R.id.sample_text_view5);
textView3.setCompoundDrawablesWithIntrinsicBounds(R.drawable.icon_key_3,0,0,0);
Drawable img = getResources().getDrawable(R.drawable.icon_key_2);
img.setBounds(0,0,60,60);
textView2.setCompoundDrawables(img, null,null,null);
}
텍스트뷰의 아이디값은 sample_text_view1, sample_text_view2, sample_text_view3……… 앞에 문자열은 동일하고 식별하기위한 값으로 뒤에 숫자를 주었습니다. 프로그래밍 방식으로 접근하여 리소스 ID를 가져오기 위해 getResources().getIdentifier() 메소드를 사용합니다. 첫번째 인자값은 텍스트뷰에 지정한 id이름 값입니다.textView의 id값을 가져오기 위해 “id”값을 인자로 주었습니다. 세번째 인자값은 패키지이름입니다. 5개의 텍스트뷰에 접근하여 값을 찍어보는 로직입니다.
for(int i=1; i<=5;i++){
int viewId = getResources().getIdentifier("sample_text_view" + i, "id", getPackageName());
TextView text = findViewById(viewId);
Log.d("TAG","" +text.getText());
}
getIdentifier()메소드의 두번째 인자값은 가져올 대상의 타입입니다. 이 타입에 해당하는 값들은 아래와 같아요. R클래스로 접근할 수 있는 변수들을 확인할 수 있어요.
만약 drawable 폴더 아래에 있는 이미지 파일에 접근할 경우 “id”대신 drawable로 접근하면 됩니다.
for(int i=1; i<=5;i++){
int resourceId = getResources().getIdentifier("icon_key_"+ i, "drawable", getPackageName());
}
다음은 5개의 텍스트뷰에 5개의 이미지를 레이아웃xml에서 drawableLeft태그 속성을 사용하지 않고, 프로그래밍방식으로 접근하는 로직입니다.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// TextView textView = findViewById(R.id.sample_text_view1);
// TextView textView2 = findViewById(R.id.sample_text_view2);
// TextView textView3 = findViewById(R.id.sample_text_view3);
// TextView textView4 = findViewById(R.id.sample_text_view4);
// TextView textView5 = findViewById(R.id.sample_text_view5);
//
//
// textView3.setCompoundDrawablesWithIntrinsicBounds(R.drawable.icon_key_3,0,0,0);
//
// Drawable img = getResources().getDrawable(R.drawable.icon_key_2);
// img.setBounds(0,0,60,60);
// textView2.setCompoundDrawables(img, null,null,null);
for(int i=1; i<=5;i++){
int viewId = getResources().getIdentifier("sample_text_view" + i, "id", getPackageName());
TextView text = findViewById(viewId);
Log.d("TAG","" +text.getText());
int resourceId = getResources().getIdentifier("icon_key_"+ i, "drawable", getPackageName());
text.setCompoundDrawablesWithIntrinsicBounds(resourceId,0,0,0);
}
}
자주 사용하게 될 코드라면 메소드로 하나 만들어서 호출해서 사용하는 방법을 추천합니다.
private int getResourceId(String name, String type){
return getResources().getIdentifier(name, type, getPackageName());
}
[번외]
버튼이나 텍스트뷰의 왼쪽 혹은 오른쪽 이미지 아이콘을 두고 싶을 때 프로그래밍 방식으로 접근하는 방법(drawableLeft)
stackoverflow.com/questions/4502605/how-to-programmatically-set-drawableleft-on-android-button