티스토리 뷰

Android

[Android]프래그먼트 (Fragment)

감자형 2017. 9. 24. 21:05

    프래그 먼트란(Fragment)?


1
2
3
- 액티비라는것 안에 부분화면이 만들어 지는경우가 있는데, 화면의 일부만 차지하는것을 말한다.
 버튼같은경우도 하나의 위젯만 만들어 진다. 이것을 뷰처럼 아예 정의해서 사용하는경우가 있다. 
부분화면을 뷰로 만들어서 집어 넣다보니까 만약에 화면이 여러개가 될경우에 화면각각에다가
그 반복되는부분을 넣어야 되는 문제점이 생기게 된다. 태그를 계속 복사해야하는 복잡함이 발생하게 된다.
액티비티는 독립적인 구성요소 이므로, 다른 기능이 아님에도 불구하고 계속 코드를 넣어줘야한다.

cs

부분적으로 잡아줘야하는것들을 독립적으로 동작할수 없을까? 하는 문제점을 제기하게 된다.

1
2
3
4
5
6
7
8
9
- 태블릿과 같이큰 화면에서는 한 화면에 여러 부분화면을 넣는것이 효율적이다.
- 지금은 독립적으로 이렇게 화면을 구성할 수 있는데, 이것을 프래그 먼트라고 한다.
- 프래그먼트는 부분 화면을 독립적으로 만들어 주며 액티비티를 그대로 본떠 만든것이다.
프래그먼트 #1 , #2를 만들어 놓으면 프래그먼트 매니저가 메소드호출로서 간단하게 사용할 수 있다.
(직접 접근 X , 하나의 액티비티과 같은것이라고 생각하면 된다. 시스템이 모든것이 제어하므로,
 중간 역할자가 필요하다(프래그먼트 매니저에게 요청을 해야한다))
- 액티비티 위에 올라가야한다 ( 프래그먼트, 프래그먼트 매니저)
- 일반적으로 액티비티는 인텐트로 넘겨주지만, 프래그먼트는 메소드를 하나 정의해서 호출하는 방식이다. 
cs

    프래그먼트를 이용해 화면 전환 하기

1
2
3
4
5
6
7
8
1. #1화면을 제거 하고 화면 #2를 추가 하면 -> 화면전환 효과를 만들어 낸다.
 
2. 액티비티는 시스템에서 관리하므로 리소스가 무겁다
 
3. 프래그먼트를 사용하게 되면 실제로는 매우 가볍게 화면이 전환이가능하다
 
4. 시스템에서 접근하지 않으므로 보안쪽으로 장점도 있다.
 
cs

    프래그먼트를 화면에 추가하기

1
2
3
4
5
1. 프래그먼트는 액티비티 위에 올라가야 프래그먼트로 동작한다
 
2. 인플레이션을 위한 별도의 콜백 메소드를 제공한다.
 
3. 직접 인플레이션 과정을 거쳐야한다 (XML -> JAVA)
cs

    Example_Fragment 프로젝트 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1. main.xml파일 수정
 RelativeLayout 을 기본 레이아웃으로 설정
 
2. 프레그먼트 만들기
res -> layout ->new -> new Resource file (fragment_main.xml 생성) 부분화면을 뜻함.
 
3. app -> java -> MainFragment.java 생성 -> superclass(android support.v4.app) 선택 -> 생성 해준다.
 
4. onCreateView 함수 사용 (오버라이드 한다)
 
5. 그다음에 이제 메인.xml로 가서 플래그먼트 추가 시켜준다.
 
6. 플래그먼트든 뷰든 메인액티비티에 추가하는방법 2가지
- xml , java 소스 코드 두가지 방법
- MainFrgment.java를 만들면 view를 만들어서 추가할수 있다.
- 플래그먼트는 플래그먼트 매니저가 추가 할 수 있다.
 
7. 플래그 먼트를 소스파일에서 추가하는 것을 해보도록 하자.
 
 
8. Main.java 로 이동
 
 
9. fragment_menu.xml 추가
 
10.플래그먼트는 xml과 java 파일이 한꺼번에 뷰처럼 역할을 한다. 하지만 이것은 fragmentmanager에서 관리를 한다. 
cs

    *동작 원리 중요* 

1
2
3
4
5
6
7
8
9
10
11
1. fragment_main.xml 파일에 있는것을
-> MainFragment.java에서 인플레이션(메모리를 객체화 시킨다음에) 
-> MainActivity에서 MainFragment의 객체를 만든후
-> FragmentManager를 사용하여서 commit을 해주게 되는데 
-> 이때 mainActivity안의 container안에 fragment에서 객체화 한 xml 파일을 넣어 준다.

2. fragment_menu.xml 파일에 있는것을 
-> MenuFragment.java에서 인플레이션(메모리를 객체화 시킨다음에)
-> MainActivity에서 MainFragment의 객체를 만든후
-> FragmentManager를 사용하여서 commit을 해주게 되는데,
-> 이때 mainActivity안의 container안에 fragment에서 객체화 한 xml 파일을 넣어 준다.
-> (결국 container 는 프레임 레이아웃을 뜻하므로 그곳에다가 플래그먼트의 화면을 띄워 주겠다는 의미이다.
cs

    <최종 소스>

<activity_main.xml>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?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">
 
 
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:text="시작"/>
    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/button"
        >
 
 
 
        <!--  주석처리 플래그먼트 이제 소스파일에서 추가하는것을 해보기 위해서
        1.첫번째 방법이다.
        <fragment
            android:id = "@+id/mainFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:name ="com.example.example_fragment.MainFragment"/>
            여기에서 메인 플래그먼트 xml에서 만든것을 자바에서 인플레이션한것들을 가져온다.
        -->
 
    </FrameLayout>
 
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="메뉴"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@+id/button"
        android:layout_toEndOf="@+id/button" />
 
</RelativeLayout>
cs

<fragment_main.xml>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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"
    android:background="@android:color/holo_blue_light"
    android:orientation="vertical"
    android:weightSum="1">
 
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0.07"
        android:text="플래그먼트 1"
        android:textSize="30dp" />
 
    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0.07"
        android:text="메뉴 화면으로" />
</LinearLayout>
cs

<fragment_menu.xml>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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"
    android:background="@android:color/darker_gray"
    android:orientation="vertical"
    android:weightSum="1">
 
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0.07"
        android:text="플래그먼트 2"
        android:textSize="30dp" />
 
    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="메인 화면으로" />
</LinearLayout>
cs

<MainActivity.java>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.example.example_fragment;
 
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
 
public class MainActivity extends AppCompatActivity {
    MainFragment fragment1;
    MenuFragment fragment2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        fragment1 = new MainFragment();
        fragment2 = new MenuFragment();
 
        Button button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                getSupportFragmentManager().beginTransaction().replace(R.id.container,fragment1).commit(); // 여러개의 명을 만들어서 쓴다
                // 꼭 commit 를 해주어야 실행이 된다. 플래그먼트 매니저가 플래그먼트를 담당 한다.
                // add라고해서 추가를 해주지 않고 replace를 써주는데, 기존에 있던것들을 대체 해 주게 된다.
 
 
 
            }
        });
 
 
        Button button2 = (Button)findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
 
                getSupportFragmentManager().beginTransaction().replace(R.id.container,fragment2).commit(); // 여러개의 명을 만들어서 쓴다
                // 꼭 commit 를 해주어야 실행이 된다. 플래그먼트 매니저가 플래그먼트를 담당 한다.
                // transaction 기반으로 한다는것을 잊지 말것.
                // add라고해서 추가를 해주지 않고 replace를 써주는데, 기존에 있던것들을 대체 해 주게 된다.
 
 
 
            }
        });
    }
}
cs

<MenuFragment.java>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.example.example_fragment;
 
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
 
/**
 *
 */
 
public class MenuFragment extends Fragment {
    //
    // fragment_main.xml 파일과 인플레이션으로 연결해주는것을 메모리 객체화를 시켜주어야한다
 
 
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        // 인플레이션이 가능하다, container 이쪽으로 붙여달라, fragment_main을
        ViewGroup rootview = (ViewGroup) inflater.inflate(R.layout.fragment_menu,container,false);
        // rootview가 플래그먼트 화면으로 보이게 된다. 부분화면을 보여주고자하는 틀로 생각하면 된다.
 
        return rootview;
    }
}
cs

<MainFragment.java>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.example.example_fragment;
 
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
 
/**
 *
 */
 
public class MainFragment extends Fragment {
    //
    // fragment_main.xml 파일과 인플레이션으로 연결해주는것을 메모리 객체화를 시켜주어야한다
 
 
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        // 인플레이션이 가능하다, container 이쪽으로 붙여달라, fragment_main을
        ViewGroup rootview = (ViewGroup) inflater.inflate(R.layout.fragment_main,container,false);
        // rootview가 플래그먼트 화면으로 보이게 된다. 부분화면을 보여주고자하는 틀로 생각하면 된다.
        // fragment_main 파일과 MainFragment와 연결 해준다.
        // 인플레이션 과정을 통해서 받을 수 있다.
        return rootview;            // 플레그먼트 화면으로 보여주게 된다.
    }
 
    // 결국 이렇게 되면 플래그먼트가 하나 만들어 지게 된것이다.
 
}
cs

    <최종 결과>


    1
    2
    3
    => MainActivity에서 클릭시 시작,메뉴 (플래그먼트 1, 2의 값을 잘 가져오는것을 알 수 있다.)
     
    그런데, 플래그먼트는 독립적이라서 플래그먼트내에서 또 동작되는것을 따로 만들어 주어야 하는데 그 예제를 지금 또 바로 실습을 해볼 것이다)
    cs
  • 이제 우리가 해볼것은? 화면에 있는 프래그먼트안에 있는 버튼을 눌렀을 때 다른 화면을 띄워 볼 것이다. 메인에 있는 버튼을 클릭-> 프래그먼트 화면 -> 액티비티쪽으로 요청해서 띄울것!
1
2
3
4
5
6
7
8
9
10
11
12
1. 액티비티 쪽으로 요청해서 띄워 볼것!
 
2. MainFragment.java 로 이동
프래그먼트도 생명주기가 있다. 생길떄 없어 질때 올라갈때 각각이 정의되어 있다.
프래그먼트에서는 액티비티를 참조 할 수 있는데, 프래그먼트 자체가 액티비티에 올라갈때 생명주기가 시작된다.
OnActtach()함수 콜백함수가 호출되는데, 플래그먼트가 액티비티에 올라간다는거고 OnDettach는 액티비티에서 내려온다는것이다.
 
3. Generate -> onAttach() , onDetach() 두개다 추가 시킬것.
 
4. fragment_main.xml에 버튼의 id값을 button2 -> button으로 바꿔준다.
 
5. 이제 MainFragment.xml으로 와서 button 값을 찾아준다. 왜? 화면을 바꿔주기위해서 프래그먼트 화면에서도 이벤트 발생시켰을 때 바꿔주기 위해서.
 
6. 혹시나 프래그먼트가 다른 액티비티에 올라갔다가 또 다른 액티비티로 올라가게 될 경우에는 implements로 구현을 하게 된다.
cs


    코드

<MainActivity.java>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.example.example_fragment;
 
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
 
public class MainActivity extends AppCompatActivity {
    MainFragment fragment1;
    MenuFragment fragment2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        fragment1 = new MainFragment();
        fragment2 = new MenuFragment();
 
        Button button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                getSupportFragmentManager().beginTransaction().replace(R.id.container,fragment1).commit(); // 여러개의 명을 만들어서 쓴다
                // 꼭 commit 를 해주어야 실행이 된다. 플래그먼트 매니저가 플래그먼트를 담당 한다.
                // add라고해서 추가를 해주지 않고 replace를 써주는데, 기존에 있던것들을 대체 해 주게 된다.
 
 
 
            }
        });
 
 
        Button button2 = (Button)findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
 
                getSupportFragmentManager().beginTransaction().replace(R.id.container,fragment2).commit(); // 여러개의 명을 만들어서 쓴다
                // 꼭 commit 를 해주어야 실행이 된다. 플래그먼트 매니저가 플래그먼트를 담당 한다.
                // transaction 기반으로 한다는것을 잊지 말것.
                // add라고해서 추가를 해주지 않고 replace를 써주는데, 기존에 있던것들을 대체 해 주게 된다.
 
 
 
            }
        });
    }
 
    public void onFragmentChange(int index){
        if(index ==0){
            getSupportFragmentManager().beginTransaction().replace(R.id.container,fragment1).commit();
 
        }else if(index ==1){
            getSupportFragmentManager().beginTransaction().replace(R.id.container,fragment2).commit();
        }
    }
}
cs

<MainFragment.java>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package com.example.example_fragment;
 
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
 
/**
 *
 */
 
public class MainFragment extends Fragment {
 
    // fragment_main.xml 파일과 인플레이션으로 연결해주는것을 메모리 객체화를 시켜주어야한다
 
    MainActivity activity;
 
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
 
        activity = (MainActivity) getActivity();
    }
 
    @Override
    public void onDetach() {
        super.onDetach();
 
        activity = null;
    }
 
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        // 인플레이션이 가능하다, container 이쪽으로 붙여달라, fragment_main을
        ViewGroup rootview = (ViewGroup) inflater.inflate(R.layout.fragment_main,container,false);
        // rootview가 플래그먼트 화면으로 보이게 된다. 부분화면을 보여주고자하는 틀로 생각하면 된다.
        // fragment_main 파일과 MainFragment와 연결 해준다.
        // 인플레이션 과정을 통해서 받을 수 있다.
 
 
        // 버튼2 -> 버튼 으로 만든다음에 인플레이션이 되고나서 메모리가 되니까 find에서 찾을 수 있다.
 
        Button button = (Button) rootview.findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            // 요청을 보내야 하는데 메인 액티비티에 다가 메소드를 하나 만들어야 한다.
            @Override
            public void onClick(View v) {
                activity.onFragmentChange(1);
 
            }
        });
 
 
        //getActivity();      // 액티비티위에 올라가게 한다.
 
 
 
 
        return rootview;            // 플레그먼트 화면으로 보여주게 된다.
    }
 
    // 결국 이렇게 되면 플래그먼트가 하나 만들어 지게 된것이다.
 
}
cs

<MenuFragment.java>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.example.example_fragment;
 
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
 
/**
 *
 */
 
public class MenuFragment extends Fragment {
    //
    // fragment_main.xml 파일과 인플레이션으로 연결해주는것을 메모리 객체화를 시켜주어야한다
 
 
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        // 인플레이션이 가능하다, container 이쪽으로 붙여달라, fragment_main을
        ViewGroup rootview = (ViewGroup) inflater.inflate(R.layout.fragment_menu,container,false);
        // rootview가 플래그먼트 화면으로 보이게 된다. 부분화면을 보여주고자하는 틀로 생각하면 된다.
 
 
 
        return rootview;
    }
}
cs

나머지 xml파일은 변동사항없음

    <결과>




이제 여기서 메뉴화면으로 클릭하면 이벤트가 발생하여 화면이 바뀌는것을 확인 할 수 있습니다.

지금 까지 감자코딩에 감자개발자였습니다. 감사합니다 :)

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함