안드로이드 프레임레이아웃 뷰 변경하기 2. [LayoutInflater] (How to change a View in Android FrameLayout 2)

2017. 5. 22. 14:39


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() 함수를 통해 뷰에 포함된 위젯에 대한 참조를 획득할 수 있습니다.

FrameLayout 뷰 변경하기 2 LayoutInflater 클래스


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() 함수가 여기서도 그대로 적용된다는 것입니다.


또한 여기서 사용하는 예제의 화면은 이전 예제와 동일한 레이아웃으로 구성됩니다.

FrameLayout 뷰 변경하기 2 예제 화면 레이아웃



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" 이라는 이름으로 작성합니다.

FrameLayout 뷰 변경하기 2 페이지 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. 예제 실행 화면

예제 작성을 완료하고 실행하면 아래와 같은 화면이 표시됩니다.

FrameLayout 뷰 변경하기 2 예제 실행 화면 1


그리고 버튼을 클릭하면, 클릭된 버튼의 순서에 따른 TextView가 FrameLayout에 번갈아 표시됩니다.

FrameLayout 뷰 변경하기 2 예제 실행 화면 2


5. 참고.

.END.


ANDROID 프로그래밍/LAYOUT