출처 : Do it! 안드로이드 앱 프로그래밍 / 정재곤
지금까지는 하나의 화면에 대하여 화면을 어떻게 보여줄지 결정하는 XML 레이아웃을 정의했다. 하지만 XML 레이아웃만 만들었다고 화면을 띄우고 앱을 실행할 수는 없다. 화면의 기능을 담당하는 소스 코드 파일이 필요하다.
그런데 두 개의 XML 레이아웃 파일과 하나의 소스 코드 파일만 있다면 어떤 XML 레이아웃 파일이 소스 파일과 연결되는 지 어떻게 알 수 있을까? 다음은 새 프로젝트를 만들 때 만들어지는 소스 파일(MainActivity.java)에 자동으로 입력된 소스다.
package com.example.project00_java;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
}
}
여기서 setContentView() 메소드에서 XML 레이아웃 파일이 소스 파일과 연결되게 된다. 이때 setContentView() 메소드에 전달하는 XML 레이아웃 파일의 이름은 R.layout.activity_main 과 같은 방법으로 확장자 없이 지정해야 한다.
이때 대문자 R은 프로젝트 창에 보이는 res 폴더를 의미한다. 그리고 layout은 res 폴더의 layout 폴더를 의미한다. 따라서 /app/res/layout 폴더 안에 들어 있는 activity_main.xml 파일은 R.layout.activity_main로 표현할 수 있다.
앱이 실행될 때 XML 레이아웃의 내용이 메모리에 객체화되고 객체화된 XML 레이아웃을 소스 파일에서 사용한다. 이렇게 XML 레이아웃의 내용이 메모리에 객체화되는 과정을 '인플레이션(Inflation)'이라고 한다.
XML 레이아웃은 앱이 실행되는 시점에 메모리에 객체화된다. 즉, XML 레이아웃 파일에 <Button> 태그를 정의해도 앱은 자신이 실행되기 전까지 버튼이 있는지 모른다. 다시 말하면 setContentView() 메소드가 호출되기 전에 어떠한 객체를 참조하려고 하면 널 포인터 예외가 생기게 된다.
궁금했던 점 : R.layout.activity_main의 경우 int형인데 이 데이터는 어디에 저장이 되어 있는가?
-> res 폴더 내의 모든 파일들을 참조할 때는 int형의 Id값으로 참조하게 되며, 이 Id값은 컴파일하는 과정에서 자동으로 생성되어 값을 가지게 된다.
화면 전체에 보여줄 XML 레이아웃이 아니라 별도의 XML 레이아웃 파일로 만든 부분 레이아웃을 소스 파일에 로딩하여 보여줄 수 있을까? setContentView() 메소드는 액티비티의 화면 전체를 설정하는 역할을 수행하여 부분 레이아웃을 메모리에 객체화할 수는 없다. 이럴 때는 인플레이터를 사용해야 한다. 안드로이드는 이를 위해 LayoutInflater라는 클래스를 제공한다. 일부 화면을 분리한 부분 화면은 LayoutInflater 객체를 사용해 뷰그룹 객체로 객체화(인플레이션)한 후 메인 레이아웃에 추가해야 된다.
LayoutInflater 객체의 inflate() 메소드에 대해 한 번 알아보자.
View inflate(int resource, ViewGroup root)
inflate() 메소드는 첫 번째 파라미터로 XML 레이아웃 리소스를, 두 번째 파라미터로 부모 컨테이너를 지정한다.
> 인플레이션 예제
package com.example.project00_java;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
LinearLayout container;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
container = findViewById(R.id.container);
Button button = findViewById(R.id.button2);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.activity_menu, container, true);
CheckBox checkBox = container.findViewById(R.id.checkBox);
checkBox.setText("로딩되었어요.");
}
});
}
}
이제 부분 레이아웃 파일이 객체화되었으므로 부분 레이아웃에 들어있더 텍스트뷰와 체크박스를 findViewById() 메소드로 참조할 수 있다. 단, 부분 레이아웃은 container 객체에 설정되었으므로 container 객체의 findViewById() 메소드를 사용해야 한다.
'Android' 카테고리의 다른 글
[Android] 안드로이드 정리 (7) - 인텐트(Intent) (0) | 2020.03.12 |
---|---|
[Android] 안드로이드 정리 (6) - 여러 화면 만들고 화면 간 전환하기 (0) | 2020.03.12 |
[Android] 안드로이드 정리 (4) - 토스트, 스낵바, 대화상자, 프로그레스바 (0) | 2020.03.12 |
[Android] 안드로이드 정리 (3) - 이벤트 처리 (0) | 2020.03.11 |
[Android] 안드로이드 정리 (2) - 기본 위젯과 드로어블 (0) | 2020.03.11 |