안드로이드앱 프래그먼트, 프래그먼트 사용하기-1 / Android Studio / 안드로이드 앱만들기 26
프래그먼트를 사용하면
전체 화면 안에 부분화면을 만들어 넣고 화면(새 액티비티)을 전환하지 않고 화면을 넓게 활용할수있다
프래그먼트가 만들어진 목표
- 분할된 화면들을 독립적으로 구성하기 위해 사용해야함
- 분할된 화면들의 상태를 관리하기 위해 사용함
- 프래그먼트가 화면 분할을 위한것이라면 액티비티의 화면과 구별할 수 있어야 한다
- 프래그먼트가 작동하는 시점은 액티비티에 올라가는 시점이다(프래그먼트가 메모리에 만들어진 시점 X)
프래그먼트 사용 전 방식
안드로이드시스템 -> 액티비티매니저 -> 액티비티1 --(인텐트)-- 액티비티2
프래그먼트 사용 후 방식
액티비티 -> 프래그먼트매니저 -> 프래그먼트1 --(메서드호출)-- 프래그먼트2
이런 방식으로 프래그먼트가 사용된다
프래그먼트는 인텐트를 사용할 수 없다
=> 인텐트는 안드로이드 시스템에서 관리하기 때문에
=> 프래그먼트는 메서드 호출을 사용해서 값 전달을 처리한다.
프래그먼트(Fragment) 주요 클래스
public final Activity getActivity()
-> 이 프래그먼트를 포함하는 액티비티를 반환함
public final Fragmentmanager getFragmentManager()
-> 이 프래그먼트를 포함하는 액티비티에서 프래그먼트 객체들과 의사소통하는 프래그먼트 매니저를 반환함
public final Fragment getParentFrgment()
-> 이 프래그먼트를 포함하는 부모가 프래그먼트일 경우 리턴함 / 액티비티면 null을 반환함
public final int getId()
-> 아이디를 반환함
프래그먼트ManagerFragment() 주요 클래스
public abstract FragmentTransaction beginTransaction()
=> 프래그먼트 변경을 하기 위한 트랜잭션 시작
public abstract Fragment findFragmentById()
=> Id를 이용해 프래그먼트 객체 찾기
public abstract Fragment findFragmentByTag(String tag)
=> 태그 정보를 사용해 프래그먼트 객체 찾음.
public abstract boolean executePendingTransactions()
=> 트랜잭션은 commit() 메서드를 호출하면 실행되지만 비동기(asynchronous) 방식으로
실행되므로 즉시 실행하고 싶다면 이 메서드를 추가로 호출해야 함.
- getSupportFragmentManager() 메서드가 getFragmentManager() 메서드와 같은 기능을 한다.
- getSupportFragmentManager() 메서드를 사용하면 예전 버전까지 호환되도록 만들어 준다.
프래그먼트의 특성
특성 | 설명 |
뷰 특성 | 뷰 그룹에 추가되거나 레이아웃의 일부가 될 수 있음 (뷰에서 상속 받는 것은 아니며 뷰를 담고 있는 일종의 틀) |
액티비티 특성 | 액티비티처럼 수명주기(Lifecycle)을 가지고 있다. (컨텍스트 객체는 아니며 라이프사이클은 액티비티에 종속됨) |
- DialogFragment 액티비티 수명주기에 의해 관리되는 대화상자를 보여줄 수 있도록 한다.(액티비티 기본 대화상자 대신 사용할 수 있다)
새로운 프래그먼트를 액티비티 화면에 올리는 과정
1. 새 프로젝트를 만든다
- 책에서는 패키지 이름이 너무 길면 패키지 명을 쓰기 힘들어 패키지 이름을 변경하라고 한다
2. 새 프래그 먼트 추가하기
- 프로젝트 목록화면에서 app에서 우클릭 New -> Fragment -> Fragment (Blank)
3. 새로운 프래그먼트를 만들 수있는 대화상자에 FragmentName:에 글자를 MainFragment로 변경
자동으로 xml 파일까지 만들어진다.
4. FrameLayout으로 되어있는 최상위 레이아웃을 리니어 레이아웃으로 변경한다 orientation vertical
5. 텍스트뷰를 지우고 버튼을 추가한다 "메인 프래그먼트"
6. 버튼을 추가한다 "메뉴 화면으로"
7. MainFragment.java 파일에 많은 내용이 있는데
onCreateView()메서드를 제외한 나머지 코드는 삭제한다고 한다.
(나는 그냥 사용했다 딱히 설명외엔 소스코드에 추가하는거 없었음)
8. onCreateView()메서드 설명
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
// inflater.inflater(레이아웃 파일, xml레이아웃 설정 될 뷰그룹 객체, false)
// container 객체가 전달되는 이유 : 이 프래그먼트의 가장 상위 레이아웃이 container여서
// inflate()메서드를 호출하면 인플레이션이 진행된다 결과로 ViewFroup 객체가 반환된다
// return을 통해 반환한다.
return inflater.inflate(R.layout.fragment_main, container, false);
}
// Inflate the layout for this fragment
// inflater.inflater(레이아웃 파일, xml레이아웃 설정 될 뷰그룹 객체, false)
// container 객체가 전달되는 이유 : 이 프래그먼트의 가장 상위 레이아웃이 container여서
// inflate()메서드를 호출하면 인플레이션이 진행된다 결과로 ViewFroup 객체가 반환된다
// return을 통해 반환한다.
9. XML 레이아웃에 태그로 프래그먼트 추가하기
프래그먼트를 추가하는 방법은 두가지다
- 메인 액티비티의 XML 레이아웃에 태그로 추가
- 메인 액티비티 java소스코드에서 추가)
책에서는 XML 레이아웃에 태그로 추가하는 방법을 알려줌
최상위 레이아웃을 RelatriveLayout으로 변경 id=container
그아래 <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:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<fragment
android:id="@+id/fragment"
android:name="com.togapp.samplefrgment.MainFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
<View 클래스 추가 태그방법이 있다> 그냥 <fragment> 태그를 사용해도 될듯하다
아래 작성된건 View 클래스 추가방법이다.
<com.togapp.samplefrgment.MainFragment
android:id="@+id/fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
실행화면 : 프래그먼트 화면이 메인 액티비티화면에 올라가져 있는 모습
기억하기
프래그먼트 만들어 사용하는 과정
1. 프래그먼트를 위한 XML 레이아웃 만들기
2. 프래그먼트 클래스 만들기
---> New -> Fragment -> Fragment (Blank)
3. 액티비티를 XML 레이아웃에 추가하기
액티비티 화면에 만들어둔 프래그먼트 뷰 추가하기 방법은 2개다
1. XML 레이아웃에 추가하는 방법
2. 자바 소스코드에 추가하는 방법
버튼 클릭하면 코드에서 프래그먼트 추가하기
이번엔 프래그먼트를 만들어주는 메류를 사용하지 않고 프래그먼트 추가한다고한다.
1. /app/res/layout에 있는 fragment_main.xml 파일 복사해서 붙여넣기 후 fragment_menu.xml로 변경
텍스트뷰 "메뉴 프래그먼트"로 변경 버튼 글자 "메인 화면으로" 변경
화면 구분이 가능하게 바탕화면 주황색으로 변경
2. MainFragment.java 복사해서 붙여넣기 MenuFragment.java 만들기
책에서는 3번과 4번을 바꿔 작성하지만 나는 메인액티비티부터 봐야겠다.
3. MainActivity.java 코드 작성
package com.togapp.samplefrgment;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
MainFragment mainFragment;
MenuFragment menuFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// mainFragment는 XML파일에 <Fragment>로 추가되어 있기 때문에 id를 찾아와야한다.
// Activity 클래스에 있는것을 사용할수 없다 (기존에 사용하던 방법으로는 안된다)
// -> FragmentManager를 사용해 findFragmentById() 메서드를 사용해 찾는다.
mainFragment = (MainFragment) getSupportFragmentManager().findFragmentById(R.id.mainFragment);
// 메뉴 프래그먼트는 new 연산자로 새로운 객체를 만들어 변수에 할당한다.
menuFragment = new MenuFragment();
}
public void onFragmentChanged(int index){
// 메인 액티비티에서 프래그먼트를 사용하려면
// getFragmentManager()를 호출해 매니저 객체를 참조해야한다.
// public FragmentManager getFragmentManager()
// 프래그먼트 매니저는 프개르먼트를 추가, 삭제, 교체 등의 작업을 해주는데
// 프래그먼트를 변경할 때 오류가 생기면 다시 원래 상태로 돌릴 수 있어야 해서 트랜잭션을 사용한다.
// 트랜잭션 객체는 beginTransaction() 메서드를 호출하면 시작
// commit()하면 실행
if (index == 0){
getSupportFragmentManager().beginTransaction().replace(R.id.container,menuFragment).commit();
} else if (index == 1){
getSupportFragmentManager().beginTransaction().replace(R.id.container,mainFragment).commit();
}
}
}
***mainFragment = (MainFragment) getSupportFragmentManager().findFragmentById(R.id.mainFragment);
- mainFragment는 XML파일에 <Fragment>로 추가되어 있기 때문에 id를 찾아와야한다.
- Activity 클래스에 있는것을 사용할수 없다 (기존에 사용하던 방법으로는 안된다)
-> FragmentManager를 사용해 findFragmentById() 메서드를 사용해 찾는다.
*** menuFragment = new MenuFragment();
- 메뉴 프래그먼트는 new 연산자로 새로운 객체를 만들어 변수에 할당한다.
- 메인 액티비티에서 프래그먼트를 사용하려면 getFragmentManager()를 호출해 매니저 객체를 참조해야한다.
public FragmentManager getFragmentManager()
- 프래그먼트 매니저는 프개르먼트를 추가, 삭제, 교체 등의 작업을 해주는데 프래그먼트를 변경할 때 오류가 생기면 다시 원래 상태로 돌릴 수 있어야 해서 트랜잭션을 사용한다.
- 트랜잭션 객체 beginTransaction() 메서드를 호출하면 시작 commit()하면 실행
if (index == 0){
getSupportFragmentManager().beginTransaction().replace(R.id.container,menuFragment).commit();
} else if (index == 1){
getSupportFragmentManager().beginTransaction().replace(R.id.container,mainFragment).commit();
}
4. MainFragment.java 코드 작성
- 이제 메뉴화면이 생겼으니 버튼을 클릭하면 메뉴 프래그먼트로 전환되도록 만들어야한다.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// 최상위 레이아웃은 인플레이션을 통해 참조 (rootView는 메인프래그먼트 안에 들어있다 이 레아웃을 화면에 보여주기 위한 틀)
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_main, container, false);
Button button = rootView.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MainActivity activity = (MainActivity) getActivity();
// onFragmentChanged() 메인 액티비티에 추가될 메서드다
// 메인 액티비티에 추가할 메서드로 프래그먼트 매니저를 이용해 프래그먼트를 전환할 메서드를 만들것
activity.onFragmentChanged(0);
}
});
return rootView;
}
5. 실행하면 화면이 나와야한다.
오류가 생김
T:\Android\SampleFrgment\app\src\main\res\values\ids.xml:3:5-60:
AAPT: error: <item> inner element must either be a resource reference or empty.
이런 오류가 생겼는데 일단 책에 있는 그대로 따라하지 않고
디자인툴에서 사용한 문제인거 같다 <item>의 내부요소를 비우라는거 같다
파일 위치를 갔다
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="mainFragment" type="id">mainFragment</item>
</resources>
이렇게 작성된걸
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="mainFragment" type="id"></item>
</resources>
비워버리니 문제가 없다
아까 mainActivity.java 코드 작성할때
mainFragment = (MainFragment) getSupportFragmentManager().findFragmentById(R.id.mainFragment);
이부분에서 마지막 (R.id.mainFragment) 가 빨간부분으로 오류였다. 아무래도 이문제였던거 같다.
/app/res/values/ids.xml 파일이 어떤 파일인지는 알지 못하나 일단 해결
6. 실행화면
![]() |
![]() |
github.com/young-0112/SampleFrgment
young-0112/SampleFrgment
Frgment 프래그먼트 프래그먼트매니저 활용법 태그를 통해 추가하는법. Contribute to young-0112/SampleFrgment development by creating an account on GitHub.
github.com