본문 바로가기

유저 인터페이스/프래그먼트(Fragment)

프래그먼트(Fragment) 정복! - (2) 프래그먼트 자세히 알아보기

프래그먼트를 가장 간단하게 표현하자면 '뷰(View)처럼 사용할 수 있는 액티비티(Activity)'라 할 수 있습니다. 즉, 액티비티와 뷰의 특징을 모두 가지고 있습니다. 프래그먼트는 뷰에게 레이아웃 내에 자유롭게 배치될 수 있는 특징을 물려받았는데, 그렇다면 액티비티에서는 어떤 특징을 물려받았을까요? 바로 '생애주기'를 갖는 특징입니다.

프래그먼트의 생애주기


 프래그먼트는 액티비티와 같이 프래그먼트의 상태가 계속해서 변하며, 상태가 변할 때마다 그에 해당하는 생애주기 메서드(콜백 메서드)가 호출됩니다. 프래그먼트의 생애주기 메서드 및 각 메서드의 호출 순서는 다음과 같습니다.

프래그먼트의 생애주기 메서드


각 생애주기 메서드에 대해 더 자세히 알아보도록 하겠습니다. 액티비티의 생애주기 메서드와 매우 유사한 형태를 띄고 있으며, 뷰 생성과 관련된 몇몇 메서드가 더 추가되어 있습니다.

onAttach(Activity)
프래그먼트가 액티비티 레이아웃에 포함되는 순간 호출됩니다. 액티비티 레이아웃에 프래그먼트를 정적으로 배치했다면 액티비티가 시작될 때 같이 호출되며, 동적으로 레이아웃에 추가할 땐 프래그먼트를 레이아웃에 추가하는 순간 호출됩니다.


onCreate(Bundle)
액티비티의 onCreate() 콜백 메서드와 유사하게 프래그먼트가 최초로 생성될 때 호출됩니다.


onCreateView(LayoutInflater, ViewGroup, Bundle)
프래그먼트의 UI를 구성하는 뷰(View)를 반환합니다. UI를 가지지 않는 프래그먼트일 경우 null을 반환할 수도 있습니다.


onStart()
프래그먼트가 화면에 표시될 때 호출됩니다. 하지만, 아직 사용자와 상호작용은 할 수 없는 상태입니다.


onResume()
프래그먼트가 사용자와 상호작용을 할 수 있게 되었을 때 호출됩니다. 즉, 프래그먼트가 완전히 화면에 표시되어 제 역할을 수행할 수 있게 된 상태입니다.


onPause()
액티비티의 onPause()와 유사하게 프래그먼트가 사용자와 상호작용을 할 수 없게 될 때 호출됩니다. 프래그먼트가 아직 화면에 표시되고 있는 상태이나, 다른 요소에 의해 프래그먼트가 가려져 상호작용을 하지 못하는 상태입니다.


onStop()
프래그먼트가 화면에서 보이지 않게 될 때 호출됩니다. 액티비티가 화면에서 보이지 않게 될 때 onStop() 메서드가 호출되는 것과 유사합니다.


onDestroyView()
프래그먼트가 화면에서 사라진 후, 뷰의 현재 상태가 저장된 후 호출됩니다. 여기에서 저장된 뷰의 상태는 액티비티와 유사하게 Bundle 형태로 저장되며, 저장된 뷰의 상태는 onCreate() 및 onCreateView()에서 다시 불러들일 수 있습니다.


onDestroy()
프래그먼트가 더 이상 사용되지 않을 때 호출됩니다. 


onDetach()
프래그먼트가 액티비티 레이아웃에서 제거될 때 호출됩니다. 


위와 같이 프래그먼트의 생애주기는 액티비티와 매우 유사합니다. 때문에 기존에 액티비티로 작성되어 있던 코드를 쉽게 프래그먼트로 옮겨올 수 있습니다. 

프래그먼트에는 위의 생애주기 메서드 외에도 프래그먼트를 포함하고 있는 액티비티의 생성이 완료되었을 때 호출되는 콜백 메서드도 포함하고 있으며, 그 메서드는 다음과 같습니다.

onActivityCreated(Bundle)
프래그먼트를 포함하고 있는 액티비티의 생성이 완료되었을 때, 즉 액티비티의 onCreate() 메서드가 끝났을 때 호출됩니다.


프래그먼트를 레이아웃에 추가하기 (XML 사용)


프래그먼트의 특징에 대해 간단히 알아보았으니, 우선 프래그먼트를 레이아웃에 추가하는 방법에 대해 알아보도록 하겠습니다. 프래그먼트를 레이아웃에 추가하는 방법은 여러 가지가 있지만, 그 중에서도 가장 간단한 방법인 XML 레이아웃을 사용하여 추가하는 방법을 알아보겠습니다.

[어플리케이션 정보]

액티비티
  • Main (Main.java)

레이아웃
  • main.xml (Main)
  • fragment_one.xml (FragmentOne 프래그먼트)

API Level
  • Android 3.0 (API Level 11)



우선, 프래그먼트에 표시할 레이아웃 파일을 작성합니다. 다음과 같이 fragment_one.xml 레이아웃 파일을 추가한 후,TextView 하나를 추가합니다.

[fragment_one.xml]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  
  	<TextView android:layout_width="wrap_content"
  		android:layout_height="wrap_content"
  		android:text="Fragment One" />
  
</LinearLayout>

액티비티 코드에 프래그먼트 클래스를 추가한 후, 프래그먼트에 표시할 뷰를 지정해주기 위해 onCreateView() 다음과 같이 메서드를 오버라이드합니다. 프래그먼트에서 표시할 뷰를 반환하기 위해 onCreateVIew()의 인자 중 하나인 LayoutInflater를 사용합니다.


[Main.java]
public class Main extends Activity {
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    
    public static class FragmentOne extends Fragment{

		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			return inflater.inflate(R.layout.fragment_one, null);
		}
    	
    }
    
}

다음, 액티비티의 레이아웃을 작성합니다. 프래그먼트를 XML 레이아웃 파일에서 선언할 때는 프래그먼트의 클래스(class)와 프래그먼트를 구분할 수 있는 id 혹은 tag를 필히 지정해야 합니다. 여기에서는 프래그먼트를 구분하기 위해 id를 지정해 주었습니다.

이 예제에서 프래그먼트 클래스가 Main 클래스의 내부 클래스로 선언되어 있기 때문에 Main$FragmentOne과 같이 클래스 이름을 지정해 주었습니다.


[main.xml]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
>
	<fragment
		android:id="@+id/fragment_one"
		class="com.androidhuman.example.SimpleFragment.Main$FragmentOne"
		android:layout_width="match_parent"
		android:layout_height="match_parent" />
</LinearLayout>


이것으로 모든 구현이 끝났습니다. 생각보다 간단하지요? 예제를 실행하면 다음과 같이 프래그먼트가 표시되는 것을 확인할 수 있습니다.


프래그먼트라는 것을 처음 접할 때는 아직 익숙하지 않아 어려워 보였을지도 모릅니다. 간단한 예제를 통해 알아본 것과 같이 접해보면 그리 어렵지 않습니다.

다음 포스트에서는 프래그먼트를 사용하는 가장 큰 장점 중 하나라 할 수 있는 프래그먼트 전환에 대해 다루어보도록 하겠습니다. :)