안드로이드 프레임레이아웃 뷰 변경하기 2. [LayoutInflater] (How to change a View in Android FrameLayout 2)
1. addView(), removeView() 함수로 FrameLayout 뷰 변경하기.
[안드로이드 프레임레이아웃(Android FrameLayout)]에서 FrameLayout
에 대해 설명하고, [안드로이드 프레임레이아웃 뷰 변경하기 1. [addView(), removeView()]]에서는 ViewGroup의 addView(), removeView() 함수를 사용하여 FrameLayout
에 표시될 뷰를 변경하는 방법을 살펴보았습니다.
[안드로이드 프레임레이아웃 뷰 변경하기 1. [addView(), removeView()]]에서 작성한 예제에서는, 레이아웃 리소스 XML에서 FrameLayout
의 자식(Children) 뷰 위젯들을 미리 추가 해놓고, 앱 시작 시 화면에 표시할 뷰(View)를 제외한 모든 뷰를 removeView() 함수로 제거했습니다. 그리고 나서 버튼 클릭 이벤트에 따라 removeView()와 addView() 함수를 호출하여 뷰(View)를 바꿔 표시했죠.
그런데, 하나의 레이아웃 리소스 XML의 FrameLayout
아래에 모든 자식(Children) 뷰 위젯들을 선언하는 방법은 그리 좋은 방법이 아닙니다. 특히, 자식(Children) 뷰 위젯의 갯수가 많아지고 구조가 복잡해지면, 그에 따라 레이아웃 리소스 XML의 내용도 늘어나므로, 소스를 작성하고 수정하는 작업이 매우 번거로워질 수 있습니다.
이런 경우, 코드 작성 및 관리를 편하게 수행하기 위해 개발자가 취할 수 있는 방법은, FrameLayout
에 표시될 자식(Children) 뷰를 각각 별도의 레이아웃 리소스 XML로 분리하여 작성한 다음, LayoutInflater
를 사용하여 View로 변환하는 것입니다.
2. LayoutInflater
LayoutInflater
는 리소스 XML 파일에 선언된 레이아웃을 자바 코드 상에서 View 객체로 변환할 때 사용하는 클래스입니다. LayoutInflater
를 통해 획득된 View 객체는 리소스 XML에 작성된 모든 뷰 그룹(ViewGroup) 및 뷰(View)를 포함하므로, findViewById() 함수를 통해 뷰에 포함된 위젯에 대한 참조를 획득할 수 있습니다.
LayoutInflater
를 사용할 때는 new를 통해 직접적으로 객체를 생성하는 방법을 사용할 수 없습니다. 대신, Context
클래스의 getSystemService()함수를 호출하거나, Activity
의 getLayoutInflater() 함수를 사용하여 LayoutInflater
의 참조를 획득할 수 있습니다.
// 방법 1.
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// 방법 2.
LayoutInflater inflater = getLayoutInflater() ;
LayoutInflater
에 대한 참조를 획득하고나면, inflate() 함수를 호출하여 리소스 XML 파일에 선언된 레이아웃을 View 객체로 변환할 수 있습니다.
리턴 타입 | 함수 | 설명 |
---|---|---|
View | inflate(int resource, ViewGroup root) | resource(XML 리소스)로부터 새로운 View를 inflate하여 root 아래에 추가. |
View | inflate(XmlPullParser parser, ViewGroup root) | resource(XML 노드)로부터 새로운 View를 inflate하여 root 아래에 추가. |
View | inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) |
resource(XML 노드)로부터 새로운 View를 inflate. root 아래에 추가할 것인지 여부는 attachToRoot의 값에 따라 결정. |
View | inflate(int resource, ViewGroup root, boolean attachToRoot) | resource(XML 리소스)로부터 새로운 View를 inflate. root 아래에 추가할 것인지 여부는 attachToRoot의 값에 따라 결정. |
다음은 inflate() 함수를 사용하여 레이아웃 리소스 XML을 View로 변환하는 예제입니다.
// "/res/layout/page1.xml" 파일을 inflate. (root = frame, attachToRoot = false)
View view = inflater.inflate(R.layout.page1, frame, false) ;
3. FrameLayout 뷰(View) 변경하기
예제를 통해 FrameLayout
에 표시되는 뷰(View)를 변경하는 방법에 대해 살펴보겠습니다.
참고로, [안드로이드 프레임레이아웃 뷰 변경하기 1. [addView(), removeView()]]에서 설명한, 뷰(View) 변경 방법은 여기서도 그대로 사용됩니다. 즉, addView(), removeView() 함수가 여기서도 그대로 적용된다는 것입니다.
또한 여기서 사용하는 예제의 화면은 이전 예제와 동일한 레이아웃으로 구성됩니다.
3.1 MainActivity의 레이아웃 구성.
가장 먼저 MainActivity에 표시될 레이아웃 리소스 XML을 작성합니다. 이 때 FrameLayout
에 표시될 뷰(View)는 FrameLayout
의 아래가 아닌, 별도의 XML 파일에 작성됨을 주의하세요.
[STEP-1] "activity_main.xml" - MainActivity의 레이아웃 구성.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.recipes4dev.examples.framelayoutchangingview2.MainActivity"
tools:showIn="@layout/activity_main">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:id="@+id/linear">
<Button
android:id="@+id/button1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Text 1" />
<Button
android:id="@+id/button2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Text 2" />
<Button
android:id="@+id/button3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Text 3" />
</LinearLayout>
<FrameLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:id="@+id/frame"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linear"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
</FrameLayout>
</android.support.constraint.ConstraintLayout>
3.2 FrameLayout에 표시될 뷰(View)에 대한 레이아웃 리소스 XML 추가.
이제 FrameLayout
에 표시될 뷰를 위한 레이아웃 리소스 XML 파일을 추가합니다. 뷰 레이아웃 리소스 XML 파일은 별도의 XML 파일로 작성되며, 각각 "page1.xml", "page2.xml", "page3.xml" 이라는 이름으로 작성합니다.
[STEP-2.1] "page1.xml" - 첫 번째 레이아웃 XML 작성.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#4CAF50"
android:gravity="center"
android:id="@+id/text1"
android:text="TEXT 1" />
</LinearLayout>
[STEP-2.2] "page2.xml" - 두 번째 레이아웃 XML 작성.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF9800"
android:gravity="center"
android:id="@+id/text2"
android:text="TEXT 2" />
</LinearLayout>
[STEP-2.3] "page3.xml" - 세 번째 레이아웃 XML 작성.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#009688"
android:gravity="center"
android:id="@+id/text3"
android:text="TEXT 3" />
</LinearLayout>
3.3 각 버튼 클릭 이벤트 처리.
다음 단계로, 화면에 배치된 버튼의 클릭 이벤트를 작성합니다. 버튼 클릭 시 실질적인 뷰(View) 변경은 다음 단계에서 작성되는 changeView() 라는 함수에 구현하고, 여기서는 단지 changeView() 함수만을 호출하도록 만듭니다.
[STEP-3] "MainActivity.java" - onCreate() 함수에서 각 버튼 클릭 이벤트 처리.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// ... 코드 계속
Button button1 = (Button) findViewById(R.id.button1) ;
button1.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
changeView(0) ;
}
});
Button button2 = (Button) findViewById(R.id.button2) ;
button2.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
changeView(1) ;
}
});
Button button3 = (Button) findViewById(R.id.button3) ;
button3.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
changeView(2) ;
}
});
// 코드 계속 ...
}
}
3.4 FrameLayout에 표시될 뷰 변경 코드 작성.
이제 FrameLayout
에 표시될 뷰(View)를 변경하는 기능을 changeView() 함수에 구현합니다.
[STEP-4] "MainActivity.java" - FrameLayout에 표시될 뷰 변경 코드 작성.
public class MainActivity extends AppCompatActivity {
private void changeView(int index) {
// LayoutInflater 초기화.
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
FrameLayout frame = (FrameLayout) findViewById(R.id.frame) ;
if (frame.getChildCount() > 0) {
// FrameLayout에서 뷰 삭제.
frame.removeViewAt(0);
}
// XML에 작성된 레이아웃을 View 객체로 변환.
View view = null ;
switch (index) {
case 0 :
view = inflater.inflate(R.layout.page1, frame, false) ;
break ;
case 1 :
view = inflater.inflate(R.layout.page2, frame, false) ;
break ;
case 2 :
view = inflater.inflate(R.layout.page3, frame, false) ;
break ;
}
// FrameLayout에 뷰 추가.
if (view != null) {
frame.addView(view) ;
}
}
}
3.5 FrameLayout의 초기 상태 결정.
마지막으로, 앱 시작 시 FrameLayout
에 첫 번째 뷰(View)가 표시되도록 만들기 위해, MainActivity의 onCreate() 함수에서 changeView(0) 을 호출합니다.
[STEP-5] "MainActivity.java" - onCreate() 함수에서 최초 FrameLayout에 표시될 뷰 결정.
public class MainActivity extends AppCompatActivity {
// ... 코드 계속
@Override
protected void onCreate(Bundle savedInstanceState) {
// ... 코드 계속
// 첫 번째 뷰 표시.
changeView(0) ;
}
}
4. 예제 실행 화면
예제 작성을 완료하고 실행하면 아래와 같은 화면이 표시됩니다.
그리고 버튼을 클릭하면, 클릭된 버튼의 순서에 따른 TextView가 FrameLayout
에 번갈아 표시됩니다.
5. 참고.
- 개발자 레시피 - 프레임레이아웃(FrameLayout)
- [안드로이드 프레임레이아웃(Android FrameLayout)]을 참고하세요.
- [안드로이드 프레임레이아웃 뷰 변경하기 1. [addView(), removeView()]]을 참고하세요.
- FrameLayout에 대한 자세한 도움말.
- [안드로이드 개발 참조문서 FrameLayout]을 참고하세요.
- LayoutInflater에 대한 자세한 도움말.
- [안드로이드 개발 참조문서 LayoutInflater]을 참고하세요.
- 개발자 레시피 - 레이아웃 관련 항목
- [안드로이드 레이아웃 (Android Layout)]을 참고하세요.
- [안드로이드 레이아웃 공통사항 (Android Layout Common)]을 참고하세요.
- [안드로이드 리니어레이아웃 (Android LinearLayout)]을 참고하세요.
- [안드로이드 렐러티브레이아웃 (Android RelativeLayout)]을 참고하세요.
- 레이아웃에 대한 자세한 도움말.
- [안드로이드 개발 참조문서 레이아웃 항목]을 참고하세요.
.END.