ANDROID 프로그래밍/LAYOUT

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

뽀따 2017. 5. 19. 12:57


1. FrameLayout에 표시되는 뷰 변경하는 방법

[안드로이드 프레임레이아웃(Android FrameLayout)]에서 설명했듯이, FrameLayout은 자식(Children)으로 추가된 여러 뷰(View) 위젯들 중 하나를 Layout의 전면에 표시할 때 사용하는 Layout 클래스입니다. 그리고 안드로이드에서는 FrameLayout이 오직 하나의 자식(Child) 뷰 위젯만을 표시하게 만들도록 권고하고 있죠.


FrameLayout에 하나의 뷰(View)만을 표시하는 방법은, addView() 및 removeView()를 사용하여 FrameLayout이 하나의 뷰(View)만을 가지게 만들거나, FrameLayout에 여러 자식(Children) 뷰 위젯을 추가해두고 자식(Child) 뷰 위젯의 visibility 속성을 사용하여 하나의 뷰(View)만 화면에 보이도록 만드는 방법이 있습니다.


여기서는 두 가지 방법 중, addView() 및 removeView() 함수를 사용하여 하나의 뷰(View)만 가지도록 만드는 방법에 대해 살펴보겠습니다.

2. addView() 함수와 removeView()

FrameLayout에 뷰(View)를 추가하는 함수는 addView() 함수입니다. addView() 함수를 사용하여 여러 개의 뷰(View)를 추가하면, 마지막으로 추가된 뷰(View)가 FrameLayout의 전면에 표시됩니다. "액자"의 제일 앞에 사진을 끼우는 것처럼 말이죠. 또한 addView() 함수는 파라미터가 다른 여러 함수가 오버로딩(overloading)되어 있습니다.


함수명 설명
addView(View child,
ViewGroup.LayoutParams params)
params 설정을 가진 child 뷰 추가.
addView(View child, int index) index 위치에 child 뷰 추가.
addView(View child, int index,
ViewGroup.LayoutParams params)
params 설정을 가진 index 위치에 child 뷰 추가.
addView(View child) chlid 뷰 추가.
addView(View child, int width, int height) width x height 크기를 가진 child 뷰 추가.


FrameLayout에서 뷰(View)를 삭제하는 함수는 removeView() 함수입니다. 그런데 removeView() 함수는 파라미터가 다른 동일한 함수가 존재하지 않습니다. 대신, 기능에 따라 구분된 다른 이름의 함수가 정의되어 있습니다.


함수명 설명
removeAllViews() FrameLayout에 포함된 모든 자식(Children) 뷰 제거.
removeAllViewsInLayout() FrameLayout 내부에서 모든 자식(Children) 뷰 제거.
removeView(View view) FrameLayout에서 view 제거.
removeViewAt(int index) FrameLayout의 index 위치 자식(Child) 뷰 제거.
removeViewInLayout(View view)

FrameLayout 내부에서 view 제거.

removeViews(int start, int count) FrameLayout의 start 위치부터 count 갯수만큼 자식(Children) 뷰 제거.
removeViewsInLayout(int start, int count) FrameLayout에서 start 위치부터 count 갯수만큼 자식(Children) 뷰 제거.

3. FrameLayout 뷰(View) 변경하기

그럼 이제 예제를 통해, addView()와 removeView() 함수를 사용하여 FrameLayout에 표시되는 뷰(View)를 변경하는 방법에 대해 살펴보겠습니다.


예제에서 작성하는 화면은 아래와 같은 레이아웃으로 구성됩니다.



참고로 예제 소스에서는, 코드의 쉬운 이해를 위해 FrameLayout에 표시될 뷰(View)들을 개별적인 변수로 선언하였습니다. 하지만 개별 변수로 선언하는 방법은, 전환될 뷰(View)가 많아지면 구현 및 관리가 용이하지 않습니다. 그래서 개선된 코드를 주석에 같이 기록하였으며, "개선된 코드"라는 주석에서 확인할 수 있습니다.

3.1 MainActivity의 레이아웃 구성.

예제 작성을 위해 가장 먼저 할 일은, 앞서 설계한 화면에 따라 MainActivity에 표시될 레이아웃 리소스 XML을 작성하는 것입니다.

[STEP-1] "activity_main.xml" - MainActivity의 Layout 구성.
<?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.framelayoutchangingview1.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">

        <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" />

        <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" />

        <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" />

    </FrameLayout>

</android.support.constraint.ConstraintLayout>

3.2 각 버튼 클릭 이벤트 처리.

화면에는 세 개의 버튼이 있고, 각 버튼을 클릭하면 순서에 따른 텍스트뷰가 화면에 표시됩니다. 이를 위해 각 버튼의 클릭 이벤트를 작성합니다. 단, 실질적인 FrameLayout의 뷰(View) 변경은 다음 단계에서 changeView() 라는 함수에 작성하고, 버튼 클릭 이벤트 핸들러에서는 changeView() 함수를 호출하도록 만듭니다.

[STEP-2] "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.3 FrameLayout에 표시될 뷰 변경 코드 작성.

이제 FrameLayout에 표시될 뷰(View)를 변경하는 기능을 구현합니다. 이를 위해 changeView()라는 함수를 추가한 다음, removeViewAt() 함수와 addView() 함수를 호출하여 뷰(View)를 제거 및 추가합니다.

[STEP-3] "MainActivity.java" - FrameLayout에 표시될 뷰 변경 코드 작성.
public class MainActivity extends AppCompatActivity {

    // textView 참조를 저장하기 위한 변수.
    TextView textView1 ;
    TextView textView2 ;
    TextView textView3 ;
    // TextView textViews[3] ;  // 개선된 코드 (textView 참조를 저장하기 위한 변수.)

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        // ... 코드 계속

        // textView에 대한 참조 획득.
        textView1 = (TextView) findViewById(R.id.text1) ;
        textView2 = (TextView) findViewById(R.id.text2) ;
        textView3 = (TextView) findViewById(R.id.text3) ;
        /* // 개선된 코드 (textView에 대한 참조 획득.)
        textViews[0] = (TextView) findViewById(R.id.text1) ;
        textViews[1] = (TextView) findViewById(R.id.text2) ;
        textViews[2] = (TextView) findViewById(R.id.text3) ;
        */

        // 코드 계속 ...
    }

    private void changeView(int index) {

        FrameLayout frame = (FrameLayout) findViewById(R.id.frame) ;

        // 0 번째 뷰 제거. (뷰가 하나이므로, 0 번째 뷰를 제거하면 모든 뷰가 제거됨.)
        frame.removeViewAt(0) ;

        // index에 해당하는 textView 표시
        switch (index) {
            case 0 :
                frame.addView(textView1) ;
                break ;
            case 1 :
                frame.addView(textView2) ;
                break ;
            case 2 :
                frame.addView(textView3) ;
                break ;
        }

        /* // 개선된 코드 (index에 해당하는 textView 표시.)
            if (index < 3) {
                frame.addView(textViews[index]) ;
            } else {
                // TODO : index error.
            }
        */
    }
}

3.4 FrameLayout의 초기 상태 결정.

마지막으로, 앱 시작 시 FrameLayout에 표시될 뷰(View)를 결정하기 위해 textView2와 textView3는 removeView() 함수로 제거합니다.

[STEP-4] "MainActivity.java" - onCreate() 함수에서 화면에 표시될 뷰를 제외한 모든 뷰 제거.
public class MainActivity extends AppCompatActivity {

    // ... 코드 계속

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        // ... 코드 계속

        FrameLayout frame = (FrameLayout) findViewById(R.id.frame) ;

        // textView1을 제외한 모든 뷰 제거.
        // frame.removeView(textView1) ;
        frame.removeView(textView2) ;
        frame.removeView(textView3) ;
        /* // 개선된 코드 (textView1을 제외한 모든 뷰 제거.)
        frame.removeAllViews() ;
        frame.addView(textView1) ;
        */
    }
}

4. 예제 실행 화면

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


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


5. 참고.

.END.