본문 바로가기
Android/Concepts

Fragment 사용법

by JuHy_ 2020. 4. 9.

Fragment란?

앱을 개발하다 보면 하나의 액티비티 안에 부분적인 화면을 추가하고 싶을 때가 있다.

특히 액티비티 안에 여러 부분 화면이 전환되게 만들 때 이를 액티비티로 구현하면 앱이 무거워지고 복잡해진다.

그리고 하나의 똑같은 화면을 여러 액티비티에서 사용하고 싶은데 액티비티마다 모두 구현하는 것은 비효율적이다.

이를 해결하기 위해 부분 화면을 독립적으로 분리되어 사용할 수 있게 만들어 놓은 것이 Fragment이다.

 

Fragment의 특징

Fragment는 기본적으로 액티비티를 본따 만들었기 때문에 비슷한 구조와 특징을 갖고 있다.

액티비티 간 이동은 시스템에서 Intent를 통해 이동하듯이, Fragment는 Fragment Manager를 통해 이동한다.

이 때 Fragment는 Activity 위에서 동작하기 때문에 Intent가 아닌 메소드 호출을 통해 이동하게 된다.

 

Fragment 사용법

Fragment도 액티비티처럼 기본적으로 xml 파일과 class 파일 하나로 구성되며 이를 name을 통해 불러올 수 있다.

그리고 setContentView() 함수가 없기 때문에 직접 inflation을 통해 view들을 불러와야 한다.

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F44336">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="40sp"
        android:textColor="#FFFFFF"
        android:text="Fragment 1" />

</RelativeLayout>

△fragment_main.xml

 

먼저 fragment의 화면 구성 layout 파일을 만들어주자.

간단하게 배경 색과 textview 하나만 띄워주었다.

 

package com.juhy.myapplication;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class MainFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_main, container, false);

        return rootView;
    }
}

△MainFragment

 

그 다음 Fragment를 상속받아 클래스 파일을 하나 만들어준 뒤

액티비티에서 onCreate() 함수를 사용하듯이 onCreateView() 함수를 override 해준다.

그리고 앞서 말했듯 setContentView() 함수가 아닌 파라미터의 inflater 객체를 통해 레이아웃 파일을 inflate 해준다.

마지막으로 inflate() 함수에서 반환받을 객체를 ViewGroup 객체에 담은 뒤 return 해주면 된다.

 

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@id/button" >

    <fragment
        android:id="@+id/fragment_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.juhy.myapplication.MainFragment" />

</FrameLayout>

△activity_main.xml

 

fragment를 띄울 액티비티의 layout에 fragment를 넣어준 뒤, name으로 만들어준 fragment 클래스를 넣어준다.

 

package com.juhy.myapplication;

import androidx.fragment.app.FragmentActivity;

import android.os.Bundle;

public class MainActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

}

△MainActivity

 

※ API 28부터는 Activity나 AppCompatActivity에서는 fragment를 사용할 수 없다.

따라서 API 28 이상이라면 fragment가 올라갈 액티비티는 FragmentActivity를 상속받도록 바꿔주자.

 

실행해보면 정상적으로 부분 화면이 구현된 것을 볼 수 있다.

 

java 코드로 추가하기

package com.juhy.myapplication;

import androidx.fragment.app.FragmentActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainFragment fragment1 = new MainFragment();
                getSupportFragmentManager().beginTransaction().add(R.id.framelayout, fragment1).commit();
            }
        });

    }

}

△MainActivity

 

Fragment 객체를 생성해준 뒤 SupportFragmentManager를 통해 추가할 위치와 fragement 객체를 넣어주면 된다.

이 때 transaction이란 명령어를 수행하기 위한 기반이고, add() 함수는 fragment를 추가하겠다는 뜻이다.

 

Activity에서 Fragment 전환하기

package com.juhy.myapplication;

import androidx.fragment.app.FragmentActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends FragmentActivity {

    MainFragment fragment_main;
    MenuFragment fragment_menu;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fragment_main = new MainFragment();
        fragment_menu = new MenuFragment();

        Button button_main = findViewById(R.id.button_main);
        button_main.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getSupportFragmentManager().beginTransaction().replace(R.id.framelayout, fragment_main).commit();
            }
        });

        Button button_menu = findViewById(R.id.button_menu);
        button_menu.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getSupportFragmentManager().beginTransaction().replace(R.id.framelayout, fragment_menu).commit();
            }
        });

    }

}

△MainActivity

 

fragment를 추가할 때와 마찬가지로 FragmentManager를 사용하면 된다.

이 때 add() 함수가 아닌 replace() 함수를 사용하면 된다.

 

버튼을 눌러보면 정상적으로 fragment가 전환되는 것을 볼 수 있다.

 

Fragment 내부에서 다른 Fragment로 전환하기

앞에서는 fragment가 올라가 있는 activity에서 코드를 작성했기 때문에 전환이 수월했다.

하지만 fragment 끼리는 독립적으로 분리되어 있기 때문에 서로에게 직접적인 접근을 권장하지 않는다.

따라서 fragment 내부에서 다른 fragment를 호출하려면 올라가 있는 activity에 요청해야 한다.

 

package com.juhy.myapplication;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class MainFragment extends Fragment {

    MainActivity activity;

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);

        activity = (MainActivity) getActivity();
    }

    @Override
    public void onDetach() {
        super.onDetach();

        activity = null;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_main, container, false);

        Button btn_change = rootView.findViewById(R.id.button_change);
        btn_change.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                activity.changeFragment(2);
            }
        });

        return rootView;
    }
}

△MainFragment

 

fragment가 activity에 올라갔을 때(onAttach) getActivity() 메소드를 통해 올라간 activity를 저장해준다.

(onAttach는 fragment의 생명주기 중 하나로 onCreateView보다 먼저 activity에 올라간 시점에 호출된다)

그리고 버튼을 눌렀을 때 activity에 fragment를 전환해주는 메소드를 호출한다.

 

public void changeFragment(int index){
    switch(index){
        case 1:
            getSupportFragmentManager().beginTransaction().replace(R.id.framelayout, fragment_main).commit();
            break;
        case 2:
            getSupportFragmentManager().beginTransaction().replace(R.id.framelayout, fragment_menu).commit();
            break;
    }
}

△MainActivity의 changeFragment()

 

changeFragment()에서는 index에 따라 다른 fragment를 replace() 함수를 통해 전환하도록 했다.

 

MainFragment를 띄운 뒤 전환 버튼을 누르면 MenuFragment로 잘 전환되는 것을 볼 수 있다.

 

 

Reference

[부스트코스]안드로이드 프로그래밍

https://www.edwith.org/boostcourse-android

'Android > Concepts' 카테고리의 다른 글

TabLayout 사용법  (1) 2020.04.14
ActionBar에 Menu 추가하기  (0) 2020.04.13
Permission 획득하기  (0) 2020.04.04
Broadcast Receiver를 이용한 SMS 수신  (3) 2020.04.04
Service의 기본적인 사용법  (0) 2020.04.03