안드로이드 Fragment 예제를 간략하게 정리했다.
API Level 11(Android 3.0) 이상에서 지원한다. 요즈음에는 최소 4.4 이상으로 컴파일을 하므로 기본적으로 제공된다고 볼 수 있다.
Fragment를 사용하는 가장 큰 목적은 분할된 화면들을 독립적으로 구성하고 그 상태를 관리하는데 있다.
Fragment는 항상 Activity 위에 올라가 있어야 한다.
Activity 로 만들어진 화면을 분할하여 각각의 부분화면을 Fragment로 만들고 그 Fragment를 독립적으로 관리하는 것을 목표로 한다.
Fragment는 항상 Activity 내에 포함되어 있어야 하며 해당 Fragment의 수명 주기는 호스트 Activity의 수명 주기에 직접적으로 영향을 받는다.
예를 들어 Activity가 일시정지되는 경우, 그 안의 모든 Fragment도 일시정지되며 Activity가 소멸되면 모든 Fragment도 마찬가지로 소멸된다. 그러나 Activity가 실행 중인 동안에는 각 Fragment를 추가 또는 제거하는 등 개별적으로 조작할 수 있다.
Activity 의 UI를 보여주기 위해서 onCreate 메소드를 Override 하고 Layout Resource ID인 R.layout.activity_main을 파라미터로 넘기면서 setContentView 메소드를 호출한다.
먼저, MainActivity 에 표시될 Layout XML 구조는 아래에 버튼을 클릭하면 Fragment 화면이 변경되도록 구성했다.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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">
<LinearLayout android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:layout_above="@+id/tabmenuLayout" />
<LinearLayout android:id="@+id/tabmenuLayout" android:layout_width="match_parent" android:layout_height="50dp" android:orientation="horizontal" android:layout_alignParentBottom="true" >
<Button android:id="@+id/btn_tab1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="Tab 1"/>
<Button android:id="@+id/btn_tab2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="Tab 2"/>
<Button android:id="@+id/btn_tab3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="Tab 3"/>
</LinearLayout> </RelativeLayout> |
fragment_container 에 표시될 Fragment XML 은 다음과 같다.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent">
<TextView android:gravity="center" android:layout_width="match_parent" android:layout_height="match_parent" android:text="프래그먼트 1" />
</RelativeLayout> |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ffe4e1">
<TextView android:gravity="center" android:layout_width="match_parent" android:layout_height="match_parent" android:text="프래그먼트 2" />
</RelativeLayout> |
<?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:orientation="vertical" android:background="#81DAF5" >
<TextView android:id="@+id/fr_tv03" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_centerInParent="true" android:text="프래그먼트 3" android:textStyle="bold"/>
</RelativeLayout> |
Fragment01.java
Alt + Insert 키를 눌러서 아래 메소드를 추가한 다음에 view를 return해 주도록 코드를 수정한다.
Fragment는 Fragment Class 를 상속하여 만들 수 있다.
public class Fragment01 extends Fragment {
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); }
@Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { // onCreateView() : 프래그먼트와 연관된 뷰 계층을 생성하기 위해 호출됨 // Inflate the layout for this fragment ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.fragment_01, container, false); return rootView; //return super.onCreateView(inflater, container, savedInstanceState); // Alt + Insert키 누르면 자동 생성되는 return } } |
Fragment02.java
- Activity 에서 전달한 데이터를 받아서 화면에 표시하기
- Fragment 로 데이터 전달법은 구글에서 Passing data to activity and fragment in Android 로 검색하면 된다.
- onCreateView 에서 Activity 에서 전달한 데이터를 받아도 된다.
public class Fragment02 extends Fragment { TextView textView; String strtext;
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { strtext = getArguments().getString("edttext"); // Activity 에서 받은 데이터 } }
@Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.fragment_02, container, false); textView = (TextView) rootView.findViewById(R.id.fr_tv02); textView.setText(strtext); return rootView; //return super.onCreateView(inflater, container, savedInstanceState); } } |
Fragment03.java
public class Fragment03 extends Fragment { TextView textView;
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); }
@Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { // onCreateView()로 전달된 container 매개변수가 상위 ViewGroup 이며(액티비티의 레이아웃으로부터), 이 안에 프래그먼트 레이아웃이 삽입 // savedInstanceState 매개변수는 Bundle이며, 프래그먼트가 재개되는 중에 프래그먼트의 이전 인스턴스에 대한 데이터를 제공 // Inflate the layout for this fragment // Inflate 시키고자 하는 Layout 의 Resource ID, Inflated 된 Layout 의 상위가 될 ViewGroup ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.fragment_03, container, false); textView = (TextView) rootView.findViewById(R.id.fr_tv03); textView.setText("Fragment 3을 선택했네요."); return rootView; } } |
MainActivity.java
Activity에서 Fragment를 불러오는 기능을 수행
public class MainActivity extends AppCompatActivity implements View.OnClickListener { Context context; private Button tab1, tab2, tab3; private Fragment fragment = null;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); context = this.getBaseContext();
tab1 = findViewById(R.id.btn_tab1); tab2 = findViewById(R.id.btn_tab2); tab3 = findViewById(R.id.btn_tab3);
tab1.setOnClickListener(this); tab2.setOnClickListener(this); tab3.setOnClickListener(this);
if(findViewById(R.id.fragment_container) != null){ if(savedInstanceState != null) return; Fragment01 fragment01 = new Fragment01(); fragment01.setArguments(getIntent().getExtras());
FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); // add() 메서드를 사용하여 프래그먼트를 추가하고, 추가할 프래그먼트와 이를 삽입할 뷰를 지정 fragmentTransaction.add(R.id.fragment_container, fragment01); // FragmentTransaction을 변경하고 나면, 반드시 commit()을 호출해야 변경 내용이 적용됨 fragmentTransaction.commit(); } // 상세 설명은 https://developer.android.com/guide/components/fragments?hl=ko 참조 }
@Override public void onClick(View v) { switch (v.getId()){ case R.id.btn_tab1: fragment = new Fragment01(); changeFragment(fragment); break; case R.id.btn_tab2: Bundle bundle = new Bundle(); bundle.putString("edttext", "From Activity"); fragment = new Fragment02(); fragment.setArguments(bundle); // Fragment 로 데이터 전달 changeFragment(fragment); break; case R.id.btn_tab3: fragment = new Fragment03(); changeFragment(fragment); break; } }
private void changeFragment(Fragment fragment) { // 프로그래밍 방식으로 프래그먼트를 기존의 ViewGroup에 추가 // 액티비티가 실행 중인 동안에는 언제든 액티비티 레이아웃에 프래그먼트를 추가 가능 // 액티비티 내의 프래그먼트를 관리하려면 FragmentManager를 사용해야 함. FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.replace(R.id.fragment_container,fragment); //fragmentTransaction.addToBackStack(null); // back 버튼을 눌렀을 때 동작하는 옵션. fragmentTransaction.commit(); // 트랜잭션을 액티비티에 적용하려면 반드시 commit()을 호출해야 함. } } |
Fragment는 Activity가 아니기 때문에 context를 갖지 않는다.
Fragment 구현시 context를 이용해야 할 경우 getActivity()함수를 이용한다.
getActivity().getApplicationContext();
getActivity().finish();
getActivity().getSharedPreferences("pref", Activity.MODE_PRIVATE);
getActivity().getSystemService(Context.USB_SERVICE);
getActivity().getSystemService(getActivity().CLIPBOARD_SERVICE);
테스트 파일
src.zip
사양이 낮은 폰에서 테스트를 못해봤는데 만약 동작되지 않는다면, import 수정.
http://www.androhub.com/android-pass-data-from-activity-to-fragment/ 에 나오는 import 참조하면 될 듯....
참조하면 도움되는 게시글
http://family-gram.tistory.com/60