-
Fragment - OverViewAndroid 공식문서 2020. 9. 11. 15:39반응형
A Fragment represents a behavior or a portion of user interface in a FragmentActivity. You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a modular section of an activity, which has its own lifecycle, receives its own input events, and which you can add or remove while the activity is running (sort of like a "sub activity" that you can reuse in different activities).
Fragment는 동작을 나타내거나 FragmentActivity에서 사용자 인터페이스의 일부를 나타냅니다.
여러 Fragment를 단일 activity에 결합하여 다중 pane UI에 빌드할 수 있고,
여러 activity에서 fragment를 재사용할 수 있습니다.
fragment는 자기의 생명주기를 가지고 있고, 입력 이벤트를 수신받을 수도 있습니다 그리고 activity가 실행되는 동안에 fragment를 추가할 수도 있고 삭제할 수도 있습니다. 이러한 fragment를 activity의 modular section이라고 생각할 수 있습니다. (다른 activity에서 재사용할 수 있는 일종의 "sub activity"입니다.)
A fragment must always be hosted in an activity and the fragment's lifecycle is directly affected by the host activity's lifecycle. For example, when the activity is paused, so are all fragments in it, and when the activity is destroyed, so are all fragments. However, while an activity is running (it is in theresumed lifecycle state), you can manipulate each fragment independently, such as add or remove them. When you perform such a fragment transaction, you can also add it to a back stack that's managed by the activity—each back stack entry in the activity is a record of the fragment transaction that occurred. The back stack allows the user to reverse a fragment transaction (navigate backwards), by pressing theBackbutton.
fragment는 activity안에서만 호스팅되어야 합니다.
fragment의 생명주기는 호스팅한 activity의 생명주기의 영향을 직접적으로 받습니다.
예를 들어 activity가 일시 정지 됐을 때 안에 있는 모든 fragment들도 일시 정지 됩니다.
actvitiy가 삭제되면 안에 있는 모든 fragment들도 삭제 됩니다.
하지만, actitiy가 실행되는 동안(onResume)에는 각각의 fragment를 추가하거나,
삭제같은 것을 독립적으로 다룰 수 있습니다.
fragment transaction을 수행할 때 activity가 관리하는 백 스택에 추가 할 수 있습니다.
각각의 백스택 entry는 발생된 fragment transaction을 기록합니다.
백 스택을 사용하면 뒤로 가기 버튼을 눌러 fragment transaction을 되돌릴 수 있습니다.When you add a fragment as a part of your activity layout, it lives in a ViewGroup inside the activity's view hierarchy and the fragment defines its own view layout. You can insert a fragment into your activity layout by declaring the fragment in the activity's layout file, as a <fragment> element, or from your application code by adding it to an existing ViewGroup.
activity layout의 일부로 fragment를 추가 하면 activity view 계층안에 ViewGroup에 머물게 됩니다.
그리고 fragment는 자기의 view layout을 정의합니다.
<fragment> 요소 또는 application의 코드로 부터 기존 VIewGroup에 추가하여
activity layout 파일에서 fragment를 선언해 activity layout에 fragment를 넣을 수 있습니다.This document describes how to build your application to use fragments, including how fragments can maintain their state when added to the activity's back stack, share events with the activity and other fragments in the activity, contribute to the activity's app bar, and more.
이 문서는 fragment를 사용하는 application을 빌드하는 방법, fragment를 activity 백 스택에 추가 했을때 상태를 유지 할 수 있는 방법, activity와 같은 acitivity안에 있는 다른 fragment들과 이벤트를 공유하는 방법, 앱 바등에 기여하는 방법을
설명합니다.Design Philosophy
Android introduced fragments in Android 3.0 (API level 11), primarily to support more dynamic and flexible UI designs on large screens, such as tablets. Because a tablet's screen is much larger than that of a handset, there's more room to combine and interchange UI components. Fragments allow such designs without the need for you to manage complex changes to the view hierarchy. By dividing the layout of an activity into fragments, you become able to modify the activity's appearance at runtime and preserve those changes in a back stack that's managed by the activity. They are now widely available through the fragment support library.
fragment는 Android 3.0(API 11)일 때 도입 됐습니다.
테블릿은 일반 핸드폰 보다 화면이 더 크고 UI 요소를 더 교환하고 결합 할 공간이 많기 때문에
fragment는 주로 테블릿 같은 큰화면에서 동적이고 유연한 UI를 디자인 하는 것을 도왔습니다.
fragment를 사용하면 view 계층 구조 변경 관리를 복잡하게 할 필요 없이 디자인을 할 수 있습니다.
activity layout을 fragment로 나누면 런타임중에 activity의 모양을 수정 할 수 있습니다.
그리고 activity가 관리하는 백 스택의 변경 사항을 보존 할 수 있습니다.For example, a news application can use one fragment to show a list of articles on the left and another fragment to display an article on the right—both fragments appear in one activity, side by side, and each fragment has its own set of lifecycle callback methods and handle their own user input events. Thus, instead of using one activity to select an article and another activity to read the article, the user can select an article and read it all within the same activity, as illustrated in the tablet layout in figure 1.
예를 들어, 뉴스 앱은 하나의 activity에서 두 fragment를 사용하여 왼쪽에 기사 목록과 오른쪽에 기사 목록을 나란히 나타 낼 수 있습니다. 그리고 각각의 fragment는 자기의 생명주기 콜백 함수를 가지고 사용자 입력 이벤트를 다룰 수 있습니다.
그러므로, 그림 1처럼 사용자는 하나의 activity에서 기사를 선택하고 그런다음 다른 activity에서 기사를 읽는 것이 아닌, 같은 activity에서 기사를 선택하고 읽을 수 있습니다.You should design each fragment as a modular and reusable activity component. That is, because each fragment defines its own layout and its own behavior with its own lifecycle callbacks, you can include one fragment in multiple activities, so you should design for reuse and avoid directly manipulating one fragment from another fragment. This is especially important because a modular fragment allows you to change your fragment combinations for different screen sizes. When designing your application to support both tablets and handsets, you can reuse your fragments in different layout configurations to optimize the user experience based on the available screen space. For example, on a handset, it might be necessary to separate fragments to provide a single-pane UI when more than one cannot fit within the same activity.
fragment는 activity 요소로 재사용 할 수 있게 modular 처럼 설계 해야 합니다.
각 fragment들은 자기의 레이아웃을 정의하고 자기의 생명주기 콜백을 통해 자기의 동작을 정의하고, 여러 activity에 하나의 fragment를 사용 할 수 있습니다. 그렇기 때문에 다른 fragment에서 하나의 fragment를 직접 조작하지 않고 재사용 할 수 있게 설계 해야합니다.
이것은 modular fragment는 다양한 화면 크기를 위해 fragment 조합을 변경 할 수 있기 때문에 특히 중요 합니다.
테블렛과 일반 핸드폰 둘다 지원 할 수 있게 앱을 설계 할때, 다양한 레이아웃 구성할 때 fragment를 재사용하여 사용 가능한 화면 공간에 사용자 경혐을 최적화 시킬 수 있습니다.
예를들어 일반 핸드폰에서, 같은 activity안에 하나 이상의 UI를 맞출 수 없는 경우 단일 창 UI를 제공하기 위해 fragment를
분리 해야합니다.Figure 1 Figure 1. An example of how two UI modules defined by fragments can be combined into one activity for a tablet design, but separated for a handset design.
For example—to continue with the news application example—the application can embed two fragments in Activity A, when running on a tablet-sized device. However, on a handset-sized screen, there's not enough room for both fragments, so Activity A includes only the fragment for the list of articles, and when the user selects an article, it starts Activity B, which includes the second fragment to read the article. Thus, the application supports both tablets and handsets by reusing fragments in different combinations, as illustrated in figure 1.
그림 1은 테블렛 디자인에서 하나의 activitiy안에 두가지 UI modules의 fragment를 결합하여 어떻게 정의 했는지 보여줍니다. 하지만 일반 핸드폰에서는 UI가 분리 돼 있습니다.
계속 뉴스 앱을 예로 들면 테블렛 사이즈 장치에서 실행중일 때 A activity에 두개의 fragment를 포함 시킬 수 있습니다.
그러나 일반 핸드폰 사이즈 화면에서는, 두개의 fragment를 넣을 공간이 충분하지 않습니다.
그래서 A activity에는 오직 뉴스 기사 목록을 위한 하나의 fragment만 포함 시킵니다.
그리고 사용자가 기사를 선택 했을때 뉴스 기사를 읽을 수 있는 두번째 fragment가 포함된 B activity가 실행 됩니다.
그러므로 이 뉴스 앱은 다양한 조합으로 fragment를 사용하여 테블렛과 일반 핸드폰을 둘 다 지원합니다.Creating a Fragment
To create a fragment, you must create a subclass of Fragment (or an existing subclass of it). The Fragment class has code that looks a lot like an Activity. It contains callback methods similar to an activity, such as onCreate(), onStart(), onPause(), and onStop(). In fact, if you're converting an existing Android application to use fragments, you might simply move code from your activity's callback methods into the respective callback methods of your fragment.
fragment를 만들기 위해서는 Fragment의 하위 클래스(또는 기존의 하위 클래스)를 만들어야 합니다.
Fragment 클래스는 Activity와 거의 비슷한 코드를 가지고 있습니다.
activity와 유사한 onCreate(), onStart(), onPause(), onStop() 같은 콜백 메서드를 가지고 있습니다.
만약 기존 안드로이드 앱에서 fragment를 사용하도록 바꾼다면, activity 콜백 메서드에 있는 코드들을 fragment 콜백 메서드 안에 옮기면 됩니다.Usually, you should implement at least the following lifecycle methods:
일반적으로 fragment를 구현하려면 다음 생명주기 메서드를 구현해야합니다. The system calls this when creating the fragment. Within your implementation, you should initialize essential components of the fragment that you want to retain when the fragment is paused or stopped, then resumed.
fragment를 생성할때 호출하는 메서드입니다.
fragment가 일시 정지되거나 멈춘다음 다시 시작할때 onCreate()에서 필수 요소들을 초기화 하는 역할을 합니다.The system calls this when it's time for the fragment to draw its user interface for the first time. To draw a UI for your fragment, you must return a View from this method that is the root of your fragment's layout. You can return null if the fragment does not provide a UI.
fragment에 사용자 인터페이스를 처음 그릴때 호출하는 메서드입니다.
fragment에 UI를 그리기 위해 fragment layout root에서 View를 리턴 해야합니다.
만약 fragment가 UI를 제공하지 않으면 null을 반환 할 수 있습니다.The system calls this method as the first indication that the user is leaving the fragment (though it doesn't always mean the fragment is being destroyed). This is usually where you should commit any changes that should be persisted beyond the current user session (because the user might not come back).
유저가 fragment를 떠난다는 첫번째 신호입니다.( fragment를 항상 삭제한다는 것은 아닙니다.)
일반적으로 현재 사용자 세션 이후에도 유지돼야하는 변경사항을 커밋하는 역할을 합니다.
(사용자가 돌아오지 않을 수도 있기 때문에)Most applications should implement at least these three methods for every fragment, but there are several other callback methods you should also use to handle various stages of the fragment lifecycle. All the lifecycle callback methods are discussed in more detail in the section about Handling the Fragment Lifecycle.
대부분의 앱은 모든 fragment에 최소한 3가지 메서드를 구현해야합니다.
하지만 fragment 생명주기에 다양한 단계를 처리하기 위한 몇가지 콜백 메서드가 있습니다.
모든 생명주기 콜백 메서드는 해당 링크에서 자세하게 설명합니다.Note that the code implementing lifecycle actions of a dependent component should be placed in the component itself, rather than directly in the fragment callback implementations. See Handling Lifecycles with Lifecycle-Aware Components to learn how to make your dependent components lifecycle-aware.
fragment 콜백 구현부에 직접 구현하는게 아니라
구성요소의 라이프 사이클을 구현하는 코드는 구성요소 자체에 구현돼야 합니다.
종속 구성 요소의 수명주기를 인식하는 방법을 알아 보려면 해당 링크를 참조하세요.There are also a few subclasses that you might want to extend, instead of the base Fragment class:
기본 Fragment 클래스 대신 확장 할 수있는 몇 가지 하위 클래스도 있습니다. Displays a floating dialog. Using this class to create a dialog is a good alternative to using the dialog helper methods in the Activity class, because you can incorporate a fragment dialog into the back stack of fragments managed by the activity, allowing the user to return to a dismissed fragment.
floating dialog를 표시합니다.
DialogFragment를 사용하여 dialog를 만드는 것은 Activity에서 dialog helper를 사용하는 것보다 좋은 방법입니다.
왜냐하면 activity에 fragment를 관리하는 백스택에 dialog를 통합하여 사용자가 해제 된 fragment로 돌아 갈 수 있기
때문입니다.ListFragment
Displays a list of items that are managed by an adapter (such as a SimpleCursorAdapter), similar to ListActivity. It provides several methods for managing a list view, such as the onListItemClick() callback to handle click events. (Note that the preferred method for displaying a list is to use RecyclerView instead of ListView. In this case you would need to create a fragment that includes a RecyclerView in its layout. See Create a List with RecyclerView to learn how.)ListActivity와 유사한 어댑터 (예 : SimpleCursorAdapter)에서 관리하는 항목 리스트를 표시합니다.
리스트 뷰를 관리하는 몇몇의 메서드들을 제공합니다.(클릭 이벤트를 다루기위한 onListItemClick() 같은 콜백 메서드)
(목록을 표시하는 데 선호되는 방법은 ListView 대신 RecyclerView를 사용하는 것입니다.)
이 경우에는 RecyclerView를 포함하는 fragment를 만들어야 합니다.Displays a hierarchy of Preference objects as a list. This is used to create a settings screen for your application.
Preference 개체의 계층을 목록으로 표시합니다.
앱의설정 화면을 만드는 데 사용됩니다.Adding a user interface
A fragment is usually used as part of an activity's user interface and contributes its own layout to the activity.
fragment는 일반적으로 activity 사용자 인터페이스의 일부로 사용됩니다.
그리고 activity에 자체적인 레이아웃을 제공합니다.To provide a layout for a fragment, you must implement the onCreateView() callback method, which the Android system calls when it's time for the fragment to draw its layout. Your implementation of this method must return a View that is the root of your fragment's layout.
fragment에 대한 레이아웃을 제공하려면, onCreateView()를 구현해야 합니다,
onCreateView()는 fragment가 레이아웃을 그릴때 호출됩니다.
메소드의 구현은 프래그먼트 레이아웃의 루트 인 View를 반환해야합니다.To return a layout from onCreateView(), you can inflate it from a layout resource defined in XML. To help you do so, onCreateView() provides a LayoutInflater object.
onCreateView에서 레이아웃을 반환하려면 이 메소드의 구현은 프래그먼트 레이아웃의 루트 인 View를 반환해야합니다.
이를 위해 onCreateView )는 LayoutInflater를 제공합니다.For example, here's a subclass of Fragment that loads a layout from the example_fragment.xml file:
예 : example_fragment.xml 파일에서 레이아웃을 불러오는 Fragment의 하위 클래스입니다. Class ExampleFragment : Fragment() { override fun onCreateView(inflater : LayoutInflater, container : ViewGroup?, savedInstanceState : Bundle?) : View { return inflater.inflate(R.layout.example_fragment,container, false) } }
The container parameter passed to onCreateView() is the parent ViewGroup (from the activity's layout) in which your fragment layout is inserted. The savedInstanceState parameter is a Bundle that provides data about the previous instance of the fragment, if the fragment is being resumed (restoring state is discussed more in the section about Handling the Fragment Lifecycle).
onCreateView()에서 전달받은 container는 fragment가 들어갈 상위 ViewGroup(Activity 레이아웃으로 부터)입니다.
savedInstanceState는 fragment가 다시 시작 됐을때 fragment의 이전 인스턴스에 대한 데이터를 제공하는 Bundle입니다.The inflate() method takes three arguments:
- The resource ID of the layout you want to inflate.
- The ViewGroup to be the parent of the inflated layout. Passing the container is important in order for the system to apply layout parameters to the root view of the inflated layout, specified by the parent view in which it's going.
- A boolean indicating whether the inflated layout should be attached to the ViewGroup (the second parameter) during inflation. (In this case, this is false because the system is already inserting the inflated layout into the container—passing true would create a redundant view group in the final layout.)
inflate() 메서드는 3개의 인자를 받습니다.
1. inflate 하려는 레이아웃의 resource ID를 받습니다.
2. inflate된 레이아웃의 부모가 될 ViewGroup을 받습니다.
inflate된 레이아웃의 Root View에 레이아웃 매개 변수를 적용하려면 컨테이너를 전달하는 것이 중요합니다. 상위 뷰에
의해 지정됩니다.
3. inflate 중에 inflate된 레이아웃이 container (두 번째 매개 변수)에 첨부돼야 하는지 여부를 나타내는 boolean 입니다.
(이 경우, 이미 inflated된 레이아웃을 시스템이 container에 넣고 있기 때문에 false입니다.
true를 전달 하면 최종 레이아웃에 중복 view group이 생성됩니다.)Now you've seen how to create a fragment that provides a layout. Next, you need to add the fragment to your activity.
레이아웃을 제공하는 fragment를 만드는 방법을 보았습니다. 이제 activity에 fragment를 추가해야합니다. Adding a fragment to an activity
Usually, a fragment contributes a portion of UI to the host activity, which is embedded as a part of the activity's overall view hierarchy. There are two ways you can add a fragment to the activity layout:
일반적으로, fragment는 UI의 일부를 host activity 기여합니다.
activity의 전체 view 계층의 일부로 포함됩니다.
activity 레이아웃에 fragment를 추가할 수 있는 두 가지 방법이 있습니다.- Declare the fragment inside the activity's layout file.
In this case, you can specify layout properties for the fragment as if it were a view. For example, here's the layout file for an activity with two fragments:
Activity의 레이아웃 파일 내에서 fragment를 선언합니다.
이 경우, View처럼 fragment의 레이아웃 속성을 지정할 수 있습니다.
다음은 두 개의 fragment가있는 activity에 대한 레이아웃 파일입니다.<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:name="com.example.news.ArticleListFragment" android:id="@+id/list" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" /> <fragment android:name="com.example.news.ArticleReaderFragment" android:id="@+id/viewer" android:layout_weight="2" android:layout_width="0dp" android:layout_height="match_parent" /> </LinearLayout>
The android:name attribute in the <fragment> specifies the Fragment class to instantiate in the layout.
When the system creates this activity layout, it instantiates each fragment specified in the layout and calls the onCreateView() method for each one, to retrieve each fragment's layout. The system inserts the View returned by the fragment directly in place of the <fragment> element.
<fragment> 안에 있는 android:name 속성은 레이아웃에서 인스턴스화 할 Fragment 클래스를 지정합니다.
시스템이 activity 레이아웃을 생성할 때, 레이아웃에 있는 각각의 fragment들을 인스턴스화 합니다.
그리고 각각 onCreateView()를 호출하여 layout을 검색 합니다.
시스템은 <fragment> 요소 대신에 fragment가 반환 한 View를 직접 삽입합니다.Note: Each fragment requires a unique identifier that the system can use to restore the fragment if the activity is restarted (and which you can use to capture the fragment to perform transactions, such as remove it). There are two ways to provide an ID for a fragment:
- Supply the android:id attribute with a unique ID.
- Supply the android:tag attribute with a unique string.
각각 fragment에는 activity가 다시 시작되는 경우 시스템에서 fragment를 복원하는데 사용할 수있는 고유 식별자가 필요합니다. (fragment를 트랜잭션을 수행하는 데 사용할 수 있습니다 (예 : 제거))
식별자는 두가지 방법이 있습니다.
1. android:id 속성을 사용하여 ID를 지정
2. android:tag 속성을 사용하여 고유의 string 값 지정Or, programmatically add the fragment to an existing ViewGroup.
At any time while your activity is running, you can add fragments to your activity layout. You simply need to specify a ViewGroup in which to place the fragment.
기존 ViewGroup에 프로그래밍 방식으로 fragment을 추가합니다.
acitivity가 실행되는 동안 언제든지, activity 레이아웃에 fragment를 추가할 수 있습니다.
fragment를 배치 할 ViewGroup을 지정하기 만하면됩니다.To make fragment transactions in your activity (such as add, remove, or replace a fragment), you must use APIs from FragmentTransaction. You can get an instance of FragmentTransaction from your FragmentActivity like this:
activity에서 fragment transaction(추가 또는 교체, 제거)을 수행하려면 FragmentTransaction Api를 사용해야 합니다.
다음과 같이 FragmentActivity에서 FragmentTransaction의 인스턴스를 가져올 수 있습니다.val fragmentManager = supportFragmentManager val fragmentTransaction = fragmentManager.beginTransaction()
You can then add a fragment using the add() method, specifying the fragment to add and the view in which to insert it. For example:
add() 메서드를 사용하여 fragment를 추가하고 추가할 fragment와 삽입할 view를 지정할 수 있습니다. val fragment = ExampleFragment() fragmentTransaction.add(R.id.fragment_container, fragment) fragmentTransaction.commit()
The first argument passed to add() is the ViewGroup in which the fragment should be placed, specified by resource ID, and the second parameter is the fragment to add.
Once you've made your changes with FragmentTransaction, you must call commit() for the changes to take effect.
add()로 전달한 첫번째 매개 변수는 ViewGroup이다. 여기에 리소스 ID로 지정된 fragment를 배치해야합니다.
두번째 매개 변수는 추가할 fragment입니다.
fragmentTransaction을 통하여 변경 한 다음에 변경 사항을 적용시키기 위해 commit()을 호출 해야 합니다.Managing Fragments
To manage the fragments in your activity, you need to use FragmentManager. To get it, call getSupportFragmentManager() from your activity.
fragment를 관리하기 위해서는 FragmentManager가 필요합니다.
FragmentManager를 얻으려면 activity에서 getSupportFragmentManager()를 호출합니다.Some things that you can do with FragmentManager include:
FragmentManager로 수행 할 수있는 작업은 다음과 같습니다. - Get fragments that exist in the activity, with findFragmentById() (for fragments that provide a UI in the activity layout) or findFragmentByTag() (for fragments that do or don't provide a UI).
- Pop fragments off the back stack, with popBackStack() (simulating a Back command by the user).
- Register a listener for changes to the back stack, with addOnBackStackChangedListener().
For more information about these methods and others, refer to the FragmentManager class documentation.
As demonstrated in the previous section, you can also use FragmentManager to open a FragmentTransaction, which allows you to perform transactions, such as add and remove fragments.
메서드 및 기타 방법에 대한 자세한 내용은 FragmentManager 클래스 설명서를 참조하세요.
FragmentManager를 사용하여 FragmentTransaction을 열 수 있으며, 이를 통해 fragment 추가 및 제거와 같은
Transaction을 수행 할 수 있습니다.Performing Fragment Transactions
A great feature about using fragments in your activity is the ability to add, remove, replace, and perform other actions with them, in response to user interaction. Each set of changes that you commit to the activity is called a transaction and you can perform one using APIs in FragmentTransaction. You can also save each transaction to a back stack managed by the activity, allowing the user to navigate backward through the fragment changes (similar to navigating backward through activities).
activity에서 fragment를 사용할 때의 장점은 사용자 상호 작용에 대한 응답으로 fragment를 추가, 제거, 교체 및 수행하는
기능입니다.
activity에 commit한 각 변경 사항 집합을 Transaction이라고합니다.
FragmentTransaction에서 API를 사용하여 사용 할 수 있습니다.
또한 각 Transaction을 백 스택에 저장하여 사용자가 fragment의 변경 사항을 뒤로 탐색 할 수 있습니다.You can acquire an instance of FragmentTransaction from the FragmentManager like this:
다음과 같이 FragmentManager에서 FragmentTransaction의 인스턴스를 얻을 수 있습니다. val fragmentManager = supportFragmentManager val fragmentTransaction = fragmentTransaction.beginTransaction()
Each transaction is a set of changes that you want to perform at the same time. You can set up all the changes you want to perform for a given transaction using methods such as add(), remove(), and replace(). Then, to apply the transaction to the activity, you must call commit().
각각의 transaction은 동시에 수행하려는 변경 사항의 집합입니다.
add(), remove(), replace()등 메서드를 사용하여 주어진 transaction에 대해 수행하려는 모든 변경 사항을 설정할 수 있습니다. 그다음 트랜잭션을 activity에 적용하기 위해 commit()을 호출해야 합니다.
Before you call commit(), however, you might want to call addToBackStack(), in order to add the transaction to a back stack of fragment transactions. This back stack is managed by the activity and allows the user to return to the previous fragment state, by pressing the Back button.
commit()을 호출하기 전에 fragmentTransaction의 백 스택에 Transaction을 추가하려면 addToBackStack ()을 호출 해야합니다. activity가 관리하는 백 스택입니다. 그리고 사용자가 back 버튼을 눌러 이전 fragment 상태로 돌아갈 수 있습니다. For example, here's how you can replace one fragment with another, and preserve the previous state in the back stack:
예시에서 다른 fragment 와 어떻게 replace 할 수 있는지, 백 스택에 이전 상태를 어떻게 보존하는지 보여줍니다. val newFragment = ExampleFragment() val transaction = supportFragmentManager.beginTransaction() transaction.replace(R.id.fragment_container, newFragment) transaction.addToBackStack(null) transaction.commit()
In this example, newFragment replaces whatever fragment (if any) is currently in the layout container identified by the R.id.fragment_container ID. By calling addToBackStack(), the replace transaction is saved to the back stack so the user can reverse the transaction and bring back the previous fragment by pressing the Back button.
예시에서, newFragment는 id가 R.id.fragment_container인 container에 있는 모든 fragment를 대체합니다.
addToBackStack()을 호출하면, replace Transaction은 백 스텍에 저장되므로 사용자는 transaction을 되돌릴 수 있고, 백 버튼을 눌러 이전 fragment를 가져 올 수 있습니다.FragmentActivity then automatically retrieve fragments from the back stack via onBackPressed().
FragmentActivity는 onBackPressed()를 통하여 자동적으로 백스택에서 fragment를 검색합니다. If you add multiple changes to the transaction—such as another add() or remove()—and call addToBackStack(), then all changes applied before you call commit() are added to the back stack as a single transaction and the Back button reverses them all together.
add() 나 remove() 같이 transaction에 여러 변경 사항을 추가하고 addToBackStack을 호출하면 commit()이 호출되기 전에
적용된 모든 변경 사항이 단일 transaction과 백 버튼으로 백스택에 저장됩니다.The order in which you add changes to a FragmentTransaction doesn't matter, except:
- You must call commit() last.
- If you're adding multiple fragments to the same container, then the order in which you add them determines the order they appear in the view hierarchy.
FragmentTransaction에 변경 사항을 추가하는 순서는 다음을 제외하고는 중요하지 않습니다.
1. 반드시 commit()을 마지막에 호출 해야합니다.
2. 같은 container에 여러 fragment를 추가하는 경우, 뷰 계층 구조에 나타나는 순서가 추가하는 순서대로 결정됩니다.If you don't call addToBackStack() when you perform a transaction that removes a fragment, then that fragment is destroyed when the transaction is committed and the user cannot navigate back to it. Whereas, if you do call addToBackStack() when removing a fragment, then the fragment is stopped and is later resumed if the user navigates back.
remove transaction을 수행할 때 addToBackStack()을 호출하지 않으면, commit 할때 fragment가 파괴된다.
그리고 사용자가 그 fragment를 되돌릴 수 없다.
addToBackStack()을 호출 한다면 그 fragment는 정지하고 사용자가 나중에 다시 시작 시킬 수 있습니다.Tip: For each fragment transaction, you can apply a transition animation, by calling setTransition() before you commit.
각 fragment transaction에 대해 commit 하기 전에 setTransition()을 호출하여 전환 애니메이션을 적용 할 수 있습니다. Calling commit() doesn't perform the transaction immediately. Rather, it schedules it to run on the activity's UI thread (the "main" thread) as soon as the thread is able to do so. If necessary, however, you may call executePendingTransactions() from your UI thread to immediately execute transactions submitted by commit(). Doing so is usually not necessary unless the transaction is a dependency for jobs in other threads.
commit()을 호출하면 transaction을 바로 수행하지 않습니다.
스레드가 수행 할 수있는 즉시 activity 의 UI 스레드 (Main스레드)에서 실행되도록 예약합니다.
UI 스레드에서 executePendingTransactions()을 호출하여 commit()에 의해 제출 된 트랜잭션을 즉시 실행할 수 있습니다.
일반적으로 트랜잭션이 다른 스레드의 작업에 대한 종속성이 아니면 할 필요는 없습니다.Communicating with the Activity
Although a Fragment is implemented as an object that's independent from a FragmentActivity and can be used inside multiple activities, a given instance of a fragment is directly tied to the activity that hosts it.
Specifically, the fragment can access the FragmentActivity instance with getActivity() and easily perform tasks such as find a view in the activity layout:
Fragment는 FragmentActivity와 독립적인 오브젝트로 구현돼고 여러 activity안에서 사용할 수 있지만 주어진 fragment는 직접 호스팅하는activity에 연결됩니다.
fragment는 getActivity()를 통해 FragmentActivity 인스턴스에 접근합니다.
그리고 쉽게 작업(예 : activity layout에서 view를 찾는것)을 수행합니다.val listView : View? = actvitiy?.findViewById(R.id.list)
Likewise, your activity can call methods in the fragment by acquiring a reference to the Fragment from FragmentManager, using findFragmentById() or findFragmentByTag(). For example:
activity는 findFragmentById () 또는 findFragmentByTag ()를 사용하여 FragmentManager에서 Fragment에 대한 참조를 가져 와서 프래그먼트의 메서드를 호출 할 수 있습니다. val fragment = supportFragmentManager.findFragmentById(R.id.example_fragment) as ExampleFragment
Creating event callbacks to the activity
In some cases, you might need a fragment to share events or data with the activity and/or the other fragments hosted by the activity. To share data, create a shared ViewModel, as outlined in the Share data between fragments section in the ViewModel guide. If you need to propagate events that cannot be handled with a ViewModel, you can instead define a callback interface inside the fragment and require that the host activity implement it. When the activity receives a callback through the interface, it can share the information with other fragments in the layout as necessary.
어떤 경우에는 activity나 activity안에 있는 다른 fragment와 데이터 또는 이벤트를 공유 하기 위해 fragment가 필요할 수 있습니다. 데이터를 공유 하기 위해서는 shared ViewModel을 생성해야합니다.
(ViewModel guide 페이지 fragment 간 데이터 공유 섹션에 설명되어 있습니다.)
ViewModel에서 다룰 수 없는 이벤트를 보내야하는 경우, fragment내부에 콜백 인터페이스를 정의할 수 있습니다.
그리고 호스트 activity에서 인터페이스를 구현해야합니다.
인터페이스를 통해 activity가 콜백을 수신받으면 필요에 따라 다른 fragment와 정보를 공유 할 수 있습니다.For example, if a news application has two fragments in an activity—one to show a list of articles (fragment A) and another to display an article (fragment B)—then fragment A must tell the activity when a list item is selected so that it can tell fragment B to display the article. In this case, the OnArticleSelectedListener interface is declared inside fragment A:
예를 들어, 뉴스 앱은 activity 안에 두개의 fragment를 가지고 있습니다.
하나는 기사의 리스트를 보여주는 fragmentA, 하나는 기사 내용을 보여주는 fragmentB 입니다.
fragmentA는 기사가 선택 되면 activity에게 알려줘야 fragmentB가 기사를 표시할 수 있게 지시합니다.
이 경우 OnArticleSelectedListener 인터페이스는 fragmentA 내에서 선언됩니다.public class FragmentA : ListFragment() { ... // Container Activity must implement this interface interface OnArticleSelectedListener { fun onArticleSelected(articleUri : Uri) } ... }
Then the activity that hosts the fragment implements the OnArticleSelectedListener interface and overrides onArticleSelected() to notify fragment B of the event from fragment A. To ensure that the host activity implements this interface, fragment A's onAttach() callback method (which the system calls when adding the fragment to the activity) instantiates an instance of OnArticleSelectedListener by casting the Activity that is passed into onAttach():
fragment를 호스팅하고 있는 activity는 OnArticleSelectedListener를 impl합니다.
그리고 onArticleSelected()를 override하고 A의 이벤트를 B에 알려줍니다.
호스트 activity가 인터페이스를 구현하는지 확인하기 위해 fragment A의 onAttach () 콜백 메서드 (activity에 fragment를
추가 할 때 호출 함)는 onAttach ()로 전달되는 activity을 캐스팅하여 OnArticleSelectedListener 인스턴스를 인스턴스화합니다.public class FragmentA : ListFragment() { var listener : OnArticleSelectedListener? = null ... override fun onAttach(context : Context){ super.onAttach(context) listener = context as? OnArticleSelectedListener if(listener == null) throw ClassCastException("$context must implement OnArticleSelectedListener") } }
If the activity hasn't implemented the interface, then the fragment throws a ClassCastException. On success, the mListener member holds a reference to activity's implementation of OnArticleSelectedListener, so that fragment A can share events with the activity by calling methods defined by the OnArticleSelectedListener interface. For example, if fragment A is an extension of ListFragment, each time the user clicks a list item, the system calls onListItemClick() in the fragment, which then calls onArticleSelected() to share the event with the activity:
activity가 인터페이스를 구현하지 않았으면 fragment는 ClassCastException을 던진다.
성공하면, mListener는 OnArticleSelectedListener의 activity impl에 대한 참조를 가지게 됩니다.
그래서 fragmentA는 OnArticleSelectedListener interface에 정의된 메서드 호출을 하여 activity에 이벤트를 공유 할 수 있습니다. 예를 들어, fragmentA가 ListFragment를 확장한경우,
사용자가 아이템을 클릭할 때 마다 onListItemClick()을 호출 하고 onArticleSelected()를 호출하여 activity에 이벤트를 공유합니다.public class FragmentA : ListFragment() { var listener : OnArticleSelectedListener? = null ... override fun onListItemClick(l : ListView, v: View, position : Int, id : Long) { // Append the clicked item's row Id with the content provider Uri val noteUri : Uri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id) // Send the event and Uri to the host activity listener?.onArticleSelected(noteUri) } }
The id parameter passed to onListItemClick() is the row ID of the clicked item, which the activity (or other fragment) uses to fetch the article from the application's ContentProvider.
onLIstItemCLick()로부터 전달된 id는 클릭된 아이템의 행 id입니다.
activity (또는 다른 fragment)가 앱의 ContentProvider에서 기사를 가져 오는 데 사용합니다.More information about using a content provider is available in the Content Providers document.
Content Provider 사용에 대한 자세한 내용은 Content Providers 문서에서 확인할 수 있습니다. Adding items to the App Bar
Your fragments can contribute menu items to the activity's Options Menu (and, consequently, the app bar) by implementing onCreateOptionsMenu(). In order for this method to receive calls, however, you must call setHasOptionsMenu() during onCreate(), to indicate that the fragment would like to add items to the Options Menu. Otherwise, the fragment doesn't receive a call to onCreateOptionsMenu().
fragment는 onCreateOptionsMenu()를 구현해 activity의 Options Menu (app bar)에 메뉴 아이템을 제공 할 수 있습니다.
메서드가 호출 수신하려면 onCreate() 동안에 setHasOptionsMenu를 호출해서 fragment가 옵션 메뉴에 아이템을 추가하려고 함을 나타냅니다. 그렇지 않으면 fragment는 onCreateOptionsMenu ()에 대한 호출을 수신하지 않습니다.Any items that you then add to the Options Menu from the fragment are appended to the existing menu items. The fragment also receives callbacks to onOptionsItemSelected() when a menu item is selected.
fragment로부터 Options Menu에 추가하려는 모든 아이템은 기존 메뉴 아이템에 추가됩니다.
메뉴 아이템을 선택할 때 fragment는 onOptionsItemSelected() 콜백을 수신 받습니다.You can also register a view in your fragment layout to provide a context menu by calling registerForContextMenu(). When the user opens the context menu, the fragment receives a call to onCreateContextMenu(). When the user selects an item, the fragment receives a call to onContextItemSelected().
registerForContextMenu()를 호출하여 컨텍스트 메뉴를 제공하기 위해 fragment layout에 view를 등록 할 수도 있습니다.
사용자가 컨텍스트 메뉴를 열었을때, fragment는 onCreateContextMenu()에 대한 호출을 수신받습니다.
사용자가 아이템을 선택했을때, fragment는 onContextItemSelected()에 대한 호출을 수신받습니다.Note: Although your fragment receives an on-item-selected callback for each menu item it adds, the activity is first to receive the respective callback when the user selects a menu item. If the activity's implementation of the on-item-selected callback does not handle the selected item, then the event is passed to the fragment's callback. This is true for the Options Menu and context menus.
fragment는 추가하는 각 메뉴 item에 대해 onItemSelected 콜백을 수신하지만 사용자가 메뉴 item을 선택할 때 activity는 먼저 해당 콜백을 수신합니다.
activity의 onItemSelected 콜백 구현이 선택한 item을 처리하지 않으면 이벤트가 fragment의 콜백으로 전달됩니다.
Options Menu 그리고 context menus에 해당됩니다.For more information about menus, see the Menus developer guide and the App Bar training class.
메뉴에 대한 자세한 내용은 메뉴 개발자 가이드 및 앱 바 교육 과정을 참조하세요. Handling the Fragment Lifecycle
Figure 3. The effect of the activity lifecycle on the fragment lifecycle. Managing the lifecycle of a fragment is a lot like managing the lifecycle of an activity. Like an activity, a fragment can exist in three states:
fragment의 생명 주기 관리는 activity의 생명주기를 관리하는것과 비슷합니다.
activity와 동일하게 세 가지 상태로 존재 할 수 있습니다.Resumed
The fragment is visible in the running activity.
activity가 동작하는동안 fragment가 보입니다. Paused
Another activity is in the foreground and has focus, but the activity in which this fragment lives is still visible (the foreground activity is partially transparent or doesn't cover the entire screen).
다른 activity가 foregeround에 있고 focus가 맞춰져있는 상태 입니다.
하지만 fragment가 있는 activity는 여전히 표시되고 있습니다.
(activity가 부분적으로 투명하거나 화면 전체를 덮고 있지 않는 상태)Stopped
The fragment isn't visible. Either the host activity has been stopped or the fragment has been removed from the activity but added to the back stack. A stopped fragment is still alive (all state and member information is retained by the system). However, it is no longer visible to the user and is killed if the activity is killed.
fragment가 보이지 않습니다. activity가 중지 되었거나 fragment가 activity에서 제거 됐지만 백 스택에 추가 됐습니다.
중지된 fragment는 아직 살아 있습니다.(모든 상태 그리고 멤버 정보는 시스템에 의해 유지되고 있습니다.)
하지만 더 이상 사용자에게 보이지 않고 activity가 종료되면 똑같이 종료됩니다.Also like an activity, you can preserve the UI state of a fragment across configuration changes and process death using a combination of onSaveInstanceState(Bundle), ViewModel, and persistent local storage. To learn more about preserving UI state, see Saving UI States.
또한 activity 처럼 구성을 변경시에도 fragment의 UI 상태를 유지할 수 있습니다.
그리고 onSaveInstanceState(Bundle), ViewModel, persistent local storage를 사용해 프로세스를 종료 시킬 수 있습니다.
UI 상태 보존에 대한 자세한 내용은 Saving UI States을 참조하십시오.The most significant difference in lifecycle between an activity and a fragment is how one is stored in its respective back stack. An activity is placed into a back stack of activities that's managed by the system when it's stopped, by default (so that the user can navigate back to it with the Back button, as discussed in Tasks and Back Stack). However, a fragment is placed into a back stack managed by the host activity only when you explicitly request that the instance be saved by calling addToBackStack() during a transaction that removes the fragment.
생명주기에서 fragment와 activity의 가장 중요한 차이점은 백 스택에 저장되는 방법입니다.
activity는 중지 될 때 시스템에서 관리하는 activity의 백 스택에 배치됩니다.
(사용자가 백 버튼을 사용하여 다시 탐색 할 수 있게)
반면에 fragment는 fragment 제거 하는 transaction중에 addToBackStack() 호출에 의해 인스턴스를 저장하도록 요청하는 경우에만 호스트 activity에서 관리하는 백 스택에 배치됩니다.Otherwise, managing the fragment lifecycle is very similar to managing the activity lifecycle; the same practices apply. See The Activity Lifecycle guide and Handling Lifecycles with Lifecycle-Aware Components to learn more about the activity lifecycle and practices for managing it.
그렇지 않으면 fragmnet 생명주기 관리는 activity와 매우 유사합니다.
The Activity Lifecycle 가이드 및 Handling Lifecycles with Lifecycle-Aware Components 를 참조하여 활동 생명주기 및 관리하는 방법에 대해 자세히 알아보십시오.Caution: If you need a Context object within your Fragment, you can call getContext(). However, be careful to call getContext() only when the fragment is attached to an activity. When the fragment isn't attached yet, or was detached during the end of its lifecycle, getContext() returns null.
Fragment에서 Context가 필요하다면 getContext()를 사용 할 수 있습니다.
하지만 getContext()는 오직 fragment가 activity에 연결되어 있을때만 호출 해야합니다.
아직 연결이 되어있지 않을때나 연결이 끊겼을때 호출한다면 null을 리턴할 수 있습니다.Coordinating with the activity lifecycle
The lifecycle of the activity in which the fragment lives directly affects the lifecycle of the fragment, such that each lifecycle callback for the activity results in a similar callback for each fragment. For example, when the activity receives onPause(), each fragment in the activity receives onPause().
fragment를 가지고 있는 activity의 생명주기는 fragment의 생명주기에 직접적인 영향을 줍니다.
(activity에 대한 각 생명 주기 콜백이 각 fragment에 대해 유사한 콜백을 생성하도록합니다.)
예를 들어, activity가 onPause()를 수신 받으면, 각 fragment가 onPause()를 수신합니다.Fragments have a few extra lifecycle callbacks, however, that handle unique interaction with the activity in order to perform actions such as build and destroy the fragment's UI. These additional callback methods are:
Fragments는 fragment의 UI 빌드 및 삭제와 같은 작업을 수행, activity의 고유한 상호 작용을 처리하는 몇가지 추가적인 생명주기 콜백을 가지고 있습니다. Called when the fragment has been associated with the activity (the Activity is passed in here).
fragment가 activity에 연결되었을 때 호출됩니다.( activity가 여기에 전달됩니다.) Called to create the view hierarchy associated with the fragment.
fragment와 관련된 view 계층을 만들기 위해 호출됩니다. Called when the activity's onCreate() method has returned.
activty의 onCreate()가 반환되면 호출됩니다. Called when the view hierarchy associated with the fragment is being removed.
fragment와 관련된 view 계층 구조가 제거 될 때 호출됩니다. Called when the fragment is being disassociated from the activity.
activity와 fragment가 연결이 해제 될때 호출됩니다. The flow of a fragment's lifecycle, as it is affected by its host activity, is illustrated by figure 3. In this figure, you can see how each successive state of the activity determines which callback methods a fragment may receive. For example, when the activity has received its onCreate() callback, a fragment in the activity receives no more than the onActivityCreated() callback.
host activity의 영향을 받는 fragment의 생명주기 흐름은 그림3에서 볼 수 있습니다.
그림을 보면, activity의 각 연속 상태가 fragment가 수신 할 수있는 콜백 메소드를 결정하는 방법을 볼 수 있습니다.
예를 들어, activity가 onCreate() 콜백을 수신받을때 fragment는 onActivityCreated() 콜백만 수신받습니다.Once the activity reaches the resumed state, you can freely add and remove fragments to the activity. Thus, only while the activity is in the resumed state can the lifecycle of a fragment change independently.
activity가 onResume() 상태가 되면 fragment를 자유롭게 추가 및 삭제 할 수 있습니다.
그러므로 actvity가 onResme() 상태일 때만 fragment가 독립적으로 변경할 수 있습니다.However, when the activity leaves the resumed state, the fragment again is pushed through its lifecycle by the activity.
하지만 activity가 resume 상태를 떠나면 fragment는 다시 activity에 의해 생명주기가 push됩니다. Example
To bring everything discussed in this document together, here's an example of an activity using two fragments to create a two-pane layout. The activity below includes one fragment to show a list of Shakespeare play titles and another to show a summary of the play when selected from the list. It also demonstrates how to provide different configurations of the fragments, based on the screen configuration.
이 문서에서 논의 된 모든 내용을 모으기 위해 두 fragment를 사용하여 두 개의 pane으로 구성된 레이아웃을 만드는 activity의 예가 있습니다.
activity에는 셰익스피어 연극 제목 목록을 표시하는 fragment 와 목록에서 선택했을 때 연극 요약을 표시하는 fragment가
포함되어 있습니다.
또한 화면 구성에 따라 fragment의 다양한 구성을 제공하는 방법을 보여줍니다.Note: The complete source code for this activity is available in the sample app showing use of an example FragmentLayout class.
이 활동의 전체 소스 코드는 예제 FragmentLayout 클래스 사용을 보여주는 샘플 앱에서 사용할 수 있습니다. The main activity applies a layout in the usual way, during onCreate():
main activity은 onCreate () 동안 일반적인 방식으로 레이아웃을 적용합니다. override fun onCreate(savedInstanceState : Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.fragment_layout) }
The layout applied is fragment_layout.xml:
적용된 레이아웃은 fragment_layout.xml입니다. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment class="com.example.android.apis.app.FragmentLayout$TitlesFragment" android:id="@+id/titles" android:layout_weight="1" android:layout_width="0px" android:layout_height="match_parent" /> <FrameLayout android:id="@+id/details" android:layout_weight="1" android:layout_width="0px" android:layout_height="match_parent" android:background="?android:attr/detailsElementBackground" /> </LinearLayout>
Using this layout, the system instantiates the TitlesFragment (which lists the play titles) as soon as the activity loads the layout, while the FrameLayout (where the fragment for showing the play summary appears) consumes space on the right side of the screen, but remains empty at first. As you'll see below, it's not until the user selects an item from the list that a fragment is placed into the FrameLayout.
레이아웃을 사용하여, 시스템은 activity가 레이아웃을 로드하면 TitlesFragment를 인스턴스화 합니다.
FrameLayout은 (해당 Fragment를 표시하기위해)화면 오른쪽 공간을 사용합니다.
하지만 처음에는 비어있습니다.
아래서 볼 수 있듯이 사용자가 목록에서 아이템을 선택하기 전까지는 fragment가 FrameLayout에 배치됩니다.However, not all screen configurations are wide enough to show both the list of plays and the summary, side by side. So, the layout above is used only for the landscape screen configuration, by saving it at res/layout-land/fragment_layout.xml.
하지만 모든 화면 구성이 다 표시할 만큼 넓지는 않습니다.
그래서 위의 레이아웃은 res / layout-land / fragment_layout.xml에 저장하여 가로 화면 구성에만 사용됩니다.Thus, when the screen is in portrait orientation, the system applies the following layout, which is saved at res/layout/fragment_layout.xml:
화면이 세로 방향 일 때 시스템은 res / layout / fragment_layout.xml에 저장된 다음 레이아웃을 적용합니다. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment class="com.example.android.apis.app.FragmentLayout$TitlesFragment" android:id="@+id/titles" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout>
This layout includes only TitlesFragment. This means that, when the device is in portrait orientation, only the list of play titles is visible. So, when the user clicks a list item in this configuration, the application starts a new activity to show the summary, instead of loading a second fragment.
해당 layout은 TitlesFragment만 포함합니다.
이것은, 기기가 세로 방향일때, 오직 list of play titles만 표시합니다.
그래서 사용자가 이 구성에서 아이템 목록을 클릭하면, 어플리케이션은 두번째 fragment를 불러오는 대신 새 activity를 시작합니다.Next, you can see how this is accomplished in the fragment classes. First is TitlesFragment, which shows the list of Shakespeare play titles. This fragment extends ListFragment and relies on it to handle most of the list view work.
fragment 클래스에서 이게 어떻게 동작하는지 볼 수 있습니다.
첫번째는 Shakespeare play titles의 목록을 보여주는 TitlesFragment입니다.
이 fragment는 ListFragment를 확장하고 list view 작업을 대부분 처리합니다.As you inspect this code, notice that there are two possible behaviors when the user clicks a list item: depending on which of the two layouts is active, it can either create and display a new fragment to show the details in the same activity (adding the fragment to the FrameLayout), or start a new activity (where the fragment can be shown).
코드를 살펴보면, 사용자가 아이템 목록을 클릭 할 때 2가지 가능한 동작이 있습니다.
두 레이아웃 중 어느 것이 활성 상태인지 따라서 동일한 activity의 상세 정보를 표시하기 위해 새로운 fragment를 만들거나
(FrameLayout에 fragment가 추가됩니다.) 새로운 actvitiy가 시작 할 수 있습니다.(fragment가 표시 될 수 있습니다.)class TitlesFragment : ListFragment() { private var dualPane : Boolean = false private var curCheckPosition = 0 override fun onActivityCreated(savedInstanceState : Bundle?) { super.onActivityCreated(savedInstanceState) // Populate list with our static array of titles. listAdapter = ArrayAdapter<String>( activity, android.R.layout.simple_list_item_activated_1, Shakespeare.TITLES ) // Check to see if we have a frame in which to embed the details // fragment directly in the containing UI. val detailsFrame: View? = activity?.findViewById(R.id.details) dualPane = detailsFrame?.visibility == View.VISIBLE curCheckPosition = savedInstanceState?.getInt("curChoice", 0) ?: 0 if (dualPane) { // In dual-pane mode, the list view highlights the selected item. listView.choiceMode = ListView.CHOICE_MODE_SINGLE // Make sure our UI is in the correct state. showDetails(curCheckPosition) } } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putInt("curChoice", curCheckPosition) } override fun onListItemClick(l: ListView, v: View, position: Int, id: Long) { showDetails(position) } /** * Helper function to show the details of a selected item, either by * displaying a fragment in-place in the current UI, or starting a * whole new activity in which it is displayed. */ private fun showDetails(index: Int) { curCheckPosition = index if (dualPane) { // We can display everything in-place with fragments, so update // the list to highlight the selected item and show the data. listView.setItemChecked(index, true) // Check what fragment is currently shown, replace if needed. var details = fragmentManager?.findFragmentById(R.id.details) as? DetailsFragment if (details?.shownIndex != index) { // Make new fragment to show this selection. details = DetailsFragment.newInstance(index) // Execute a transaction, replacing any existing fragment // with this one inside the frame. fragmentManager?.beginTransaction()?.apply { if (index == 0) { replace(R.id.details, details) } else { replace(R.id.a_item, details) } setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE) commit() } } } else { // Otherwise we need to launch a new activity to display // the dialog fragment with selected text. val intent = Intent().apply { setClass(activity, DetailsActivity::class.java) putExtra("index", index) } startActivity(intent) } } }
The second fragment, DetailsFragment shows the play summary for the item selected from the list from TitlesFragment:
DetailsFragment는 TitlesFragment의 리스트에서 선택한 항목에 대한 요약을 보여줍니다. class DetailsFragment : Fragment() { val shownIndex: Int by lazy { arguments?.getInt("index", 0) ?: 0 } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { if (container == null) { // We have different layouts, and in one of them this // fragment's containing frame doesn't exist. The fragment // may still be created from its saved state, but there is // no reason to try to create its view hierarchy because it // isn't displayed. Note this isn't needed -- we could just // run the code below, where we would create and return the // view hierarchy; it would just never be used. return null } val text = TextView(activity).apply { val padding: Int = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 4f, activity?.resources?.displayMetrics ).toInt() setPadding(padding, padding, padding, padding) text = Shakespeare.DIALOGUE[shownIndex] } return ScrollView(activity).apply { addView(text) } } companion object { /** * Create a new instance of DetailsFragment, initialized to * show the text at 'index'. */ fun newInstance(index: Int): DetailsFragment { val f = DetailsFragment() // Supply index input as an argument. val args = Bundle() args.putInt("index", index) f.arguments = args return f } } } }
Recall from the TitlesFragment class, that, if the user clicks a list item and the current layout does not include the R.id.details view (which is where the DetailsFragment belongs), then the application starts the DetailsActivity activity to display the content of the item.
TitlesFragment 클래스에서 사용자가 아이템 리스트를 클릭하고 현재 레이아웃에 R.id.details 뷰 (DetailsFragment가 속한 위치)가 포함되지 않은 경우, 애플리케이션이 DetailsActivity를 시작시켜 콘텐츠를 표시합니다. Here is the DetailsActivity, which simply embeds the DetailsFragment to display the selected play summary when the screen is in portrait orientation:
DetailsActivity는 세로 화면일때 선택된 play summary를 표시하기 위해 DetailsFragment를 포함 시키면 됩니다. class DetailsActivity : FragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) { // If the screen is now in landscape mode, we can show the // dialog in-line with the list so we don't need this activity. finish() return } if (savedInstanceState == null) { // During initial setup, plug in the details fragment. val details = DetailsFragment().apply { arguments = intent.extras } supportFragmentManager.beginTransaction() .add(android.R.id.content, details) .commit() } } }
Notice that this activity finishes itself if the configuration is landscape, so that the main activity can take over and display the DetailsFragment alongside the TitlesFragment. This can happen if the user begins the DetailsActivity while in portrait orientation, but then rotates to landscape (which restarts the current activity).
가로 화면일 경우 activity가 스스로 완료되므로 main activity는 TitlesFragment 와 DetailsFragment를 인수하고 표시 할 수 있습니다.
세로 방향으로 시작하고 가로로 회전하면(현재 acitivity가 다시 시작됩니다.) 이러한 상황이 발생 할 수 있습니다.반응형'Android 공식문서' 카테고리의 다른 글
Test your app's activites (0) 2020.10.27 Handle Activity State Changes (0) 2020.10.22 Understand the Activity Lifecycle (0) 2020.10.16 Introduction to Activities (0) 2020.09.22