Android片段
Android片段是一个GUI组件,可以"存在"于"活动"内部。 Android片段本身并不是大多数其他GUI组件都是的View的子类。相反,片段内部有一个视图。最终将在片段所在的活动内部显示此视图。
由于Android片段不是视图,因此将其添加到活动中看起来与添加视图有些不同(例如TextView)。片段被添加到活动内的" ViewGroup"中。片段的视图显示在此" ViewGroup"中。下图显示了向活动添加片段时发生的情况:
首先,活动获得对该片段的引用。然后,它获取对ViewGroup的引用,该片段的视图将其中呈现。然后,活动将添加片段。然后,该片段创建其视图并将其返回到活动。然后将视图插入到ViewGroup父级中,并且该片段处于活动状态。
创建片段
要创建片段,我们必须做两件事:
- `创建一个片段类。
- 创建一个片段布局XML文件。
创建一个片段类
要创建Fragment类,请创建一个扩展了android.app.Fragment的普通Java类。这是一个例子:
import android.app.Fragment; public class MyFragment extends Fragment { }
onCreateView()
这个Fragment
子类还没有做任何事情。 MyFragment类需要重写从Fragment继承的onCreateView()方法,以创建片段的View,该View将在添加片段的活动中显示。这是片段示例onCreateView()的实现:
public class MyFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup parentViewGroup, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_my, parentViewGroup, false); return rootView; } }
onCreateView()方法获取一个layoutInflater,一个ViewGroup和一个Bundle作为参数。
" LayoutInflater"是一个可以基于布局XML文件创建" View"实例的组件。如我们所见,该示例实际上是通过调用layout.inflate()
来实现的。
inflate()方法具有三个参数:布局XML文件的ID(在R.layout内部),将片段的View插入其中的父ViewGroup和第三个布尔值。判断是否应将从布局XML文件扩展来的片段的"视图"插入父级"视图组"中。在这种情况下,我们传递了false,因为View将会通过我们调用的某些Android代码(换句话说,在背后)添加到父ViewView的其他位置。当我们将false
作为最后一个参数传递给inflate()
时,父ViewGroup
仍用于膨胀的View
的布局计算,因此我们不能将null
作为父ViewGroup
传递。
onCreateView()的ViewGroup参数是父ViewGroup,片段的View将插入其中。这是活动内部的" ViewGroup",将"托管"该片段。
onCreateView()的Bundle参数是一个Bundle,片段可以将信息保存到其中,就像Activity一样。
向活动添加片段
为了在活动中显示片段的"视图",必须将片段添加到活动中。我们可以在活动中执行此操作。这是一个从活动的oncreate()内部添加片段的示例:
public class MyActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); if (savedInstanceState == null) { getFragmentManager() .beginTransaction() .add(R.id.fragmentParentViewGroup, new MyFragment()) .commit(); } } }
该片段被添加到if
语句中。与其他"视图"组件不同,该活动会记住向该活动中添加了哪些片段。因此,我们仅应在活动的生命周期内向该活动添加一个片段,否则该片段将出现多次。即使用户在纵向和横向之间更改设备的方向,即使活动在此过程中被破坏,也是如此。 Android操作系统会记住在创建此类新活动时向该活动添加了一个片段,并将该片段重新添加到该活动。
如果savedInstanceState
为null,则这是第一次为该活动创建任何状态,因此尚未向其添加任何片段。记住,如果一个应用程序被Android完全销毁了,它的savedInstanceState``Bundle
变量也会被销毁,那么在活动开始时,我们需要重新添加该片段。
片段必须在" FragmentTransaction"内部添加(或者替换或者删除)。我们可以通过" FragmentManager"获得" FragmentTransaction"。我们可以通过getFragmentManager()
方法获得FragmentManager
。从" FragmentManager"中,我们可以通过调用" beginTransaction()"方法获得" FragmentTransaction"。现在,在由beginTransaction()返回的" FragmentTransaction"上,我们可以添加,替换或者删除活动中的片段。
是FragmentTransaction上的add()方法将片段添加到活动中。 add()方法有两个参数。第一个参数是要插入片段的"视图"的父"视图组"的ID。第二个参数是要添加的片段的实例。
完成添加,替换或者删除片段后,我们必须提交FragmentTransaction
。为此,我们可以通过调用FragmentTransaction中的commit()方法来实现。仅当FragmentTransaction
提交后,我们所做的所有更改才会生效。
这是活动的布局XML文件。请注意,根元素的ID与R.layout
常量集合中引用的ID相同。
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/fragmentParentViewGroup" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MyActivity" tools:ignore="MergeRootFrame" />
这个布局XML文件只有一个FrameLayout
元素。这个FrameLayout元素被用作片段的父ViewGroup。因此,在实践中,片段将占据整个屏幕。我们可以使用其他ViewGroup
作为该片段的父对象。这是一个活动布局XML文件示例,显示了外观:
<LinearLayout 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:orientation="vertical" tools:context=".MyActivity" > <TextView android:text="Activity Title" android:layout_width="match_parent" android:layout_height="wrap_content" /> <LinearLayout android:id="@+id/fragmentParentViewGroup" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> </LinearLayout> </LinearLayout>
注意内部的LineLayout元素如何具有idfragmentParentViewGroup。该片段将使用此LinearLayout作为父ViewGroup。
碎片生命周期
Android片段的生命周期类似于活动生命周期。片段生命周期如下所示:
首先,将片段添加到活动中。这开始了片段的生命周期。
其次,调用方法onAttach(),onCreate(),onCreateView(),onActivityCreated(),onStart()和onResume()。完全创建托管活动后,将调用onActivityCreated()。
如果将片段从其托管活动中删除,或者将托管片段的活动移至应用程序的后台(另一个活动移至前台),则onPause(),onStop()和onDestroyView ()`方法被调用。如果片段返回可见性,则片段可以从onDestroyView()过渡到onCreateView()并再次变得可见。
替换片段
我们可以用另一个片段替换添加到活动中的片段。我们可以通过" FragmentTransaction"对象上的" replace()"方法来实现。这是一个" FragmentTransaction"replace()
示例:
getFragmentManager().beginTransaction() .replace(R.id.fragmentParentViewGroup, new MySecondFragment()) .commit();
我们可以在活动仍处于活动状态时替换片段。活动销毁后,我们将无法再替换其中的碎片。
我们可以根据需要多次替换片段。我们可以替换片段,以更改部分用户界面,或者更改整个用户界面(如果我们需要/喜欢)。
删除碎片
我们可以使用" FragmentTransaction"从活动中删除片段。我们可以通过remove()
方法来实现。这是一个" FragmentTransaction"remove()
示例:
getFragmentManager().beginTransaction() .remove(mySecondFragment) .commit();
remove()
方法有一个参数:对要删除的片段的引用。该片段将从添加该片段的任何父" ViewGroup"中删除。
将片段事务添加到后台堆栈
我们可以将片段事务添加到后台堆栈。后退堆栈可跟踪我们应用中的操作,当用户单击设备上的Android标准"后退"按钮时,这些操作可以后退。如果将片段事务添加到后台堆栈,则可以通过单击设备上的"后退"按钮来回溯(撤消)事务。
这是显示如何将片段事务添加到后台堆栈的示例:
MySecondFragment mySecondFragment = new MySecondFragment(); getFragmentManager().beginTransaction() .replace(R.id.fragmentParentViewGroup, mySecondFragment) .addToBackStack(null) .commit();
此示例用MySecondFragment实例替换ID为R.id.fragmentParentViewGroup的任何已添加到父视图组的片段。该示例还将替换事务添加到后台堆栈。 addToBackStack()方法采用可选的String参数,该参数可以标识后退堆栈上的此状态。在大多数情况下,我们不需要此参数,因此传递`null'就足够了。
提交此替换事务后,可以通过用户单击Android设备的"后退"按钮来撤消它,以相同的方式,"后退"按钮可以将用户带回到先前可见的活动。